NADA 5.6
Overview
NADA is the open-source microdata cataloguing platform developed by the International Household Survey Network (IHSN) and the World Bank. National statistics offices, central banks and research institutions use it to publish survey, census and administrative data as a searchable online catalogue. Studies are documented with DDI and Dublin Core metadata, and each data file carries an access policy: open, direct download, licensed with an application workflow, or enclave only. Everything is also available through a REST API, which tools such as PyNADA and NADAR use.
This guide covers launching and using the NADA 5.6 on Ubuntu 24.04 AMI from SecureAnyCloud on Amazon EC2. It is one version of the SecureAnyCloud BI and web analytics listing on AWS Marketplace. You pick it as the software version when you subscribe and launch.
What the SecureAnyCloud image adds:
- A database created on your instance. The image ships with an empty MySQL data directory. On first boot it creates MySQL's system tables (and MySQL's own TLS and RSA key pairs) on your instance. It then creates the NADA database, loads the upstream schema, applies the upstream migrations and creates one site administrator, with nothing to click through. No database file, account or password hash from the image build is on your instance.
- No web installer, no open sign-up. Upstream NADA's installer (
index.php/install) makes whoever reaches it first the administrator. On this image the installer, the legacy upgrade pages and an unauthenticated test page are removed, and Apache denies/install. Self-registration is switched off until you decide to open it (Step 9). - Secrets unique to your instance. The administrator password, an administrator API key, the MySQL password NADA uses and the session encryption key are generated on first boot and written to
/root/nada-credentials.txt(rootonly). The image ships with no database and no account, and Apache refuses to start until first boot has finished. MySQL root signs in through the local socket only, with no password anywhere. - HTTPS from the first boot. Apache serves NADA on port 443 with a certificate generated on your instance. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve get HTTP 421.
- Links that cannot be poisoned. Upstream NADA builds its links from the
Hostheader of each request. This image writes NADA'sbase_urlfrom the instance's own address (or a name you set). Apache hands NADA that name and the real client address from the connection, never values a client sends. - Only the application on the web. PHP runs only through NADA's front controller. The code (
application/,system/,modules/,vendor/), the data and log directories and the session store are never served, and the upload directories never execute PHP. - Hardened defaults. MySQL listens on
127.0.0.1only (the X Protocol port is off). Apache, MySQL and the first-boot service are blocked from the instance metadata service, the AMI requires IMDSv2, and the session cookie isSecureandHttpOnly. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- Patched PHP and libraries. PHP is Ubuntu's 8.3.6-0ubuntu0.24.04.13 build (USN-8948-1, the fix for CVE-2026-109618 and CVE-2026-109619), and the build checks that the running Apache has loaded it. The PHP libraries that NADA 5.6 bundles (auth0-php, Guzzle, PSR-7, FPDI and the MongoDB library) and its browser libraries (lodash, Underscore, Bootstrap 4, jQuery UI and Plupload) are updated to releases that fix their published vulnerabilities.
What is on the image: NADA 5.6 (the upstream v5.6 release, checksum verified), Apache 2.4 with mod_php, PHP 8.3, MySQL 8.0, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent.
Default user: ubuntu. Architecture: x86_64. Recommended instance type: m5.large.
Prerequisites
You need:
- 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 that you use for management)
- A security group that allows TCP 22 (SSH) from your admin network, and TCP 443 (NADA) and TCP 80 (redirects to HTTPS) from the networks your users work from. Never open 3306.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick NADA 5.6 on Ubuntu 24.04 as the software version and select your Region, then choose Launch through EC2.
Choose m5.large, your key pair and a security group as described above. The catalogue database and uploaded microdata files live on the root volume, so give it room to grow (30 GiB or more for a production catalogue).
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> \
--block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=30,VolumeType=gp3}' \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=nada}]'First boot creates the MySQL data directory, the catalogue, the migrations and the secrets. In our tests it took 26 to 28 seconds on a freshly launched t3.medium, measured from the start of the MySQL data directory setup to the end of the catalogue setup. It finishes within a minute on m5.large.
The web server starts as soon as first boot has finished. Allow a minute after the instance reports running before you browse to it.
Connect to your instance
For NADA 5.6 on Ubuntu 24.04, the SSH user is ubuntu:
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot creates the MySQL data directory, then the catalogue and the secrets, and then Apache starts. Run these commands to check the services and markers:
systemctl is-active mysql nada-firstboot apache2
sudo test -d /var/lib/mysql/mysql && echo MYSQL_DATADIR_CREATED
sudo test -f /var/lib/sac/data/nada-firstboot.done && echo FIRSTBOOT_DONEThe three units are active, and the markers show that the MySQL data directory and the first-boot setup are done. The nada-mysql-init unit runs on the first boot only, so on later boots it reports inactive:
active active active MYSQL_DATADIR_CREATED FIRSTBOOT_DONEOnly SSH and Apache listen on network ports. MySQL listens on the loopback address only:
sudo ss -lnt | awk 'NR>1 {print $4}' | grep -v '^127.0.0.5' | sort -u*:443 *:80 0.0.0.0:22 127.0.0.1:3306 [::]:22Get your URL, password and API key
Read the credentials file as root. No other user can read it:
sudo cat /root/nada-credentials.txtThe file contains the following:
# NADA 5.6 - generated on first boot by nada-firstboot.service
# These values are unique to this instance; none was baked into the image. Keep this file secret. NADA_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ NADA_ADMIN_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/index.php/admin NADA_ADMIN_EMAIL=admin@sac.local NADA_ADMIN_PASSWORD=<NADA_ADMIN_PASSWORD> NADA_API_KEY=<NADA_API_KEY> NADA_DB_NAME=nada NADA_DB_USER=nada NADA_DB_PASSWORD=<NADA_DB_PASSWORD>
# CodeIgniter session encryption key (application/config/config.php); you never need to type it. NADA_ENCRYPTION_KEY=<NADA_ENCRYPTION_KEY>
# The certificate is self signed (minted on this instance); port 80 redirects to https.
# Change the name NADA is served as:
sudo nada-set-hostname <your-dns-name>
# MySQL listens on 127.0.0.1 only; on-box maintenance as root:
sudo mysql
# User guide: https://secureanycloud.com/stacks/nada-5-6/The URL uses the instance's public DNS name from the EC2 instance metadata. The certificate also names the public and private IP addresses, so https://<public-ip>/ works too.
If you stop and start the instance without an Elastic IP, the boot service picks up the new address, updates NADA's base_url and issues a new certificate for it. To serve NADA under your own DNS name, see Step 8.
You need the MySQL password only for your own tools. NADA already has it in /var/www/html/nada/application/config/database.php.
Sign in
Open the NADA_URL in your browser. The certificate is self-signed, so your browser asks you to confirm it the first time. You can also install your own certificate (Step 8).
Choose Login and enter the NADA_ADMIN_EMAIL. NADA then asks for the password. Enter the NADA_ADMIN_PASSWORD from Step 4.
After you sign in, open Site administration from the user menu, or browse to the NADA_ADMIN_URL. The dashboard summarises the catalogue, collections, licensed requests and users, and links to every management area.
You can also check the sign-in from the instance. The script below signs in through the two-step login over HTTPS with the instance's password and reaches the dashboard. It shows that a blank password, admin and common weak passwords are refused. It then creates a study with the instance's API key, finds it in the public search and deletes it again:
sudo nada-cred-roundtrip.shOK per-instance admin signs in over HTTPS (dashboard); blank, admin and weak guesses refused; API key create/search/delete passed; bogus key refused (HTTP 400)Check the versions and the catalogue database
The public version API reports the NADA release. Check it together with the PHP, MySQL and Apache versions:
H=$(sudo grep '^NADA_URL=' /root/nada-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/index.php/api/version"; echo php -v | head -1 mysql --version apache2 -v | head -1{"version":"5.6"} PHP 8.3.6 (cli) (built: Oct 19 2026 15:16:58) (NTS) mysql Ver 8.0.46-0ubuntu0.24.04.4 for Linux on x86_64 ((Ubuntu)) Server version: Apache/2.4.58 (Ubuntu)The schema and the upstream migrations are applied, and exactly one administrator exists, stored with a bcrypt password hash. As root, you reach MySQL over the local socket with no password:
sudo mysql nada -e "SELECT COUNT(*) AS nada_tables FROM information_schema.tables WHERE table_schema='nada'"
sudo mysql nada -e "SELECT u.username, u.email, u.active, LEFT(u.password,4) AS hash, r.name AS role FROM users u JOIN user_roles ur ON ur.user_id=u.id JOIN roles r ON r.id=ur.role_id"nada_tables 90 username email active hash role admin admin@sac.local 1 $2a$ adminPublish your first study
You can add Studies in the browser or through the REST API. In the browser, open Studies, then Manage studies, then Add study, and import a DDI file or fill in the metadata. For the REST API, use the NADA_API_KEY.
This example creates a survey study from the instance. The key is read from the credentials file into a request header, so it never appears on a command line:
H=$(sudo grep '^NADA_URL=' /root/nada-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -sk --resolve "$H:443:127.0.0.1" -X POST \
-H @<(sudo grep '^NADA_API_KEY=' /root/nada-credentials.txt | sed 's/^NADA_API_KEY=/X-API-KEY: /') \
-H 'Content-Type: application/json' \
-d '{"repositoryid":"central","published":1,"overwrite":"yes","study_desc":{"title_statement":{"idno":"DEMO-HBS-2026","title":"Household Budget Survey 2026"},"study_info":{"abstract":"Household budget survey measuring income, expenditure and living conditions across urban and rural households.","nation":[{"name":"Example Country","abbreviation":"EXC"}],"coll_dates":[{"start":"2026-01","end":"2026-12"}]},"authoring_entity":[{"name":"National Statistics Office"}]}}' \
"https://$H/index.php/api/datasets/create/survey/DEMO-HBS-2026" | cut -c1-110; echo{"status":"success","dataset":{"id":"2","doi":null,"repositoryid":"central","type":"survey","idno":"DEMO-HBS-2026"The study is immediately findable through the public search API:
H=$(sudo grep '^NADA_URL=' /root/nada-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
curl -sk --resolve "$H:443:127.0.0.1" "https://$H/index.php/api/catalog/search?keywords=household" | grep -o -m1 '"idno":"DEMO-HBS-2026"'"idno":"DEMO-HBS-2026"In the browser, the public Microdata Catalog lists the published studies with their abstracts. Visitors can search by keyword and filter by year.
Each study page renders its DDI documentation (identification, producers and sponsors, data collection) with DDI/XML and JSON metadata downloads. The Get Microdata tab shows the access policy you set for the study's data files.
Curators manage studies, their data files, external resources and access policies under Studies, Manage studies.
Use your own DNS name and certificate
Point a DNS record at the instance. An Elastic IP keeps the address stable. Then set the name that NADA is served as.
The command below writes NADA's base_url, creates a new self-signed certificate for the name, and updates Apache and the URLs in /root/nada-credentials.txt. The name persists across reboots.
sudo nada-set-hostname <your-domain>To use a certificate from a public or private certificate authority instead, copy it over the generated pair and reload Apache. One example is a certificate issued by Let's Encrypt for <your-domain>. Running nada-set-hostname again replaces it with a self-signed one.
sudo install -m 0644 <your-domain>.crt /etc/ssl/nada/nada.crt
sudo install -m 0600 <your-domain>.key /etc/ssl/nada/nada.key
sudo apache2ctl -t && sudo systemctl reload apache2Manage users, sign-up and email
- Change the administrator password after your first sign-in. Open the user menu (your name, top right) and choose Password. Then update or delete
NADA_ADMIN_PASSWORDin/root/nada-credentials.txt, so that the file does not hold an old password. - Add accounts for your curators under Users in Site administration. Give each the role they need, rather than sharing the administrator account.
- Self-registration (researchers creating their own accounts to request licensed data) is off on this image. To open it, set
$config['site_user_register'] = 'yes';in/var/www/html/nada/application/config/config.php(edit it withsudo). NADA then shows a Register link on the login page. Configure email first, so that new accounts can be activated. - Email: NADA sends account activation, password reset and data access request messages. Copy
email.sample.phptoemail.phpin/var/www/html/nada/application/config/(ownerroot, groupwww-data, mode 0640, like the other configuration files). Then setsmtp_host,smtp_port,smtp_user,smtp_passandsmtp_cryptofor your relay. Amazon SES works as the relay (port 587 withtls). If you restrict egress, allow outbound 587 in your security group or network ACLs. - API keys: the image creates one administrator key (
NADA_API_KEY). Users create and revoke their own keys from their profile. Once you have your own key, you can revoke the image's key there too.
Security checks
The installer is gone and Apache serves only the application. The code, the data and log directories and the session store are refused, self-registration answers 404, plain HTTP redirects to HTTPS, and a host name the instance does not serve gets 421. NADA's base_url is the configured name, and NADA trusts no proxy headers. Run these commands to confirm:
H=$(sudo grep '^NADA_URL=' /root/nada-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#') for p in /index.php/catalog /index.php/install /install/ /index.php/auth/register /application/config/database.php /vendor/autoload.php /datafiles/ /files/sessions/; do curl -sk -o /dev/null -w "%{http_code} $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p" done curl -s -o /dev/null -w 'http:// -> %{http_code} %{redirect_url}\n' --resolve "$H:80:127.0.0.1" "http://$H/" curl -sk -o /dev/null -w 'other host name -> %{http_code}\n' --resolve "example.com:443:127.0.0.1" https://example.com/
sudo grep -E "sac-base-url|^.config\['(site_user_register|cookie_secure|proxy_ips)'\]" /var/www/html/nada/application/config/config.php200 /index.php/catalog 404 /index.php/install 403 /install/ 404 /index.php/auth/register 403 /application/config/database.php 403 /vendor/autoload.php 403 /datafiles/ 403 /files/sessions/ http:// -> 301 https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ other host name -> 421 $config['base_url'] = 'https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/'; // sac-base-url: set by nada-set-hostname, never from the request $config['cookie_secure'] = TRUE; $config['proxy_ips'] = ''; $config['site_user_register'] = 'no';The instance generated its own certificate, and the certificate names the instance's own addresses:
H=$(sudo grep '^NADA_URL=' /root/nada-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#')
echo | openssl s_client -connect 127.0.0.1:443 -servername "$H" 2>/dev/null | openssl x509 -noout -subject -ext subjectAltNamesubject=CN = ec2-<public-ip-dashed>.compute-1.amazonaws.com, O = sac X509v3 Subject Alternative Name: DNS:ec2-<public-ip-dashed>.compute-1.amazonaws.com, IP Address:<public-ip>, IP Address:<private-ip>, DNS:ip-<private-ip-dashed>.ec2.internal, IP Address:127.0.0.1, DNS:localhostApache (and NADA's PHP code, which runs inside it), MySQL and the two first-boot services cannot reach the instance metadata service. A URL that NADA is asked to fetch can therefore never return your instance's credentials:
systemctl show apache2 mysql nada-firstboot nada-mysql-init -p Id -p IPAddressDenyIPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=apache2.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=mysql.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=nada-firstboot.service IPAddressDeny=169.254.169.254/32 168.63.129.16/32 fd00:ec2::254/128 Id=nada-mysql-init.serviceBackup and maintenance
The catalogue lives in the MySQL database nada (/var/lib/mysql). The microdata files, external resources and thumbnails you upload live under /var/www/html/nada/datafiles and /var/www/html/nada/files.
The simplest backup is an EBS snapshot of the root volume. For a consistent file-level copy while NADA is running, use:
sudo mysqldump --single-transaction --routines nada | gzip > <backup-dir>/nada-$(date +%F).sql.gz
sudo tar -czf <backup-dir>/nada-files-$(date +%F).tar.gz -C /var/www/html/nada datafiles filesOperating system security updates install automatically. Run sudo apt-get update && sudo apt-get upgrade to apply everything else. Apache and MySQL restart cleanly, and NADA keeps all of its data.
Key files and paths:
- NADA (document root): /var/www/html/nada
- Configuration: /var/www/html/nada/application/config/config.php and database.php (mode 0640)
- Microdata and resource files: /var/www/html/nada/datafiles
- Database: MySQL database nada (/var/lib/mysql)
- Apache site: /etc/apache2/sites-available/sac-nada.conf
- Apache logs: /var/log/apache2/nada-access.log, nada-error.log
- Certificate and key: /etc/ssl/nada/
- Boot services: /usr/local/sbin/nada-mysql-init.sh (MySQL data directory, first boot only), /usr/local/sbin/nada-firstboot.sh
- Host name helper: /usr/local/sbin/nada-set-hostname
- Credentials: /root/nada-credentials.txt (mode 0600)
- Licence: /usr/share/doc/nada/LICENSE
Security recommendations
- Allow port 22 from your admin network only, and ports 80 and 443 only from the networks your users work from. Never open 3306.
- Use your own DNS name and a certificate that your users' browsers trust (Step 8).
- Give each curator their own account and role. Change the administrator password if it may have been shared (Step 9).
- Keep the operating system patched, and snapshot the root volume regularly.
- A few browser libraries bundled with NADA 5.6 (Bootstrap 3, Vue 2, Vuetify 2 and Quill) have published advisories with no fix on the release lines that NADA 5.6 uses. The image build checks that NADA does not use them in the ways those advisories describe. Give administration accounts only to people you trust.
Support and licensing
NADA is open source under the MIT licence. The text ships at /usr/share/doc/nada/LICENSE, and there is no per-user or per-CPU licence fee. The AMI price covers SecureAnyCloud's hardening, first-boot setup and support.
NADA is developed by the International Household Survey Network and the World Bank. SecureAnyCloud is not affiliated with or endorsed by them.
- Email: sales@secureanycloud.com
Deploy on AWS
Launch NADA 5.6 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