Self-hosted service
yusing/godoxy avatar
yusing/godoxy

GoDoxy: a self-hosted reverse proxy that reads your Docker labels

High-performance reverse proxy and container orchestrator for self-hosters

4,163 stars186 forksGoNOASSERTION

At a glance

What is it?
GoDoxy is a Go reverse proxy and container orchestrator aimed at self-hosters. It discovers Docker and Podman containers, turns labels into routes, and manages certificates and idle sleep from a WebUI.
Who is it for?
GoDoxy fits self-hosters who already run Docker Compose, want routes derived from container labels, and are willing to give the container host network mode and a mounted Docker socket. It is the wrong tool if you need a Kubernetes ingress controller, if you cannot grant that socket access, or if you want a proxy that never talks to the Docker daemon.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What GoDoxy solves for people running a stack of containers

The README describes GoDoxy as a lightweight reverse proxy with a WebUI, and the problem it targets is the bookkeeping that follows a growing Compose stack. Every new service means another hostname, another certificate, another entry in a config file that has to be reloaded. GoDoxy's answer is to treat the Docker daemon as the source of truth. The README's own summary of the mechanism is four steps: list all the containers, read container name, labels, and port configurations, create a route if applicable, then watch for container and config changes and update automatically. A route is described in the README as roughly equivalent to a Virtual Host in NPM, which is the comparison most self-hosters will reach for.

The audience is narrow and clearly stated: people running Docker or Podman on their own hardware, on Linux amd64 or arm64. The feature list points at the same person. Idle sleep stops and wakes Docker containers based on traffic, and there is a parallel implementation for Proxmox LXC containers. If you run a single static site behind Nginx, none of this is for you. If you run twenty containers and keep forgetting which subdomain points where, the label-driven model removes a class of mistakes.

How GoDoxy turns container labels into routes

The naming rule is the part worth internalising before you install anything. GoDoxy uses the label proxy.aliases as the subdomain, and if that label is unset it falls back to the container_name field in docker compose. The README gives a concrete example: with the label proxy.aliases: qbt, the app becomes reachable at qbt.domain.com. That fallback is convenient and also a trap. A container named postgres in your compose file will produce a route named postgres unless you override it, and the README does not describe any prompt or confirmation step before that happens.

Configuration can live in Docker labels or in route files, and the WebUI manages routes, config, containers, logs, metrics, and uptime. Certificates come from Let's Encrypt through DNS-01 providers, which is why the quick start insists on wildcard DNS records. The README gives both an A record example (*.domain.com pointing at 10.0.10.1) and an AAAA example, and notes that GoDoxy is designed to run in host network mode and that this should not be changed. Listening ports are changed through .env instead, where the example file sets GODOXY_HTTP_ADDR=:80 and GODOXY_HTTPS_ADDR=:443.

Beyond HTTP there is TCP and UDP port forwarding, OpenID Connect SSO, ForwardAuth integration such as TinyAuth, HTTP middlewares, and custom error pages. Access control covers IP and CIDR rules plus country and timezone rules, the latter requiring a MaxMind account. The Proxmox side adds a reverse lookup: routes bind automatically to a node when the hostname, IP, or alias matches a node name or IP, and to an LXC container when it matches that container. The README shows a routes entry with host pve-node-01.internal and port 8006 linking itself to the node pve-node-01.

Installing GoDoxy and getting a first route working

Wildcard DNS has to exist before anything else, because certificate issuance depends on it. Point *.domain.com at the machine running GoDoxy, and add the AAAA equivalent if you use IPv6.

The README's quick start is a setup script run inside an empty directory. It generates a compose.yml, a .env, and a config directory. The script is fetched over curl and piped to /bin/sh, so read it before running it if that pattern bothers you.

bash
/bin/sh -c "$(curl -fsSL https://raw.githubusercontent.com/yusing/godoxy/main/scripts/setup.sh)"

Then start the service from the generated compose file. The README expects this to come up cleanly, after which the WebUI is reachable at https://godoxy.yourdomain.com for further configuration.

bash
docker compose up -d

If you prefer not to run the script, the manual setup path is four wget commands. The README gives them as a single line for the config file, plus one each for .env and compose.yml.

bash
mkdir -p config && wget https://raw.githubusercontent.com/yusing/godoxy/main/config.example.yml -O config/config.yml
wget https://raw.githubusercontent.com/yusing/godoxy/main/.env.example -O .env
wget https://raw.githubusercontent.com/yusing/godoxy/main/compose.example.yml -O compose.yml

The .env.example file carries the settings you are most likely to edit. GODOXY_UID and GODOXY_GID must match the owner of the mounted directories. The API and WebUI credentials are GODOXY_API_USER and GODOXY_API_PASSWORD, and the example file states both are required unless OIDC is enabled or authentication is explicitly disabled. GODOXY_API_JWT_SECRET should be generated, and the example file suggests openssl rand -base64 32.

To add a service, give its container the proxy.aliases label and let GoDoxy pick it up. The README's example is the label proxy.aliases: qbt producing qbt.domain.com. After that, the container should appear as a route in the WebUI without a restart.

Host network mode, the Docker socket, and other things to accept

The most consequential constraint is stated plainly in the README: GoDoxy is designed to be running in host network mode, and you should not change it. That is a real cost. The container shares the host's network namespace, so port 80 and port 443 on the host belong to GoDoxy, and any other service that wants them has to move. It also means the isolation you get from a bridged network is gone. For a home server this is usually acceptable; on a shared machine it may not be.

Route discovery depends on reading container state, and the repository layout shows a socket-proxy directory alongside rootless-compose.example.yml and rootless.env.example, which suggests the project is aware of the socket-exposure question. The README itself does not document how to run GoDoxy without access to the Docker socket, so if you want a proxy that never talks to the daemon, this is not the design you are looking for.

The automatic naming fallback deserves a second mention as a failure mode rather than a feature. Because the container name becomes the subdomain when proxy.aliases is absent, a container that is not meant to be public can still get a route. The README does not describe a default-deny mode for discovery. Treat the label as opt-in-per-container and set it deliberately.

Finally, the country and timezone access rules require a MaxMind account. That is an external dependency and a data source you have to keep current, and the README lists it without describing the update path.

How GoDoxy differs from Traefik and Nginx Proxy Manager

Traefik also reads Docker labels, so the closest comparison is not about the mechanism but about the surrounding surface. Traefik's label model is built around routers, services, and middleware providers, and its configuration is largely declarative files plus labels. GoDoxy puts a WebUI in front of the same idea: the README lists routes, config, containers, logs, metrics, and uptime as things you manage from the interface, and it ships periodic access summaries. Traefik has a dashboard, but the operational centre of gravity is the config. If you want to click a container and read its logs, GoDoxy is closer to what you want. If you want one config format that also works for Kubernetes ingress, Traefik is the broader bet.

Nginx Proxy Manager is the other reference point, and the README itself uses NPM's vocabulary when it calls a route like a Virtual Host in NPM. The difference in approach is where routes come from. NPM is form-driven: you create a host in the UI and it writes the Nginx config. GoDoxy derives routes from container metadata and watches for changes, so the container is the unit of configuration. That is faster when containers come and go, and more surprising when a container name silently becomes a public hostname.

GoDoxy also reaches outside Docker in a way neither of those does, with Proxmox node and LXC discovery, lifecycle control, and log streaming over WebSocket. If your services live in LXC containers rather than Docker, that is the feature that decides it.

Licence, releases, and what upgrades cost

The repository's licence field reports NOASSERTION, which means GitHub could not map the LICENSE file to a known identifier. The LICENSE file exists at the top level, so the terms are written down, but you should open it and read it yourself rather than assume it is MIT or Apache-2.0. This is not legal advice, and the practical implication is narrow: if you plan to redistribute GoDoxy or bundle it into something you ship, resolve the licence question before you build on it. For running it on your own hardware the question matters much less.

Release cadence is visible in the tags: v0.31.0 on 2026-08-21, v0.31.1 on 2026-08-28, and v0.31.2 on 2026-09-10, with the last push to the default branch on 2026-09-10. Three releases inside a month at a 0.x version number is a signal about upgrade frequency. The .env.example exposes TAG with the values latest and nightly, so you can pin or track. The README documents an update path for the system agent, run through install-agent.sh with an update argument, and the same script with uninstall. It does not document a rollback procedure, so if a release breaks a route you are restoring from your own backup of the config directory rather than following a documented downgrade.

The folder structure in the README is worth noting for backup purposes: config holds config.yml, middlewares, and provider files, and data/metrics holds uptime.json and system_info.json. Those two directories are what you copy before an upgrade.

Building GoDoxy from source and where the build is unusual

The README's build instructions are short but they name a tool most Go developers will not have installed. After cloning with git clone --depth=1 and installing Go (the README says >=1.22, while go.mod declares go 1.27.0), the steps are go clean -cache if you built before under an older Go, then shadowtree mod-tidy for dependencies, then shadowtree build. shadowtree is a separate project by the same author, and the Dockerfile installs it with go install github.com/yusing/shadowtree/cmd/shadowtree@latest.

The build is not a plain go build. The Dockerfile stages a Bun and Node toolchain to build the webui directory, and go.mod carries a long replace block pointing at internal copies of go-oidc, gopsutil, and several goutils packages, plus a local agent module. That means the module graph is not the upstream one you would get from a normal dependency resolution. If you vendor or mirror dependencies for compliance reasons, budget time for those replacements. The Dockerfile also notes that the webui build pulls from oven/bun:1-alpine and node:lts-alpine3.22, so an air-gapped build needs those images available locally.

Editorial conclusion

GoDoxy fits self-hosters who already run Docker Compose, want routes derived from container labels, and are willing to give the container host network mode and a mounted Docker socket. It is the wrong tool if you need a Kubernetes ingress controller, if you cannot grant that socket access, or if you want a proxy that never talks to the Docker daemon. Before adopting it, verify three things on your own host: that wildcard DNS resolves to the machine, that your UID and GID match the mounted directories, and that the generated compose.yml starts cleanly with docker compose up -d.

Frequently asked questions

What is a Docker proxy, and is GoDoxy one?

GoDoxy is a reverse proxy that also reads the Docker daemon to discover containers and build routes from their names and labels. The README describes the flow as listing containers, reading name, labels, and ports, creating a route if applicable, then watching for changes.

Can I use Nginx as a proxy in Docker instead of GoDoxy?

Yes, Nginx can run in a container as a reverse proxy, but it does not discover Docker containers on its own. GoDoxy's stated design is to read container labels and container names and create routes automatically, which Nginx requires you to write and reload by hand.

Does GoDoxy have to run in host network mode?

The README states that GoDoxy is designed to be running in host network mode and instructs you not to change it. Listening ports are changed through .env instead, where GODOXY_HTTP_ADDR and GODOXY_HTTPS_ADDR are defined.

How does GoDoxy decide what subdomain a container gets?

It uses the label proxy.aliases as the subdomain, and if that label is unset it falls back to the container_name field in docker compose. The README's example is the label proxy.aliases: qbt, which makes the app reachable at qbt.domain.com.

What licence is GoDoxy released under?

The repository reports the licence as NOASSERTION, meaning GitHub could not match the LICENSE file to a known identifier. The LICENSE file is present at the top level, so the terms are written down and should be read directly.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. yusing/godoxy on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/yusing-godoxy.svg)](https://hysenlabs.com/projects/yusing-godoxy)