From 4a4034420dc132f63fe3dd85d3433e14f0816374 Mon Sep 17 00:00:00 2001 From: Michael Pilosov Date: Thu, 23 Apr 2026 20:04:31 -0600 Subject: [PATCH] web: systemd user service for uvicorn on :8000 (make prod) Adds `make prod` (no --reload) as the service entrypoint, mirrors the worker unit under deploy/, and splits the makefile service targets into `worker-*` / `web-*` with the install scaffolding factored into a macro. --- deploy/dr-sandbox-web.service.in | 16 +++++++ makefile | 79 ++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 deploy/dr-sandbox-web.service.in diff --git a/deploy/dr-sandbox-web.service.in b/deploy/dr-sandbox-web.service.in new file mode 100644 index 0000000..b59ff1e --- /dev/null +++ b/deploy/dr-sandbox-web.service.in @@ -0,0 +1,16 @@ +[Unit] +Description=dr-sandbox web app (uvicorn, port 8000) +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +WorkingDirectory=@ROOT@ +ExecStart=@ROOT@/.venv/bin/python -m uvicorn app.web.main:app --host 0.0.0.0 --port 8000 +Restart=on-failure +RestartSec=5 +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=default.target diff --git a/makefile b/makefile index 250a060..98eb204 100644 --- a/makefile +++ b/makefile @@ -4,6 +4,9 @@ run: web: .venv/bin/python -m uvicorn app.web.main:app --host 0.0.0.0 --port 8001 --reload +prod: + .venv/bin/python -m uvicorn app.web.main:app --host 0.0.0.0 --port 8000 + demo: .venv/bin/python -m uvicorn app.demo.main:app --host 0.0.0.0 --port 8010 --reload @@ -11,48 +14,64 @@ compile: uv pip compile pyproject.toml -o requirements-frozen.txt # ------------------------------------------------------------------------ -# systemd user service — persistent equivalent of `make run` (the Prefect -# worker for the embedding_flow deployment). User-scope, no sudo needed. +# systemd user services. User-scope, no sudo needed. +# worker-* — Prefect worker for the embedding_flow deployment (make run) +# web-* — uvicorn web app on :8000 (make prod) # ------------------------------------------------------------------------ -SERVICE_NAME := dr-sandbox-worker.service -SERVICE_DIR := $(HOME)/.config/systemd/user -SERVICE_PATH := $(SERVICE_DIR)/$(SERVICE_NAME) -SERVICE_TMPL := deploy/dr-sandbox-worker.service.in +SERVICE_DIR := $(HOME)/.config/systemd/user -.PHONY: service-install service-uninstall service-start service-stop service-restart service-status service-logs +WORKER_NAME := dr-sandbox-worker.service +WORKER_TMPL := deploy/dr-sandbox-worker.service.in +WORKER_PATH := $(SERVICE_DIR)/$(WORKER_NAME) -service-install: +WEB_NAME := dr-sandbox-web.service +WEB_TMPL := deploy/dr-sandbox-web.service.in +WEB_PATH := $(SERVICE_DIR)/$(WEB_NAME) + +define install_service @mkdir -p $(SERVICE_DIR) - sed 's|@ROOT@|$(CURDIR)|g' $(SERVICE_TMPL) > $(SERVICE_PATH) + sed 's|@ROOT@|$(CURDIR)|g' $(1) > $(2) systemctl --user daemon-reload - systemctl --user enable --now $(SERVICE_NAME) - systemctl --user restart $(SERVICE_NAME) + systemctl --user enable --now $(3) + systemctl --user restart $(3) @echo - @echo "installed $(SERVICE_NAME) -> $(SERVICE_PATH)" - @echo " status: make service-status" - @echo " logs: make service-logs" + @echo "installed $(3) -> $(2)" + @echo " status: make $(4)-status" + @echo " logs: make $(4)-logs" @loginctl show-user $$USER 2>/dev/null | grep -q "Linger=yes" || \ echo " linger: sudo loginctl enable-linger $$USER # to survive logout / reboot" +endef -service-uninstall: - -systemctl --user disable --now $(SERVICE_NAME) - -rm -f $(SERVICE_PATH) +.PHONY: worker-install worker-uninstall worker-start worker-stop worker-restart worker-status worker-logs +.PHONY: web-install web-uninstall web-start web-stop web-restart web-status web-logs + +worker-install: + $(call install_service,$(WORKER_TMPL),$(WORKER_PATH),$(WORKER_NAME),worker) + +worker-uninstall: + -systemctl --user disable --now $(WORKER_NAME) + -rm -f $(WORKER_PATH) -systemctl --user daemon-reload - @echo "removed $(SERVICE_NAME)" + @echo "removed $(WORKER_NAME)" -service-start: - systemctl --user start $(SERVICE_NAME) +worker-start: ; systemctl --user start $(WORKER_NAME) +worker-stop: ; systemctl --user stop $(WORKER_NAME) +worker-restart: ; systemctl --user restart $(WORKER_NAME) +worker-status: ; systemctl --user status $(WORKER_NAME) +worker-logs: ; journalctl --user -u $(WORKER_NAME) -f -service-stop: - systemctl --user stop $(SERVICE_NAME) +web-install: + $(call install_service,$(WEB_TMPL),$(WEB_PATH),$(WEB_NAME),web) -service-restart: - systemctl --user restart $(SERVICE_NAME) - -service-status: - systemctl --user status $(SERVICE_NAME) - -service-logs: - journalctl --user -u $(SERVICE_NAME) -f +web-uninstall: + -systemctl --user disable --now $(WEB_NAME) + -rm -f $(WEB_PATH) + -systemctl --user daemon-reload + @echo "removed $(WEB_NAME)" +web-start: ; systemctl --user start $(WEB_NAME) +web-stop: ; systemctl --user stop $(WEB_NAME) +web-restart: ; systemctl --user restart $(WEB_NAME) +web-status: ; systemctl --user status $(WEB_NAME) +web-logs: ; journalctl --user -u $(WEB_NAME) -f