> Homerun is a free, MIT-licensed self-hosted PaaS and a Dokploy, Coolify, Dokku and Cloud Run alternative: deploy Docker images or git repos from a form, get TLS routing via Traefik. One box to start, Swarm workers when you want more. Nothing paywalled.
> Source: https://zedensix.com/homerun · Site index: https://zedensix.com/llms.txt

# Homerun

A self-hosted PaaS for your own hardware, starting on one box. Point it at an
image or a git repo, fill in the form, hit deploy. Traefik puts it on
`slug.yourdomain.com` with TLS. No Kubernetes. No separate control plane. No
pricing page. MIT licensed, all of it.

![Homerun: point at an image, hit deploy. A service page with its actions, resource usage and live logs](https://zedensix.com/images/7e5f1bf2901be5fa2cc026757832c90a1fbc22d0.webp)
**Point at an image. Hit deploy.** One service, running, on its own domain, with
its logs streaming underneath. That is most of what Homerun is for, and all of
what it asks of you.

## At a glance

<iframe src="https://www.youtube-nocookie.com/embed/RFsqD8JSvZE?rel=0" title="Homerun at a glance" loading="lazy" allow="encrypted-media; picture-in-picture; fullscreen" allowfullscreen style="display:block;width:100%;aspect-ratio:16/9;border:0;border-radius:12px"></iframe>

## Why it exists

Coolify carries a lot of tech debt and a matching pile of bugs. Dokploy started
moving features homelabbers relied on behind an enterprise plan. Both are fine
projects; neither is what I wanted running on my hardware at home.

So Homerun stays deliberately small where it counts: **one Docker daemon in
charge, no control plane to run separately, no pricing page.** It scales the
way a homelab actually scales, Swarm replicas on your own boxes, extra
machines added as workers or build agents, not by outsourcing your
infrastructure to someone else's cluster. Admin, developer, read-only and
custom accounts if more than one person touches it. Everything it does, it does
for free, under the MIT license.

## Showcase

None of these are mockups. Playwright drives a real instance from a blank
database: a real sign-up, the first-run wizard, then a stack with three
services, two of them actually deployed as containers on the host’s Docker
socket. If a screen stops rendering the run fails instead of publishing it.
Light or dark follows your system; both are the real thing.

![The Homerun dashboard, showing service counts and live host resources](https://zedensix.com/images/342625fab64f6c5d97fcea711832788ff40720ef.webp)
**The dashboard** Service counts, live host CPU, memory and disk (plus GPU if
there’s an NVIDIA card), a host usage chart from live to a year back,
per-service usage, recent deploys and errors, and a banner for any setup issue
that links straight to the field it’s complaining about.

![The services list, with status, domain and image on each row](https://zedensix.com/images/7993544b8ce6b81c017d995c7b8b07dafa8d8ba2.webp)
**Every service** Status, domain and image per row. Search, sort and filters run
server-side, the checkboxes drive start, stop, restart and delete in bulk, and a
compose file imports from the same page.

![A service overview with its actions, resource usage, connections and a live log tail](https://zedensix.com/images/75378a44934499127cc27f79930099305f3dddbe.webp)
**A service** Status, image, the public hostname and the internal address other
services reach it at. Redeploy, pull, stop, restart or kill, resource usage over
time, the services it connects to, and a live log tail. Everything else is a tab
away: source, revisions, observability, errors, env vars, volumes, networking,
compute and a web terminal.

![The five-step deploy wizard, on the basic info step](https://zedensix.com/images/164d1ad22145c2ec3859cad433ea31788a735f1a.webp) **Deploying
something new** Five steps: basic info, networking, environment, volumes,
compute. From a Docker image or straight from a git repo.

![The template gallery, showing built-in app cards with their logos](https://zedensix.com/images/97f9f5ced5f6f2a5cbf43b29547cd7b5de8487b2.webp)
**Templates** Around 100 common self-hosted apps with their real logos bundled
in, searchable and filtered by category. Quick Deploy skips the wizard entirely;
Configure pre-fills it.

![A service’s observability tab: uptime checks above a live log stream](https://zedensix.com/images/4241f022bad7f494607388791a70774e6bab1580.webp)
**Logs and uptime** `stdout`/`stderr` streamed from the container as it runs,
ANSI colours intact, under uptime probes from the network and from its own
hostname.

![A stack page listing its three services with their status](https://zedensix.com/images/efdd77c58fe337446f72494cf26206cce659e324.webp)
**Stacks** A stack puts its services on a shared Docker network, so they reach
each other by slug (`http://cache:6379`) without going back out through Traefik.
Substacks nest inside it, and the architecture view draws what talks to what,
read from env vars pointing at another service’s slug.

![A service’s networking tab: its domains, automatic TLS and internal address](https://zedensix.com/images/b5bbdbae8bd8212339c8018b8d52febb7073a641.webp)
**Domains and access** As many domains as you want per service, each one
optionally sent to another port of the same container, one of them marked main.
TLS comes from Traefik’s resolver with nothing to configure, and the internal
address other services use sits right below. These are Traefik labels, so the
tab says plainly that changing them needs a redeploy.

![The instance settings page, on the General tab](https://zedensix.com/images/94c011fec748c5e456ecf220ad5c655819c9a005.webp) **Settings, not
files** Base domain, Docker, networking, email and migration from Dokploy or
Coolify, stored in the database and applied live. Leave a field blank and it
falls back to the env var shown as its placeholder.

Env vars, compute limits, revisions, users and signing in are in the
[full showcase](https://zedensix.com/homerun/docs/showcase), all of it generated the same way.

## Features

### Image or git deploys

Any Docker image, or build a git repo with a `Dockerfile`, Docker Bake,
Nixpacks, Railpack or Heroku/Paketo buildpacks, no Dockerfile required. Env
vars, CPU/memory limits, restart policy, private registry auth.

### Your git host, connected

An admin registers an OAuth app once for GitHub, GitLab, self-hosted Gitea or
Bitbucket; everyone else connects their own account and picks a repo and branch
from a list. Private repos without a token in the clone URL, and the branch is
checked for a `Dockerfile` before you commit to it.

### Deploy on push & PR previews

Homerun registers a webhook on your repo so every push redeploys the service,
and falls back to polling the branch when the git provider can’t reach the
dashboard. Turn on pull request previews and every open PR gets its own
`slug-pr-<n>` service, redeployed on each push and deleted on merge or close;
forks are never previewed.

### Deploy from CI

When your pipeline builds and pushes the image itself, it tells Homerun when to
deploy and waits for it, so a broken deploy fails the pipeline. GitHub Actions
for deploy, rollback and previews, a Docker image for GitLab or any other CI,
or one API call.

### Environments & release channels

Environments are copies of a service running another branch or tag (`staging`,
`qa`), each a real service with its own hostname. Release channels are “a
branch is canary, a tag is stable” in one switch: a managed `slug-canary`
deployed on every push, the service itself on every matching tag.

### Version pinning & update checks

Swap `:latest` for the exact tag that’s running, then let Homerun watch the
registry for a newer release on the same track, trial-run it before telling
you, and update in one click.

### Live, zero-downtime deploys

Pull, build, create and start streamed to the browser in real time, and it
resumes correctly if you reload mid-deploy. The new container only takes traffic
once it passes its healthcheck; one that never comes up is removed and the old
container keeps serving.

### Revisions & rollback

Every attempt recorded with status, image digest and its full log. Roll back to
an earlier revision with one click (the last five distinct images per service
are kept on hand, so it needs no rebuild), or turn on auto-rollback so an
unhealthy revision reverts itself.

### Image scanning

Every deploy is scanned for known vulnerabilities with Trivy before the workload
starts, on by default and never enforced unless you ask for it. An admin policy
can block deploys at or above a chosen severity, optionally fixable findings
only. The Security tab shows the findings by severity.

### Required status checks

A git-based service can refuse to build until its CI agrees: GitHub check runs,
GitLab pipelines, Gitea/Forgejo or Bitbucket statuses, read live for the exact
commit being deployed.

### Config as code

Commit a `.homerun.json` (or `.homerun.yaml`) next to your code and every deploy
applies it: port, env, resources, health check, build method, domains, login
wall, previews. For the whole instance, a Terraform/OpenTofu provider and
Pulumi, with state kept in one of your own buckets, a starter config written
from what’s already running, and drift detection.

### Stacks

Group services on one Docker network so they reach each other by slug, like
`http://api:8080`. Substacks nest inside, and a dependency diagram shows what
talks to what.

### A template catalog

Around 100 built-in apps (Immich, Jellyfin, Plex, the \*arr stack, Postgres,
Redis, Pi-hole, Grafana, Vaultwarden and the rest), each with its real logo
bundled in, so the gallery renders with no outbound internet. Quick Deploy skips
the wizard; a details page pulls the repo’s README, stars and latest release
from GitHub. Save any service of your own as a template too.

### Linked containers

A template can bring its companions along: WordPress ships linked to MySQL,
Umami to Postgres. `{{db}}` resolves to the companion’s hostname and
`{{db.POSTGRES_PASSWORD}}` to its own value, so the two agree on a password you
never typed.

### Compose import

Paste a `docker-compose.yaml` and get services, volumes and dependency order,
with a preview of whatever doesn’t map.

### Migrate from Dokploy or Coolify

Point `Settings → Migrate` at an existing Dokploy or Coolify instance and it
reads its apps, compose stacks and databases and recreates them here, unstarted
until you deploy them. Read-only against the other side; nothing there is
touched.

### Smart service links

Point a new service at an existing Postgres, MySQL, Redis, Mongo, RabbitMQ or
HTTP service and the connection URL fills itself in. Unlink it later with one
click.

### Logs & terminals

Tail stdout/stderr or open an interactive shell into a running container from
the browser, with uptime probes from the network and from the service’s own
hostname beside them. Machine terminals give you a shell on this server and
every remote host too, over SSH from Homerun’s worker.

### Monitoring

Requests, average response time, error rate, bandwidth, uptime, CPU and memory
per service, recorded from Traefik’s metrics every minute, from today back to
all time.

### Error tracking & tracing

Sentry-protocol compatible: point the official Sentry SDKs at Homerun and your
exceptions land on the service, grouped into issues, with source maps applied.
A built-in OpenTelemetry collector draws every span as a waterfall. One less
Sentry and one less Jaeger to host.

### Status pages

Build an uptime page from your services’ probes (every service you own, one
stack, or a hand-picked set) and publish it, unauthenticated, at
`/status/<slug>`. A public page shows only names, up/down and recent uptime,
never images, ports or hostnames.

### Domains & SSL

As many hostnames per service as you like, each optionally on its own container
port, plus bring-your-own cert and key for domains outside Traefik’s ACME
coverage. Every hostname belongs to exactly one thing, and a conflict is refused
with the owner named.

### Path-based routing

Send `example.com/api` to one service and `example.com` to another on the same
origin, with optional prefix stripping and a login wall scoped to the path.

### Redirects & error pages

Send a hostname, or a path under one, to another URL, answered by Traefik with
no container involved. And when an app is still starting or down, visitors get a
branded page that says so instead of a bare `404 page not found` or
`Bad Gateway`.

### Blocked paths & IP bans

Turn away the `.env`, `.git` and `wp-login.php` scanners before they reach the
app, ban repeat offenders, and push the bans to CrowdSec.

### Remote hosts & build cache

Register other Docker daemons over `tcp://`, `ssh://` (nothing to install but
sshd) or the lightweight Homerun Agent, then build images, run workstations or
run cron jobs on them. Point a build at a registry credential and it pulls the
last image as a layer cache and pushes the fresh layers back, so a repeat build
doesn’t start cold.

### A built-in registry

Turn the internal image mirror into a real private registry, `docker push`
included, with push/pull tokens and an optional public hostname. Your CI gets
somewhere to push without a Docker Hub account.

### Swarm mode by default

The installer sets the daemon up as a Docker Swarm manager, so every service
gets real replica scaling and load balancing out of the box, and more machines
join as workers with one command. `--docker=rootless` opts into the older,
standalone-only setup instead.

### Storage volumes

Define bind-mounts or Docker-managed volumes once, mount them into as many
services as you like. A database or cache gets one at its data directory
automatically.

### Object storage

S3 buckets without paying for a cloud: a built-in object store Homerun runs for
you, plus any S3-compatible provider you connect, with buckets, expiry and
public access managed from one page.

### Workstations

A dev box in the browser: code-server or openvscode-server with a persistent
home volume, your repository 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.

### Scheduled jobs & backups

Cron-style auto-redeploy per service. Cron jobs as a throwaway container, a Bun,
Node, Deno, Python or `sh` script, or a host command, here or on another host,
with output and exit codes kept per run. Scheduled volume backups to a named
destination, defined once and pointed at from as many volumes as you like: S3
(AWS, MinIO, R2, B2, Wasabi), SFTP, SMB or WebDAV.

### One Scheduling page

Every cron redeploy, cron job and backup schedule on the instance in one
read-only view, with the job queue underneath it: what’s running now, what’s
waiting, and how the last handful finished.

### Backup history & restore

One row per attempt across every volume, scheduled or manual, with the uploaded
size and the error if it failed. Searchable, filterable by outcome, and paged
all the way back. Browse a volume’s backups and restore one from the dashboard,
optionally wiping the volume first.

### REST API, OpenAPI, CLI & MCP

Everything the UI does is a typed JSON API at `/api/v1`, with live Swagger UI
and a `homerun` CLI built against the generated types. `homerun login` is a
device-code flow: approve it in the browser and the binary keeps its own API
key, and `homerun update` replaces itself. An MCP server lets an AI agent read
logs, deploys and settings, then fix, redeploy or roll back, with
credential-shaped values redacted.

### One-click self-update

Three release channels in settings: stable (tagged releases, the default),
canary (every build merged to `main` that passed the end-to-end tests) and
nightly (the same builds before the tests run, so expect breakage). The updater
boots the new version next to the running one first and only switches once it
answers; if it doesn’t, or the new version falls over after the switch, it
rolls back on its own. Traefik and Postgres are left alone, apps without a login
wall never notice, and no SSH session is needed.

### Users, roles & invites

Admin, developer, read-only, app-access-only and custom roles, email or
direct-create invites, and optional OAuth/OIDC login with one-click presets for
Pocket ID, Keycloak, Authelia, Authentik, Logto, Zitadel and Kanidm. Passkeys
and two-factor authentication, either one required instance-wide if you want.
Each account gets its own sessions list, revocable one by one, and its own API
keys.

### Service accounts

Non-human accounts for CI and scripts: no sign-in method, API keys as the 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.

### Sign in with Homerun

Homerun is also an OpenID Connect provider, so apps you host can offer “Sign in
with Homerun” on the same accounts as the dashboard (passkeys, two-factor and
sign-in methods included) instead of running Pocket ID or Keycloak just for
that.

### Per-service auth gate

Optionally require a Homerun login to reach a deployed service. Every container
is labelled `homerun.managed=true`, so it never touches anything it didn’t
create.

### DNS automation

Your domains’ records at 16 DNS providers (Cloudflare, Route 53, Google Cloud
DNS, Azure, Hetzner, Namecheap, GoDaddy, OVH and the rest) or as Pangolin
resources, created and removed as services come and go. Homerun can run the
Pangolin Newt tunnel client itself, set up straight from onboarding. No manual
cleanup when a domain changes.

### Docker cleanup

Host-wide `docker system df` and prune from the dashboard, with a preview
before anything is removed, plus automatic garbage collection of the scan
mirror.

### Search, filters & bulk actions

Server-side search, filters and paging on every list page, plus multi-select
start/stop/restart/delete with a typed confirmation before anything destructive
runs. `⌘K` anywhere opens a command palette that jumps to any dashboard page
and, after two characters, searches everything you own.

### Simple and advanced modes

Simple mode is a short click-ops sidebar for the homelab. Advanced mode is the
full engineering surface. Switching only changes what’s in view.

### Host metrics & self-diagnostics

Live CPU, memory, disk and GPU usage (with an NVIDIA card present) for the
host, alongside per-service CPU, memory and traffic, and a chart of host usage
over the last hour up to a year. Read-only checks run on every dashboard load
and any that fail become a banner that deep-links into the offending settings
field.

### System logs

Traefik’s own output streamed live, which is where a 404 on a service that
deployed fine, or a certificate that won’t issue, actually shows up. Admins can
restart or update the Traefik container from the same panel, without touching
the compose file.

### Errors that stick around

Anything Homerun logs at warn or error level about one of your services is
persisted and shown on that service, and the newest few sit on the dashboard. A
container’s own scrollback is no longer the only record of what went wrong.

### Notifications

A per-account bell for deploy succeeded or failed, service created, started or
stopped, an auto-redeploy firing, and runtime errors attributed to one of your
services. Click through to the service it happened to. Discord, Slack, Telegram,
generic webhook and email notification channels carry the same events outside
the dashboard, each with its own event matrix and a send-test button.

### Configured from the dashboard

A six-step first-run wizard, then `/settings` for the rest, stored in the
database and applied live with no restart. Three env vars genuinely can’t live
there (the database URL, `AUTH_SECRET` and `ORIGIN`), and the installer writes
all three. A `homerun.yaml` exists if you’d rather keep config as code, and is
entirely optional.

## An alternative to what, exactly

People arrive here from a specific frustration, usually a bill or a bug. So here
is where Homerun sits against the things it gets compared to, including where it
loses.

### Dokploy alternative

Dokploy keeps part of its code under its own source-available license and moved
features homelabbers relied on behind an enterprise plan. Homerun is MIT, all of
it, in one image: multi-node Swarm, roles and service accounts, previews, IaC,
backups, the API and the CLI. `Settings → Migrate` reads an existing Dokploy (or
Coolify) instance and recreates it here. Where it loses: Dokploy has a company,
a team and a far bigger community behind it, and its multi-server setup has
been run by far more people than mine. Homerun has one maintainer. If I stop,
it stops.

### Coolify alternative

Coolify does far more than this, and carries the tech debt and bug count of
doing far more than this. Homerun keeps the surface small enough that you can
actually read it, even with Swarm and multiple accounts turned on.

### Dokku & CapRover alternative

Dokku is a git push and an SSH session; CapRover is captain-definition files.
Homerun is a form in a browser with live build logs, a compose importer and a
web terminal.

### Google Cloud Run alternative

Container in, URL with TLS out, which is the part of Cloud Run most people
actually use. No scale-to-zero, no regions, no per-request billing, no console
with nine nested menus.

### AWS alternative

If ECS, App Runner or Elastic Beanstalk is running three side projects and an
invoice you don’t read, this replaces it with hardware you own. If you need
IAM, autoscaling groups and multi-region failover, it very much does not.

### Heroku, Render, Railway & Fly.io alternative

The same deploy-a-repo ergonomics, minus the seat pricing, the sleeping dynos
and the usage meter. Your build time costs electricity, not credits.

### Portainer alternative

Portainer manages containers that already exist. Homerun builds them, routes
them, gives them TLS certificates and redeploys them on a schedule, and labels
everything `homerun.managed=true` so it never touches what it didn’t create.

### Kubernetes alternative

No control plane to babysit, no YAML dialect, no 3am cluster archaeology. Docker
Swarm gives you real replica scaling by default; drop to standalone, one
container per service, if you’d rather not run rootful.

Since we’re being honest about search: people get here looking for a _Dokploy
alternative_, _Coolify alternative_, _Dokku alternative_, _CapRover
alternative_, _Cloud Run alternative_, _Google Cloud alternative_, _AWS
alternative_, _Heroku alternative_, _Vercel alternative_, _Netlify alternative_,
_Render alternative_, _Railway alternative_, _Fly.io alternative_, _DigitalOcean
App Platform alternative_, _Easypanel alternative_, _Portainer alternative_ or a
_Kubernetes alternative_ for one box. That is the list. It is a self-hosted
PaaS, it is MIT licensed, and it is free.

## Run it

### One-liner, fresh Linux server

```bash
curl -fsSL https://raw.githubusercontent.com/orochibraru/homerun/main/cmd/installer/bootstrap.sh \
  | sudo bash -s -- --mode=full --domain=homerun.example.com
```

That installs Docker Engine, sets it up as a **Swarm manager** so the instance
starts in swarm mode, writes a compose file, and brings up Traefik, Postgres,
the app and its worker from published images. Pass `--dry-run` first on a box
that matters, or `--docker=rootless` for a per-user rootless daemon instead
(standalone only, since rootless Docker can’t run Swarm). Use `--mode=agent` if
this host is only going to be a remote build server for another instance.

### Docker Compose

```bash
# already have Docker set up your way? just take the stack
curl -fsSLO https://raw.githubusercontent.com/orochibraru/homerun/main/compose.prod.yaml
curl -fsSLO https://raw.githubusercontent.com/orochibraru/homerun/main/.env.example
mv .env.example .env    # set AUTH_SECRET and ORIGIN
docker network create homerun
docker compose -f compose.prod.yaml up -d
```

`compose.prod.yaml` is self-contained and pulls Traefik, Postgres, the app and
its worker from published images. No installer, no rootless setup, no source
checkout. You fill in exactly two values: `AUTH_SECRET` (any long random
string, and never change it) and `ORIGIN`, the address you will actually reach
the dashboard at. It is never `localhost`, or the first sign-up fails with an
invalid origin from any browser that is not on the box.

Either way, that is the last file you touch. The first sign-in drops you into a
six-step wizard, and after that the base domain, Docker, Traefik, email,
sign-in methods and DNS automation are all pages in the dashboard, stored in the
database and applied live. Both paths are covered properly in the
[getting started guide](https://zedensix.com/homerun/docs/getting-started).

## Status

Actively developed and running on real hardware, but still finding its shape.
What’s solid and what isn’t is written down honestly in
[the FAQ and limitations doc](https://zedensix.com/homerun/docs/faq-and-limitations). Read it before
you point production at it. MIT licensed: fork it, read it, break it.
