Architecture & Concepts
Learn how epd routes incoming traffic, provides true zero-downtime blue/green switches, and enables multiple independent applications to peacefully share a single host.
High-Level Request Flow
Internet (HTTP: 80 / HTTPS: 443)
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ HOST SERVER (e.g. 203.0.113.10) │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Shared Traefik Proxy (:80 / :443) │ │
│ │ Dynamic Config Provider (/var/lib/epd/proxy/dynamic/*.yml) │ │
│ │ Let's Encrypt ACME Certificate Resolver │ │
│ └───────────────┬───────────────────────────────┬─────────────────┘ │
│ │ │ │
│ Host: blog.example.com Host: store.example.com │
│ ▼ ▼ │
│ ┌───────────────────────────────┐ ┌─────────────────────────────┐ │
│ │ App 1: Blog │ │ App 2: Store │ │
│ │ Slot: Green (Live) │ │ Slot: Blue (Live) │ │
│ │ 2 Replicas │ │ 1 Replica │ │
│ └───────────────┬───────────────┘ └─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────┐ │
│ │ Accessory: Postgres │ │
│ │ /var/lib/epd/volumes/blog-db │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘Key Principles
1. Zero Daemons or Control Planes
Traditional container orchestrators (like Kubernetes, Nomad, or Docker Swarm) require running complex background agents, control planes, and consensus databases.
epd uses standard SSH. When you run epd deploy, it connects over SSH, executes necessary Docker/PM2 commands, writes declarative Traefik configuration files, and disconnects. Your servers remain lightweight, predictable, and free of proprietary locks.
2. The Shared Traefik Reverse Proxy
Traefik binds to ports 80 and 443 on the host server. Rather than restarting or modifying a master configuration file on every deployment:
- Traefik watches a dynamic configuration directory:
/var/lib/epd/proxy/dynamic/. - Each deployed app maintains its own file, e.g.,
/var/lib/epd/proxy/dynamic/blog.yml. - Traefik hot-reloads routing tables in memory with zero dropped requests whenever a file changes.
- Adding, updating, or deleting one application has zero impact on any other app running on the same server.
3. Server Filesystem Layout
On every server managed by epd, files are neatly arranged under /var/lib/epd:
/var/lib/epd/
├── proxy/
│ ├── traefik.yml # Static Traefik configuration
│ ├── acme.json # Let's Encrypt SSL certificates (0600)
│ └── dynamic/ # Traefik hot-reloaded routing directory
│ ├── app1.yml # App 1 dynamic routing rules
│ └── app2.yml # App 2 dynamic routing rules
├── apps/
│ ├── my-app/
│ │ ├── env # Secret environment variables (0600)
│ │ ├── state.json # Active slot, version, and replica state
│ │ └── releases/ # (Process mode) Versioned releases
├── volumes/ # Persistent accessory storage (Postgres, Redis)
└── locks/ # Atomic deployment concurrency locksHow epd Compares
| Feature | epd | Kamal | Kubernetes | Docker Swarm |
|---|---|---|---|---|
| Zero-Downtime Blue/Green | ✅ Built-in | ✅ Rolling | ✅ Complex | ✅ Rolling |
| Multi-Site on Single VPS | ✅ Native (Shared Traefik) | ❌ Port 80/443 conflict | ⚠️ Requires Ingress Controller | ⚠️ Requires Traefik/Nginx |
| No-Docker Process Mode (PM2) | ✅ Built-in | ❌ Docker only | ❌ Containers only | ❌ Containers only |
| Hetzner & DNS Automation | ✅ Built-in | ❌ Third-party | ❌ External operator | ❌ None |
| Cross-Host Failover | ✅ Built-in | ❌ Single host proxy | ✅ Ingress / Mesh | ✅ Ingress routing mesh |
| Resource Overhead | ~30MB (Traefik) | ~50MB | >1GB - 2GB RAM | ~250MB |
Next Steps
- Explore the Blue/Green Deployment Lifecycle
- Learn about Deployment Modes: Docker vs. Process
- See how Multi-Site Hosting works