Compile the API instead of running its TypeScript in production.
The unit's ExecStart named src/index.ts, so every start depended on the host having Node 22.18 or newer for native type stripping. A deploy onto a host with Node 20 met ERR_UNKNOWN_FILE_EXTENSION, exited in under a second, and was restarted 464 times over fifteen hours with nothing anywhere going red. api/tsconfig.json now emits to api/dist. The source keeps its explicit .ts import specifiers, which is what makes `node --watch src/index.ts` work in development; rewriteRelativeImportExtensions turns them into .js on the way out, so what runs in production is ordinary ESM that any Node from 20.18 up will start. `pnpm build` builds shared, then api, then web. `pnpm dev` is unchanged. deploy/ is tracked rather than ignored: the unit files are the thing an operator copies to /etc/systemd/system, and the alert unit added next has to live somewhere a deploy can find it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
06ba3d35e7
commit
65307ba278
@@ -0,0 +1,56 @@
|
||||
# /etc/systemd/system/cashumints.service
|
||||
[Unit]
|
||||
Description=cashumints.space indexer and API
|
||||
Wants=network-online.target
|
||||
After=network-online.target
|
||||
# Stop after five failures in a minute rather than restarting forever. A wrong Node on
|
||||
# PATH once produced four thousand identical crashes in the journal before anyone read
|
||||
# one of them; `failed` in `systemctl status` says the same thing in one line. Both keys
|
||||
# belong to [Unit] — under [Service] systemd only warns and ignores them.
|
||||
StartLimitIntervalSec=60
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=cashumints
|
||||
Group=cashumints
|
||||
WorkingDirectory=/home/cashumints/CashuMints.space/api
|
||||
|
||||
# StateDirectory creates /var/lib/cashumints with the service user's ownership.
|
||||
StateDirectory=cashumints
|
||||
Environment=NODE_ENV=production
|
||||
Environment=PORT=8788
|
||||
Environment=DB_PATH=/var/lib/cashumints/cashumints.db
|
||||
Environment=ICON_DIR=/var/lib/cashumints/icons
|
||||
|
||||
# Compiled JavaScript, run by the distribution's own node.
|
||||
#
|
||||
# This line used to read `src/index.ts`, which made every start depend on the host
|
||||
# having Node 22.18 or newer for native type stripping. A host with Node 20 answered
|
||||
# that with ERR_UNKNOWN_FILE_EXTENSION in under a second, 464 times over fifteen hours,
|
||||
# and nothing anywhere went red. `pnpm build` now emits api/dist, so what runs here is
|
||||
# ordinary ESM and any Node from 20.18 up will start it.
|
||||
#
|
||||
# Deliberately /usr/bin/node and nothing else: an nvm or fnm path is invisible to this
|
||||
# unit's ProtectHome and breaks silently at the next version bump.
|
||||
ExecStart=/usr/bin/node --env-file-if-exists=../.env dist/index.js
|
||||
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
KillSignal=SIGTERM
|
||||
TimeoutStopSec=30s
|
||||
UMask=0027
|
||||
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=read-only
|
||||
ReadWritePaths=/var/lib/cashumints
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user