From d87067e88c149e3b4ff0c422561219dc94e86ab4 Mon Sep 17 00:00:00 2001 From: Daniel Bedeleanu Date: Sat, 11 Apr 2026 12:39:38 +0300 Subject: [PATCH] feat: add systemd service template and installer for production 1.3.1 --- backend/logs/backend.log | 46 ++++++++++++++++++++++++++++ export_prod.sh | 6 ++++ install_service.sh | 62 ++++++++++++++++++++++++++++++++++++++ inventory.service.template | 16 ++++++++++ 4 files changed, 130 insertions(+) create mode 100755 install_service.sh create mode 100644 inventory.service.template diff --git a/backend/logs/backend.log b/backend/logs/backend.log index 89d1d01d..bfb221c0 100644 --- a/backend/logs/backend.log +++ b/backend/logs/backend.log @@ -172,3 +172,49 @@ [2026-04-11 12:31:35] [INFO] [uvicorn.error] Waiting for application startup. [2026-04-11 12:31:35] [INFO] [uvicorn.error] Application startup complete. [2026-04-11 12:31:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:32:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:32:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:33:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:33:36] [WARNING] [uvicorn.error] Invalid HTTP request received. +[2026-04-11 12:33:36] [INFO] [uvicorn.access] ::ffff:127.0.0.1:0 - "POST /exa.language_server_pb.LanguageServerService/GetUnleashData HTTP/1.1" 404 +[2026-04-11 12:33:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:34:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:34:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:35:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:35:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:36:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:36:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:37:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:37:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:38:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:38:37] [WARNING] [uvicorn.error] Invalid HTTP request received. +[2026-04-11 12:38:37] [INFO] [uvicorn.access] ::ffff:127.0.0.1:0 - "POST /exa.language_server_pb.LanguageServerService/GetUnleashData HTTP/1.1" 404 +[2026-04-11 12:38:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 +[2026-04-11 12:39:03] [INFO] [uvicorn.error] Shutting down +[2026-04-11 12:39:03] [INFO] [uvicorn.error] Waiting for application shutdown. +[2026-04-11 12:39:03] [INFO] [uvicorn.error] Application shutdown complete. +[2026-04-11 12:39:03] [INFO] [uvicorn.error] Finished server process [88490] +[2026-04-11 12:39:04] [INFO] [ainventory] Database tables verified. +[2026-04-11 12:39:04] [INFO] [ainventory] TFM aInventory API process started. +[2026-04-11 12:39:04] [INFO] [uvicorn.error] Started server process [88972] +[2026-04-11 12:39:04] [INFO] [uvicorn.error] Waiting for application startup. +[2026-04-11 12:39:04] [INFO] [uvicorn.error] Application startup complete. +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Shutting down +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Waiting for application shutdown. +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Application shutdown complete. +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Finished server process [88972] +[2026-04-11 12:39:05] [INFO] [ainventory] Database tables verified. +[2026-04-11 12:39:05] [INFO] [ainventory] TFM aInventory API process started. +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Started server process [88982] +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Waiting for application startup. +[2026-04-11 12:39:05] [INFO] [uvicorn.error] Application startup complete. +[2026-04-11 12:39:06] [INFO] [uvicorn.error] Shutting down +[2026-04-11 12:39:06] [INFO] [uvicorn.error] Waiting for application shutdown. +[2026-04-11 12:39:06] [INFO] [uvicorn.error] Application shutdown complete. +[2026-04-11 12:39:06] [INFO] [uvicorn.error] Finished server process [88982] +[2026-04-11 12:39:07] [INFO] [ainventory] Database tables verified. +[2026-04-11 12:39:07] [INFO] [ainventory] TFM aInventory API process started. +[2026-04-11 12:39:07] [INFO] [uvicorn.error] Started server process [89006] +[2026-04-11 12:39:07] [INFO] [uvicorn.error] Waiting for application startup. +[2026-04-11 12:39:07] [INFO] [uvicorn.error] Application startup complete. +[2026-04-11 12:39:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200 diff --git a/export_prod.sh b/export_prod.sh index f62fe1d7..8ec4ccca 100755 --- a/export_prod.sh +++ b/export_prod.sh @@ -22,6 +22,8 @@ rsync -a --exclude '__pycache__' --exclude '.pytest_cache' --exclude '.venv' bac cp docker-compose.yml "$PROD_DIR/" cp Caddyfile "$PROD_DIR/" cp start_server.sh "$PROD_DIR/" +cp install_service.sh "$PROD_DIR/" +cp inventory.service.template "$PROD_DIR/" cp .git_path "$PROD_DIR/" 2>/dev/null || true cp VERSION.json "$PROD_DIR/" @@ -41,6 +43,10 @@ TO RUN VIA DOCKER (Recommended): 3. Run: docker-compose up -d 4. Access via https://:3003 (Accept the internal security warning). +TO INSTALL AS A LINUX SYSTEM SERVICE (Optional): +1. sudo ./install_service.sh +2. sudo systemctl start inventory + TO RUN BARE-METAL (No Docker): 1. Install Python 3.12+ and Node.js 20+. 2. Ensure you have network access for npm installs. diff --git a/install_service.sh b/install_service.sh new file mode 100755 index 00000000..630b4cc5 --- /dev/null +++ b/install_service.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# install_service.sh - Installs the inventory system as a systemd service + +if [[ $EUID -ne 0 ]]; then + echo "🚫 This script must be run as root (use sudo)" + exit 1 +fi + +echo "⚙️ Installing TFM aInventory as a Systemd service..." + +# Detect working directory +WORKING_DIR="$(pwd)" + +# Detect Docker binary +DOCKER_BIN=$(which docker) +if [ -z "$DOCKER_BIN" ]; then + echo "❌ Docker not found! Please install Docker first." + exit 1 +fi + +# Determine if we use 'docker compose' or legacy 'docker-compose' +if docker compose version >/dev/null 2>&1; then + DOCKER_CMD="$DOCKER_BIN" + COMP_VER="v2 (plugin)" +else + DOCKER_BIN=$(which docker-compose) + if [ -z "$DOCKER_BIN" ]; then + echo "❌ neither 'docker compose' nor 'docker-compose' found!" + exit 1 + fi + DOCKER_CMD="$DOCKER_BIN" + COMP_VER="v1 (legacy)" +fi + +echo "✅ Found $COMP_VER at $DOCKER_CMD" + +# Create the final service file from template +TEMPLATE="inventory.service.template" +TARGET="/etc/systemd/system/inventory.service" + +if [ ! -f "$TEMPLATE" ]; then + echo "❌ Template file $TEMPLATE not found in current directory!" + exit 1 +fi + +sed "s|__WORKING_DIR__|$WORKING_DIR|g; s|__DOCKER_BIN__|$DOCKER_CMD|g" "$TEMPLATE" > "$TARGET" + +echo "📝 Service file created at $TARGET" + +# Reload and enable +systemctl daemon-reload +systemctl enable inventory.service + +echo "" +echo "🚀 TFM aInventory service installed and enabled!" +echo " Commands:" +echo " 👉 sudo systemctl start inventory" +echo " 👉 sudo systemctl status inventory" +echo " 👉 sudo systemctl stop inventory" +echo "" +echo "Note: The service is currently ENABLED to start on boot, but NOT started." +echo " Run 'sudo systemctl start inventory' to launch it now." diff --git a/inventory.service.template b/inventory.service.template new file mode 100644 index 00000000..7c225b07 --- /dev/null +++ b/inventory.service.template @@ -0,0 +1,16 @@ +[Unit] +Description=TFM aInventory Docker Stack +After=docker.service +Requires=docker.service + +[Service] +Type=simple +WorkingDirectory=__WORKING_DIR__ +ExecStart=__DOCKER_BIN__ compose up --build +ExecStop=__DOCKER_BIN__ compose down +Restart=always +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target