Docs
Domains & TLS
Traefik routing, Let's Encrypt, wildcards, middlewares and free smoke hosts.
Attach a domain
On any application or compose service: Domains → add host, path, container port, HTTPS. Nixploy writes Traefik dynamic config — you do not hand-edit container labels. A service joins the shared, Traefik-facing network only while it has at least one domain, and the attachment is reconciled on every domain change.
- The container port is the port your app listens on inside the container. An empty port is the number-one cause of 502s, so the form requires it
- Internal path rewrites the prefix — public /public/* can reach the container as /internal/*
- A host is one namespace for the whole instance: a host another organization already routes is refused, so nobody can hijack a route
Certificates
- Let's Encrypt (HTTP-01) when the panel / service has a real DNS name
- Let's Encrypt (DNS-01) for wildcard hosts — configure a DNS provider under Settings → Platform → Wildcard certificates
- Custom certificates uploaded under Settings → Certificates
- None / HTTP-only for internal smoke tests
New Let's Encrypt domains are capped at 20 per organization per hour: the instance shares one ACME account, so hosts that do not resolve burn the whole box's budget. Wildcard rows (*.apps.example.com) are instance-admin only — Nixploy cannot prove an organization owns the parent zone, and a wildcard swallows every unclaimed subdomain of it. Traefik reads DNS-01 provider credentials from its own environment, and saving them pushes them to the proxy for you — the panel diffs the current environment first, because applying a change recreates the proxy's task and that is a few seconds of downtime for every routed domain.
HTTPS is per domain
There is no entrypoint-level HTTP → HTTPS redirect any more: it overrode every domain's own toggle. A domain with HTTPS on gets a per-router redirect middleware; a domain with HTTPS off is served plain on :80, which is what the toggle was always supposed to mean. The panel's own router stays HTTPS-only.
Middlewares
Every domain — application or compose — carries an ordered list of Traefik middlewares, typed and validated by the panel (no raw YAML).
- Rate limit (429 over the burst) and IP allow-list (403 outside the CIDRs)
- Headers: custom request/response headers, HSTS, CORS — Host and X-Forwarded-* stay proxy-owned and are rejected
- Compression, sticky sessions, and maintenance mode (serve a maintenance page without touching DNS or the certificate)
- Forward auth for an SSO proxy such as Authentik or Authelia
- Redirects and basic auth are available on compose services too, per compose-file service
Chain order is internal-path rewrite → app-wide redirects → basic auth → the domain's middlewares. Disabling a row keeps it stored but leaves it out of the rendered YAML, and the chain is reloaded on every deploy so a deploy no longer wipes it.
TCP and UDP
A domain is an HTTP route by default. Set its Protocol to TCP or UDP and Traefik forwards the raw stream on a dedicated entrypoint instead — see TCP & UDP routing.
traefik.me
Generate a free *.traefik.me host for local or quick demos (it resolves to 127.0.0.1 — use it for smoke tests, not for production Let's Encrypt).
Panel access
Settings → Platform → Access: set the dashboard domain and Let's Encrypt email. Once a dashboard domain is configured the low-priority catch-all router is dropped, so the panel answers on its own host only instead of on every hostname pointed at the box. Traefik's config viewer and restart live under Proxy.
Diagnose a route
A host answers 502 or 404 and the service says it is running. The stethoscope on the domain row (also nixploy domain diagnose and the get_domain_diagnosis MCP tool) walks the request path in order and names the fix at each step: DNS, the Traefik route file, a second file claiming the same host, the upstream task, the shared-network attachment, the container port (a throwaway busybox on the overlay), Traefik's own answer for the host, and the certificate. Deterministic — no model involved.
DNS records created for you
Link a DNS provider once (Settings → Platform → DNS provider — the same link wildcard certificates use) and switch on Create DNS records automatically. From then on, attaching a domain — by hand, through the API or CLI, or with a template deploy — also creates the host's A record in the matching zone at the provider, pointing at the server's public IPv4. An existing record that points elsewhere is updated; a round-robin set is left alone; a host no zone contains is skipped and says so. Forty providers are offered for DNS-01; eight of them — Cloudflare, DigitalOcean, Gandi LiveDNS, Hetzner DNS, Linode, Porkbun, Spaceship and Vultr — also have a record client. The rest are certificates-only, and the panel says so.
The write never fails the domain: the row and the route exist either way, and the response carries a dns outcome the panel toasts and nixploy domain add prints. Retry on demand with the globe button on the domain row, nixploy domain ensure-dns, or domain.ensureDnsRecord — which also creates the record for a domain attached while the switch was off. Check link on the settings card lists the zones the stored credentials see. Records are never deleted when a domain is removed.
External upstreams
An external upstream is an HTTP origin outside the Swarm — the host your old panel still runs on, a SaaS endpoint — that Traefik fronts like a service: domains, Let's Encrypt, middlewares and uptime probes attach to it the same way. Add one from the project page (Add service → External upstream) with a target such as https://old-host.example.com, attach the hostnames, and point DNS at Nixploy once: every hostname keeps answering from the old host through the new proxy, and each workload moves behind its hostname when it is ready.
- The target is an origin only (scheme, host, port); path rewrites live on the domain's internal path.
- Pass the public Host header (default) for a reverse-proxied app; turn it off for a SaaS origin that must see its own hostname.
- Bare names, cluster-internal addresses, cloud metadata, the panel's own host and the server's own address are refused; a LAN target needs private egress enabled under Settings → Platform.
- The target is re-checked hourly. One that stops passing has its route withheld until it passes again (Re-check now on its page); one that merely stops resolving is left alone.
HTTP only — a TCP/UDP row on an upstream is refused — and not yet part of the nixploy.yaml manifest.
Also see the repository guides under docs/ · REST API reference
