Container Ports

Which ports the Pro Self-Hosted Docker image binds inside the container, and how to override them.

This article applies to: Pro Self-Hosted (Docker Compose / Podman)

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)

  1. Assign your domain in Billing and point DNS at the host.
  2. Run your personalized install command (TLS_DOMAIN is written into .env).
  3. 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

  1. Unset TLS_DOMAIN in .env.
  2. Point the proxy upstream at container port 80 (or your HTTP_PORT).
  3. 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