Per-PR preview environments for frontend projects — self-hosted, one binary, no Kubernetes, no cloud lock-in.
Install prevly's GitHub App on a repo, drop a .prevly.yml, and every pull
request gets a live preview URL of the frontend(s) built from that PR —
redeployed on each commit, torn down when the PR closes. Think "AWS Amplify
previews", but open-source and running on your own Docker host, under your own
domain.
Status: v1 implemented. The daemon (webhook → build → run → proxy → PR feedback → lifecycle) is built and tested.
For "I just want PR previews, on a Docker host I already have, under my own domain", nothing fits cleanly:
- Coolify / Dokploy do PR previews but are full PaaS (panel + DB + generic app hosting) — overkill if you only want previews.
- preevy is previews-focused but uses tunnels + provisions a VM, and its URLs aren't under your domain (breaks cookie/same-site auth).
- Uffizzi / Qovery / Argo ApplicationSet / vcluster / … are Kubernetes- or SaaS-bound.
prevly fills that gap: previews-only, runs on a plain Docker host, under your own wildcard domain, GitHub-native, single binary, secure-by-default.
PR opened/updated ──webhook──▶ prevly daemon (on your Docker host)
for each app whose paths changed: build (host BuildKit) → run (hardened container)
embedded proxy (CertMagic) serves https://pr-<N>-<app>.<your-domain> (auto TLS)
sticky PR comment + GitHub Deployment with the URL
PR closed ──▶ torn down. Idle ──▶ sleeps, wakes on next request in ~1-3s.
On a Docker host with a public IP and a wildcard DNS record
(*.<base_domain> → host):
go build ./cmd/prevly # or grab a release binary
cp examples/config.yaml /etc/prevly/config.yaml # edit base_domain, tls
cp examples/env.example /etc/prevly/prevly.env # fill secrets (never commit)
install -m644 packaging/prevly.service /etc/systemd/system/prevly.service
systemctl enable --now prevlyOn first start, with no GitHub App configured, prevly serves a one-time setup
page on your domain: open the URL printed in the logs
(https://<base_domain>/setup?token=…), choose a name (and optional org), and
prevly runs GitHub's App-manifest flow for you — the App is created with the
right permissions and webhook, and its credentials are persisted under
data_dir. Then install the App on your repos and add a .prevly.yml
(prevly init scaffolds one; see examples/.prevly.yml).
No localhost dance, no copying secrets around.
prevly run run the daemon (foreground; wrap in systemd)
prevly init scaffold a .prevly.yml in the current repo
prevly status list previews across repos
prevly secret inspect the env-backed secret table
prevly destroy admin teardown of a PR's previews
prevly doctor check Docker access, config, disk, rootless
prevly version version info
- Single Go binary. The daemon is also the reverse proxy and the ACME client (via CertMagic). Nothing else to install.
- Frontend previews against an existing backend (not full ephemeral envs).
- Secure by default. Hardened containers, isolated networks, no prod secrets, fork-PR gating. (Rootless Docker recommended.)
- Cloud-agnostic. Anything with a Docker daemon: Hetzner, Scaleway, OVH, bare metal, a laptop. No Kubernetes, no per-cloud SDK.
- GitHub-native UX. Sticky PR comment + GitHub Deployments + ChatOps
(
/preview redeploy|destroy|status). No custom web dashboard.
MIT.