# BamBuddy Systemd Service Template
#
# INSTALLATION:
# 1. Copy this file to /etc/systemd/system/bambuddy.service
# 2. Replace placeholders:
#    - INSTALL_PATH: Where BamBuddy is installed (e.g., /opt/bambuddy)
#    - SERVICE_USER: User to run as (e.g., bambuddy)
#    - DATA_DIR: Data directory (e.g., /opt/bambuddy/data)
#    - LOG_DIR: Log directory (e.g., /opt/bambuddy/logs)
# 3. Run: sudo systemctl daemon-reload
# 4. Run: sudo systemctl enable bambuddy
# 5. Run: sudo systemctl start bambuddy
#
# Or use the install script: ./install/install.sh
#

[Unit]
Description=BamBuddy - Bambu Lab Print Management
Documentation=https://github.com/maziggy/bambuddy
After=network.target

[Service]
Type=simple
User=SERVICE_USER
Group=SERVICE_USER
WorkingDirectory=INSTALL_PATH

# Environment file (optional - created by install script)
EnvironmentFile=-INSTALL_PATH/.env

# Use virtual environment
Environment="PATH=INSTALL_PATH/venv/bin:/usr/local/bin:/usr/bin:/bin"

# Server configuration
# --loop asyncio is required: uvloop's SSL layer can silently truncate VP FTP
# uploads on a ragged client close over slow storage (#1896). Do not remove.
#
# --timeout-graceful-shutdown is also required. Uvicorn's default is to wait
# forever for in-flight requests, and an MJPEG camera stream is a response that
# never completes — one open camera tile would hang the stop until systemd gave
# up and SIGKILLed, skipping the WAL checkpoint, the MQTT disconnect and the
# virtual-printer teardown entirely. On timeout uvicorn cancels the request
# tasks; the camera generators unwind cleanly on CancelledError.
ExecStart=INSTALL_PATH/venv/bin/uvicorn backend.app.main:app --host 0.0.0.0 --port ${PORT:-8000} --loop asyncio --timeout-graceful-shutdown 5

# Restart policy
Restart=on-failure
RestartSec=5

# Graceful shutdown. Uvicorn now bounds its own wait at 5s and the app's own
# teardown takes ~1-2s, so this only has to be comfortably longer than that —
# it is the backstop, not the mechanism. The old 10s could clip a slow teardown
# on a Pi with several virtual printers.
TimeoutStopSec=30

# Kill zombie ffmpeg processes (timelapse processing)
ExecStartPre=-/usr/bin/pkill -9 -f "ffmpeg.*bambuddy"
ExecStopPost=-/usr/bin/pkill -9 -f "ffmpeg.*bambuddy"

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=bambuddy

# Allow binding to privileged ports (322 RTSP, 990 FTPS) for Virtual Printer
# mode. Without this the VP's sockets never open and the slicer simply never
# sees the printer — with no obvious error, since the bind failure is one line
# in the journal (#2549). Works alongside NoNewPrivileges=true below: systemd
# raises the ambient set at exec, which is not the privilege escalation that
# setting forbids.
AmbientCapabilities=CAP_NET_BIND_SERVICE

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
# ProtectHome=true hides /home/* and breaks ExecStart when INSTALL_PATH is
# under /home (issue #1685). Default is the safer read-only; flip to true if
# your INSTALL_PATH is outside /home (e.g. /opt/bambuddy).
ProtectHome=read-only
#
# ProtectSystem=strict mounts EVERYTHING outside these three paths read-only for
# this service — including a NAS share you have mounted yourself and can write to
# from your own shell. Writes there fail with EROFS ("Read-only file system"),
# which looks like a permission problem but is not one (issue #2544).
#
# So if you point Scheduled Backups at a directory outside the install, data and
# log dirs, add it here — or better, in a drop-in that survives a reinstall:
#
#   sudo systemctl edit bambuddy
#   [Service]
#   ReadWritePaths=/mnt/your-nas-share
#
ReadWritePaths=DATA_DIR LOG_DIR INSTALL_PATH

[Install]
WantedBy=multi-user.target
