$ aoox

DocsInfrastructure

Proxy & domain

Turning on the Traefik reverse proxy, pointing domains at applications, automatic HTTPS from Let's Encrypt, and checking DNS.

Proxy
Traefik v3, the aoox-proxy container
HTTPS
Let's Encrypt HTTP-01 automatic per host, or your own certificate
Scope
The aoox host and each remote server

One request's flow

  1. 01browserhttps://app.example.com
  2. 02DNSA record → server IP
  3. 03Traefik :443the <app>-secure router, ACME certificate
  4. 04containerthe aoox network → :<container port>

Traefik uses the docker provider: it reads labels on application containers and only exposes the ones with a label (exposedbydefault=false). There's no configuration file to edit — aoox writes the labels when a container is created.

Provisioning the reverse proxy

Traefik runs per daemon: one on the aoox host, and optionally one on each remote server with its own port and ACME email. The steps below are for the host.

  1. Make sure ports 80/443 are free on the host

    ss -ltnp | grep -E ':80 |:443 '   # should be empty

    The ports can be changed via PROXY_HTTP_PORT / PROXY_HTTPS_PORT in .env.dist, but Let's Encrypt HTTP-01 needs port 80 and browsers expect 443.

  2. Set PROXY_ACME_EMAIL (for HTTPS)

    .env.dist
    PROXY_ACME_EMAIL=you@example.com
    PROXY_ACME_STAGING=false     # true while testing, to avoid the rate limit

    Without an email, Traefik runs without an ACME resolver: domains are served over http only and the HTTPS toggle in the UI is disabled. Changing this value after provisioning → remove the proxy then provision it again.

  3. Settings → Reverse proxy (Traefik) → provision (owner)

    The aoox-proxy container is created on the aoox network with the aoox_proxy_acme volume for certificates. The card shows a Running status and whether ACME is active.

Adding a domain to an application

  1. Point DNS

    DNS
    app.example.com.   A      203.0.113.10
    # or
    app.example.com.   CNAME  server.example.com.

    DNS can be set up later — aoox doesn't block on it. But a certificate can only be issued once DNS is correct.

  2. Application page → Domain tab → add

    Fill in the Hostname (app.example.com, no scheme/path) and turn on HTTPS if the proxy has ACME. The container is recreated with the new Traefik label — no build. One application can have several hostnames.

  3. Clear the Host port (recommended)

    With a domain, a host port isn't needed; clearing it enables blue/green deploys and closes off direct IP:port access.

  4. Check DNS

    The DNS check button on the domain row compares the resolved result with the expected IP — PUBLIC_IP if set, auto-detected via ipify (cached 10 minutes), or the remote server's host:

    BadgeMeaningAction
    okPoints at this server.—
    mismatchResolves to a different IP.Fix the A/CNAME record; wait out the TTL.
    unresolvedNo record yet.Create the record with your DNS provider.
    ?The server's public IP is unknown.Set PUBLIC_IP in .env.dist (server behind NAT/Cloudflare).

When another container already uses the domain

If a container on the same daemon already routes the host (typically a leftover of a project deleted on an older version, or another stack), two routers answer for it and requests are split between them. The Domain tab shows a warning on that domain naming the container, and adding the domain returns the same information. Nothing is blocked. When the container is a leftover, the warning points to the Docker page (Details), where the owner can remove it. The deployment log also notes it.

How HTTPS works

RouterEntrypointCreated whenDoes
<app>web (:80)AlwaysServes http for hosts without HTTPS
<app>-securewebsecure (:443)When HTTPS is onTLS via the le certresolver
<app>-redirectweb (:80)HTTPS on + ACME set up301 http → https
  • A certificate is requested via HTTP-01 the first time the host is reached; Let's Encrypt must be able to reach port 80 on the server from the internet. Traefik renews it automatically.
  • The http → https redirect is only created when ACME is active, so that without PROXY_ACME_EMAIL (dev) a host is still reachable over http, rather than redirected to Traefik's self-signed certificate.
  • A container that becomes unhealthy is automatically dropped from the router (404) — that's what the health check is for.

Behind Cloudflare

  • The DNS check shows mismatch because the hostname resolves to a Cloudflare IP — ignore it if it's proxied on purpose. When issuing a certificate for the first time, set the record to DNS only first so HTTP-01 can reach the server, then switch proxying back on.
  • Cloudflare's SSL mode must be Full (strict) so the origin is served over Traefik's HTTPS; Flexible mode causes a redirect loop with the -redirect router.

Don't want Let's Encrypt? Upload your own certificate (corporate CA, wildcard, Cloudflare Origin CA) and pick it per domain on the Domain tab — see Custom SSL certificates. It applies to application domains; the panel's domains keep using ACME.

Need basic auth, security headers, rate limiting, an IP allowlist or a www redirect for a domain? Write your own Traefik middleware (or use a preset) and attach it per domain on the Domain tab — see Proxy configuration.

Operations

ActionEffect
Maintenance modeShow a 503 page on all of an application's domains without stopping it — see Applications.
Remove a domainThe container is recreated without that host's label; the certificate stays on the ACME volume.
Toggle HTTPSThe container is recreated; the -secure/-redirect routers are added/removed.
Remove the proxy (owner)All domains stop being served; application containers aren't touched. You'll be asked about the ACME volume.
Change PROXY_ACME_EMAIL / portChange .env.dist → remove the proxy → provision it again.

Notes

  • Applications on a remote server use that server's own proxy: provision it from the server card (port + ACME email), then point DNS at that server's IP — see Remote servers. Without a proxy there, use a host port instead.
  • Compose stacks use a domain per service — see Compose stacks. A compose file can also carry its own traefik.* labels, as long as it joins the aoox network.
  • The domain for the aoox panel itself is set via env, not the Domain tab — see Domain for the panel.
  • Local dev uses ports 8088/8443 (80 is often taken); production uses 80/443. Don't mix values between environments.

Common pitfalls

SymptomCause & fix
Domain tab: Proxy not runningProvision it in Settings first.
HTTPS toggle disabledPROXY_ACME_EMAIL was empty at provision time. Fill it in, remove the proxy, provision again.
404 page not found from TraefikThe container isn't healthy yet, or the domain was added but the container hasn't been recreated (check the deploy log).
Self-signed certificate / TRAEFIK DEFAULT CERTACME failed: DNS isn't correct yet, port 80 is closed, or a rate limit was hit. Check the aoox-proxy container's log in the terminal; test with PROXY_ACME_STAGING=true.
Redirect loopCloudflare in Flexible mode, or another reverse proxy in front terminating TLS. Use Full (strict), or turn off HTTPS in aoox.
Works via IP:port but not via the domainA host port still being set isn't a problem — check DNS and that the proxy is Running.
Not available yet
www ↔ apex redirects; path/prefix routing; basic auth per domain. A certificate that fails to issue is now reported via notifications. Wildcard certificates (DNS-01) and automatic DNS records are available with a Cloudflare connection — see Cloudflare DNS.

Next steps

Found a mistake? Edit this page on GitHub ↗