Skip to content

Docker Compose Setup

This guide covers deploying VaultSandbox using Docker Compose, from basic development setups to production-ready configurations.

Choose your setup method:

MethodVariablesDNS SetupBest For
VSX DNS1AutomaticQuick testing, CI/CD, getting started
Custom Domain2ManualProduction, compliance, branding

Zero-config setup with automatic domain assignment. Just 1 environment variable:

services:
gateway:
image: vaultsandbox/gateway:latest
ports:
- '25:25'
- '80:80'
- '443:443'
environment:
VSB_VSX_DNS_ENABLED: 'true'
volumes:
- gateway-data:/app/data
volumes:
gateway-data:
Terminal window
docker compose up -d

Your domain is automatically assigned (e.g., 1mzhr2y.vsx.email). Find it at vsx.email or run:

Terminal window
docker compose exec gateway cat /app/data/certificates/metadata.json; echo

Use your own domain with just 2 environment variables:

services:
gateway:
image: vaultsandbox/gateway:latest
ports:
- '25:25'
- '80:80'
- '443:443'
environment:
VSB_SMTP_ALLOWED_RECIPIENT_DOMAINS: 'qa.example.com'
VSB_CERT_ENABLED: 'true'
volumes:
- gateway-data:/app/data
volumes:
gateway-data:

Requires DNS setup: Create A and MX records pointing to your server. See Custom Domain Quick Start for details.


VaultSandbox runs as a single unified gateway service that includes the SMTP server, API, and web UI all in one container.

VariableDescription
VSB_VSX_DNS_ENABLEDSet to true to enable automatic DNS via vsx.email
VariableDescriptionExample
VSB_SMTP_ALLOWED_RECIPIENT_DOMAINSDomains to accept emails for (comma-separated)qa.example.com,test.example.com
VSB_CERT_ENABLEDEnable automatic Let’s Encrypt TLS certificatestrue

Override defaults for advanced use cases:

VariableDefaultDescription
VSB_LOCAL_INBOX_MAX_TTL604800Max email retention in seconds (7 days)
VSB_LOCAL_INBOX_DEFAULT_TTL3600Default inbox TTL in seconds (1 hour)
VSB_LOCAL_CLEANUP_INTERVAL300Cleanup interval for expired inboxes (5 min)
VSB_SMTP_PORT25SMTP port (must be 25 for real email)
VSB_SERVER_PORT80HTTP port for ACME challenges
VSB_SERVER_HTTPS_PORT443HTTPS port for Web UI and API
VSB_SERVER_ORIGIN(auto)CORS origins (auto-derived from domain, or use *)
VSB_DATA_PATH/app/dataPath for certificates and API keys
NODE_ENVproductionNode environment
Terminal window
mkdir vaultsandbox && cd vaultsandbox

Create docker-compose.yml. Choose your mode:

VSX DNS (recommended for getting started):

services:
gateway:
image: vaultsandbox/gateway:latest
container_name: vaultsandbox-gateway
restart: unless-stopped
ports:
- '25:25' # SMTP
- '80:80' # HTTP (ACME + VSX verification)
- '443:443' # HTTPS (Web UI + API)
environment:
VSB_VSX_DNS_ENABLED: 'true'
volumes:
- gateway-data:/app/data
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
gateway-data:

Custom Domain:

services:
gateway:
image: vaultsandbox/gateway:latest
container_name: vaultsandbox-gateway
restart: unless-stopped
ports:
- '25:25' # SMTP
- '80:80' # HTTP (ACME challenges)
- '443:443' # HTTPS (Web UI + API)
environment:
VSB_SMTP_ALLOWED_RECIPIENT_DOMAINS: 'qa.example.com'
VSB_CERT_ENABLED: 'true'
volumes:
- gateway-data:/app/data
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
volumes:
gateway-data:
Terminal window
docker-compose up -d
Terminal window
# Check service status
docker compose ps
# View logs
docker compose logs -f gateway
# Check health endpoint
curl http://localhost/health
# Get your API key
docker compose exec gateway cat /app/data/.api-key; echo

Navigate to https://qa.example.com/app (or your domain).

Production deployments typically use Custom Domain mode for branding and compliance.

Terminal window
mkdir vaultsandbox && cd vaultsandbox

Create docker-compose.yml with production settings:

services:
gateway:
image: vaultsandbox/gateway:latest
container_name: vaultsandbox-gateway
restart: unless-stopped
ports:
- '25:25' # SMTP
- '80:80' # HTTP (ACME challenges)
- '443:443' # HTTPS (Web UI + API)
environment:
# Core configuration
VSB_SMTP_ALLOWED_RECIPIENT_DOMAINS: 'qa.example.com,staging.example.com'
VSB_CERT_ENABLED: 'true'
# Optional production settings
VSB_LOCAL_INBOX_MAX_TTL: '604800' # 7 days
VSB_SERVER_ORIGIN: 'https://qa.example.com' # Restrict CORS
volumes:
- gateway-data:/app/data # Persist certificates and API keys
healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# Resource limits (adjust based on your needs)
deploy:
resources:
limits:
cpus: '2'
memory: 4G
reservations:
cpus: '1'
memory: 2G
# Logging configuration
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '3'
volumes:
gateway-data:
Terminal window
docker-compose up -d
Terminal window
# Follow logs
docker compose logs -f gateway
# Check for errors
docker compose logs gateway | grep ERROR
# Verify certificate provisioning
docker compose logs gateway | grep -i certificate

VaultSandbox includes built-in health checks:

healthcheck:
test: ['CMD', 'curl', '-f', 'http://localhost/health']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

Customize health check behavior:

healthcheck:
interval: 60s # Check every 60 seconds
timeout: 5s # Timeout after 5 seconds
retries: 5 # Retry 5 times before marking unhealthy
start_period: 60s # Wait 60s before starting checks

Control log output:

logging:
driver: 'json-file'
options:
max-size: '10m' # Max 10MB per log file
max-file: '3' # Keep 3 log files

Or use syslog:

logging:
driver: 'syslog'
options:
syslog-address: 'tcp://192.168.0.42:514'
Terminal window
docker compose up -d
Terminal window
docker compose stop
Terminal window
docker compose restart
# Or restart gateway specifically
docker compose restart gateway
Terminal window
# Follow logs
docker compose logs -f gateway
# Last 100 lines
docker compose logs --tail=100 gateway
# Filter for specific events
docker compose logs gateway | grep -i "certificate\|api key\|error"
Terminal window
# Pull latest images
docker compose pull
# Restart with new images
docker compose up -d
Terminal window
# Stop and remove containers
docker compose down
# Remove containers and volumes (WARNING: deletes all data)
docker compose down -v

Check logs:

Terminal window
docker compose logs gateway

Common issues:

  • Port 25 already in use (another mail server running)
  • Ports 80/443 already in use
  • Invalid domain configuration in VSB_SMTP_ALLOWED_RECIPIENT_DOMAINS

Check if gateway is running:

Terminal window
docker compose ps gateway

Test from server:

Terminal window
curl http://localhost/health
curl http://localhost/app

Check DNS:

Terminal window
dig A qa.example.com

Access web UI at correct path: Remember the UI is at /app, not root:

https://qa.example.com/app

Check certificate logs:

Terminal window
docker compose logs gateway | grep -i certificate

Common issues:

  • Ports 80/443 not accessible from internet
  • DNS not pointing to server
  • Domain validation timeout

Disable certificates for local testing:

environment:
VSB_CERT_ENABLED: 'false'

Check SMTP logs:

Terminal window
docker compose logs gateway | grep -i smtp

Test SMTP connection:

Terminal window
telnet qa.example.com 25

Verify MX records:

Terminal window
dig MX qa.example.com

Use the DNS Setup Tool: Visit vaultsandbox.com/setup to verify your DNS configuration.

Check current usage:

Terminal window
docker stats vaultsandbox-gateway

Reduce resource limits:

deploy:
resources:
limits:
memory: 2G # Reduce from 4G

Reduce email retention:

environment:
VSB_LOCAL_INBOX_MAX_TTL: '86400' # 24 hours instead of 7 days

Check logs:

Terminal window
docker compose logs gateway --tail=50

Check health status:

Terminal window
docker inspect vaultsandbox-gateway | grep Health -A 10

Disable health checks temporarily:

healthcheck:
disable: true

Check API key from container:

Terminal window
docker compose exec gateway cat /app/data/.api-key; echo

Check logs:

Terminal window
docker compose logs gateway | grep -i "api key"

If file doesn’t exist: Remove the volume and restart to regenerate:

Terminal window
docker compose down
docker volume rm vaultsandbox_gateway-data # Or your volume name
docker compose up -d

For different workload sizes:

Light (< 1000 inboxes):

deploy:
resources:
limits:
cpus: '1'
memory: 2G

Medium (1000-5000 inboxes):

deploy:
resources:
limits:
cpus: '2'
memory: 4G

Heavy (5000+ inboxes):

deploy:
resources:
limits:
cpus: '4'
memory: 8G

Shorter TTL = less memory usage:

environment:
# 1 hour (good for CI/CD pipelines)
VSB_LOCAL_INBOX_MAX_TTL: "3600"
# 24 hours (good for manual testing)
VSB_LOCAL_INBOX_MAX_TTL: "86400"
# 7 days (default, good for staging)
VSB_LOCAL_INBOX_MAX_TTL: "604800"

VaultSandbox automatically generates a secure API key on first startup. The key is persisted to a Docker volume at /app/data/.api-key.

Retrieve your API key:

Terminal window
# From Docker container
docker compose exec gateway cat /app/data/.api-key; echo
# Or using Docker CLI
docker exec vaultsandbox-gateway cat /app/data/.api-key; echo

Rotate API key:

Terminal window
# Delete the key file from inside the container
docker compose exec gateway rm /app/data/.api-key
# Restart the gateway to generate a new key
docker compose restart gateway
# Retrieve the new key
docker compose exec gateway cat /app/data/.api-key; echo

For production deployments:

  • Explicitly set VSB_LOCAL_API_KEY in your environment to use a custom key
  • Use VSB_LOCAL_API_KEY_STRICT=true to require manual configuration

For production, restrict CORS to specific origins:

environment:
VSB_SERVER_ORIGIN: 'https://qa.example.com,https://app.example.com'

Only expose necessary ports:

Terminal window
# Allow required ports
sudo ufw allow 25/tcp # SMTP
sudo ufw allow 80/tcp # HTTP (ACME)
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
# Deny all other incoming traffic
sudo ufw default deny incoming