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). 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: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;
client_max_body_size 25m;
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.
Backups
Both database volumes are mountable. 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')"