Homerun
A self-hosted PaaS that starts on one box. Swarm workers when you want more. No Kubernetes, no separate control plane. Deploy Docker containers with a click-config form, a Dokploy / Cloud Run alternative for your own hardware, for you alone or a whole team. MIT licensed.
Point at an image (or a git repo), fill in env vars / port / resources, hit
deploy: Traefik routes it to <slug>.yourdomain.com with TLS, automatically.
Then drive the same instance from a REST API, a CLI, an MCP agent, GitHub
Actions, a manifest in your repo or Terraform, whichever fits.
Status: Actively developed, running on real hardware, but still finding its shape: see
docs/faq-and-limitations.mdfor what's solid and what isn't yet.
See the full showcase →: every screen, light and dark, generated from a real instance.
#Why Homerun
Dokploy, Coolify, and friends are great, but a few things I can't get around:
- Coolify has many bugs and a lot of tech debt
- Dokploy has started paywalling features that homelab enthusiasts could use, for the benefit of enterprise.
Homerun keeps everything in the open, MIT licensed: multi-node swarm, teams and roles, previews, IaC and the API are all just features, not a paid tier.
#Features
#Deploying
- Image or git repo: deploy any Docker image (private registry auth included), or clone a repo by branch, tag or pinned commit and build it on the host, with no registry in between
- Six build methods: a
Dockerfileor a Docker Bake target built with BuildKit (cache mounts, multi-stage,# syntax=), or no Dockerfile at all with Nixpacks, Railpack, Heroku or Paketo buildpacks, builder binaries checksum-verified - Deploy on push: Homerun registers the webhook on your repo for you, and falls back to polling the branch when the git provider can't reach your dashboard (LAN, VPN)
- Pull request previews: every pull request
gets its own
<slug>-pr-<n>service, redeployed on each push and deleted on merge or close, with forks never previewed - Required status checks: a git service waits for the CI checks you pick to pass, then builds exactly the commit they passed on
- Build servers & build cache:
compile on another Docker daemon (
tcp://,ssh://or the lightweight Homerun Agent), and share BuildKit layer cache through a registry - Live deploy progress: pull/build/create/start streamed to the UI in real time, and it resumes if you reload mid-deploy or the deploy started somewhere else
- Zero-downtime, health-gated redeploys: the new container starts next to the old one and only gets traffic once it's ready (its healthcheck, the image's, or a port check Homerun adds itself); a new copy that never comes up is removed and the old one keeps serving
- Revisions & rollback: every deploy recorded with its image digest, commit and full log; redeploy any earlier revision's exact image, with opt-in auto-rollback when a new one turns unhealthy
- Image scanning: every deploy scanned with Trivy through a local registry mirror before it starts, so the container runs exactly what was scanned, with an admin policy that blocks deploys at or above a chosen severity (optionally fixable findings only)
- Environments: copies of a service running another
branch or tag (
staging,qa), each one a real service of its own with its own hostname, listed with its previews and canary on one tab - Release channels: "a branch is canary, a tag
is stable" in one switch, a managed
<slug>-canaryservice deployed on every push and the service itself on every matching tag - Version pinning & update checks:
swap
:latestfor the exact tag that's running, watch the registry for a newer release on the same track, trial-run it before you're notified, and update in one click - Homerun Manifest: keep a service's whole config in a
.homerun.json/.homerun.yamlin the repo, applied before every build, or push it at any service from the CLI or API - Compose import: paste a
docker-compose.yamland get its services, volumes, runtime options and dependency order as Homerun services, with a preview of anything that doesn't map across - Migrate from Dokploy or Coolify: read another instance's apps, compose stacks and databases (read-only on their side) and recreate them here, builders and start commands included
#Running services
- Multi-node with Swarm: the installer's default, every service is a Docker Swarm service with replica scaling and load balancing across nodes, and another machine joins as a worker with one command; standalone (one container per service) stays available for a single box
- Remote hosts: register other Docker
daemons over
tcp://,ssh://(nothing to install but sshd) or the Homerun Agent to build images, run workstations or run cron jobs on - Env vars & env files: key/value rows plus
.envfiles read off the host at each deploy, with a per-variable secret lock always redacted for AI agents regardless of name - Smart service links: point a service at an existing Postgres, MySQL, Redis, Mongo, RabbitMQ or HTTP service and get the connection URL, JDBC URL or one variable per value filled in for you, unlink it later with one click
- Runtime options: entrypoint, command, custom labels, and (System permission) added capabilities, device mappings and privileged mode
- Compute & settings: CPU/memory limits, replicas, restart and pull policies, a healthcheck command, and scanning and auto-rollback per service
- Live logs & a web terminal: tail stdout/stderr or open an interactive shell into a running container from the browser, or on the machines themselves over SSH
- The services list: server-side search, filters and paging on every list page, a list/card toggle, a dependency-tree view across every service, and bulk Start/Stop/Restart/Delete with a typed confirmation before anything destructive
#Stacks & templates
- Stacks: group services on their own private Docker
network so they reach each other by slug (
http://api:8080), with prefixed subdomains, nested substacks, a dependency tree/diagram of a stack's services, and one-step delete of the whole stack - ~100 built-in templates: Immich, Jellyfin, Plex, the *arr stack, Pi-hole, Vaultwarden, Grafana, Uptime Kuma, PostgreSQL, Redis, n8n and more, with real app logos, one-click Quick Deploy, and a details page that pulls in the project's GitHub README, stars and latest release
- Linked containers: companions
deploy with the primary (WordPress brings MySQL), and env vars like
{{db.POSTGRES_PASSWORD}}wire them together without retyping - Custom templates: save any service's config as your own template, or build one from scratch
#Workstations & terminals
- Machine terminals: a shell on this server and every remote host, in the browser, over SSH from Homerun's worker, so a machine only needs an SSH server and Homerun's public key
- Browser-based dev boxes: a code-server or openvscode-server container with a persistent home volume, your repo already cloned and its dev container config applied, on this server or any remote host, behind the login wall, with auto-stop and presets for the setups you reuse; personal to each account
#Networking & domains
- Automatic routing & TLS: Traefik routes every service to
<slug>.<baseDomain>with a certificate, with no host ports published - Domains & SSL: any number of extra hostnames per service, each with its own router, plus bring-your-own cert/key for domains outside Traefik's automatic ACME coverage
- Path-based routing: route
example.com/apito one service andexample.comto another on the same origin, with optional prefix stripping and a login wall scoped to the path - Hostname ownership: every domain belongs to exactly one service, workstation, redirect or the dashboard itself, conflicts are refused with the owner named, and a domain can be taken over on purpose
- Redirects: send a hostname or a path to another URL, answered by Traefik with no container
- Blocked paths & IP bans: turn away
the
.env/.git/wp-login.phpscanners before they reach the app, ban repeat offenders, and push bans to CrowdSec - Branded error pages: replace Traefik's bare
404andBad Gatewaywith a page that says what's going on - Host networking: for apps that need the host's network directly (mDNS/SSDP discovery)
- DNS automation: your domains' records at 16 DNS providers (Cloudflare, Route 53, Google Cloud DNS, Azure, Hetzner, Namecheap, GoDaddy, OVH…), managed from the dashboard and created and removed as services come and go, or Pangolin resources, and Homerun can run the Pangolin Newt tunnel client for you, set up straight from onboarding
- Per-app login wall: put any deployed service behind a Homerun login (passkeys and 2FA included) through Traefik forwardAuth
#Storage & backups
-
Storage volumes: bind mounts or Docker-managed volumes defined once, mounted into one or more services, read-write or read-only, with a database or cache getting one at its data directory automatically
-
Volume backups: scheduled or on-demand backups of both volume kinds to any S3-compatible bucket, or over SFTP, SMB or WebDAV (a Hetzner Storage Box, a NAS), with optional service stop or a pre-backup command (
pg_dump,mysqldump) for consistent database copies -
Restore from the dashboard: browse a volume's backups at its destination and restore one, optionally wiping the volume first, with a searchable history of every run
-
Object storage: a built-in S3 store Homerun runs for you, plus any S3-compatible provider you connect, with buckets, expiry and public buckets managed from one page
#Observability & notifications
-
Monitoring: requests, average response time, error rate, bandwidth, uptime and CPU and memory per service, from today to all time, recorded from Traefik's metrics every minute
-
Uptime probes: every service probed every minute from the Docker network and from its public hostname, with failure reasons and fix hints
-
Status pages: private or public uptime pages for every service, one stack, or services you pick
-
Resource history: live and historical CPU, memory, disk, network and NVIDIA GPU usage for the host and each service, kept for a year, plus top consumers per instance and per stack
-
Errors in context: failed deploys and the warnings Homerun logged about a service, on that service's page, with crash and "container is gone" banners
-
Error tracking: Sentry-protocol compatible, so the official Sentry SDKs report straight to Homerun, grouped into issues with stack traces linked back to your source and source maps applied
-
Tracing: a built-in OpenTelemetry collector and a waterfall view of every span, including Homerun's own background jobs
-
Notifications: an in-app bell, plus Discord, Slack, Telegram, webhook and email channels subscribed to build, deploy, update, rollback, scan and up/down events, retried when delivery fails
#Scheduling
- Scheduled redeploys: cron-style auto-redeploy per service to pick up new images
- Cron jobs: a throwaway container, a script
on a Bun, Node, Deno, Python or
shruntime, or a host command (needs the System permission), on a schedule or on demand, with secret env vars, config files, volumes, exit codes, output and traces kept per run, and on another host overtcp://orssh:// - The Scheduling page: every cron redeploy, job and backup schedule, plus the live job queue, on one page
#Users & security
- Multi-user, with roles & invites: five roles (admin, developer, read-only, app access only and custom, where you pick the areas), email or direct-create invites, and a resource pool the whole team shares; an app access only account never sees the dashboard, it only gets through the login walls of the apps you choose
- Service accounts: non-human accounts for CI and scripts, with no sign-in method, API keys as their only credential, permissions capped at yours and every use logged on an Activity tab; they can also get CI through an app's login wall
- OAuth/OIDC sign-in: one-click presets for Pocket ID, Keycloak, Authelia, Authentik, Logto, Zitadel and Kanidm
- Passkeys & two-factor: which an admin can require for every account
- Sign in with Homerun: Homerun is an OpenID Connect provider too, so the apps you host (Grafana, Gitea, Outline, Immich…) log in with your Homerun accounts, passkeys and 2FA rules
- Git provider accounts: connect GitHub, GitLab, self-hosted Gitea or Bitbucket and pick a repo and branch instead of pasting URLs
- API keys: per-area permissions and an
expiry, created by hand or through
homerun login - Hands off everything else: every container is labeled
homerun.managed=true, and Homerun never touches anything it didn't create (Docker Cleanup being the one deliberate exception)
#Automation: API, CLI, IaC & CI
Everything you can click, you can script.
- REST API & OpenAPI: everything in the dashboard is
also a typed JSON API (
/api/v1), authenticated by session or API key, with a live Swagger UI - The
homerunCLI: a small (~6MB) standalone Go binary covering services, stacks, previews, workstations, version pins, the registry and more; logs in through a device-code flow and updates itself - Infrastructure as code: a Terraform / OpenTofu provider and Pulumi for stacks, services, every setting and the objects around them, with state kept in your own object storage, a starter config generated from what's already running, and drift detection
- Deploying from CI: when your pipeline builds the image, it tells Homerun to deploy (optionally switching to the tag it just pushed) and waits for the deploy, so a failed deploy fails the pipeline
- GitHub Actions:
deploy,rollbackandpreviewactions that deploy the image CI just pushed and wait for it, so a broken deploy fails the pipeline, plusgate-sessionto run E2E tests behind a login wall; a Docker image does the same for GitLab and every other CI - Preview testing recipes: E2E against every pull request's preview, then ship the exact image that passed; or main is canary, tags are stable
- MCP server: let Claude or any MCP agent diagnose and fix your services, with credential-shaped values redacted; an agent that supports Client ID Metadata Documents only needs the URL, others sign in through a client you register on the IDP page, and Claude Code uses an API key
#Install & operations
- One-line installer: Docker, a swarm manager, Traefik, Postgres and Homerun on a fresh Linux box in one command, or rootless Docker if you'd rather, and a rootless-to-rootful migration for older installs
- First-run wizard: configure
base domain, email, sign-in and DNS in the dashboard, with no config file to
maintain, and an
optional
homerun.yamlif you want config as code - One-click self-update: from the sidebar, on the stable, canary or nightly release channel; the new version boots next to the running one as a candidate first and only takes over once it answers its readiness check, and a switch that doesn't come up rolls back to the version you had
- Setup diagnostics: a banner that deep-links to the exact setting that's wrong
- System logs: live logs of Traefik, Postgres and Homerun itself, with Traefik restart and update buttons
- Docker Cleanup: needs the System permission
docker system df/prune from the dashboard with a preview before anything goes, plus automatic garbage collection of the scan mirror - Docker Registry: turn the internal image mirror into a
real private registry,
docker pushincluded, with push/pull tokens and an optional public hostname through Traefik - Simple & advanced modes: a short click-ops sidebar for the homelab, or the full engineering surface; switching only changes what's in view
⌘Ksearch: jump to any page, or to anything on the instance, from anywhere- Appearance: light/dark/system theme, and a color palette or a custom accent color per account
#Configuration
You configure Homerun from its own dashboard. The installer sets up everything
the container needs to boot and then hands you a first-run wizard; after that,
base domain, Docker, Traefik, email, sign-in methods, DNS automation and
orchestration mode are all settings pages. There's no config file to maintain,
just AUTH_SECRET and ORIGIN if you're running docker compose by hand
instead of using the installer. An optional homerun.yaml file mirrors every
setting for config-as-code setups, with a dashboard change always winning over
the file. See docs/configuration.md.
#Documentation
docs/ in this repo is the source of truth, plain Markdown,
readable straight from the file browser. Start with
Getting started. The
website renders the same files.
#Sub-projects
Three standalone tools live under cmd/ alongside the main app, each compiling
to its own binary. All three are Go packages sharing one go.mod at the repo
root, not part of the SvelteKit build:
cmd/worker/: the Go worker that runs Homerun's Docker access and background jobs next to the app; run standalone with noDATABASE_URL, the same binary becomes a small token-authenticated HTTP server that lets a second machine build images for this one, without exposing its Docker daemon (agent mode)cmd/installer/: the one-liner installer used above (Docker as a swarm manager, or rootless, plus the agent or full stack, and--migrate-to-rootfulfor older rootless installs)cmd/cli/: a CLI (homerun services deploy <id>, etc.) against the REST API
Plus the Terraform provider under terraform/ and the
GitHub Actions under actions/.
#License
MIT, see LICENSE.
This guide lives in the project repo: edit it there, and this page follows within a day.
