[Unit] # The real service. Replaces mechcomp-placeholder.service, which existed only to # prove the nginx chain on CT 101 independently of the application # (STAGING-STATE.md, "Placeholder backend"). That proof is done and the # application now exists, so the placeholder is removed rather than left # competing for 10.20.0.10:8770. Description=Mechanical Compiler composer Documentation=https://gitea.barternetwork.us/TheRON/mechanical-compiler After=network-online.target Wants=network-online.target [Service] Type=simple User=mechcomp Group=mechcomp # Binding, base URL and everything else come from here. The unit deliberately # passes no --host or --port: the deployment declares those, not the command # line, and a flag here would silently outrank the file the operator edits. EnvironmentFile=/etc/mechcomp/mechcomp.env WorkingDirectory=/var/www/mechcomp ExecStart=/var/www/mechcomp/venv/bin/python -m mechcomp.web Restart=on-failure RestartSec=3 # Hardening, matching the set the placeholder already carried. NoNewPrivileges=yes PrivateTmp=yes PrivateDevices=yes ProtectSystem=strict ProtectHome=yes ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX RestrictNamespaces=yes LockPersonality=yes MemoryDenyWriteExecute=yes RestrictRealtime=yes RestrictSUIDSGID=yes RemoveIPC=yes # ProtectSystem=strict makes everything read-only except what is named here. # The composer writes nothing today; the data directory is listed because the # design record and any future artifact belong there and not in the working # tree, which is also the service user's home (F-029). ReadWritePaths=/var/lib/mechcomp StandardOutput=journal StandardError=journal SyslogIdentifier=mechcomp [Install] WantedBy=multi-user.target