[Unit] Description=JRay public server Documentation=https://gitea.tourolle.paris/dtourolle/JRay-public-server After=network-online.target Wants=network-online.target [Service] Type=exec ExecStart=/usr/bin/jray-server EnvironmentFile=/etc/jray-server/env # No user to create at install time: systemd allocates one for the lifetime of # the unit and remaps StateDirectory ownership to it, so the package ships no # useradd and leaves nothing behind on purge. DynamicUser=yes StateDirectory=jray-server StateDirectoryMode=0700 WorkingDirectory=/var/lib/jray-server # main.rs installs a SIGTERM handler that stops accepting, drains in-flight # requests and lets the cast-check worker finish its tick before exit. SIGTERM is # already systemd's default; this only gives it room to finish rather than being # killed mid-drain. TimeoutStopSec=30 Restart=on-failure RestartSec=5 # The binary is static (musl, bundled SQLite, bundled TLS roots). It opens one # database file under StateDirectory and makes outbound HTTPS calls to TMDB. It # needs nothing else, so everything else is denied. NoNewPrivileges=yes CapabilityBoundingSet= AmbientCapabilities= PrivateTmp=yes PrivateDevices=yes ProtectSystem=strict ProtectHome=yes ProtectProc=invisible ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes RestrictNamespaces=yes RestrictRealtime=yes RestrictSUIDSGID=yes # No AF_UNIX: musl resolves DNS itself from /etc/resolv.conf and the TLS roots # are compiled in (reqwest `rustls-tls` uses webpki-roots), so there is no NSS # socket and no CA bundle to read. A glibc build would need AF_UNIX added back. RestrictAddressFamilies=AF_INET AF_INET6 LockPersonality=yes MemoryDenyWriteExecute=yes SystemCallArchitectures=native SystemCallFilter=@system-service SystemCallFilter=~@privileged @resources UMask=0077 [Install] WantedBy=multi-user.target