Skip to content
Blog
AWS Lightsail
Default provider
Hetzner
Cloud alternative
auto TLS
proxy_tls + custom domains

Full-fidelity preview environments for GitHub

PullPreview is a GitHub Action that automatically deploys your pull requests to your own AWS Lightsail or Hetzner infrastructure. Works with any application that can be launched with Docker Compose.
PullPreview preview environment ready state shown with URL from PR comment

Git push, deployed

Once installed in your repository, this action is triggered whenever a change is made to pull requests labeled with pullpreview.

When triggered, PullPreview:

  1. Checks out repository code.
  2. Provisions an instance with Docker + Docker Compose on your selected provider:
    • lightsail (default)
    • hetzner
  3. Deploys updates continuously from pull requests.
  4. Reports preview URLs in the GitHub UI.
PR label changed PullPreview sync PR comment with preview link

Features

  • Works with your existing tooling: if your app can run with Docker Compose, it can run as a PullPreview environment.
  • Starts and destroys environments from PR labels.
  • Runs on your cloud account (AWS Lightsail by default, Hetzner as an alternative).
  • Supports privacy-first review workflows: your code stays within GitHub and your own infrastructure.
  • Keeps preview state across deploys through Docker volumes.
  • Makes reviewer access straightforward:
    • preview links in PR checks,
    • SSH access via installed GitHub user keys.
  • Auto HTTPS and custom domain support:
    • proxy_tls injects a Caddy sidecar and handles Let’s Encrypt,
    • dns lets you use rev*.click built-ins or your custom domain.

Workflow examples

Use the provider-specific tab below and copy the complete workflow for your deployment target.

name: PullPreview
on:
schedule:
- cron: "30 */4 * * *"
push:
branches:
- main
pull_request:
types: [labeled, unlabeled, synchronize, reopened, opened, closed]
permissions:
contents: read
pull-requests: write
jobs:
deploy:
if: github.event_name == 'schedule' || github.event_name == 'push' || (github.event.action != 'closed' && github.event.action != 'unlabeled' && (github.event.label.name == 'pullpreview' || contains(github.event.pull_request.labels.*.name, 'pullpreview')))
runs-on: ubuntu-slim
timeout-minutes: 30
steps:
- uses: actions/checkout@v5
- uses: pullpreview/action@v6
with:
admins: "@collaborators/push"
provider: lightsail
app_path: .
instance_type: nano
default_port: 80
compose_files: docker-compose.yml
proxy_tls: web:80
ttl: 1h
env:
AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}"
AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}"
AWS_REGION: "us-east-1"

HTTPS and custom domains

  • proxy_tls configures HTTPS termination and routes traffic to your selected service.
  • dns controls the public domain prefix used for generated preview hostnames.
# auto TLS using built-in rate-limit-friendly domain
with:
proxy_tls: web:80
dns: rev1.click
# custom domain
with:
dns: preview.example.com

If you use proxy_tls on the shared default domain (my.preview.run), Let’s Encrypt rate limits can be reached with high preview churn. Use a domain from rev1.click to rev9.click or your own custom domain for safer issuance capacity.

Testimonials

It saved us thousands in development costs, and the monthly cost of the Lightsail instances is immaterial compared to SaaS tools that want to license on a per user or per repository basis.

-
Casey Kinsey, CEO at HireLofty

An incredibly valuable tool for enhancing my workflow and improving collaboration with my team. One of the standout features of this action is its ease of setup.

-
Neil Raina, CTO at Copilot

We were stuck trying out lots of different managed solutions with Vercel, Render etc, but they all had problems. Using docker-compose with self-hosting made it so much simpler 👍

-
Tristan, Lead Engineer at Layer3

We were struggling with product reviews, as we performed them too late on the developpement cycle and faced difficulties to isolate the issues. It lead to long threads, frictions and was energy and time consuming for both technical and product teams. Then came PullPreview: an easy way to review PRs for product teams and ease communication between developers and PM/Designers.

-
Adam Feral, Head of Product at Malo

Useful for the entire team

  • Product Owners: Interact with new features as they are built and catch issues earlier.
  • Developers: Share work in progress with instant, reproducible review environments.
  • Ops: Keep operations ownership in your own cloud account.
  • CTOs: Avoid third-party SaaS lock-in; your code and data stay in GitHub and your own servers.

Installation & Usage

-> Please see the wiki for the full documentation.

Pricing

The action is open source, but commercial use is licensed separately.

  • Non-profit individual use can be free.
  • In all other cases, you need a commercial license (300€/year, currently covering one organization).
Purchase license

Then, for each preview environment you pay your provider’s compute cost. In practice, that means you pay only for the underlying infrastructure resources you actually run, with no extra per-preview markup.

Why this approach

  • Simple architecture: One VM per preview, no Kubernetes complexity.
  • Full GitHub integration: status updates and checks keep feedback in the PR flow.
  • Secure by default: SSH access is scoped and controlled via GitHub users.
  • Cost efficient: choose one of two providers and right-size instances via instance_type.

Who did this?

👋 I’m Cyril Rohr, a freelance CTO/DevOps from France.

If you’re also optimizing CI/CD spend, check out runs-on.com. Their GitHub Actions runners are advertised as up to 10x cheaper than GitHub-hosted runners in many common workloads.