Deployment
Docker
The recommended way to deploy Substrukt in production.
Build the image
docker build -t substrukt .
The Dockerfile uses a multi-stage build:
- Builder stage: Compiles the Rust binary with
cargo build --releaseusing a nightly Rust image. Dependencies are cached separately for faster rebuilds. - Runtime stage: Copies the binary and templates into a minimal Debian image with only
ca-certificatesinstalled.
Run the container
docker run -p 3000:3000 -v substrukt-data:/data substrukt
All persistent data is stored in the /data volume:
substrukt.db– users, sessions, API tokensaudit.db– audit logschemas/– JSON Schema filescontent/– content entriesuploads/– uploaded files
Configuration
Override defaults with command arguments:
docker run -p 8080:8080 \
-v substrukt-data:/data \
substrukt serve \
--data-dir /data \
--port 8080 \
--secure-cookies
Docker Compose example
services:
substrukt:
build: .
ports:
- "3000:3000"
volumes:
- substrukt-data:/data
command: >
serve
--data-dir /data
--db-path /data/substrukt.db
--port 3000
--secure-cookies
restart: unless-stopped
volumes:
substrukt-data:
Binary deployment
For environments without Docker:
cargo build --release
Copy the binary and templates directory to your server:
/opt/substrukt/
substrukt # binary
templates/ # template files
Run it:
/opt/substrukt/substrukt serve \
--data-dir /var/lib/substrukt \
--secure-cookies
Systemd service
[Unit]
Description=Substrukt CMS
After=network.target
[Service]
Type=simple
User=substrukt
ExecStart=/opt/substrukt/substrukt serve \
--data-dir /var/lib/substrukt \
--secure-cookies
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Reverse proxy
Substrukt listens on 0.0.0.0:3000 by default. In production, place it behind a reverse proxy for TLS termination.
Nginx example
server {
listen 443 ssl;
server_name cms.example.com;
ssl_certificate /etc/letsencrypt/live/cms.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cms.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 100M;
}
}
When using HTTPS, pass --secure-cookies to Substrukt so that session cookies have the Secure flag set.
Production checklist
- Use
--secure-cookieswhen behind HTTPS - Set
X-Forwarded-Forheader in your reverse proxy and use--trust-proxy-headers(used for rate limiting) - Mount persistent storage for
/data(Docker) or--data-dir(binary) - Back up
substrukt.dbregularly (contains users and tokens), or configure S3 backups via the UI - Set
RUST_LOG=substrukt=infofor production logging level - Configure deployment targets in the UI if using the deploy workflow