Installation
Full reference for the Docker Compose deployment, including reverse proxy and TLS.
System requirements
| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 2 GB | 4-8 GB |
| Disk | 10 GB | 50 GB+ (depends on register size) |
| OS | Any Linux with Docker 20.10+ | Ubuntu LTS, Debian stable, RHEL 8+ |
The compose file
Three services: app (Rust / Actix-web 4), mysql (business data) and clickhouse (analytics & activity). A fourth, optional, stores contract documents: any S3 bucket, or the commented silo service of the repository's compose file (see Documents). Data is persisted in named Docker volumes; both databases include healthchecks - the app waits for them before starting. The image is pulled from GHCR.
services:
app:
image: ghcr.io/mlab-sh/tprm.mlab.sh:latest
ports:
- "8080:8080"
depends_on:
mysql: { condition: service_healthy }
clickhouse: { condition: service_healthy }
env_file: .env
environment:
- DB_HOST=mysql
- CH_HOST=clickhouse
volumes:
- uploads:/app_mlab_sh/uploads
- logs:/app_mlab_sh/logs
restart: unless-stopped
mysql:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: mlabtprm
MYSQL_USER: ${DB_USERNAME}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
restart: unless-stopped
clickhouse:
image: clickhouse/clickhouse-server:26.8 # the version tprm.mlab.sh is tested against; not latest
environment:
CLICKHOUSE_USER: ${CH_USERNAME}
CLICKHOUSE_PASSWORD: ${CH_PASSWORD}
CLICKHOUSE_DB: mlabtprm
volumes:
- clickhouse_data:/var/lib/clickhouse
healthcheck:
test: ["CMD", "clickhouse-client", "--query", "SELECT 1"]
interval: 5s
restart: unless-stopped
volumes:
mysql_data:
clickhouse_data:
uploads:
logs:Ports
| Service | Port | Exposed? |
|---|---|---|
app | 8080 | Yes - behind your reverse proxy |
mysql | 3306 | No - internal network only |
clickhouse | 8123 / 9000 | No - internal network only |
Pulling the image
Images are published to GitHub Container Registry via GitHub Actions. No authentication is required for the public image:
docker pull ghcr.io/mlab-sh/tprm.mlab.sh:latestReverse proxy & TLS
Don't expose app directly. Put nginx, Caddy or Traefik in front for TLS termination, HTTP/2 and request limits.
Caddy
tprm.example.com {
reverse_proxy localhost:8080
encode gzip
}nginx
server {
listen 443 ssl http2;
server_name tprm.example.com;
ssl_certificate /etc/letsencrypt/live/tprm.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/tprm.example.com/privkey.pem;
# Contract documents go up to S3_MAX_UPLOAD_MB (2048 by default)
client_max_body_size 2048m;
proxy_request_buffering off;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Behind TLS. Set COOKIE_SECURE=true in .env once a TLS-terminating proxy sits in front of the app. On plain HTTP leave it false, or the browser drops the session cookie and login fails without an error. Set PUBLIC_URL to the address users reach (https://tprm.example.com) if you use single sign-on.
Caddy accepts request bodies of any size by default. With another proxy, allow
bodies as large as S3_MAX_UPLOAD_MB, or document uploads fail with 413.
Backups
Both database volumes are mountable, and documents live in your S3 bucket (or the silo_data volume): back them up together. The recommended backup is volume-level snapshots plus a logical dump:
docker exec mysql mysqldump -uroot -p$DB_ROOT_PASSWORD mlabtprm | gzip > mlabtprm-$(date +%F).sql.gz
docker exec clickhouse clickhouse-client --query="BACKUP DATABASE mlabtprm TO Disk('backups','mlabtprm-$(date +%F).zip')"