Guides

Deploy from CI

CI runs the same CLI you do. No server-side git integration, no webhooks to host.


One-time setup

Export your context (server credentials + kubeconfig) as a blob:

jekyo context export my-server

Store the output as a JEKYO_CONTEXT secret in your repo. If your app has build: services, also add an SSH private key with access to the server as JEKYO_SSH_KEY.

The workflow

name: deploy
on:
  push:
    branches: [main]

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

      - name: Install jekyo
        run: |
          curl -fsSL https://github.com/jekyo/jekyo/releases/latest/download/jekyo-linux-amd64 \
            -o /usr/local/bin/jekyo && chmod +x /usr/local/bin/jekyo

      - name: Restore context
        run: echo "${{ secrets.JEKYO_CONTEXT }}" | jekyo context import

      - name: Restore SSH key
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.JEKYO_SSH_KEY }}" > ~/.ssh/jekyo
          chmod 600 ~/.ssh/jekyo

      - name: Deploy
        run: jekyo up --ssh-key ~/.ssh/jekyo

Because deploys are content-hashed and idempotent, pushing a README change doesn't rebuild your images, and re-running a failed workflow is always safe.

PR preview environments

Rewrite the app name per PR and every PR gets an isolated namespace:

sed -i "s/^app: shop/app: shop-pr-${{ github.event.number }}/" jekyo.yaml
jekyo up --ssh-key ~/.ssh/jekyo

Clean up on close with jekyo down shop-pr-N --volumes.

Reachability

The kubeconfig inside the context points at your server's public IP on port 6443. If you firewall that port, allow your CI provider's egress ranges.

Previous
Migrate from Compose