version: '3.8' services: finger: build: . # IMPORTANT: host networking is what lets the daemon's abuse protection # work. Under Docker's default bridge networking every external client is # SNAT'd to the bridge gateway (a 172.16/12 address), so the daemon sees a # single source IP for everyone -- the per-IP ban logic can't tell clients # apart and (by design) treats that private address as untrackable, leaving # banning inert. Host networking exposes the real client IP, so repeat # offenders actually get blocked. network_mode: host # Under host networking the container shares the host net namespace, which # uses the host's privileged-port rule -- so the image's non-root user # (UID 1000) cannot bind port 79 and the daemon fails to listen silently. # Run as root to bind it. (Alternative: setcap cap_net_bind_service on the # binary in the image to keep it non-root.) user: "0:0" # FINGER_BAN_ALLOWLIST: comma-separated client IPs that are never tracked or # banned. Use it for trusted aggregating front-ends — e.g. the finger-web # proxy, which funnels every federated lookup through one IP; without an # allowlist a burst from any single client of the proxy is attributed to the # proxy and bans it for everyone (per-client abuse protection for that path # lives in the proxy). Leave unset for a directly-exposed daemon. # environment: # - FINGER_BAN_ALLOWLIST=203.0.113.10,2001:db8::10 volumes: - ./users:/var/finger/users restart: unless-stopped healthcheck: test: ["CMD-SHELL", "nc -w 1 127.0.0.1 79 < /dev/null || exit 1"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Bridge-networking alternative (quick local testing only). NOTE: with this # mode the daemon only ever sees the bridge gateway IP, so abuse protection # is effectively disabled. Prefer host networking above for any public-facing # deployment. # finger: # image: ghcr.io/waffle2k/finger:latest # ports: # - "79:79" # volumes: # - ./users:/var/finger/users # restart: unless-stopped