Production Deployment
This guide covers everything needed to deploy mik in a production environment.
Pre-flight Checklist
Section titled “Pre-flight Checklist”Before deploying to production:
- Build mik with release optimizations:
cargo build --release - Configure reverse proxy (nginx/Caddy) for TLS termination
- Set up monitoring and alerting
- Configure log aggregation
- Test health endpoints
System Requirements
Section titled “System Requirements”| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 2 cores | 4+ cores |
| RAM | 512 MB | 2+ GB |
| Disk | 1 GB | 10+ GB (for AOT cache) |
Memory Considerations
Section titled “Memory Considerations”- Each WASM module consumes memory when loaded
- AOT-compiled modules are cached on disk (
.wasm.aotfiles) - LRU cache evicts least-used modules when
max_cache_mbis reached
Network Architecture
Section titled “Network Architecture”[Client] --> [Reverse Proxy (nginx/Caddy)] --> [mik :3000] --> [Sidecars] | [TLS, Rate Limiting]Port Configuration
Section titled “Port Configuration”| Port | Service | Access |
|---|---|---|
| 443 | Reverse proxy (HTTPS) | Public |
| 3000 | mik HTTP server | Internal only |
| 9919 | Daemon API | Internal only |
Security Hardening
Section titled “Security Hardening”API Key Authentication
Section titled “API Key Authentication”Always set a strong API key for daemon endpoints:
# Generate a strong API keyexport MIK_API_KEY="$(openssl rand -hex 32)"
# Start with API keymik run --api-key "$MIK_API_KEY" myapp.wasm
# Or for daemon modemik devAll daemon API requests must include the key:
curl -H "X-API-Key: $MIK_API_KEY" http://localhost:9919/instancesFile Permissions
Section titled “File Permissions”# Restrict mik data directorychmod 700 /var/lib/mik
# Protect configurationchmod 600 /etc/mik/mik.toml
# Ensure WASM modules are read-onlychmod 644 /var/lib/mik/modules/*.wasmNetwork Restrictions
Section titled “Network Restrictions”Limit outbound HTTP access in mik.toml:
[server]# Only allow specific hostshttp_allowed = ["api.internal.example.com", "*.supabase.co"]
# Or disable all outbound HTTPhttp_allowed = []Reverse Proxy Setup
Section titled “Reverse Proxy Setup”nginx Configuration
Section titled “nginx Configuration”upstream mik { server 127.0.0.1:3000; keepalive 32;}
server { listen 443 ssl http2; server_name api.example.com;
ssl_certificate /etc/ssl/certs/api.example.com.pem; ssl_certificate_key /etc/ssl/private/api.example.com.key;
# Security headers add_header X-Frame-Options "DENY" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always;
# Rate limiting limit_req zone=api burst=20 nodelay;
location / { proxy_pass http://mik; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts proxy_connect_timeout 5s; proxy_read_timeout 60s; proxy_send_timeout 60s; }
# Health check endpoint (no rate limiting) location /health { proxy_pass http://mik; limit_req off; }}Caddy Configuration
Section titled “Caddy Configuration”api.example.com { reverse_proxy localhost:3000 { header_up X-Forwarded-Proto {scheme} }
# Rate limiting rate_limit { zone api { key {remote_host} events 100 window 1m } }}Production mik.toml
Section titled “Production mik.toml”[project]name = "production-api"version = "1.0.0"
[server]port = 3000modules = "modules/"cache_size = 100max_cache_mb = 512execution_timeout_secs = 30max_concurrent_requests = 2000max_per_module_requests = 50shutdown_timeout_secs = 60log_max_size_mb = 50log_max_files = 10http_allowed = ["*.internal.example.com"]
[tracing]service_name = "production-api"otlp_endpoint = "http://tempo:4317"Environment Variables
Section titled “Environment Variables”| Variable | Description | Example |
|---|---|---|
PORT | Server port | 3000 |
HOST | Bind address | 127.0.0.1 |
RUST_LOG | Log level | info |
MIK_API_KEY | Daemon API key | <hex string> |
MIK_HOT_RELOAD | Enable hot reload | 0 (disabled in prod) |
Deployment Patterns
Section titled “Deployment Patterns”Single Instance
Section titled “Single Instance”Simplest deployment for low-traffic services:
mik run --port 3000 /var/lib/mik/app.wasmMultiple Instances (Load Balanced)
Section titled “Multiple Instances (Load Balanced)”For horizontal scaling:
# Instance 1mik run --port 3001 app.wasm
# Instance 2mik run --port 3002 app.wasmnginx upstream:
upstream mik { least_conn; server 127.0.0.1:3001; server 127.0.0.1:3002;}Daemon Mode with Services
Section titled “Daemon Mode with Services”For applications needing KV, SQL, or Storage:
# Starts daemon on 9919, app on 3000mik run --detach --name myapp --port 3000Health Checks
Section titled “Health Checks”Configure load balancer health checks:
# Basic livenesscurl -sf http://localhost:3000/health
# Readiness (checks module cache)curl -sf http://localhost:3000/healthExpected response:
{ "status": "ready", "cache_size": 5, "cache_capacity": 100, "total_requests": 1000}Graceful Shutdown
Section titled “Graceful Shutdown”mik handles SIGTERM gracefully:
- Stops accepting new connections
- Waits for in-flight requests (up to
shutdown_timeout_secs) - Closes connections cleanly
- Exits with code 0
# Graceful shutdownkill -TERM $(pgrep mik)Backup and Recovery
Section titled “Backup and Recovery”What to Back Up
Section titled “What to Back Up”| Path | Contents | Frequency |
|---|---|---|
/var/lib/mik/modules/ | WASM modules | On deploy |
/var/lib/mik/data/ | Daemon state (redb, SQLite) | Daily |
/etc/mik/mik.toml | Configuration | On change |
Recovery Procedure
Section titled “Recovery Procedure”- Stop mik:
systemctl stop mik - Restore files from backup
- Verify permissions
- Start mik:
systemctl start mik - Verify health:
curl http://localhost:3000/health
Next Steps
Section titled “Next Steps”- systemd Service Setup - Running as a system service
- Monitoring & Observability - Metrics and tracing
- Operations Runbook - Troubleshooting guide