Skip to content

Automated Deployments with GitHub Actions (CI/CD)

epd is designed to be executed directly inside GitHub Actions. Because your entire deployment configuration (services, replicas, ports, health probes, zero-downtime blue/green slots, accessories, domains, and DNS sync) is declared in epd.yml, your CI/CD workflow is concise and maintainable.


1. Quick Setup

Generate a preconfigured workflow automatically with:

bash
epd init --ci

This creates .github/workflows/deploy.yml in your repository.


2. Complete Workflow Example

Create .github/workflows/deploy.yml:

yaml
name: Deploy

on:
  push:
    branches: [main]

concurrency:
  group: deploy-${{ github.ref }}
  cancel-in-progress: false # Do not cancel in-flight deployments

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Configure SSH Agent
        uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Deploy with EPD
        run: npx @fabioplunser/epd deploy
        env:
          # DNS & Cloud Provider Tokens (if used in epd.yml)
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          HETZNER_API_TOKEN: ${{ secrets.HETZNER_API_TOKEN }}
          HETZNER_DNS_API_TOKEN: ${{ secrets.HETZNER_DNS_API_TOKEN }}
          # Application Secrets referenced in epd.yml
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          SESSION_SECRET: ${{ secrets.SESSION_SECRET }}

3. Configuring SSH Deploy Keys

To allow GitHub Actions to securely communicate with your server(s):

1. Generate an SSH Key Pair

Run on your local machine:

bash
ssh-keygen -t ed25519 -C "github-actions-epd" -f /tmp/epd_deploy_key

2. Add the Public Key to Your Server

Copy the contents of /tmp/epd_deploy_key.pub to /root/.ssh/authorized_keys on each server configured in epd.yml.

3. Add the Private Key to GitHub Secrets

In your GitHub repository:

  1. Go to SettingsSecrets and variablesActions.
  2. Click New repository secret.
  3. Name: SSH_PRIVATE_KEY
  4. Secret: Paste the entire contents of /tmp/epd_deploy_key (including -----BEGIN OPENSSH PRIVATE KEY----- and -----END OPENSSH PRIVATE KEY-----).

4. Docker Image Strategies in CI/CD

epd gives you three flexible approaches for handling Docker container images in GitHub Actions:

Strategy A: Zero Registry (Easiest)

If you do not specify a registry: in epd.yml:

  • The image is built on GitHub's runner.
  • It is saved and streamed directly over SSH to the target server (docker save | ssh docker load).
  • No container registry account or setup required.

Strategy B: GitHub Container Registry (ghcr.io)

If deploying to multiple servers or wanting fast image caching:

In epd.yml:

yaml
image: ghcr.io/${{ github.repository }}/app
registry:
  server: ghcr.io
  username: ${{ github.actor }}
  password_env: GITHUB_TOKEN

In .github/workflows/deploy.yml:

yaml
      - name: Deploy with EPD
        run: npx @fabioplunser/epd deploy
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Strategy C: Remote Server Build

Build the image directly on the remote server using host CPU/memory and local layer cache:

yaml
# epd.yml
build:
  remote: true

5. Multi-Environment Deployments (Staging vs. Production)

Use epd destination overlays:

yaml
# .github/workflows/deploy-staging.yml
on:
  push:
    branches: [develop]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: webfactory/ssh-agent@v0.9.0
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY_STAGING }}
      - run: npx @fabioplunser/epd deploy -d staging

This applies epd.staging.yml over your base epd.yml.


Released under the MIT License.