Container Ports
Which ports the Pro Self-Hosted Docker image binds inside the container, and how to override them.
Open source Password Pusher? Ports differ. OSS commonly uses application port 5100. See OSS Container Ports.
Pro Self-Hosted images (registry.apnotic.com/pwpush-pro, -advanced, -enterprise) put a built-in HTTP proxy in front of the application. That proxy provides HTTP/2, optional Let’s Encrypt TLS, asset caching, and compression. The public edge is 80 / 443 — not the OSS 5100 port.
Default ports inside the container
| Port | Layer | Role |
|---|---|---|
| 80 | Built-in HTTP proxy | Public HTTP listener (HTTP_PORT) |
| 443 | Built-in HTTP proxy | Public HTTPS listener (HTTPS_PORT) when TLS_DOMAIN is set |
The application listens on an internal port behind that proxy. It is not published and is not port 5100. Compose healthchecks probe http://localhost:80/up (the built-in proxy’s HTTP port).
Client / reverse proxy
│
▼
Built-in HTTP proxy (:80 / :443) ← public edge (override with HTTP_PORT / HTTPS_PORT)
│
▼
Application (internal only) ← not published; do not use OSS port 5100
Important: Compose mappings such as "8095:80" only change how the host reaches the container. They do not stop the built-in proxy from binding :80 inside the container unless you set HTTP_PORT.
Do not add 5100:5100 for Pro. That mapping is for the open-source image. See Migrate from OSS to Pro if you are switching editions.
Environment variables
These control the built-in HTTP proxy (they are not Admin → Settings keys). You can optionally prefix any of them with THRUSTER_ (for example THRUSTER_HTTP_PORT); the prefixed form wins if both are set.
| Variable | Description | Default in Pro image |
|---|---|---|
TLS_DOMAIN |
Domain(s) for automatic Let’s Encrypt certificates. Usually set by install.sh to your licensed hostname. If unset, the proxy serves HTTP only (no cert provisioning). |
Set at install (your domain) |
HTTP_PORT |
Port the built-in proxy listens on for HTTP | 80 |
HTTPS_PORT |
Port the built-in proxy listens on for HTTPS (used when TLS_DOMAIN is set) |
443 |
FORWARD_HEADERS |
Whether the built-in proxy forwards inbound X-Forwarded-* to the application |
On when TLS_DOMAIN is unset; off when TLS_DOMAIN is set. See Behind a reverse proxy. |
Other .env values (SECRET_KEY_BASE, encryption keys, HOST_PROTOCOL, …) are separate — see Backups and Configuration.
Common setups
Automatic TLS in the container (default install)
- Assign your domain in Billing and point DNS at the host.
- Run your personalized install command (
TLS_DOMAINis written into.env). - Publish 80 and 443 so certificate issuance and HTTPS work.
ports:
- "80:80"
- "443:443"
Browse to https://your-licensed-hostname. See Getting started checklist.
Behind your own reverse proxy
- Unset
TLS_DOMAINin.env. - Point the proxy upstream at container port 80 (or your
HTTP_PORT). - Send
X-Forwarded-*headers.
Full steps: Behind a reverse proxy.
# TLS_DOMAIN unset in .env
ports:
- "127.0.0.1:80:80"
# - "443:443" # not needed when the proxy owns TLS
Change the public HTTP port (Podman, rootless, or bind denied)
The built-in proxy still defaults to :80. That fails when the process cannot bind privileged ports—common with rootless Podman, locked-down runtimes, or some host-network setups:
Failed to start HTTP listener","error":"listen tcp :80: bind: permission denied"
Set an unprivileged HTTP_PORT, publish that container port, and override the healthcheck (image default probes http://localhost:80/up):
services:
pwpush-pro:
image: registry.apnotic.com/pwpush-pro:latest
env_file:
- .env
environment:
HTTP_PORT: "8080"
volumes:
- pwpush-pro-data:/opt/PasswordPusher/storage
ports:
- "8095:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/up"]
interval: 30s
timeout: 3s
restart: unless-stopped
volumes:
pwpush-pro-data:
driver: local
Match the right-hand Compose port and the healthcheck to HTTP_PORT. Recreate after changes:
docker compose up -d --force-recreate
Step-by-step for this error: Troubleshooting.
Alternative: keep container port 80
If your runtime allows it:
sysctls:
- net.ipv4.ip_unprivileged_port_start=0
# or
cap_add:
- NET_BIND_SERVICE
On some rootless hosts those options are blocked; use HTTP_PORT instead.
Quick reference
| Goal | What to set / publish |
|---|---|
| Let’s Encrypt inside the container | TLS_DOMAIN + host ports 80 and 443 |
| HTTP only / external TLS | Unset TLS_DOMAIN; proxy or publish 80 (or your HTTP_PORT) |
Avoid privileged bind on :80 |
HTTP_PORT ≥ 1024 (e.g. 8080) + matching publish/healthcheck |
| Coming from OSS examples | Use 80, not 5100 |
| Wrong URLs / headers behind a proxy | Behind a reverse proxy |
Related
| Topic | Doc |
|---|---|
| Install & first login | Getting started checklist |
| External TLS / proxy headers | Behind a reverse proxy |
| Bind permission denied | Troubleshooting |
| Kubernetes Ingress | Deploy on Kubernetes |
| OSS ports (5100) | OSS Container Ports |
| Overview | Pro Self-Hosted |