Configuration Reference
Complete reference for iop.yml configuration options
Configuration Reference
Complete reference for all configuration options available in iop.yml
.
Basic Structure
name: my-project # Required: Project name used for Docker networks and container naming
# Global settings
ssh: # SSH connection settings
username: iop # SSH username (default from config)
port: 22 # SSH port (default: 22)
key_file: ~/.ssh/id_rsa # Path to SSH private key (optional)
proxy: # Global proxy settings
image: elitan/iop-proxy:latest # Custom proxy image (optional)
apps: # Applications (zero-downtime deployments)
web: # App name
# App configuration here
services: # Services (direct replacement deployments)
database: # Service name
# Service configuration here
Apps Configuration
Apps are user-facing applications that get zero-downtime blue-green deployments. They are built locally and transferred via SSH.
Basic App Configuration
apps:
web:
server: server1.com # Target server (single server per app)
build: # Build configuration (for local builds)
context: . # Build context (default: .)
dockerfile: Dockerfile # Dockerfile path (default: Dockerfile)
args: # Build arguments from environment
- NODE_ENV
- API_URL
target: production # Multi-stage build target (optional)
platform: linux/amd64 # Target platform (optional)
proxy: # Reverse proxy configuration
app_port: 3000 # Port your app runs on inside container
hosts: # Custom domains (optional)
- example.com
- www.example.com
ssl: true # Enable HTTPS (default: true)
ssl_redirect: true # Redirect HTTP to HTTPS (optional)
forward_headers: false # Forward X-Forwarded-* headers (optional)
response_timeout: 30s # Request timeout (default: 30s)
environment: # Environment variables
plain: # Plain text variables (KEY=VALUE format)
- NODE_ENV=production
- PORT=3000
secret: # Variables from .iop/secrets (KEY format)
- DATABASE_URL
- API_KEY
health_check: # Health check configuration
path: /up # Health endpoint (default: /up)
replicas: 2 # Number of replicas (default: 1)
Advanced App Options
apps:
api:
server: api.example.com
image: my-app/api # Docker image name (optional, auto-generated)
# Multiple replicas for load balancing
replicas: 3
# Port mapping (rarely needed since proxy handles routing)
ports:
- "8080:8080"
# Volume mounts
volumes:
- ./logs:/app/logs
- app_data:/data
# Custom registry (for pre-built images instead of local build)
registry:
url: ghcr.io # Registry URL (optional)
username: myuser # Registry username
password_secret: REGISTRY_PASSWORD # Password from .iop/secrets
# Override default command
command: "npm start --production"
Services Configuration
Services are infrastructure components (databases, caches, etc.) that get direct replacement during deployment. They use pre-built Docker images.
Basic Service Configuration
services:
postgres:
image: postgres:17 # Required: Docker image with tag
server: db.example.com # Target server
ports: # Port mapping
- "5432:5432"
volumes: # Persistent volumes
- ./pgdata:/var/lib/postgresql/data
- db_logs:/var/log/postgresql
environment: # Environment variables
plain:
- POSTGRES_USER=postgres
- POSTGRES_DB=myapp
secret:
- POSTGRES_PASSWORD # From .iop/secrets
Advanced Service Options
services:
redis:
image: redis:7-alpine
server: cache.example.com
# Custom registry for private images
registry:
url: private-registry.com
username: myuser
password_secret: REGISTRY_TOKEN
# Override default command
command: "redis-server --appendonly yes"
# Multiple port mappings
ports:
- "6379:6379"
- "16379:16379" # Sentinel port
# Named and bind volumes
volumes:
- redis_data:/data # Named volume
- ./redis.conf:/usr/local/etc/redis/redis.conf:ro # Bind mount (read-only)
Global Configuration
SSH Configuration
ssh:
username: iop # Default SSH username for all servers
port: 22 # Default SSH port
key_file: ~/.ssh/id_rsa # Path to SSH private key
You can override SSH settings per server by using different usernames in your app/service server specifications.
Proxy Configuration
proxy:
image: elitan/iop-proxy:latest # Custom proxy Docker image
The proxy handles:
- SSL certificate management (Let's Encrypt)
- HTTP to HTTPS redirects
- Reverse proxy routing
- Load balancing between app replicas
Environment Variables
Plain Environment Variables
environment:
plain:
- NODE_ENV=production # Simple key=value
- DEBUG=app:* # Can contain special characters
- PORT=3000
Secret Environment Variables
Sensitive values are stored in .iop/secrets
and referenced by key name:
In iop.yml
:
environment:
secret:
- DATABASE_URL
- JWT_SECRET
- STRIPE_API_KEY
In .iop/secrets
:
DATABASE_URL=postgres://user:password@localhost:5432/myapp
JWT_SECRET=your-super-secret-jwt-key
STRIPE_API_KEY=sk_live_...
Build Arguments
For apps with build configuration, you can pass environment variables as build arguments:
apps:
web:
build:
context: .
args:
- NODE_ENV # Will pass NODE_ENV from environment section
- API_URL
environment:
plain:
- NODE_ENV=production
- API_URL=https://api.example.com
Health Checks
Apps should implement health check endpoints for zero-downtime deployments:
apps:
web:
health_check:
path: /up # Default endpoint
Your application must respond with HTTP 200 at this endpoint when healthy:
// Express.js example
app.get('/up', (req, res) => {
// Check database connectivity, etc.
res.status(200).send('OK');
});
// Go example
http.HandleFunc("/up", func(w http.ResponseWriter, r *http.Request) {
// Check dependencies
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
Volumes
Named Volumes
volumes:
- postgres_data:/var/lib/postgresql/data
- app_logs:/app/logs
Bind Mounts
volumes:
- ./data:/app/data # Relative to iop.yml location
- /host/path:/container/path # Absolute paths
- ./config/nginx.conf:/etc/nginx/nginx.conf:ro # Read-only
Volume Best Practices
- Use named volumes for database data
- Use bind mounts for configuration files
- Ensure host directories exist and have proper permissions
- Use read-only (
:ro
) for configuration files
Multi-Server Deployment
Each app/service can target a single server. For multi-server deployments, create multiple entries:
apps:
web-primary:
server: server1.com
# ... config
web-secondary:
server: server2.com
# ... same config
web-cdn:
server: cdn.server.com
# ... same config with different domains
proxy:
hosts:
- cdn.example.com
Registry Configuration
Global Registry
docker:
registry: ghcr.io
username: myuser
# Password should be in .iop/secrets as DOCKER_REGISTRY_PASSWORD
Per-App/Service Registry
apps:
web:
registry:
url: private-registry.com
username: appuser
password_secret: APP_REGISTRY_TOKEN
Registry configuration is only needed for:
- Services using private images
- Apps using pre-built images (instead of local build)
Apps with build
configuration don't need registries (images are built locally and transferred via SSH).
Complete Example
Here's a complete example showing all major features:
name: my-fullstack-app
ssh:
username: iop
key_file: ~/.ssh/deployment_key
apps:
web:
server: web.example.com
replicas: 2
build:
context: .
dockerfile: Dockerfile.web
args:
- NODE_ENV
- API_URL
proxy:
hosts:
- myapp.com
- www.myapp.com
app_port: 3000
ssl: true
environment:
plain:
- NODE_ENV=production
- API_URL=https://api.myapp.com
secret:
- JWT_SECRET
- DATABASE_URL
health_check:
path: /health
volumes:
- ./logs:/app/logs
api:
server: api.example.com
build:
context: ./api
dockerfile: Dockerfile
proxy:
hosts:
- api.myapp.com
app_port: 8000
environment:
plain:
- NODE_ENV=production
- CORS_ORIGIN=https://myapp.com
secret:
- DATABASE_URL
- JWT_SECRET
- STRIPE_SECRET_KEY
health_check:
path: /api/health
services:
postgres:
image: postgres:17
server: db.example.com
ports:
- "5432:5432"
environment:
plain:
- POSTGRES_USER=postgres
- POSTGRES_DB=myapp
secret:
- POSTGRES_PASSWORD
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
server: cache.example.com
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: "redis-server --appendonly yes"
Configuration Validation
iop validates your configuration and provides helpful error messages:
- Missing required fields - Clear error messages about what's missing
- Invalid formats - Validation errors with suggestions
- Reserved names - Apps/services cannot be named:
init
,status
,proxy
Use iop --verbose
to see detailed configuration validation information.
Environment-Specific Configurations
Create multiple configuration files for different environments:
# Development
iop.development.yml
# Staging
iop.staging.yml
# Production
iop.production.yml
Deploy with specific configurations:
iop -c iop.staging.yml # Deploy to staging
iop -c iop.production.yml # Deploy to production
This allows different:
- Server targets
- Environment variables
- Replica counts
- SSL settings
- Domain configurations