mlab docs

Installation

Full reference for the Docker Compose deployment, including reverse proxy and TLS.

System requirements

ResourceMinimumRecommended
CPU2 cores4+ cores
RAM2 GB4-8 GB
Disk10 GB50 GB+ (depends on register size)
OSAny 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.

docker-compose.yml
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:

Download docker-compose.yml

Ports

ServicePortExposed?
app8080Yes - behind your reverse proxy
mysql3306No - internal network only
clickhouse8123 / 9000No - 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:latest

Reverse proxy & TLS

Don't expose app directly. Put nginx, Caddy or Traefik in front for TLS termination, HTTP/2 and request limits.

Caddy

Caddyfile
tprm.example.com {
    reverse_proxy localhost:8080
    encode gzip
}

nginx

/etc/nginx/sites-available/tprm.conf
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')"

On this page