-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathreceiver.service
More file actions
53 lines (50 loc) · 2.97 KB
/
Copy pathreceiver.service
File metadata and controls
53 lines (50 loc) · 2.97 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
# UNTESTED EXAMPLE (DES-WORKER-ON-HOST) -- a starting point, not a shipped, verified unit. Adapt it.
#
# The receiver runs on the HOST as the public edge: it verifies GitHub deliveries and enqueues jobs.
# Requires node >=22.19.0 on PATH for User=pi -- or pin an absolute `ExecStart=/usr/bin/node ...`.
# This is a Linux/systemd unit. The worker ships cross-platform daemon artifacts under deploy/
# (com.pi-dispatch.worker.plist for launchd, nssm-install.cmd for Windows); receiver daemonization is
# out of scope, but a launchd/nssm receiver would follow the same .env-wrapper pattern those use.
#
# NAT / tunnel: the receiver binds `RECEIVER_BIND` (default 0.0.0.0) and must be reachable by GitHub's
# webhook delivery. On a home machine behind NAT, put it behind a tunnel (cloudflared / ngrok /
# tailscale funnel) or a reverse proxy with TLS -- do not port-forward it raw without one.
# `WEBHOOK_SECRET` is what authenticates deliveries; without a public URL GitHub cannot deliver.
#
# Env vars come from your `.env` (see `.env.example`) via EnvironmentFile -- never commit real secrets.
# WorkingDirectory / EnvironmentFile / User / node path below are PLACEHOLDERS: set them to wherever
# you cloned the repo and whoever owns it.
[Unit]
Description=pi-dispatch webhook receiver (public edge: verifies GitHub deliveries and enqueues jobs)
After=network-online.target
Wants=network-online.target
# Crash-loop bound: at most StartLimitBurst restarts within StartLimitIntervalSec, then systemd stops
# trying. The worker unit has carried this since it shipped; the receiver did not, and the gap is not
# cosmetic -- the receiver is the process that dies on a triggers file it cannot parse, and it dies on
# EVERY start. Pairs with Restart=on-failure below.
#
# This bounds CRASH loops (a process dying in milliseconds), not transient outages (issue #318): a
# transient identity failure at boot retries INSIDE the process for RECEIVER_IDENTITY_RETRY_SECONDS
# (default 600, floored at 60 -- see .env.example) before exiting 1, so a retrying boot exits at most
# once per window and can never place StartLimitBurst starts inside this interval. Keep these values
# and widen the env key instead: raising the burst here would only re-open the crash-loop hole.
StartLimitIntervalSec=60
StartLimitBurst=5
[Service]
Type=simple
User=pi
WorkingDirectory=/opt/pi-dispatch
EnvironmentFile=/opt/pi-dispatch/.env
ExecStart=/usr/bin/node receiver/src/start.mjs
Restart=on-failure
RestartSec=5
# Exit 2 is EXIT_POLICY: a determinate config refusal (a triggers file that cannot parse, a missing
# secret), not infra. Never restart it -- the next start reads the same file and fails the same way, so
# the loop is pure noise with a five-second period and no end. Only infra failures are worth a restart,
# and Restart=on-failure already covers those.
RestartPreventExitStatus=2
# The receiver handles SIGTERM: it closes the HTTP server and the queue connection, then exits.
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.target