Repository navigation
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
107 lines (104 loc) · 4.32 KB
/
Copy pathdocker-compose.yml
File metadata and controls
107 lines (104 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# Run Signet: one binary, one database — plus an optional browser sidecar.
#
# docker compose up -d # app + database, on http://localhost:8000
# docker compose logs -f app
# docker compose pull && docker compose up -d # upgrade to a newer image
# docker compose down # add -v to drop the database volume too
#
# The app image is pulled from GHCR; nothing here builds from source, so this
# file works as-is on a NAS or a PaaS that has no toolchain. To run a build of
# your working tree instead, tag it under the same name and select it:
#
# docker build -t ghcr.io/flthibaud/signet:local .
# SIGNET_TAG=local docker compose up -d
#
# The browser sidecar for anti-bot fetching is opt-in, since it pulls a full
# browser image (see the `solver` service at the bottom).
#
# Note for devcontainer users: nothing here publishes 5432, so this stack can run
# alongside the devcontainer's own Postgres without a port clash.
services:
db:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_DB: signet
POSTGRES_USER: signet
POSTGRES_PASSWORD: signet
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U signet -d signet"]
interval: 5s
timeout: 5s
retries: 10
app:
image: ghcr.io/flthibaud/signet:${SIGNET_TAG:-latest}
restart: unless-stopped
# The app writes nothing to disk — the frontend is embedded in the binary and
# all state lives in Postgres — so it runs unprivileged (USER in the
# Dockerfile) on a read-only root filesystem. /tmp stays writable as a tmpfs
# because the Go runtime and the HTTP stack may spill there.
read_only: true
tmpfs:
- /tmp:size=64m
security_opt:
- no-new-privileges:true
environment:
PORT: ${PORT:-8000}
ENV: ${ENV:-production}
DATABASE_URL: ${DATABASE_URL:-postgres://signet:signet@db:5432/signet?sslmode=disable}
AUTO_MIGRATE: ${AUTO_MIGRATE:-true}
SCHEDULER_INTERVAL: ${SCHEDULER_INTERVAL:-15m}
SCHEDULER_WORKERS: ${SCHEDULER_WORKERS:-5}
SCHEDULER_BATCH_SIZE: ${SCHEDULER_BATCH_SIZE:-50}
# Idle timeout: the expiry slides forward while a session is in use.
SESSION_TTL: ${SESSION_TTL:-720h}
# Closed by default; the first account is created before the door shuts.
REGISTRATION_ENABLED: ${REGISTRATION_ENABLED:-false}
RATE_LIMITER_RPS: ${RATE_LIMITER_RPS:-5}
RATE_LIMITER_BURST: ${RATE_LIMITER_BURST:-10}
RATE_LIMITER_ENABLED: ${RATE_LIMITER_ENABLED:-false}
# Only sent over HTTPS; 0 disables it.
HSTS_MAX_AGE: ${HSTS_MAX_AGE:-31536000}
# Set to true only to subscribe to feeds on your own network.
FETCH_ALLOW_PRIVATE_NETWORKS: ${FETCH_ALLOW_PRIVATE_NETWORKS:-false}
TLS_IMPERSONATE_ENABLED: ${TLS_IMPERSONATE_ENABLED:-true}
# Empty unless you enable the solver profile below.
SOLVER_URL: ${SOLVER_URL:-}
SOLVER_TIMEOUT: ${SOLVER_TIMEOUT:-60s}
SOLVER_MAX_PER_FEED: ${SOLVER_MAX_PER_FEED:-5}
ports:
- "${APP_BIND:-127.0.0.1}:${PORT:-8000}:${PORT:-8000}"
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:${PORT:-8000}/v1/readiness >/dev/null || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
# Browser sidecar for sites that require executing a JavaScript challenge.
# Opt-in: it is a full browser (hundreds of MB) and most sites are handled by
# the impersonated TLS client alone.
#
# echo 'SOLVER_URL=http://solver:8191/v1' >> .env
# docker compose --profile solver up -d
#
# It is deliberately not published to the host: it fetches arbitrary URLs on
# request, and the app reaches it over the compose network by service name.
solver:
image: ghcr.io/thephaseless/byparr:latest
profiles: ["solver"]
restart: unless-stopped
environment:
TZ: ${TZ:-Europe/Paris}
# A real browser needs more shared memory than Docker's 64 MB default.
shm_size: 2gb
# No healthcheck on purpose: Byparr's /health drives a real page load, which
# is far too expensive to run on a loop for a service nothing depends on.
# Check it by hand when needed:
# docker compose exec app wget -qO- http://solver:8191/health
volumes:
postgres-data: