Legendary Arena Lab

Systemd Service

wiki

Systemd Service

Migration in progress. api.legendary-arena.com and its PostgreSQL are moving off Render onto a self-hosted DigitalOcean Ubuntu droplet fronted by Cloudflare, per docs/PLAN.md . Until decommission, Render stays warm as the rollback target.

Summary

The la-server systemd unit is the supervisor that keeps the Legendary Arena application running on the droplet. It orders startup after PostgreSQL, loads the environment file, runs the app through an fnm-pinned Node, and restarts it on failure and after reboot.

Mechanics

The owning artifact is infra/systemd/la-server.service . Broken down by unit section:

  1. [Unit]After=network.target postgresql.service orders the service to start once the network and PostgreSQL are up; Wants=postgresql.service makes the database a soft dependency (desired, not strictly required).
  2. [Service] — runs as User=operator / Group=operator with WorkingDirectory=/opt/legendary-arena. It loads EnvironmentFile=/etc/la/.env. ExecStart invokes the app through the fnm-pinned runtime: /opt/fnm/fnm exec 24.18.0 pnpm --filter @legendary-arena/server start. Restart=on-failure with RestartSec=5 gives a 5-second backoff, and TimeoutStopSec=30 allows 30 seconds for graceful shutdown before a kill.
  3. [Install]WantedBy=multi-user.target enables the service at normal multi-user boot.
[Service]
Type=simple
User=operator
Group=operator
WorkingDirectory=/opt/legendary-arena
EnvironmentFile=/etc/la/.env
ExecStart=/opt/fnm/fnm exec 24.18.0 pnpm --filter @legendary-arena/server start
Restart=on-failure
RestartSec=5
TimeoutStopSec=30

Systemd is chosen over PM2 because it is native to the box, survives reboot, and routes logs to journald; the migration replaces the original PM2 process model with this unit, per docs/PLAN.md .

Interactions

Edge Cases

  • EnvironmentFile=/etc/la/.env must exist and be readable (mode 600); if it is missing the service fails to start — see Secrets and Env .
  • ExecStart hard-codes the fnm path /opt/fnm/fnm and Node 24.18.0, so the node-runtime step must have installed exactly that path and version or the unit cannot launch.
  • After=postgresql.service assumes a co-located database on the same box; a remote-DB topology would not satisfy this ordering as written.
  • On reboot — for example after an unattended upgrade — systemd brings the service back via WantedBy=multi-user.target, which is why reboot survival ties to Fail2ban and Unattended Upgrades .

References