feat: pivot systemd to standalone bare-metal mode v1.3.2
This commit is contained in:
13
VERSION.json
13
VERSION.json
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"version": "1.3.0",
|
||||
"last_build": "2026-04-11-1235",
|
||||
"version": "1.3.2",
|
||||
"last_build": "2026-04-11-1245",
|
||||
"commit": "PENDING",
|
||||
"changelog": [
|
||||
"v1.3.2: Systemd Standalone: Switched systemd service from Docker to bare-metal (Direct Python/Node management)",
|
||||
"v1.3.1: Systemd support added (Docker-compose based - DEPRECATED)",
|
||||
"v1.3.0: Dockerization: Dual-mode architecture, standalone Next.js, Python logger, and prod export script",
|
||||
"v1.2.9: Automatic IDE Entry Points (GEMINI.md, CLAUDE.md proxies)",
|
||||
"v1.2.8: Absolute Documentation Consolidation (Unified ARCHITECTURE and AI_RULES)",
|
||||
"v1.2.7: Documentation Refactor: Created TECH_STACK.md for SSOT and removed absolute paths",
|
||||
"v1.2.6: Hotfix - Added missing icon imports (Layers, ChevronDown)",
|
||||
"v1.2.5: Synchronized icons across UI (Layers for Categories, Package for Item Types)",
|
||||
"v1.2.4: Offline LDAP auth support and UI affordance improvements (Dropdown chevrons, soft password dots)",
|
||||
"v1.2.3: System-wide UI consistency (standardized font sizes, removed uppercase)"
|
||||
"v1.2.8: Absolute Documentation Consolidation (Unified ARCHITECTURE and AI_RULES)"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -218,3 +218,49 @@
|
||||
[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
|
||||
[2026-04-11 12:39:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:40:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:40:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:41:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:41:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:42:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:42:54] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:43:24] [INFO] [uvicorn.access] ::ffff:192.168.84.140:0 - "GET /items/ HTTP/1.1" 200
|
||||
[2026-04-11 12:43:28] [INFO] [uvicorn.error] Shutting down
|
||||
[2026-04-11 12:43:28] [INFO] [uvicorn.error] Waiting for application shutdown.
|
||||
[2026-04-11 12:43:28] [INFO] [uvicorn.error] Application shutdown complete.
|
||||
[2026-04-11 12:43:28] [INFO] [uvicorn.error] Finished server process [89006]
|
||||
[2026-04-11 12:43:29] [INFO] [ainventory] Database tables verified.
|
||||
[2026-04-11 12:43:29] [INFO] [ainventory] TFM aInventory API process started.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Started server process [89325]
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Waiting for application startup.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Application startup complete.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Shutting down
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Waiting for application shutdown.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Application shutdown complete.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Finished server process [89325]
|
||||
[2026-04-11 12:43:29] [INFO] [ainventory] Database tables verified.
|
||||
[2026-04-11 12:43:29] [INFO] [ainventory] TFM aInventory API process started.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Started server process [89332]
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Waiting for application startup.
|
||||
[2026-04-11 12:43:29] [INFO] [uvicorn.error] Application startup complete.
|
||||
[2026-04-11 12:43:30] [INFO] [uvicorn.error] Shutting down
|
||||
[2026-04-11 12:43:30] [INFO] [uvicorn.error] Waiting for application shutdown.
|
||||
[2026-04-11 12:43:30] [INFO] [uvicorn.error] Application shutdown complete.
|
||||
[2026-04-11 12:43:30] [INFO] [uvicorn.error] Finished server process [89332]
|
||||
[2026-04-11 12:43:31] [INFO] [ainventory] Database tables verified.
|
||||
[2026-04-11 12:43:31] [INFO] [ainventory] TFM aInventory API process started.
|
||||
[2026-04-11 12:43:31] [INFO] [uvicorn.error] Started server process [89341]
|
||||
[2026-04-11 12:43:31] [INFO] [uvicorn.error] Waiting for application startup.
|
||||
[2026-04-11 12:43:31] [INFO] [uvicorn.error] Application startup complete.
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Shutting down
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Waiting for application shutdown.
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Application shutdown complete.
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Finished server process [89341]
|
||||
[2026-04-11 12:43:32] [INFO] [ainventory] Database tables verified.
|
||||
[2026-04-11 12:43:32] [INFO] [ainventory] TFM aInventory API process started.
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Started server process [89361]
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Waiting for application startup.
|
||||
[2026-04-11 12:43:32] [INFO] [uvicorn.error] Application startup complete.
|
||||
[2026-04-11 12:43:37] [WARNING] [uvicorn.error] Invalid HTTP request received.
|
||||
[2026-04-11 12:43:37] [INFO] [uvicorn.access] ::ffff:127.0.0.1:0 - "POST /exa.language_server_pb.LanguageServerService/GetUnleashData HTTP/1.1" 404
|
||||
|
||||
@@ -22,6 +22,7 @@ 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 run_standalone.sh "$PROD_DIR/"
|
||||
cp install_service.sh "$PROD_DIR/"
|
||||
cp inventory.service.template "$PROD_DIR/"
|
||||
cp .git_path "$PROD_DIR/" 2>/dev/null || true
|
||||
|
||||
@@ -1,40 +1,43 @@
|
||||
#!/bin/bash
|
||||
# install_service.sh - Installs the inventory system as a systemd service
|
||||
# install_service.sh - Installs the inventory system as a standalone 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..."
|
||||
echo "⚙️ Installing TFM aInventory as a Standalone Linux 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."
|
||||
# 1. Dependency Checks
|
||||
echo "🔍 Checking dependencies..."
|
||||
for cmd in python3 node npm; do
|
||||
if ! command -v $cmd &> /dev/null; then
|
||||
echo "❌ $cmd not found! Please install it before proceeding."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# 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)"
|
||||
# 2. Setup Backend Environment
|
||||
echo "🐍 Setting up Python Virtual Environment..."
|
||||
if [ ! -d ".venv" ]; then
|
||||
python3 -m venv .venv
|
||||
fi
|
||||
source .venv/bin/activate
|
||||
pip install -q --upgrade pip
|
||||
pip install -q -r backend/requirements.txt
|
||||
|
||||
echo "✅ Found $COMP_VER at $DOCKER_CMD"
|
||||
# 3. Setup Frontend Environment
|
||||
echo "📦 Installing Node dependencies (this may take a minute)..."
|
||||
cd frontend
|
||||
npm install --quiet
|
||||
echo "🏗️ Building Frontend for Production (Next.js build)..."
|
||||
npm run build
|
||||
cd ..
|
||||
|
||||
# Create the final service file from template
|
||||
# 4. Create the final service file from template
|
||||
TEMPLATE="inventory.service.template"
|
||||
TARGET="/etc/systemd/system/inventory.service"
|
||||
|
||||
@@ -43,16 +46,20 @@ if [ ! -f "$TEMPLATE" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sed "s|__WORKING_DIR__|$WORKING_DIR|g; s|__DOCKER_BIN__|$DOCKER_CMD|g" "$TEMPLATE" > "$TARGET"
|
||||
sed "s|__WORKING_DIR__|$WORKING_DIR|g" "$TEMPLATE" > "$TARGET"
|
||||
|
||||
echo "📝 Service file created at $TARGET"
|
||||
|
||||
# Reload and enable
|
||||
# 5. Reload and enable
|
||||
systemctl daemon-reload
|
||||
systemctl enable inventory.service
|
||||
|
||||
# 6. Ensure scripts are executable
|
||||
chmod +x run_standalone.sh
|
||||
chmod +x start_server.sh
|
||||
|
||||
echo ""
|
||||
echo "🚀 TFM aInventory service installed and enabled!"
|
||||
echo "🚀 TFM aInventory Standalone service installed and enabled!"
|
||||
echo " Commands:"
|
||||
echo " 👉 sudo systemctl start inventory"
|
||||
echo " 👉 sudo systemctl status inventory"
|
||||
|
||||
@@ -6,8 +6,9 @@ Requires=docker.service
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=__WORKING_DIR__
|
||||
ExecStart=__DOCKER_BIN__ compose up --build
|
||||
ExecStop=__DOCKER_BIN__ compose down
|
||||
ExecStart=/bin/bash __WORKING_DIR__/run_standalone.sh
|
||||
# No explicit ExecStop needed as kill 0 in run_standalone handles it,
|
||||
# but systemd handles SIGTERM by default anyway.
|
||||
Restart=always
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
49
run_standalone.sh
Executable file
49
run_standalone.sh
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
# run_standalone.sh - Headless production launcher for TFM aInventory
|
||||
# manages Backend, Frontend, and SSL Proxies in a single process group.
|
||||
|
||||
echo "🚀 Starting TFM aInventory in Standalone Mode..."
|
||||
|
||||
# Trapping termination signals to clean up child processes
|
||||
trap "echo 'Stopping all processes...'; kill 0" SIGINT SIGTERM EXIT
|
||||
|
||||
# --- CONFIGURATION (Match start_server.sh) ---
|
||||
BACKEND_PORT=8000
|
||||
FRONTEND_PORT=3001
|
||||
BACKEND_SSL_PORT=3002
|
||||
FRONTEND_SSL_PORT=3003
|
||||
|
||||
# 1. Activate Environment
|
||||
if [ -d ".venv" ]; then
|
||||
source .venv/bin/activate
|
||||
fi
|
||||
|
||||
# 2. Start Backend (No Reload for Prod)
|
||||
echo "🔥 Starting Backend (Uvicorn)..."
|
||||
python3 -m uvicorn backend.main:app --host 0.0.0.0 --port $BACKEND_PORT &
|
||||
|
||||
# 3. Start Frontend (Production Start)
|
||||
echo "💻 Starting Frontend (Next.js Prod)..."
|
||||
cd frontend
|
||||
npm run start -- -p $FRONTEND_PORT &
|
||||
cd ..
|
||||
|
||||
# 4. Start Proxies (via npx)
|
||||
echo "🛡️ Starting HTTPS Proxies..."
|
||||
npx local-ssl-proxy --source $BACKEND_SSL_PORT --target $BACKEND_PORT --hostname 0.0.0.0 > /dev/null 2>&1 &
|
||||
npx local-ssl-proxy --source $FRONTEND_SSL_PORT --target $FRONTEND_PORT --hostname 0.0.0.0 > /dev/null 2>&1 &
|
||||
|
||||
# 5. Detection of IP for logs
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
LOCAL_IP=$(ipconfig getifaddr en0 || ipconfig getifaddr en1 || echo "localhost")
|
||||
else
|
||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✅ TFM aInventory is active at https://$LOCAL_IP:$FRONTEND_SSL_PORT"
|
||||
echo " Processes are running in background. Monitoring logs..."
|
||||
echo ""
|
||||
|
||||
# Wait for children
|
||||
wait
|
||||
Reference in New Issue
Block a user