Skip to content
Cyril Rohr edited this page Mar 13, 2026 · 23 revisions

1. Choose a deployment target

Upgrading from v5 and relying on always_on? See Migrating from v5 to v6 before using the workflow examples below.

PullPreview supports two deployment targets:

  • compose: deploy your app with Docker Compose on the preview instance
  • helm: bootstrap k3s on the preview instance and deploy a Helm chart

Choose compose if your repo already runs with docker compose up.
Choose helm if your app is already packaged as a Helm chart.

See Deployment Targets for the full comparison.

2. Prepare your app

For compose

  • Keep your app under app_path (default .).
  • PullPreview looks for docker-compose.yml by default.
  • If your Compose files live elsewhere, set app_path and/or compose_files.

For helm

  • Set deployment_target: helm.
  • Set chart.
  • Set proxy_tls because Helm previews are always exposed through the PullPreview-managed Caddy gateway.
  • If you use Helm values files, keep them under app_path and pass them via chart_values.

3. Create the trigger label

Create a repository label named pullpreview, or use another label and set the label input.

4. Configure cloud credentials

Lightsail (default)

Add repository secrets:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • optional AWS_REGION (defaults to us-east-1)

For least-privilege setup, see Recommended AWS Configuration.

Hetzner

Add repository secrets:

  • HCLOUD_TOKEN
  • HETZNER_CA_KEY

HETZNER_CA_KEY is a private SSH CA key used by PullPreview for per-run SSH certificate authentication.

Generate one once and store only the private key in GitHub Secrets:

ssh-keygen -t rsa -b 3072 -m PEM -N "" -f hetzner_ca_key

Optional Hetzner action inputs:

  • provider: hetzner
  • region: nbg1 (default)
  • image: ubuntu-24.04 (default)
  • instance_type: cpx21 (default)

5. Add a workflow

Minimal compose workflow

name: PullPreviewon:
schedule:
- cron: "30 */4 * * *"pull_request:
types: [labeled, unlabeled, synchronize, closed, reopened, opened]permissions:
contents: readpull-requests: writejobs:
deploy:
if: github.event_name == 'schedule' || github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview')runs-on: ubuntu-slimtimeout-minutes: 30steps:
- uses: actions/checkout@v6
- uses: pullpreview/action@v6with:
app_path: .deployment_target: composeadmins: "@collaborators/push"# optional HTTPS# proxy_tls: web:80env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}AWS_REGION: us-east-1

schedule is optional and is only used for cleanup of dangling deployments. v6 preview deploys themselves are driven by pull request events.

Minimal helm workflow

name: PullPreview Helmon:
pull_request:
types: [labeled, unlabeled, synchronize, closed, reopened, opened]permissions:
contents: readpull-requests: writejobs:
deploy:
if: github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview')runs-on: ubuntu-slimtimeout-minutes: 45steps:
- uses: actions/checkout@v6
- uses: pullpreview/action@v6with:
provider: hetznerdeployment_target: helmchart: ./charts/my-appchart_values: charts/my-app/values-preview.yamlproxy_tls: "{{ release_name }}-web:80"env:
HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }}HETZNER_CA_KEY: ${{ secrets.HETZNER_CA_KEY }}

6. Deploy

Open a pull request, add the trigger label, and let the workflow run.

On success you get:

  • a live preview URL
  • PR status comments updated by PullPreview
  • a GitHub job summary with preview and SSH details
  • action outputs: live, url, host, and username

Next:

Clone this wiki locally