Hardened Images
VaultSandbox offers hardened Docker images for security-conscious deployments. These images have shell access removed, reducing the attack surface for production environments.
Overview
Section titled “Overview”| Image Tag | Shell Access | Use Case |
|---|---|---|
vaultsandbox/gateway:latest | ✅ Yes | Development, debugging, standard deployments |
vaultsandbox/gateway:latest-harden | ❌ No | Production, compliance, security-hardened environments |
Quick Start
Section titled “Quick Start”services: gateway: image: vaultsandbox/gateway:latest-harden ports: - '25:25' - '80:80' - '443:443' environment: VSB_VSX_DNS_ENABLED: 'true' VSB_LOCAL_API_KEY: 'your-secure-api-key-minimum-32-chars' volumes: - gateway-data:/app/data
volumes: gateway-data:API Key Configuration
Section titled “API Key Configuration”Since you cannot execute commands inside the container, you must provide the API key via environment variable.
Generate a Secure API Key
Section titled “Generate a Secure API Key”Generate a 32+ character key before deployment:
# Using OpenSSLopenssl rand -base64 32 | tr -d "=+/" | cut -c1-32
# Using /dev/urandomhead -c 32 /dev/urandom | base64 | tr -d "=+/" | cut -c1-32Example output:
7kB9qF2mP5tX8nL3wR6vY1zA4cE0sJ7hConfigure the API Key
Section titled “Configure the API Key”Option 1: Direct in docker-compose.yml
services: gateway: image: vaultsandbox/gateway:latest-harden environment: VSB_LOCAL_API_KEY: '7kB9qF2mP5tX8nL3wR6vY1zA4cE0sJ7h'Option 2: Using .env file (Recommended)
Create a .env file:
VSB_LOCAL_API_KEY=7kB9qF2mP5tX8nL3wR6vY1zA4cE0sJ7hReference in docker-compose.yml:
services: gateway: image: vaultsandbox/gateway:latest-harden env_file: - .envOption 3: Using Docker Secrets (Production)
services: gateway: image: vaultsandbox/gateway:latest-harden environment: VSB_LOCAL_API_KEY_FILE: /run/secrets/api_key secrets: - api_key
secrets: api_key: file: ./secrets/api_key.txtRetrieving an Auto-Generated API Key
Section titled “Retrieving an Auto-Generated API Key”If you started a hardened container without setting VSB_LOCAL_API_KEY, the gateway will auto-generate one. It’s possible to retrieve it using tools like docker debug (Docker Desktop) or other debugging techniques, but this is beyond the scope of this guide. For simplicity, always set VSB_LOCAL_API_KEY explicitly when using hardened images.
Accessing Logs
Section titled “Accessing Logs”Without shell access, use Docker’s logging system to view container logs.
View Logs
Section titled “View Logs”# Follow logs in real-timedocker compose logs -f gateway
# View last 100 linesdocker compose logs --tail=100 gateway
# View logs since a specific timedocker compose logs --since="2024-01-15T10:00:00" gateway
# View logs with timestampsdocker compose logs -t gatewayFilter Logs
Section titled “Filter Logs”# Filter for API key confirmationdocker compose logs gateway | grep -i "api key"
# Filter for certificate eventsdocker compose logs gateway | grep -i "certificate"
# Filter for errorsdocker compose logs gateway | grep -i "error"
# Filter for SMTP eventsdocker compose logs gateway | grep -i "smtp"Configure Log Output
Section titled “Configure Log Output”Control log retention and format in your docker-compose.yml:
services: gateway: image: vaultsandbox/gateway:latest-harden logging: driver: 'json-file' options: max-size: '10m' # Max 10MB per log file max-file: '5' # Keep 5 rotated log filesFor centralized logging:
services: gateway: image: vaultsandbox/gateway:latest-harden logging: driver: 'syslog' options: syslog-address: 'tcp://logserver.example.com:514' tag: 'vaultsandbox-gateway'Health Monitoring
Section titled “Health Monitoring”Use Docker’s health check and the /health endpoint:
# Check container health statusdocker inspect vaultsandbox-gateway --format='{{.State.Health.Status}}'
# View health check logsdocker inspect vaultsandbox-gateway --format='{{json .State.Health}}' | jq
# External health checkcurl -f http://localhost/healthConfigure health checks in docker-compose.yml:
services: gateway: image: vaultsandbox/gateway:latest-harden healthcheck: test: ['CMD', 'curl', '-f', 'http://localhost/health'] interval: 30s timeout: 10s retries: 3 start_period: 40sFull Production Example
Section titled “Full Production Example”Complete docker-compose.yml for hardened production deployment:
services: gateway: image: vaultsandbox/gateway:latest-harden container_name: vaultsandbox-gateway restart: unless-stopped
ports: - '25:25' # SMTP - '80:80' # HTTP (ACME challenges) - '443:443' # HTTPS (Web UI + API)
environment: # DNS Configuration (choose one) VSB_VSX_DNS_ENABLED: 'true' # OR for custom domain: # VSB_SMTP_ALLOWED_RECIPIENT_DOMAINS: 'qa.example.com' # VSB_CERT_ENABLED: 'true'
# API Key (required for hardened images) VSB_LOCAL_API_KEY: '${VSB_LOCAL_API_KEY}'
# Optional settings VSB_LOCAL_INBOX_MAX_TTL: '604800' # 7 days VSB_LOCAL_INBOX_DEFAULT_TTL: '3600' # 1 hour
volumes: - gateway-data:/app/data
healthcheck: test: ['CMD', 'curl', '-f', 'http://localhost/health'] interval: 30s timeout: 10s retries: 3 start_period: 40s
deploy: resources: limits: cpus: '2' memory: 4G reservations: cpus: '1' memory: 2G
logging: driver: 'json-file' options: max-size: '10m' max-file: '5'
volumes: gateway-data:With .env file:
VSB_LOCAL_API_KEY=7kB9qF2mP5tX8nL3wR6vY1zA4cE0sJ7hVSX DNS Domain Discovery
Section titled “VSX DNS Domain Discovery”When using VSX DNS with hardened images, your domain is automatically assigned. Since you can’t run commands inside the container, discover your domain through:
Option 1: Check the VSX DNS Dashboard
Visit vsx.email and look up your IP address to find your assigned domain.
Option 2: Check the Logs
docker compose logs gateway | grep -i "domain\|vsx"Option 3: Via API
Once you have the domain, verify it via the API:
curl -H "X-API-Key: your-api-key" https://your-domain.vsx.email/api/inboxesMigration from Standard Images
Section titled “Migration from Standard Images”To migrate from standard to hardened images:
-
Export your API key (if auto-generated):
Terminal window # From the standard image containerdocker compose exec gateway cat /app/data/.api-key > ./api-key-backup.txt -
Update your docker-compose.yml:
services:gateway:image: vaultsandbox/gateway:latest-harden # Changed from :latestenvironment:VSB_LOCAL_API_KEY: 'your-exported-api-key' # Add this -
Deploy the hardened image:
Terminal window docker compose pulldocker compose up -d
Troubleshooting
Section titled “Troubleshooting”Cannot Access Container Shell
Section titled “Cannot Access Container Shell”Expected behavior. Hardened images have no shell. Use Docker logs and the /health endpoint instead.
API Key Not Working
Section titled “API Key Not Working”Check logs for API key status:
docker compose logs gateway | grep -i "api key"Look for: [ConfigValidation] ✓ Local API key loaded from environment
Verify key format:
- Must be at least 32 characters
- No extra whitespace or newlines
- Check for copy/paste errors
Service Won’t Start
Section titled “Service Won’t Start”Check logs:
docker compose logs gatewayCommon issues:
- Missing
VSB_LOCAL_API_KEYenvironment variable - API key shorter than 32 characters
- Port conflicts (25, 80, 443 already in use)
Cannot Find Assigned VSX Domain
Section titled “Cannot Find Assigned VSX Domain”Check logs for domain assignment:
docker compose logs gateway | grep -E "domain|vsx|assigned"Verify via the VSX dashboard:
Visit vsx.email to look up your server’s IP address.
Comparison: Standard vs Hardened
Section titled “Comparison: Standard vs Hardened”| Feature | Standard (:latest) | Hardened (:latest-harden) |
|---|---|---|
| Shell access | ✅ Available | ❌ Removed |
| API key auto-generation | ✅ Supported | ⚠️ Requires env var |
docker exec commands | ✅ Work | ❌ No shell |
| Log access | ✅ Logs + exec | ✅ Docker logs only |
| Attack surface | Standard | Reduced |
| Compliance | Standard | Enhanced |
Next Steps
Section titled “Next Steps”- Docker Compose Setup - Standard deployment guide
- API Keys & Authentication - API key management details
- Gateway Configuration - Full configuration reference
- Security & Encryption - Security model deep dive