HDS-Explorer · user guide

HDS-Explorer on Ubuntu

For the site's data managers and supervisors. Installs the server on an empty Ubuntu machine, ending at backup and upgrade. Every step was performed on a test machine with the accounts and passwords of chapter 1.4. Site setup, the tablet app and the rounds are in Using HDS-Explorer.

Ubuntu 26.04 LTS · x64 or ARM64Java 17MySQL 8.4 LTSTomcat 9Ports 8081 · 3307Plain HTTP

1. Before you start

What the server needs, the accounts this guide uses, and the check to make before installing. This guide installs HDS-Explorer 1.0.0 build 7 and was tested with it.


1.1 What gets installed

The server is a web application. Data managers use its console in a browser. The tablet app is an Android app that field workers use, and that sends its data to the server.

The server is three programs on one machine:

Program Version
Java (JDK) 17
Apache Tomcat 9.0
MySQL 8.4 LTS

Use exactly these major versions. Java 21, Tomcat 10 or 11, and MySQL 8.0 or 9.x are not supported.


1.2 The server machine

Minimum Recommended
Operating system Ubuntu Server or Desktop 26.04 LTS, 64-bit
Processor x64 or ARM64, 2 cores 4 cores
Memory 4 GB 8 GB
Disk 40 GB free 100 GB free
Network A fixed address on the network the tablets use

The tablets are given the server's address once and keep it. If the address changes, every tablet has to be told again.

The tablets talk to the server over plain HTTP, for example http://192.168.1.10:8081/hds-explorer-server. Put the server on a network you trust. Never open its port to the internet. The tablets use the local build of the app, local-4.apk.


1.3 The tablets

Android 6.0 or newer, 2 GB free, and Wi-Fi or mobile data that reaches the server. The tablet app, local-4.apk (1.0.0 build 4-local, 34 MB), is installed in Using HDS-Explorer, chapter C.


1.4 Accounts and passwords

Every site uses the same accounts and passwords for the test, so any step can be repeated anywhere.

Account Where User name Password
MySQL administrator MySQL root Hdsx-root-1
The server's database account MySQL, database hds_explorer_db hdsx_app Hdsx-app-1
Read-only database account MySQL hdsx_read Hdsx-read-1
First administrator Console, first sign-in only admin Change-me-1
Administrator Console admin Hdsx-admin-1 (set at the first sign-in)
Data manager Console dm01 Hdsx-dm01-1
Supervisor Console and tablet sv01 Hdsx-sv01-1
Field worker Tablet fw01 Hdsx-fw01-1

Before the server holds real data, change every one of these passwords.


1.5 Ports

Port Used by Open to
8081 Tomcat: the console and the tablets The site network
3307 MySQL This machine only

1.6 Check the machine is empty

Run:

systemctl list-units --type=service --all | grep -Ei 'tomcat|mysql|mariadb'
sudo ss -ltnp | grep -E ':(3306|3307|8080|8081) '
java -version

The first two print nothing, and java -version says Command 'java' not found. If anything else shows, another system uses this machine: install HDS-Explorer on a machine of its own.

You also need an account that can use sudo, internet access on the machine, and its fixed address.

2. Install

Installs Java 17, MySQL 8.4 and Tomcat 9, creates the database, and puts the HDS-Explorer server into Tomcat. Run every command in a terminal, as the account that can use sudo.


2.1 Java 17

Installs Java and the tools the guide uses (curl, unzip, jq):

sudo apt update
sudo apt install -y openjdk-17-jdk-headless curl unzip jq
java -version

The first line says openjdk version "17.0.20.1" (or a newer 17).


2.2 MySQL 8.4

Installs MySQL:

sudo apt install -y mysql-server
mysql --version

It says Ver 8.4.11-0ubuntu0.26.04.1 or a newer 8.4.

Creates MySQL's settings file (port 3307, this machine only, Amharic-safe text, Ethiopian time) and restarts MySQL. Use your site's offset from UTC for default-time-zone if it is elsewhere:

sudo tee /etc/mysql/mysql.conf.d/hdsx.cnf > /dev/null <<'EOF'
[mysqld]
port=3307
bind-address=127.0.0.1
mysqlx=OFF
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone=+03:00
max_allowed_packet=64M
EOF
sudo systemctl restart mysql

Gives the MySQL root account the password of chapter 1.4:

sudo mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'Hdsx-root-1';"

Checks it:

mysql -h 127.0.0.1 -P 3307 -u root -pHdsx-root-1 -e "SELECT VERSION(), @@port, @@bind_address, @@collation_server, @@time_zone;"

It prints 8.4.11-0ubuntu0.26.04.1, 3307, 127.0.0.1, utf8mb4_unicode_ci and +03:00, after a warning about a password on the command line. Every mysql command in this guide names -h 127.0.0.1 -P 3307.


2.3 Tomcat 9

Tomcat runs as its own user, hdsx, with no login:

sudo useradd --system --home-dir /opt/tomcat9 --shell /usr/sbin/nologin hdsx

Downloads Tomcat 9.0.123 and checks it:

cd /tmp
curl -fLO https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.123/bin/apache-tomcat-9.0.123.tar.gz
curl -fLO https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.123/bin/apache-tomcat-9.0.123.tar.gz.sha512
sha512sum -c apache-tomcat-9.0.123.tar.gz.sha512

The last line says apache-tomcat-9.0.123.tar.gz: OK. Do not continue if it says anything else. If 9.0.123 is no longer on dlcdn.apache.org, use the same file from https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.123/bin/.

Unpacks Tomcat and removes its sample pages:

sudo mkdir -p /opt/tomcat9
sudo tar -xzf apache-tomcat-9.0.123.tar.gz -C /opt/tomcat9 --strip-components=1
sudo rm -rf /opt/tomcat9/webapps/ROOT /opt/tomcat9/webapps/docs /opt/tomcat9/webapps/examples /opt/tomcat9/webapps/manager /opt/tomcat9/webapps/host-manager

Sets Tomcat's port to 8081, switches off its shutdown port, and keeps its Java settings out of its log:

sudo sed -i \
  -e 's/port="8080"/port="8081"/' \
  -e 's/port="8005"/port="-1"/' \
  -e 's|<Listener className="org.apache.catalina.startup.VersionLoggerListener" />|<Listener className="org.apache.catalina.startup.VersionLoggerListener" logArgs="false" />|' \
  /opt/tomcat9/conf/server.xml
sudo grep -E 'Server port=|Connector port="8081"|VersionLoggerListener' /opt/tomcat9/conf/server.xml
sudo chown -R hdsx:hdsx /opt/tomcat9

The grep shows Server port="-1", Connector port="8081" and VersionLoggerListener with logArgs="false".

Creates the Tomcat service (use your site's time zone for -Duser.timezone if it is elsewhere):

sudo tee /etc/systemd/system/tomcat9.service > /dev/null <<EOF
[Unit]
Description=Apache Tomcat 9 (HDS-Explorer)
After=network.target mysql.service
Requires=mysql.service

[Service]
Type=simple
User=hdsx
Group=hdsx
Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-$(dpkg --print-architecture)
Environment=CATALINA_HOME=/opt/tomcat9
Environment=CATALINA_BASE=/opt/tomcat9
Environment="CATALINA_OPTS=-Xms512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.timezone=Africa/Addis_Ababa -Djava.awt.headless=true"
ExecStart=/opt/tomcat9/bin/catalina.sh run
SuccessExitStatus=143
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF
grep JAVA_HOME /etc/systemd/system/tomcat9.service

The grep shows JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 (x64) or -arm64 (ARM).

Starts Tomcat, now and at every boot:

sudo systemctl daemon-reload
sudo systemctl enable --now tomcat9
systemctl is-active tomcat9
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8081/

is-active says active and curl prints 404: Tomcat answers and has nothing to serve yet. If it prints 000, wait ten seconds and run it again.


2.4 The clock

The server stamps every record with its own time. Check:

date
chronyc tracking | grep 'System time'

date shows the right time. If it is minutes off, set it at once with sudo chronyc makestep.


2.5 Firewall

Check:

sudo ufw status

If it says inactive, leave it. If it says active, let the site network reach port 8081 (replace 192.168.1.0/24 with your site network):

sudo ufw allow from 192.168.1.0/24 to any port 8081 proto tcp

2.6 Download the server

One small file, server.json, names the current server zip and release pack. The files are:

File Size
hds-explorer-server-1.0.0-build7.zip 148 MB
release-pack-standard-2.zip The standard forms, imported in Using HDS-Explorer, chapter B

Downloads both into /opt/hdsx/downloads and checks each against server.json:

sudo mkdir -p /opt/hdsx/downloads
sudo chown "$USER" /opt/hdsx/downloads
cd /opt/hdsx/downloads
curl -fLO https://apps.techallyconsult.com/hds-explorer/server/server.json
for part in server releasePack; do
  file=$(jq -r ".$part.file" server.json)
  curl -fL -o "$file" "$(jq -r ".$part.url" server.json)"
  echo "$(jq -r ".$part.sha256" server.json)  $file" | sha256sum -c
done

Each file prints OK. A FAILED means the download was cut: run the loop again.


2.7 Create the database

Opens MySQL as root:

mysql -h 127.0.0.1 -P 3307 -u root -pHdsx-root-1

At the mysql> prompt, creates the database and the server's account:

CREATE DATABASE hds_explorer_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'hdsx_app'@'localhost' IDENTIFIED BY 'Hdsx-app-1';
GRANT ALL PRIVILEGES ON hds_explorer_db.* TO 'hdsx_app'@'localhost';
SELECT default_collation_name FROM information_schema.schemata WHERE schema_name = 'hds_explorer_db';
exit

The SELECT prints utf8mb4_unicode_ci.


2.8 Put the server into Tomcat

Stops Tomcat and unpacks the server into it:

sudo systemctl stop tomcat9
sudo unzip -q /opt/hdsx/downloads/hds-explorer-server-1.0.0-build7.zip -d /opt/tomcat9/webapps
sudo chown -R hdsx:hdsx /opt/tomcat9/webapps/hds-explorer-server
sudo ls /opt/tomcat9/webapps/hds-explorer-server/WEB-INF/classes/app-config.yml

The last line prints the file's name back. The server's address is http://<server>:8081/hds-explorer-server.


2.9 The server's settings

Writes the settings to a file only root can read, and makes Tomcat's service read it:

sudo mkdir -p /etc/hds-explorer /opt/hdsx/data
sudo chown hdsx:hdsx /opt/hdsx/data
sudo tee /etc/hds-explorer/server.env > /dev/null <<'EOF'
PROD_DATABASE_URL=jdbc:mysql://127.0.0.1:3307/hds_explorer_db?sslMode=REQUIRED&zeroDateTimeBehavior=convertToNull
PROD_DATABASE_USER=hdsx_app
PROD_DATABASE_PASS=Hdsx-app-1
PROD_ADMIN_USERNAME=admin
PROD_ADMIN_PASSWORD=Change-me-1
HDS_EXPLORER_SYSTEM_PATH=/opt/hdsx/data
EOF
sudo chmod 600 /etc/hds-explorer/server.env
sudo mkdir -p /etc/systemd/system/tomcat9.service.d
sudo tee /etc/systemd/system/tomcat9.service.d/hdsx.conf > /dev/null <<'EOF'
[Service]
EnvironmentFile=/etc/hds-explorer/server.env
EOF
sudo systemctl daemon-reload
systemctl show tomcat9 -p EnvironmentFiles

The last line shows EnvironmentFiles=/etc/hds-explorer/server.env (ignore_errors=no).

To change a setting later, edit the file (sudo nano /etc/hds-explorer/server.env) and restart Tomcat.

Next: chapter 3, the first start.

3. First start and sign-in

Starts the server, checks it is healthy, and signs in as the administrator. Chapter 2 must be done.


3.1 First start

The first start builds the database and takes 1 to 5 minutes. Starts Tomcat:

sudo systemctl start tomcat9

Checks the health address, every half minute, until it answers:

curl -s http://localhost:8081/hds-explorer-server/health; echo

While the server is starting it prints nothing. When ready it prints:

{"status":"UP","checks":{"application":"UP","database":"UP","storage":"UP"},"version":"1.0.0 build 7"}
It says It means
database not UP The settings of 2.9 are wrong, or MySQL is stopped
storage not UP The server cannot write to /opt/hdsx/data
Nothing after 10 minutes Read sudo journalctl -u tomcat9 -n 100

One error line about the table _security_map not existing, just before the database is built, is harmless.


3.2 First sign-in

On any computer of the site network, open http://<server address>:8081/hds-explorer-server.

Sign in as admin with Change-me-1. The console shows Change password.

Change password at the first sign-in
Change password at the first sign-in

Type Change-me-1 in Current password, then Hdsx-admin-1 twice, and choose Save. The console opens on the Dashboard. The badge at the top says Site · no code: the site code is set in Using HDS-Explorer, chapter B.

From now on the administrator signs in with Hdsx-admin-1.


3.3 Remove the first password from the settings

Removes the two administrator settings and restarts Tomcat:

sudo sed -i '/^PROD_ADMIN_/d' /etc/hds-explorer/server.env
sudo cat /etc/hds-explorer/server.env
sudo systemctl restart tomcat9

The file shows four lines, none starting with PROD_ADMIN_. The health address answers UP again within a minute, and admin / Hdsx-admin-1 still signs in.


3.4 Where you are

Check Expected
curl -s http://localhost:8081/hds-explorer-server/health "status":"UP", "version":"1.0.0 build 7"
Sign in as admin / Hdsx-admin-1 The Dashboard
/etc/hds-explorer/server.env Four lines, no PROD_ADMIN_

Next: set up the site in Using HDS-Explorer, chapter B.

4. Running the server

Start and stop the server, and read its logs.


4.1 What is running

Two services, both started with the machine: mysql (the database) and tomcat9 (the server and the console). Starting Tomcat starts MySQL first.


4.2 Stop and start

# stop (MySQL last)
sudo systemctl stop tomcat9
sudo systemctl stop mysql

# start (Tomcat also starts MySQL)
sudo systemctl start tomcat9

# after a settings change: Tomcat only
sudo systemctl restart tomcat9

# state
systemctl is-active mysql tomcat9

Tomcat stops in a second or two and starts in under a minute. Until the health address says UP, the console shows an error page and the tablets cannot synchronise:

curl -s http://localhost:8081/hds-explorer-server/health; echo

Stopping Tomcat cuts off the console's users and any tablet that is synchronising. A cut-off tablet sends again at its next Sync; nothing is lost. Stop outside working hours and tell the console's users first.


4.3 After the machine restarts

Both services start by themselves. After a few minutes, systemctl is-active mysql tomcat9 says active twice and the health address says "status":"UP". If it does not answer after 10 minutes, read sudo journalctl -u tomcat9 -b.


4.4 The logs

Log Where What it holds
The server's errors /opt/hdsx/data/logs/server.log Every error since it started, and each change on Settings › Permissions. Read this first
Tomcat and the server's messages sudo journalctl -u tomcat9 Starting, the database being built, tablet files written
Tomcat's own messages /opt/tomcat9/logs/catalina.<date>.log Starting and stopping
MySQL /var/log/mysql/error.log MySQL's errors

An empty server.log is good news: nothing has gone wrong since the server started.

Reads a log:

# the last 50 lines
sudo tail -n 50 /opt/hdsx/data/logs/server.log

# follow it while something happens (Ctrl+C to stop)
sudo tail -f /opt/hdsx/data/logs/server.log

# today's errors in Tomcat's journal
sudo journalctl -u tomcat9 --since today | grep -E 'SEVERE|ERROR'

server.log cleans itself up after 30 days. Tomcat's files and the tablet-file logs (generate-* in /opt/hdsx/data/logs) never do. Lists those older than 90 days; add -delete to remove them:

sudo find /opt/tomcat9/logs -type f -mtime +90 -print
sudo find /opt/hdsx/data/logs -name 'generate-*' -mtime +90 -print

What to send when asking for help

  1. server.log, and the server-<date>.<n>.log.gz files of the days the problem happened.
  2. Tomcat's journal of the same days: sudo journalctl -u tomcat9 --since <first day> --until <day after the last> > tomcat9.log (days as 2026-10-29).
  3. What was done, on which page or tablet, and at what time.

5. Backup and upgrade

A nightly copy of the database, how to bring it back, and how to move to a new version.

The database hds_explorer_db holds everything the site records. A backup is a copy of it as one .sql file. The data folder, /opt/hdsx/data, needs no backup: Execute all writes the tablet files again.


5.1 A nightly backup

Creates the backup's sign-in file, readable only by root:

sudo mkdir -p /opt/hdsx/backups
sudo chmod 700 /opt/hdsx/backups
sudo tee /opt/hdsx/backups/backup.cnf > /dev/null <<'EOF'
[client]
host=127.0.0.1
port=3307
user=hdsx_app
password=Hdsx-app-1
EOF
sudo chmod 600 /opt/hdsx/backups/backup.cnf

Creates the script. It writes one file per run and deletes backups older than 14 days:

sudo tee /opt/hdsx/backups/backup.sh > /dev/null <<'EOF'
#!/bin/sh
set -e
dir=/opt/hdsx/backups
file="$dir/hds_explorer_db-$(date +%Y-%m-%d_%H%M).sql"
mysqldump --defaults-extra-file="$dir/backup.cnf" --single-transaction --routines --triggers --no-tablespaces --default-character-set=utf8mb4 --result-file="$file" hds_explorer_db
find "$dir" -name 'hds_explorer_db-*.sql' -mtime +14 -delete
EOF
sudo chmod 700 /opt/hdsx/backups/backup.sh

Runs it every night at 22:00 (choose a time when field workers do not synchronise):

sudo tee /etc/systemd/system/hds-explorer-backup.service > /dev/null <<'EOF'
[Unit]
Description=HDS-Explorer database backup
Requires=mysql.service
After=mysql.service

[Service]
Type=oneshot
ExecStart=/opt/hdsx/backups/backup.sh
EOF
sudo tee /etc/systemd/system/hds-explorer-backup.timer > /dev/null <<'EOF'
[Unit]
Description=HDS-Explorer database backup, every night

[Timer]
OnCalendar=*-*-* 22:00:00
Persistent=true

[Install]
WantedBy=timers.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now hds-explorer-backup.timer
systemctl list-timers hds-explorer-backup.timer

The list shows the timer with its next run at 22:00.

Runs one backup now and checks it:

sudo systemctl start hds-explorer-backup.service
systemctl status hds-explorer-backup.service --no-pager | grep -E 'Active|status='
sudo ls -l /opt/hdsx/backups
sudo sh -c 'head -1 /opt/hdsx/backups/hds_explorer_db-*.sql'

The status says status=0/SUCCESS, there is a .sql file, and its first line starts with -- MySQL dump.

At least once a week, copy the newest file to another machine or an external disk kept away from the server.


5.2 Bring a backup back

This replaces the whole database: everything recorded after the backup was made is lost.

  1. Stops the server and empties the database (fill in the backup's file name):

    file=/opt/hdsx/backups/hds_explorer_db-<date>_<time>.sql
    sudo systemctl stop tomcat9
    mysql -h 127.0.0.1 -P 3307 -u root -pHdsx-root-1 -e "DROP DATABASE hds_explorer_db; CREATE DATABASE hds_explorer_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
    
  2. Loads the backup. It prints nothing when it works:

    sudo sh -c "mysql --defaults-extra-file=/opt/hdsx/backups/backup.cnf --default-character-set=utf8mb4 hds_explorer_db < $file"
    
  3. Starts the server. Wait for the health address to say UP (chapter 3.1):

    sudo systemctl start tomcat9
    
  4. Sign in to the console and run Tablets › Tablet export › Execute all, so the tablets download what the database now holds.


5.3 Upgrade to a new version

The upgrade keeps the database and the settings and replaces the server's folder. Allow 15 minutes, outside the hours field workers synchronise. server.json names the new version.

  1. Download the new server zip (and the release pack, if it is new) with the commands of chapter 2.6. Each file prints OK.

  2. Back up the database:

    sudo systemctl start hds-explorer-backup.service
    sudo ls -lt /opt/hdsx/backups | head -3
    

    The newest file has the time of now.

  3. Stop the server and set the old version aside:

    sudo systemctl stop tomcat9
    sudo mkdir -p /opt/hdsx/previous
    sudo rm -rf /opt/hdsx/previous/hds-explorer-server
    sudo mv /opt/tomcat9/webapps/hds-explorer-server /opt/hdsx/previous/
    sudo rm -rf /opt/tomcat9/work/Catalina/localhost/hds-explorer-server
    
  4. Put the new version in (fill in the new zip's name) and start it:

    sudo unzip -q /opt/hdsx/downloads/hds-explorer-server-<version>-build<n>.zip -d /opt/tomcat9/webapps
    sudo chown -R hdsx:hdsx /opt/tomcat9/webapps/hds-explorer-server
    sudo systemctl start tomcat9
    
  5. Wait for the health address (chapter 3.1). It says UP and the new version:

    {"status":"UP", … ,"version":"1.0.0 build <n>"}
    
  6. Import the new release pack, if there is one, as in Using HDS-Explorer, chapter F (Forms).

  7. Write the tablet files: Tablets › Tablet export › Execute all.

Keep the old version in /opt/hdsx/previous until the new one has worked for a few days.


5.4 Go back to the previous version

If the new version does not start or does not work:

  1. Stops the server and removes the new version:

    sudo systemctl stop tomcat9
    sudo rm -rf /opt/tomcat9/webapps/hds-explorer-server /opt/tomcat9/work/Catalina/localhost/hds-explorer-server
    
  2. Bring back the backup made before the upgrade: chapter 5.2, steps 1 and 2.

  3. Puts the old version back and starts it:

    sudo mv /opt/hdsx/previous/hds-explorer-server /opt/tomcat9/webapps/
    sudo systemctl start tomcat9
    
  4. The health address says UP and the old version. Run Execute all.