version: '3.8' services: pushem: build: . ports: # Loopback-only by default so the backend can't be reached directly, # bypassing the optional Caddy proxy's TLS/security headers. # For direct LAN access (no proxy), change to "8080:8080". - "127.0.0.1:8080:8080" volumes: # Named volume: the Docker/Podman daemon initializes it with the image's # ownership (app user, UID 1000), so it works out of the box on rootful # Docker, rootless Podman, and fresh deployments. Unlike a bind mount, # which Docker auto-creates root-owned - unwritable by the non-root # container. # Reset all data (database + VAPID keys): docker compose down -v # If you need data on the host filesystem instead, use a bind mount and # prepare ownership first: # volumes: [ "./data:/app/data:Z" ] # mkdir -p data && sudo chown 1000:1000 data # Docker # (rootless Podman: use `podman unshare chown`, or add # userns_mode: keep-id to this service) - pushem-data:/app/data environment: - PORT=8080 - STATIC_DIR=../web/dist - CORS_ORIGINS=${CORS_ORIGINS:-http://localhost:*,https://localhost:*} # Secure default - VAPID_SUBJECT=${VAPID_SUBJECT} - MESSAGE_RETENTION_DAYS=${MESSAGE_RETENTION_DAYS:-7} # Keep messages for 7 days (default) - CLEANUP_INTERVAL_HOURS=${CLEANUP_INTERVAL_HOURS:-24} # Run cleanup every 24 hours (default) - SUBSCRIPTION_RETENTION_DAYS=${SUBSCRIPTION_RETENTION_DAYS:-30} # Prune subscriptions inactive for 30 days (default) - ADMIN_PASSWORD=${ADMIN_PASSWORD} # Admin panel password - ADMIN_TOKEN_EXPIRY_MINUTES=${ADMIN_TOKEN_EXPIRY_MINUTES:-60} # Token expiry (default: 60 min) - ADMIN_MAX_LOGIN_ATTEMPTS=${ADMIN_MAX_LOGIN_ATTEMPTS:-5} # Max login attempts (default: 5) - ADMIN_LOGIN_RATE_LIMIT_MINUTES=${ADMIN_LOGIN_RATE_LIMIT_MINUTES:-15} # Rate limit window (default: 15 min) - KEY_VERIFY_MAX_ATTEMPTS=${KEY_VERIFY_MAX_ATTEMPTS:-10} # Failed topic-key attempts before throttling (default: 10) - KEY_VERIFY_RATE_LIMIT_MINUTES=${KEY_VERIFY_RATE_LIMIT_MINUTES:-15} # Topic-key throttle window (default: 15 min) # Comma-separated CIDRs of reverse proxies whose X-Forwarded-For may be # trusted (e.g. the Docker network when using the Caddy service below). # Empty (default) = X-Forwarded-For is never trusted. - TRUSTED_PROXIES=${TRUSTED_PROXIES:-} command: sh -c "cd data && ../pushem" # Drop all Linux capabilities and prevent privilege escalation cap_drop: - ALL security_opt: - no-new-privileges:true restart: unless-stopped networks: - pushem-network # Optional Caddy reverse proxy with automatic HTTPS # Enable with: docker-compose --profile caddy up -d # Or for older Podman: Remove the "profiles:" section below and run: podman-compose up -d caddy: image: caddy:2-alpine profiles: - caddy # Remove this line if your Podman doesn't support profiles ports: - "80:80" - "443:443" - "443:443/udp" # HTTP/3 volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy-data:/data - caddy-config:/config restart: unless-stopped networks: - pushem-network depends_on: - pushem networks: pushem-network: driver: bridge volumes: pushem-data: caddy-data: caddy-config: