FAQ & limitations
Homerun is new. If you're used to another self-hosted PaaS, most of what you expect is here, but some things work differently and a few aren't built yet. This page is the honest list, so you find out here rather than halfway through moving your services over.
#Is this production-ready?
It's actively developed and runs on real hardware, but it's a single-maintainer project, and "production" here means your homelab or your own server. Keep backups, and take a Postgres dump before a major upgrade: migrations only run forward.
#Can several people share the same services?
Yes. Every account sees and manages every service, stack, volume, backup and the rest of the instance's resources, whoever created them. Sessions, API keys, preferences, git connections, the bell feed and notification channels stay personal. Homerun has no teams and no per-stack permissions: access is per area of the dashboard (services, stacks, DNS, settings and so on, 18 in all), each at read or write, and the roles are presets of that (admin, developer, read-only, plus a custom role where you pick the areas per user). An API key has the permissions you pick for it, never more than its account holds right now, and expires after 90 days unless you choose otherwise. Deleting an account hands what it created over to another admin. See Users and roles.
#Can it build an app without a Dockerfile?
Yes. Besides a Dockerfile or a Docker Bake file (both built with BuildKit), a
git-based service can be built with Nixpacks, Railpack, or Cloud Native
Buildpacks (Heroku or Paketo builders), picked as the build method in a
service's Environments & Deployments → Source section. A build clones a branch,
a tag or a specific commit, and pull requests can get their own preview
deployment. See Build methods.
#Can it deploy to more than one server?
Not the way you might expect. Services run on the machine Homerun is installed on. To spread a service across machines you turn on swarm mode and join the other machines to the swarm as workers. There's no "add a server and deploy to it" screen. Build servers only compile images, they never run services.
#Does it manage databases?
Not as a separate kind of resource. PostgreSQL, MySQL, Redis, MongoDB and others are templates deployed like any other service, get a data volume automatically so a redeploy doesn't wipe them, and service links fill in the connection URL for the apps that use them. Backups tar the database's volume while it runs, they don't run a dump tool, so read the backup warning below.
#Can I bring my existing services over?
Mostly. Settings → Migrate reads another instance's applications, compose
stacks and databases with an API token and recreates them here without touching
the original. Apps built with Nixpacks, Railpack or buildpacks come across with
the same builder, along with their start commands, Dokploy's private registry
credentials and file mounts; static build packs can't. Persistent storage isn't
always listed by the other side's API, so check volumes after importing. A
pasted compose file works too, including command, entrypoint, env_file,
labels, user, cap_add, devices and privileged; healthcheck, secrets and
configs are dropped with a warning. See
Importing a compose file.
#Docker stuck on a container
Rarely, the Docker daemon deadlocks on one container: docker inspect <id> and
docker rm -f <id> on it hang forever, while docker ps still lists it. It's a
bug in Docker, and only restarting the daemon clears it:
sudo systemctl restart dockerWhat you'd see before that:
- Sites routed by labels answer 404, while swarm services keep working. Traefik's Docker provider inspects every container before building routes, so one it can't inspect stalls all of them. The dashboard itself keeps answering when Homerun publishes its own route (the Traefik dynamic config directory under Settings → Networking, set by the installer), since that route doesn't go through the Docker provider.
- A backup or deploy fails with "Docker didn't answer for … the daemon may be stuck on container …" instead of running forever. Every Docker call the worker makes has a deadline, and a job with no progress for 15 minutes fails on its own (see The app and the worker to tune both).
- A notification and a dashboard banner saying Docker is stuck on a helper container, with its name. The worker cleans up its throwaway helper containers every 5 minutes; one Docker won't remove in time is reported instead of retried in a loop, and the report clears itself once Docker answers again.
After the restart, containers with a restart policy come back on their own; check the dashboard for anything that didn't.
#Known, real limitations (not hypothetical)
- The default install runs Docker as root. Swarm mode, the default, needs
the system Docker daemon because rootless Docker can't create overlay
networks, and anything that can reach that daemon's socket is root on the
host.
--docker=rootlesskeeps Docker under an unprivileged user at the cost of swarm (standalone mode only). A rootless install moves over with--migrate-to-rootful, see Getting started. - Swarm mode only sees this host's replicas. Per-replica usage, the Terminal tab and pre-backup commands only reach replicas running on this machine, and the uptime "from the network" probe doesn't run for swarm services.
- Swarm mode ignores privileged mode and devices and doesn't give a stack its own network. With several nodes, volumes are per node and locally built images need a build cache registry. See Swarm mode.
- A dropped swarm DNS alias can take up to 5 minutes to self-heal, and at most once an hour per service. Homerun's watch for this (see Swarm mode) only unit-tests the restart logic itself, it hasn't been run against a real alias drop on a live swarm; if a service can't reach another by slug right after a rolling update, that's the known window, not a new bug.
- The DNS providers haven't been tried against real accounts yet. Each is
built from its provider's documented API and tested against a stub of it;
Save and test on a connection lists its zones, the first real check.
Pangolin's has, live, against a real org and site, and passed. Every deploy
writes what each provider did into its log, so read the first one. Point
Pangolin at its Integration API (its own port, base path
/v1), not the dashboard's/api/v1. See DNS automation. - Deploy on push without a reachable dashboard polls every two minutes. A GitHub repo can't deliver a webhook to a dashboard only reachable on your LAN, so Homerun reads the branch head through the provider's API instead, which only works for GitHub, GitLab, Gitea and Bitbucket. Pull request previews still need the webhook.
- An app behind the login wall depends on the dashboard being up. Traefik asks Homerun about every request to it, so it refuses requests while Homerun itself is down; apps without the wall are served by Traefik directly and keep working. Turning the wall on or off redeploys the service. Removing someone at your identity provider is picked up within about five minutes when the app filters on groups and the provider issues refresh tokens, otherwise at their next sign-in or within eight hours. See Per-app login wall.
- Backups aren't paused for writes. A volume is tarred while its service keeps running, which can tear a database mid-write. Dump the database into a bind mount with a cron job and back that up instead. See Volume backups.
- Restoring a backup unpacks over the volume without wiping it or stopping anything. Stop the services using it first. See Volume backups.
- Non-S3 backup destinations are one stream, and SFTP skips host key checks. SFTP, SMB and WebDAV uploads are a single connection with no parallel parts, so they run at the speed of that one connection. SFTP does not verify the server's host key, and only unencrypted private keys are accepted. They were tested against generic OpenSSH, Samba and Apache WebDAV servers and against a real Hetzner Storage Box over all three. See Volume backups.
- A rollback only restores the image. Env vars, volumes and networking stay as they are now, and only the last 5 images of a service are kept on the host (configurable under Settings → Docker). Auto-rollback is off by default and replaces an unhealthy revision after it has taken traffic. See Revisions and rollback.
- Pruning volumes in Docker Cleanup deletes data, including volumes of services you've only stopped. Read the preview. See Docker Cleanup.
- Image scanning lets a deploy through when it couldn't finish, unless Fail deploys when the image can't be scanned is ticked under Settings → Docker. See Image scanning.
- Health-gated redeploys need a healthcheck to really gate. Without one the new container takes traffic as soon as it's been running a few seconds, and a service on host networking, or with a writable volume and no domain, still stops the old container first. See Deploying.
- Changing your own verified email needs SMTP configured, since the change
is confirmed from the current address. Without SMTP, an admin can change it
directly from
/users. See Your profile. - A direct-created account is a race without SMTP configured. It has no password until it's chosen one at its first sign-in, and without SMTP there's no code step proving who's asking, so anyone who knows the new account's email can set its password before its real owner does. See Users and roles.
- Every registry token can both push and pull. The built-in registry's htpasswd auth has no concept of scopes or read-only access without running a separate token server, so there's no pull-only credential to hand out. See Docker Registry.
- Publishing the registry through a real Traefik hostname hasn't been pushed
to yet. Only the container's own htpasswd auth was verified directly
(anonymous/wrong-password rejected, correct token accepted, a real
docker pushlanded in the catalogue); a push over a published hostname with a real certificate is untested. See Docker Registry.
The live backlog is TODO.md.
#Where do I report a bug or ask something not covered here?
Open an issue against the repo. If you're contributing code, read
CLAUDE.md and the .agents/notes/ it points to first.
This guide lives in the project repo: edit it there, and this page follows within a day.