The node API (leases, hour-long streams, batches of up to 256 MB JSON parsed in-process) shared the web process with the catalog API, Newznab and the web interface; voyager 1 had to make the same split on 2026-10-06. HTTP_ROUTES picks a process's routes (node, public, all by default): compose service node-api (same image, port 3335 on the compose network) serves the workers, web the rest. The workers' COORDINATOR_URL points at node-api; deploy.sh stops edge before recreating node-api. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
149 lines
4.1 KiB
YAML
149 lines
4.1 KiB
YAML
# Voyager 2 on homelab (deploy/README.md). deploy.sh copies this file to the
|
|
# deployment root (/mnt/bulk/usenet-rebuild), next to src/ (the code at the
|
|
# deployed commit), .env (credentials, tuning), pg/ and spool/; run
|
|
# `docker compose` there. Nothing is shared with voyager 1's compose project.
|
|
name: usenet-rebuild
|
|
|
|
x-app: &app
|
|
image: usenet-rebuild:latest
|
|
build:
|
|
context: ./src
|
|
target: app
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
environment: &app-env
|
|
NODE_ENV: production
|
|
HOST: 0.0.0.0
|
|
PORT: 3334
|
|
DB_HOST: postgres
|
|
DB_PORT: 5432
|
|
APP_URL: http://web:3334
|
|
SPOOL_DIR: /spool
|
|
volumes:
|
|
- ./spool:/spool
|
|
stop_grace_period: 60s
|
|
depends_on:
|
|
migrate:
|
|
condition: service_completed_successfully
|
|
|
|
services:
|
|
postgres:
|
|
image: postgres:17
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_USER: ${DB_USER}
|
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
POSTGRES_DB: ${DB_DATABASE}
|
|
volumes:
|
|
# Chunks (write-once payloads) on the HDD; the catalog in tablespace
|
|
# nvme, the database's default_tablespace (LOG.md 2026-10-09 (14)).
|
|
- ./pg:/var/lib/postgresql/data
|
|
- ${PG_NVME_DIR:-/var/lib/usenet-rebuild-catalog}:/var/lib/postgresql/nvme
|
|
# synchronous_commit = off is set with ALTER SYSTEM (postgresql.auto.conf in the data dir).
|
|
command:
|
|
- postgres
|
|
- -c
|
|
- shared_preload_libraries=pg_stat_statements
|
|
- -c
|
|
- shared_buffers=${PG_SHARED_BUFFERS:-2GB}
|
|
- -c
|
|
- max_wal_size=8GB
|
|
- -c
|
|
- checkpoint_timeout=15min
|
|
shm_size: 1g
|
|
stop_grace_period: 120s
|
|
healthcheck:
|
|
test: ['CMD-SHELL', 'pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"']
|
|
interval: 5s
|
|
retries: 30
|
|
|
|
migrate:
|
|
<<: *app
|
|
restart: 'no'
|
|
command: ['node', 'ace', 'migration:run', '--force']
|
|
volumes: []
|
|
depends_on:
|
|
postgres:
|
|
condition: service_healthy
|
|
|
|
# Catalog API, Newznab and the web interface.
|
|
web:
|
|
<<: *app
|
|
command: ['node', 'bin/server.js']
|
|
environment:
|
|
<<: *app-env
|
|
HTTP_ROUTES: public
|
|
ports:
|
|
- '3334:3334'
|
|
|
|
# The edge workers' API (leases, streams, batches), apart from the web
|
|
# interface: streams hold a connection up to an hour, batches of up to
|
|
# 256 MB are parsed in-process. Only the compose network reaches it.
|
|
node-api:
|
|
<<: *app
|
|
command: ['node', 'bin/server.js']
|
|
environment:
|
|
<<: *app-env
|
|
HTTP_ROUTES: node
|
|
PORT: 3335
|
|
|
|
# Prefetching (all NNTP connections), planning, the tail, merging, settling.
|
|
coordinator:
|
|
<<: *app
|
|
command: ['node', 'ace', 'coordinator:run']
|
|
environment:
|
|
<<: *app-env
|
|
NNTP_CONNECTIONS: ${NNTP_CONNECTIONS:-40}
|
|
|
|
# Phase 2's prober: reads the probe queue's articles over PROBE_CONNECTIONS
|
|
# connections of its own (next to the coordinator's 40 + 1; the account has 50).
|
|
prober:
|
|
<<: *app
|
|
command: ['node', 'ace', 'probe:run']
|
|
volumes: []
|
|
environment:
|
|
<<: *app-env
|
|
PROBE_CONNECTIONS: ${PROBE_CONNECTIONS:-6}
|
|
|
|
# The Rust worker; it has no NNTP account and talks to node-api only.
|
|
# Stopped before node-api (a worker holding a stream keeps the server from
|
|
# exiting).
|
|
edge:
|
|
image: usenet-rebuild-edge:latest
|
|
build:
|
|
context: ./src
|
|
target: edge
|
|
restart: unless-stopped
|
|
command: ['--threads', '${EDGE_THREADS:-8}']
|
|
environment:
|
|
COORDINATOR_URL: http://node-api:3335
|
|
NODE_TOKEN: ${NODE_TOKEN}
|
|
stop_grace_period: 60s
|
|
depends_on:
|
|
node-api:
|
|
condition: service_started
|
|
|
|
# The TypeScript worker, for comparing: docker compose --profile edge-ts up -d edge-ts
|
|
edge-ts:
|
|
<<: *app
|
|
profiles: [edge-ts]
|
|
command: ['node', 'ace', 'edge:node', '--processes', '${EDGE_THREADS:-8}']
|
|
environment:
|
|
<<: *app-env
|
|
COORDINATOR_URL: http://node-api:3335
|
|
depends_on:
|
|
node-api:
|
|
condition: service_started
|
|
|
|
# One-off ace commands: docker compose run --rm ace releases:duplicates
|
|
ace:
|
|
<<: *app
|
|
profiles: [tools]
|
|
restart: 'no'
|
|
entrypoint: ['node', 'ace']
|
|
command: ['list']
|
|
|
|
networks:
|
|
default:
|
|
name: usenet-rebuild
|