CDash 5.5.2
Overview
CDash is Kitware's open source dashboard server for software testing. CMake's test driver CTest submits each build's configure output, compiler warnings and errors, test results, coverage and memory-checker results to CDash. CDash shows them per project, build group and machine, with history, test timing, filters, e-mail notifications and an API.
This SecureAnyCloud AMI runs CDash 5.5.2 on Ubuntu 24.04 on Amazon EC2. It is one version of the SecureAnyCloud Hardened Apache Subversion (SVN) & CI/CD Tools listing on AWS Marketplace. You choose it as the software version when you subscribe and launch.
What you get:
- Nothing shared between instances. The image ships no database, no configuration file and no account. Your instance's first boot creates its own PostgreSQL 16 database cluster, CDash's application key, the administrator's password and the HTTPS certificate. The web server, PHP and CDash's background services do not start until first boot has finished. If first boot cannot finish, CDash stays offline rather than open.
- No database password to leak. PostgreSQL has no network listener at all. CDash connects over a local socket as its own operating-system user. PostgreSQL accepts that user, and only that user, for the
cdashdatabase through peer authentication, so there is no database password anywhere. - HTTPS from the first boot. nginx serves CDash on port 443 with a certificate generated on your instance. Port 80 redirects to HTTPS, and requests for a host name that the instance does not serve are dropped.
- Token-authenticated CTest submissions. CDash is set to require authenticated submissions. Every project that a non-administrator creates must use authentication tokens, and the projects you create should have Authenticate submissions ticked (Step 7). A submission without the project's token is refused.
- No public sign-up, no anonymous password reset. Self-registration is off, and you add users yourself. CDash 5.5.2's old password-recovery page sets a new random password for any e-mail address and mails it, which lets anyone lock the administrator out. For that reason, the image does not serve the page. CDash replaced it after 5.5.2.
- Cross-site requests refused. CDash 5.5.2 exempts its older
.phpendpoints from its own form-token check, so nginx refuses every request that changes something unless it comes from your CDash pages themselves. The one exception is CTest's submission endpoint,/submit.php, in its exact form. The project tokens protect that endpoint instead. - A PHP that cannot reach the shell or your network. PHP runs as its own user and cannot change the CDash code. In the web server and in the background services alike, PHP cannot run programs, fork, change its environment, send mail with
mail(), load extensions or use FFI. A program saved into a writable folder cannot be executed. CDash cannot open connections to loopback, link-local, private (RFC 1918), carrier-grade NAT, IPv6 unique-local or metadata addresses, whatever spelling a URL uses. Outbound calls to the internet (GitHub, your SMTP relay) still work. - Submitter content sandboxed. Test images, uploaded build files and every other response that is not one of CDash's own HTML pages are served with a sandboxing content security policy, in every spelling of their address, so no script in submitted content runs on your CDash site.
- The real host and client address. CDash builds every link from the host name you configure, never from a request header, and records the address of the connection, never a forwarded header.
- Rate limits. 10 sign-in attempts a minute from one address (on top of CDash's own lockout after 5 failures), 600 submissions a minute, 300 other changes a minute and 1,800 requests a minute.
- Metadata service blocked for nginx, PHP, PostgreSQL, CDash's queue worker and scheduler, and the first-boot service. The AMI requires IMDSv2.
- PHP 8.4 from the ondrej/php PPA. CDash 5.5.2 needs PHP 8.4, and Ubuntu 24.04 ships PHP 8.3. PHP 8.4 therefore comes from the ondrej/php PPA, which is trusted only through its pinned signing key and allowed to provide PHP packages only. Unattended upgrades keep it patched along with Ubuntu.
- A fully patched base. Ubuntu 24.04 LTS is patched at build time, with unattended security upgrades switched on.
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair, and a VPC subnet with a route to the internet (or a private route you use for management).
- A security group that allows TCP 22 (SSH), TCP 443 (CDash) and TCP 80 (redirects to HTTPS) from the networks that should reach them. These are your team's browsers and every machine that runs CTest. Keep port 22 open to your own networks only.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick CDash 5.5.2 on Ubuntu 24.04 as the software version, select your Region, and choose Launch through EC2.
Choose m5.large (or larger for many projects or large submissions), your key pair and a security group as described in Prerequisites.
To launch with the AWS CLI instead, replace the values in angle brackets:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=cdash}]'Connect to your instance
Connect over SSH as the login user for the version you launched:
- CDash 5.5.2 on Ubuntu 24.04: SSH user ubuntu
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot takes under a minute. Afterwards, nginx, PHP, PostgreSQL, CDash's queue worker and scheduler, and the first-boot unit should be active:
systemctl is-active nginx php8.4-fpm postgresql@16-main cdash-worker cdash-scheduler cdash-firstbootactive active active active active activenginx serves ports 80 and 443. PHP and PostgreSQL listen on local sockets only, so the only open ports are 22, 80 and 443:
sudo ss -tlnp | awk 'NR==1 || /nginx|sshd|php|postgres/' | awk '{print $1, $4, $6}' | sed -E 's/,pid=[0-9]+,fd=[0-9]+//g'State Local Peer LISTEN 0.0.0.0:22 users:(("sshd"),("systemd")) LISTEN 0.0.0.0:80 users:(("nginx"),("nginx"),("nginx")) LISTEN 0.0.0.0:443 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:22 users:(("sshd"),("systemd")) LISTEN [::]:80 users:(("nginx"),("nginx"),("nginx")) LISTEN [::]:443 users:(("nginx"),("nginx"),("nginx"))These commands show the CDash release, PHP, PostgreSQL and how the image was built:
cat /var/www/cdash/public/VERSION php -v | head -1 /usr/lib/postgresql/16/bin/postgres --version sed -n '3,4p' /usr/share/doc/cdash/SOURCE.txtv5.5.2 PHP 8.4.27 (cli) (built: Oct 21 2026 14:35:21) (NTS) postgres (PostgreSQL) 16.15 (Ubuntu 16.15-0ubuntu0.24.04.1) Upstream: the official CDash 5.5.2 release, GitHub tag v5.5.2 of https://github.com/Kitware/CDash (commit 337d905ad927a4d7a42dd1320c30227a5472be8a), archive https://codeload.github.com/Kitware/CDash/tar.gz/refs/tags/v5.5.2 (sha256 8caac71176d7301e548d0d1c947dcac302ebea10cc366c221e3e6944c6107c3a)./usr/share/doc/cdash/SOURCE.txt lists exactly how the release was built and what was left out. /usr/share/doc/cdash/frontend-packages.txt lists the JavaScript packages compiled into CDash's pages.
Get your sign-in details
The credentials file holds the address that CDash is served as (your instance's public DNS name by default), and the administrator's e-mail and password, generated on this instance:
sudo cat /root/cdash-credentials.txtCDASH_URL=https://ec2-<public-ip-dashed>.<region>.compute.amazonaws.com/ CDASH_ADMIN_EMAIL=admin@sac.local CDASH_ADMIN_PASSWORD=<24 letters and digits>There is no database password. PostgreSQL accepts CDash's own system user over the local socket only.
Sign in
Open CDASH_URL in your browser. The certificate is self-signed and was generated on your instance, so your browser asks you to confirm the first time. Step 11 shows how to use your own DNS name and certificate.
Sign in with the e-mail and password from the credentials file:
After you sign in, CDash shows its projects page. A fresh instance has no projects yet:
Open Profile (top left) to set your own name and e-mail address. Change the password from there or with sudo cdash-set-password (Step 12).
The footer's GraphQL Explorer link leads to a page that this image switches off (Step 8).
Create a project
As the administrator, open /projects/new (or Administration, then Create new project), give the project a name, choose who can see it, and tick Authenticate submissions:
Then open Profile, then Authentication Tokens (or /authtokens/manage), and create a submit only token for the project. CDash shows the token once. Store it in your CI system's secret store, never in the repository.
Submit from CTest
In your project, add a CTestConfig.cmake next to the top-level CMakeLists.txt (the project name must match the one in CDash):
set(CTEST_PROJECT_NAME "<your-project>") set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC") set(CTEST_SUBMIT_URL "https://<your-cdash-host>/submit.php?project=<your-project>")Then run a dashboard build with the token in an HTTP header (CTest 3.15 or later):
ctest -D Experimental --http-header "Authorization: Bearer <your-token>"In a CTest script, set CTEST_SUBMIT_HTTP_HEADER or pass HTTPHEADER "Authorization: Bearer ${token}" to ctest_submit().
While the certificate is self-signed, either install it on your CI machines or add --tls-verify OFF, and only on a network you trust. With your own certificate (Step 11), nothing extra is needed.
The configure output, warnings and errors, and the test results appear on the project's dashboard within seconds. CDash's queue worker parses each submission in the background:
Your tokens are listed under Authentication Tokens, where you can revoke one at any time:
A submission without the token, or with a wrong one, is refused (403 Invalid Token). Submissions are capped at 256 MB each.
The settings that are closed by default
CDash's settings live in /etc/cdash/cdash.env, which root owns and CDash can read but not change. The image sets these defaults:
sudo grep -E '^(APP_ENV|APP_DEBUG|QUEUE_CONNECTION|REQUIRE_AUTHENTICATED_SUBMISSIONS|USER_REGISTRATION_FORM_ENABLED|MINIMUM_PASSWORD_LENGTH|GRAPHIQL_ENABLED|USE_VCS_API|MAIL_MAILER|DB_HOST|DB_PASSWORD)=' /etc/cdash/cdash.envAPP_ENV=production APP_DEBUG=false DB_HOST=/var/run/postgresql DB_PASSWORD= <set-at-first-boot>=database MAIL_MAILER=log GRAPHIQL_ENABLED=false REQUIRE_AUTHENTICATED_SUBMISSIONS=true USER_REGISTRATION_FORM_ENABLED=false MINIMUM_PASSWORD_LENGTH=12 USE_VCS_API=falseUSE_VCS_API=false: CDash does not call GitHub or other repository APIs (commit details, pull-request comments) until you switch it on.MAIL_MAILER=log: CDash writes e-mails to its log until you configure SMTP (Step 12), andmail()is not available to PHP.GRAPHIQL_ENABLED=false: the GraphQL explorer page is off. CDash's own pages use the GraphQL API at/graphql, which stays on.
After any change, rebuild CDash's caches. This also restarts nothing that is not needed:
sudo /usr/local/lib/sac/cdash/rebuild-cachesYour data
CDash keeps its data in these locations:
- PostgreSQL 16 cluster (projects, builds, test results, users): /var/lib/postgresql/16/main
- Submissions waiting to be parsed, being parsed and already parsed, plus uploaded files: /var/lib/cdash/storage/app
- CDash's logs: /var/lib/cdash/storage/logs
- Settings: /etc/cdash/cdash.env
- The code (read only to CDash): /var/www/cdash
Back up the database with pg_dump as the postgres user. Also copy /var/lib/cdash/storage/app/upload and /etc/cdash/cdash.env. The settings file holds the application key, which signs sessions and stored tokens:
sudo -u postgres pg_dump -h /var/run/postgresql -Fc cdash > cdash-$(date +%F).dumpSecurity checks
Port 80 sends browsers to HTTPS, and the health endpoint answers for load balancer checks. The following are not reachable: the old password-recovery page, any path after index.php (which CDash's framework would otherwise route like the plain path, past nginx's rules), the GraphQL explorer, the settings file, the code and the logs.
Run:
H=$(sed -n 's/^set \$cd_host "\(.*\)";$/\1/p' /etc/nginx/cdash-host.conf)
curl -s -o /dev/null -w 'port 80: %{http_code} -> %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/login" | sed -E 's#https://[^/]+#https://<your host>#'
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/healthz" for p in /recoverPassword.php /index.php/recoverPassword.php /index.php/login /graphql/explorer /.env /composer.json /vendor/autoload.php /storage/logs/cdash.log /register; do
curl -sk -o /dev/null -w "$p: %{http_code}\n" -H 'Sec-Fetch-Site: same-origin' --resolve "$H:443:127.0.0.1" "https://$H$p" done
curl -s -o /dev/null -w 'unknown host name: %{http_code}\n' -H 'Host: example.com' http://127.0.0.1/ || trueport 80: 301 -> https://<your host>/login ok /recoverPassword.php: 404 /index.php/recoverPassword.php: 404 /index.php/login: 404 /graphql/explorer: 404 /.env: 404 /composer.json: 404 /vendor/autoload.php: 404 /storage/logs/cdash.log: 404 /register: 404 unknown host name: 000A status of 000 means that nginx closed the connection without an answer. A request that changes something is refused when it comes from another site, and CTest's submission endpoint answers only in its exact form (here for a project that does not exist):
H=$(sed -n 's/^set \$cd_host "\(.*\)";$/\1/p' /etc/nginx/cdash-host.conf)
curl -sk -o /dev/null -w 'cross-site POST /api/v1/buildgroup.php: %{http_code}\n' -X POST -H 'Origin: https://example.com' --data 'x=1' --resolve "$H:443:127.0.0.1" "https://$H/api/v1/buildgroup.php"
curl -sk -o /dev/null -w 'cross-site POST /graphql: %{http_code}\n' -X POST -H 'Sec-Fetch-Site: cross-site' --data '{}' --resolve "$H:443:127.0.0.1" "https://$H/graphql"
curl -sk -o /dev/null -w 'PUT /submit.php: %{http_code}\n' -X PUT --data-binary 'x' --resolve "$H:443:127.0.0.1" "https://$H/submit.php?project=no-such-project"
curl -sk -o /dev/null -w 'PUT /SUBMIT.php: %{http_code}\n' -X PUT --data-binary 'x' --resolve "$H:443:127.0.0.1" "https://$H/SUBMIT.php?project=no-such-project"cross-site POST /api/v1/buildgroup.php: 403 cross-site POST /graphql: 403 PUT /submit.php: 404 PUT /SUBMIT.php: 403Check the credentials and settings files, the code and CDash's folders:
sudo stat -c '%a %U:%G %n' /root/cdash-credentials.txt /etc/cdash /etc/cdash/cdash.env /var/www/cdash /var/lib/cdash /var/lib/cdash/storage600 root:root /root/cdash-credentials.txt 750 root:cdash /etc/cdash 640 root:cdash /etc/cdash/cdash.env 755 root:root /var/www/cdash 750 root:cdash /var/lib/cdash 750 cdash:cdash /var/lib/cdash/storagePostgreSQL has no network listener and uses only local peer authentication. CDash's database role has no password and no privileges outside its database:
sudo -u postgres psql -X -tA -h /var/run/postgresql -d postgres -c "SHOW listen_addresses" -c "SELECT rolname, rolsuper, rolpassword IS NULL AS no_password FROM pg_authid WHERE rolname = 'cdash'"
sudo grep -vE '^[[:space:]]*(#|$)' /etc/postgresql/16/main/pg_hba.confcdash|f|t local all postgres peer local cdash cdash peerThe empty first line is listen_addresses, which means no TCP listener. PHP's restrictions are in effect for the web server and the background services, and both are denied the metadata service and internal addresses:
grep -E '^php_admin_value\[(disable_functions|ffi.enable)\]' /etc/php/8.4/fpm/pool.d/cdash.conf for u in php8.4-fpm cdash-worker; do echo "$u: $(systemctl show -p IPAddressDeny --value $u | tr ' ' '\n' | grep -cE '^(127\.0\.0\.0/8|10\.0\.0\.0/8|169\.254\.0\.0/16|172\.16\.0\.0/12|192\.168\.0\.0/16|::1/128|fc00::/7)$') of 7 internal ranges denied"; donephp_admin_value[disable_functions] = exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec,pcntl_fork,putenv,mail,dl,imap_open php_admin_value[ffi.enable] = 0 php8.4-fpm: 7 of 7 internal ranges denied cdash-worker: 7 of 7 internal ranges deniedYour own DNS name and certificate
Point a DNS name at the instance, then tell CDash to use it. This command generates a new self-signed certificate for the name, pins nginx to it, and updates CDash's address:
sudo cdash-set-hostname cdash.example.comFor a trusted certificate, install certbot with the nginx plugin and request a certificate for the name. Keep nginx's ssl_certificate lines in /etc/nginx/sites-available/sac-cdash pointing at it.
Once a trusted certificate is in place, you can also add a Strict-Transport-Security header in that file. Re-run cdash-set-hostname whenever the name changes.
Passwords, users, e-mail, LDAP and upgrades
- Administrator password:
sudo cdash-set-passwordgenerates a new password, signs every session out and records the password in/root/cdash-credentials.txt. - Users: as the administrator, open Users to add accounts, or set
USER_REGISTRATION_FORM_ENABLED=truein/etc/cdash/cdash.envif you want people to register themselves. - E-mail: set
MAIL_MAILER=smtpandMAIL_HOST,MAIL_PORT,MAIL_USERNAME,MAIL_PASSWORD,MAIL_ENCRYPTIONandMAIL_FROM_ADDRESSin/etc/cdash/cdash.env, then runrebuild-cachesandsudo cdash-artisan email:test --email=you@example.com. CDash's password reset by e-mail (Laravel's, under Forgot your password? on recent releases) works once mail works. - A server inside your VPC (SMTP relay, LDAP, GitHub Enterprise): CDash may not connect to private addresses by default. Allow exactly that address for PHP and the worker with a drop-in. This example allows an LDAP server at 10.0.1.25:
for u in php8.4-fpm cdash-worker cdash-scheduler; do
sudo mkdir -p /etc/systemd/system/$u.service.d printf '[Service]\nIPAddressAllow=10.0.1.25/32\n' | sudo tee /etc/systemd/system/$u.service.d/70-allow-ldap.conf done
sudo systemctl daemon-reload && sudo systemctl restart php8.4-fpm cdash-worker cdash-scheduler- GitHub integration: set
USE_VCS_API=true, theGITHUB_*settings andGITHUB_WEBHOOK_SECRET. The webhook endpoint/api/v1/GitHub/webhook.phpis refused by the cross-site guard until you exempt it in/etc/nginx/conf.d/sac-cdash.conf(add its exact path next to/submit.phpin the$cd_submit_rawand$cd_submit_normmaps). - Artisan: run CDash's commands as
sudo cdash-artisan <command>(for examplequeue:failedorproject:delete <name>). Never put a password on its command line. The wrapper refuses--password. - Upgrades: Ubuntu and PHP security updates install automatically. A new CDash release replaces /var/www/cdash. SecureAnyCloud publishes new versions in this listing. To upgrade in place, follow CDash's upgrade notes, build the release the same way (SOURCE.txt), and run sudo cdash-artisan migrate --force.
Server components
The image runs these components:
- CDash 5.5.2
- PHP 8.4 (ondrej/php PPA), with PHP-FPM running as user cdash
- PostgreSQL 16 (Ubuntu 24.04)
- nginx 1.24 (Ubuntu 24.04)
- Operating system: Ubuntu 24.04 LTS
These services make up the stack:
- nginx: HTTPS on 443, redirect on 80
- php8.4-fpm: CDash's web pages and API
- postgresql@16-main: the database (local socket only)
- cdash-worker: parses submissions and runs CDash's background jobs
- cdash-scheduler: runs CDash's scheduled pruning and notification jobs every minute
- cdash-firstboot: creates this instance's database, keys, password and certificate (once)
Security recommendations
- Restrict port 443 to your team and CI networks unless your projects are meant to be public.
- Select Authenticate submissions on every project, use submit-only tokens for CI, and revoke tokens you no longer use.
- Use your own DNS name and a trusted certificate (Step 11), then add HSTS.
- Keep AWS backups of the EBS volume, or take regular
pg_dumpbackups (Step 9). - The front end of CDash 5.5.2 still includes AngularJS 1.8.3 for its older pages, and AngularJS is no longer maintained upstream. The two high-severity AngularJS advisories (CVE-2024-21490 and CVE-2026-11998) apply to features CDash does not use (
ng-srcsetand custom resource-URL allow lists).
Support and licensing
CDash is open source software by Kitware, released under the BSD 3-Clause licence (/usr/share/doc/cdash/LICENSE).
SecureAnyCloud provides the image, its hardening and support for launching and running it. Contact sales@secureanycloud.com for help. CDash's own documentation is at https://github.com/Kitware/CDash/tree/master/docs.
Deploy on AWS
Launch CDash 5.5.2 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com