Troubleshooting

Common Password Pusher Pro Self-Hosted Docker Compose and Podman boot issues—port binds and host remaps.

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

Common boot and networking issues when running Self-Hosted Pro. This page will grow over time. For day-to-day Compose commands, see Operations.


listen tcp :80: bind: permission denied

You may see a log line like:

Failed to start HTTP listener","error":"listen tcp :80: bind: permission denied"

What is going wrong

Compose port mappings such as "8095:80" only change how the host exposes the container. Inside the container, Thruster (the HTTP proxy in front of Rails) still tries to bind :80.

The Pro image runs as a non-root user (pwpush). Ports below 1024 are privileged:

Runtime Typical behavior
Rootful Docker Usually allows non-root processes to bind 80/443
Podman (especially rootless) Often denies bind on :80 — this error is common

Host ports already taken by other containers is a separate problem. Mapping "8095:80" already avoids that on the host. The permission error is about the in-container bind.

Listen on an unprivileged port inside the container, publish that to your host port, and override the healthcheck (the 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 host side of ports to whatever you need (for example "80:8080" if host 80 is free). The important part is that the right-hand (container) port matches HTTP_PORT and the healthcheck.

Recreate after changing env or ports:

docker compose up -d --force-recreate
# or the podman-compose equivalent

Alternative: keep container port 80

If you prefer the default internal port 80 (and your runtime allows it):

ports:
  - "8095:80"
sysctls:
  - net.ipv4.ip_unprivileged_port_start=0

or:

cap_add:
  - NET_BIND_SERVICE

On some rootless Podman hosts, sysctls and capabilities are restricted. In that case use HTTP_PORT=8080 as above.

Quick checks

Check Expectation
Log message listen tcp :80 is inside the container; host remap does not change it
HTTP_PORT Set to an unprivileged port (e.g. 8080) when bind on 80 is denied
Compose ports Right-hand port matches HTTP_PORT (e.g. "8095:8080")
Healthcheck If you set HTTP_PORT, override Compose healthcheck to match

Topic Doc
External TLS / proxy headers Behind a reverse proxy
Start / stop / logs Operations
Install runbook Getting started checklist
Overview Pro Self-Hosted