[Unit] # Freezmo — production release (self-hosted study app). # # Runs the "current" release symlink: scripts/deploy.sh atomically flips it and # restarts this unit, so production only ever runs a pushed, verified commit. # Layout: ~/freezmo-prod/{releases/,current -> releases/,shared} # current/server/server.js standalone Next server (built by the deploy) # current/server/.env.local -> shared/env.local # current/server/.freezmo -> shared/freezmo (sync/, push/) # # Install (per user, no root needed): # mkdir -p ~/.config/systemd/user # cp ~/freezmo/deploy/freezmo.service ~/.config/systemd/user/ # systemctl --user daemon-reload # systemctl --user enable --now freezmo.service # loginctl enable-linger "$USER" # start at boot without logging in # Logs: journalctl --user -u freezmo -f Description=Freezmo (self-hosted study app, production) Documentation=file://%h/freezmo/README.md After=network-online.target Wants=network-online.target # In OLLAMA_AUTH=local mode the daemon should be up first (no-op otherwise). After=ollama.service [Service] Type=simple # The standalone server keeps its own cwd; the release carries shared env/data # as symlinks, and EnvironmentFile is the belt to that pair of braces. WorkingDirectory=%h/freezmo-prod/current/server Environment=NODE_ENV=production Environment=NEXT_TELEMETRY_DISABLED=1 Environment=PORT=3207 Environment=HOSTNAME=0.0.0.0 Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin EnvironmentFile=-%h/freezmo-prod/shared/env.local # Refuse to start without a release — clearer than next crashing in a restart # loop. Run scripts/deploy.sh (from %h/freezmo) first. AssertPathExists=%h/freezmo-prod/current/server/server.js ExecStart=/bin/node %h/freezmo-prod/current/server/server.js Restart=always RestartSec=3 TimeoutStartSec=0 [Install] WantedBy=default.target