Data Validation Platform (DVP) Ubuntu Installation Instructions

Step-by-step instructions for deploying DVP on Ubuntu using Docker Compose

advancedFebruary 18, 2026

Data Validation Platform (DVP)
Ubuntu Installation Guide

Step-by-step instructions for deploying DVP on Ubuntu using Docker Compose

PlatformUbuntu 20.04 / 22.04 / 24.04 LTS
ApplicationPython 3.13 / Flask
DatabaseMySQL 8.0
RuntimeDocker & Docker Compose
Port8443 (HTTP)
Section 1

Overview

The Serpentua Data Validation Platform (DVP) is a web-based file integrity monitoring system. It continuously scans files and directories using SHA-256 checksums, alerts you when files are modified or deleted, and provides reporting and export capabilities.

DVP is delivered as a Docker Compose application consisting of two containers:

ContainerImageRole
appBuilt from Dockerfile (Python 3.13-slim)Flask web application — serves the UI on port 8443
dbmysql:8.0MySQL database — stores assets, checksums, and alerts
The application container mounts the host's root filesystem at /host (read-only), allowing DVP to scan any local path without installing agents on individual machines.
Section 2

Prerequisites

Before you begin, confirm the following:

  • Ubuntu 20.04, 22.04, or 24.04 LTS (64-bit) — server or desktop edition
  • A user account with sudo privileges
  • Internet access (to pull Docker images and Python packages)
  • At least 2 GB of free disk space for images and the MySQL data volume
  • Ports 8443 and 3306 not already in use
  • The DVP project files (folder serpentua-dvp-docker/)
Section 3

System Preparation

Update your package index and upgrade existing packages before installing anything new.

bash — update system packages
$ sudo apt update && sudo apt upgrade -y

Install a few utilities that are used during the Docker installation process:

bash — install utilities
$ sudo apt install -y \
    ca-certificates \
    curl \
    gnupg \
    lsb-release \
    git
Section 4

Install Docker & Docker Compose

Do not install Docker from the default Ubuntu repositories — that version is often outdated. Use Docker's official repository instead.

4.1 — Add Docker's GPG key and repository

bash
# Add Docker's official GPG key
$ sudo install -m 0755 -d /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
    | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the Docker stable repository
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

4.2 — Install Docker Engine and Docker Compose plugin

bash
$ sudo apt update
$ sudo apt install -y \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-buildx-plugin \
    docker-compose-plugin

4.3 — Verify the installation

bash — expected output shown below each command
$ docker --version
Docker version 27.x.x, build xxxxxxx

$ docker compose version
Docker Compose version v2.x.x

4.4 — Allow your user to run Docker without sudo

Add your account to the docker group so you do not need to prefix every Docker command with sudo. Log out and back in after running this command for it to take effect.

bash
$ sudo usermod -aG docker $USER
$ newgrp docker   # apply group change in the current session

4.5 — Enable Docker to start on boot

bash
$ sudo systemctl enable docker
$ sudo systemctl start docker
Section 5

Get the Application Source

Copy the serpentua-dvp-docker project folder to your Ubuntu machine. Choose the method that suits your situation:

Option A — Clone from a Git repository

bash
$ git clone <repository-url> ~/serpentua-dvp
$ cd ~/serpentua-dvp

Option B — Copy an existing folder via SCP

Run the following from your local machine (e.g., Windows with WSL or a separate workstation) to push the folder to the Ubuntu server:

local machine — bash / WSL
$ scp -r /path/to/serpentua-dvp-docker \
    user@<server-ip>:~/serpentua-dvp

Option C — Upload as a ZIP and extract

bash — on the Ubuntu server
# Install unzip if not already present
$ sudo apt install -y unzip

# Extract the archive
$ unzip serpentua-dvp-docker.zip -d ~/serpentua-dvp
$ cd ~/serpentua-dvp/serpentua-dvp-docker

After this step you should be inside a directory that contains, at a minimum: Dockerfile, docker-compose.yml, requirements.txt, runserver.py, .env, and the dvp/ folder.

Section 6

Configure the Environment

All runtime settings are read from the .env file in the project root. Open it with any text editor:

bash
$ nano .env

The file contains the following variables:

.env — default contents
DB_USER=dvp
DB_PASSWORD=ChangeMe!123
DB_NAME=dvp_app
DB_HOST=db
MYSQL_ROOT_PASSWORD=rootpassword
SERVER_HOST=0.0.0.0
SERVER_PORT=8443
VariableDefaultDescription
DB_USERdvpMySQL application user name
DB_PASSWORDsee filePassword for the MySQL application user — change this
DB_NAMEdvp_appName of the MySQL database
DB_HOSTdbInternal Docker service name — do not change
MYSQL_ROOT_PASSWORDsee fileMySQL root password — change this
SERVER_HOST0.0.0.0Flask bind address — leave as-is to listen on all interfaces
SERVER_PORT8443Port the application listens on
Always change the default passwords before going into production. Use strong, unique values for both DB_PASSWORD and MYSQL_ROOT_PASSWORD. The .env file should never be committed to a public Git repository.

Save the file after making your changes (Ctrl+O then Ctrl+X in nano).

Section 7

Build & Launch the Application

From the project root directory, run:

bash — build images and start all services in the background
$ docker compose up -d --build

Docker will:

1

Pull the MySQL 8.0 image

Downloaded from Docker Hub (~600 MB on first run).

2

Build the application image

Uses python:3.13-slim as the base, installs gcc + libffi-dev, then installs all Python packages from requirements.txt.

3

Start the db container

MySQL initialises the database and creates the user defined in .env. A health check polls every 10 seconds.

4

Start the app container

Waits for the database health check to pass, then launches the Flask server on port 8443.

The first build takes several minutes because Python packages must be compiled and downloaded. Subsequent starts are much faster as Docker caches the image layers.

Watching the logs in real time

bash
# Follow logs for all containers
$ docker compose logs -f

# Follow logs for the app container only
$ docker compose logs -f app
Section 8

Verify the Installation

Check container status

bash
$ docker compose ps

Both containers should show a status of running. The db container should show healthy.

expected output (approximate)
NAME                    IMAGE          STATUS          PORTS
dvp-app-1               dvp-app        Up 2 minutes    0.0.0.0:8443->8443/tcp
dvp-db-1                mysql:8.0      Up 2 minutes    0.0.0.0:3306->3306/tcp (healthy)

Access the web interface

Open a browser and navigate to:

URL — local access
http://localhost:8443

Or, from another machine on the same network:

URL — remote access
http://<server-ip-address>:8443
If the DVP dashboard loads in your browser, the installation is complete and the application is running correctly.
Section 9

File Path Mapping

The Docker Compose file mounts the Ubuntu host's root filesystem into the container at /host (read-only). When you add asset paths inside the DVP UI, you must use the container path, not the host OS path.

Host Path (Ubuntu)Container Path to Enter in DVP
/home/user/data/host/home/user/data
/var/log/host/var/log
/srv/files/host/srv/files
/mnt/nas/backups/host/mnt/nas/backups
/opt/myapp/configs/host/opt/myapp/configs
The general rule: prepend /host to any absolute Ubuntu path when entering it inside the DVP application. For example, /var/log becomes /host/var/log.
Section 10

Firewall & Remote Access

If Ubuntu's Uncomplicated Firewall (ufw) is enabled, you need to allow traffic on port 8443 so other machines can reach the DVP web interface.

bash — check ufw status and open the required port
# Check whether ufw is active
$ sudo ufw status

# Allow DVP web traffic
$ sudo ufw allow 8443/tcp

# Optional — allow SSH if you haven't already
$ sudo ufw allow OpenSSH

# Apply and confirm
$ sudo ufw enable
$ sudo ufw status verbose
Port 3306 (MySQL) is exposed on all interfaces by the default docker-compose.yml. In a production environment, consider removing the ports entry from the db service so MySQL is only accessible internally between containers.
Section 11

Auto-Start on Boot

Both containers already have restart: unless-stopped set in docker-compose.yml, which means they will restart automatically after a Docker daemon restart. Because Docker itself is set to start on boot (Section 4.5), the application will come back up after a reboot without any additional configuration.

To confirm the behaviour, simulate it:

bash — test restart behaviour
$ sudo reboot

# After the server comes back, verify containers resumed
$ docker compose -f ~/serpentua-dvp/docker-compose.yml ps

Optional — systemd service unit

If you prefer an explicit systemd service that manages the Docker Compose stack, create the following unit file:

bash — create the service file
$ sudo nano /etc/systemd/system/dvp.service
/etc/systemd/system/dvp.service
[Unit]
Description=Serpentua DVP
After=docker.service
Requires=docker.service

[Service]
WorkingDirectory=/home/YOUR_USER/serpentua-dvp
ExecStart=/usr/bin/docker compose up
ExecStop=/usr/bin/docker compose down
Restart=always
User=YOUR_USER

[Install]
WantedBy=multi-user.target
bash — enable and start the service
$ sudo systemctl daemon-reload
$ sudo systemctl enable dvp
$ sudo systemctl start dvp
Section 12

Day-to-Day Management

TaskCommand
Start all containersdocker compose up -d
Stop all containersdocker compose down
Restart all containersdocker compose restart
View live logsdocker compose logs -f
View app logs onlydocker compose logs -f app
Check container statusdocker compose ps
Open a shell in the app containerdocker compose exec app bash
Open a MySQL shelldocker compose exec db mysql -u dvp -p dvp_app
Rebuild after code changesdocker compose up -d --build
Remove containers (keeps data)docker compose down
Remove containers + volumes (deletes DB)docker compose down -v

Updating the application

bash — pull latest code and rebuild
$ git pull                      # if using git
$ docker compose down
$ docker compose up -d --build

Database backups

bash — dump the database to a file
$ docker compose exec db \
    mysqldump -u dvp -p dvp_app > dvp_backup_$(date +%Y%m%d).sql
Section 13

Troubleshooting

Container fails to start — "port already in use"

Another process is already listening on port 8443 or 3306.

bash — find what is using the port
$ sudo ss -tlnp | grep 8443
$ sudo ss -tlnp | grep 3306

Stop the conflicting process, or change the port mapping in docker-compose.yml (e.g., "8080:8443" maps host port 8080 to container port 8443).

App container restarts repeatedly

bash — inspect the error
$ docker compose logs app

Common causes:

  • Database not yet ready — the app may have started before MySQL finished initialising. Wait 30 seconds and run docker compose restart app.
  • Wrong credentials in .env — ensure DB_USER, DB_PASSWORD, and DB_NAME match what MySQL was initialised with.
  • Missing .env file — make sure the file exists in the same directory as docker-compose.yml.

Database container health check failing

bash
$ docker compose logs db

If you see InnoDB or permission errors, the MySQL data volume may be corrupted or initialised with different credentials. Remove the volume and start fresh:

The following command permanently deletes all data in the MySQL volume. Take a backup first if you have data to preserve.
bash — destructive: removes all database data
$ docker compose down -v
$ docker compose up -d --build

Cannot access the web UI from another machine

  • Confirm the UFW rule: sudo ufw status — port 8443 should be listed as ALLOW.
  • Confirm Docker is listening: sudo ss -tlnp | grep 8443.
  • Check that your cloud provider / router security group / ACL also allows port 8443.

Permission denied when running docker commands

You may not have logged out and back in after adding yourself to the docker group (Section 4.4). Run newgrp docker in the current terminal, or fully log out and log back in.

Section 14

Uninstalling

Stop and remove containers and volumes

bash
$ cd ~/serpentua-dvp
$ docker compose down -v     # stops containers and deletes the MySQL volume

Remove the Docker images

bash
$ docker image rm $(docker images -q 'dvp*') mysql:8.0 2>/dev/null || true
$ docker image prune -f    # remove any dangling build-cache images

Remove the project files

bash
$ rm -rf ~/serpentua-dvp

Optionally remove Docker itself

bash
$ sudo apt purge -y docker-ce docker-ce-cli containerd.io \
    docker-buildx-plugin docker-compose-plugin
$ sudo rm -rf /var/lib/docker /etc/docker
$ sudo rm /etc/apt/sources.list.d/docker.list
$ sudo rm /etc/apt/keyrings/docker.gpg