# EPD (Easy Project Deployer) — Full LLM & AI Agent Context Reference Version: 0.5.12 Website: https://epd.peppi.dev Repository: https://github.com/FabioPlunser/epd --- ## 1. Overview & Core Architecture EPD is an agentless, zero-dependency deployment CLI that turns any clean Linux VPS (Ubuntu, Debian) into a production-ready PaaS in 60 seconds over SSH. ### Architecture Highlights: - **Agentless over SSH**: No persistent background agent or daemon on the remote server. EPD orchestrates everything via standard SSH commands and Docker Engine API. - **Zero-Downtime Blue/Green**: Uses two alternating container slots (`blue` and `green`). EPD builds/starts the new slot, runs pre-flight health probes, hot-swaps Traefik routing dynamically, and shuts down the old slot only when the new container is verified 200 OK. - **Fronted by Traefik**: A single lightweight Traefik container manages Let's Encrypt TLS certificates (HTTP-01 / TLS-ALPN-01 / DNS-01) and routes requests to running application slots using dynamic file providers (`/etc/traefik/dynamic/`). - **Security by Default**: Auto-provisions CrowdSec IPS/IDS with Traefik bouncers to automatically block malicious scans, brute-force attacks, and DDoS patterns. - **Accessories**: Automated containerized databases (PostgreSQL, MySQL, Redis, MinIO) with automated backups to local disk or S3/Wasabi/R2. --- ## 2. Installation Methods ```bash # Method 1: Zero-Dependency Standalone Binary (Recommended for CI and AI Agents) curl -fsSL https://epd.peppi.dev/install.sh | bash # Method 2: Global Install with Bun bun add -g @fabioplunser/epd # Method 3: Global Install with NPM / PNPM npm install -g @fabioplunser/epd pnpm add -g @fabioplunser/epd ``` Verify installation: ```bash epd --version ``` --- ## 3. CLI Command Reference for AI Agents All commands are non-interactive friendly when provided with flags. ### Core Lifecycle Commands #### `epd init` Initializes `epd.yml` in the current project repository. - Options: - `--name `: Override project name (defaults to folder name or `package.json`). - `--mode `: Runtime deployment mode (default: `docker`). - `--host `: Server host IPv4/IPv6 address. - `--domain `: Public domain (e.g. `api.example.com`). - `--port `: Internal container port the app listens on (default: `3000`). - `--dockerfile`: Automatically generate an optimized multi-stage `Dockerfile`. - `--ci`: Automatically generate `.github/workflows/deploy.yml`. - Example for AI Agent: ```bash epd init --name my-app --host 159.69.120.45 --domain app.example.com --port 3000 --dockerfile ``` #### `epd setup` Bootstraps a fresh, clean Linux VPS (Ubuntu 22.04/24.04, Debian 11/12). - What it does: 1. Installs Docker Engine, Docker Compose plugin, and Git if missing. 2. Creates dedicated deploy user or sets up authorized SSH keys. 3. Deploys shared Traefik proxy with automated Let's Encrypt SSL. 4. Deploys CrowdSec IPS/IDS security engine and registers Traefik bouncer. 5. Deploys any configured accessories (Postgres, Redis). 6. Executes initial zero-downtime application deployment. - Options: - `--host `: Target host IP (overrides `epd.yml`). - `--user `: SSH user (default: `root`). - Example: ```bash epd setup --host 159.69.120.45 ``` #### `epd deploy` Performs a zero-downtime blue/green deployment. - Process: 1. Acquires atomic deployment lock on remote server. 2. Determines inactive slot (e.g., if `green` is live, deploy to `blue`). 3. Builds container image on remote server or pulls from registry. 4. Starts new container on private internal port. 5. Runs HTTP health check probe on `healthCheckPath` (e.g. `http://127.0.0.1:/health`) until 200 OK. 6. Atomically updates Traefik routing configuration to point domain to new slot. 7. Gracefully stops and cleans up old container slot after configurable drain period. 8. Releases deployment lock. - Options: - `-d, --dest `: Target server alias from `epd.yml`. - `--dry-run`: Simulate build and configuration generation without executing on server. - Example: ```bash epd deploy ``` #### `epd rollback` Instantly reverts traffic to the previous slot or version without rebuilding. - Options: - `[version]`: Optional specific semver or slot to revert to. - Example: ```bash epd rollback ``` #### `epd redeploy` Restarts currently active slot without re-uploading code or rebuilding. - Example: ```bash epd redeploy ``` #### `epd remove` Stops the application, removes Traefik routes, and deletes associated container volumes. - Options: - `-y, --yes`: Skip interactive confirmation prompt. - Example: ```bash epd remove -y ``` --- ### Observability & Health Commands #### `epd status` Shows running slots, replicas, active slot indicator, accessory statuses, and memory usage. - Options: - `--json`: Outputs machine-readable JSON structure. Perfect for AI agents to parse and verify deployment state! - Example: ```bash epd status --json ``` #### `epd doctor` Runs comprehensive pre-flight diagnostics across local tooling, `epd.yml`, SSH connectivity, Docker engine, port availability, and DNS resolution. - Options: - `-l, --local`: Skip SSH connectivity test and validate only local files and configurations. - Example: ```bash epd doctor --local epd doctor ``` #### `epd logs` Streams real-time container logs. - Options: - `-f, --follow`: Follow log output. - `-n, --tail `: Number of lines to show (default: 100). - `--slot `: View specific slot logs. - `--accessory `: View logs of an accessory (e.g. `postgres`, `redis`). - Example: ```bash epd logs -n 50 ``` #### `epd top` Displays real-time CPU, RAM, and network metrics across remote servers. - Options: - `--once`: Output single snapshot and exit (ideal for automated scripting). - Example: ```bash epd top --once ``` #### `epd ssl` Inspects Let's Encrypt certificate status, issuer, and expiration date. - Example: ```bash epd ssl ``` --- ### Remote Execution & Maintenance Commands #### `epd exec` Executes an arbitrary command inside the live application container. - Example: ```bash epd exec -- bun run migrate epd exec -- npx prisma migrate deploy ``` #### `epd maintenance` Instantly toggles zero-downtime maintenance mode (HTTP 503 with custom HTML maintenance screen via Traefik middleware). - Example: ```bash epd maintenance on epd maintenance off ``` #### `epd backup` Creates compressed database snapshot archives. - Example: ```bash epd backup postgres ``` #### `epd restore` Restores a snapshot archive into a live accessory. - Example: ```bash epd restore backups/postgres-2026-09-10.dump.zst ``` --- ## 4. `epd.yml` Configuration Specification Here is a full, production-ready `epd.yml` template: ```yaml version: "1" name: my-app mode: docker # Remote target servers servers: production: host: 159.69.120.45 user: root sshKey: ~/.ssh/id_ed25519 port: 22 # Routing & SSL routing: domain: app.example.com ssl: true acmeEmail: admin@example.com redirectWww: true traefik: enabled: true dashboard: false # Container Runtime Specification docker: dockerfile: Dockerfile port: 3000 replicas: 2 healthCheck: path: /health interval: 5s timeout: 3s retries: 5 startPeriod: 10s drainSeconds: 15 stopTimeout: 10s restart: unless-stopped resources: memory: 1024m cpus: "1.5" # Environment Variables & Secrets env: NODE_ENV: production PORT: 3000 # Secrets are loaded securely from .env or server environment secrets: - DATABASE_URL - API_SECRET_KEY # Optional Accessories (Databases, Redis, etc.) accessories: postgres: image: postgres:16-alpine port: 5432 env: POSTGRES_DB: myapp_prod POSTGRES_USER: myapp secrets: - POSTGRES_PASSWORD volumes: - /var/lib/epd/accessories/postgres:/var/lib/postgresql/data backup: schedule: "0 3 * * *" retentionDays: 14 # Automated Security Engine security: crowdsec: enabled: true remediation: ban scenarios: - http-crawl-non_statics - ssh-bf - http-probing ``` --- ## 5. Autonomous AI Agent Deployment Playbook When an AI coding assistant (Cursor, Windsurf, Claude Code, Cline, T3 Code) is asked to deploy a project with EPD, it should follow this 5-step loop: ### Step 1: Inspect Repository & Generate Dockerfile Ensure the repo has an entrypoint and an internal HTTP port (e.g. 3000). If no `Dockerfile` exists: ```bash epd init --name --host --domain --port 3000 --dockerfile ``` ### Step 2: Local Pre-flight Verification Run local linting and configuration validation without attempting remote SSH connections: ```bash epd doctor --local epd config ``` ### Step 3: Server Bootstrap (Clean VPS) If the server has not been initialized yet: ```bash epd setup --host ``` ### Step 4: Execute Zero-Downtime Deploy Deploy application: ```bash epd deploy ``` ### Step 5: Verify Deployment via JSON Status Confirm that the new slot is active, healthy, and traffic is routed: ```bash epd status --json ``` If the status shows errors, inspect logs: ```bash epd logs -n 50 ``` If fatal, perform instant rollback: ```bash epd rollback ``` --- ## 6. Exit Codes & Predictability - `0`: Command succeeded. - `1`: Pre-flight check failed (e.g., config syntax, missing secret, or Dockerfile not found). - `2`: Network or SSH connectivity error. - `3`: Health check probe timed out / returned non-200. Slot rollbacked automatically. - `4`: Locked by another running deployment (`epd lock status`).