AI Runner Headless Server Deployment
May 25, 2026 ยท View on GitHub
This directory contains configuration files for deploying AI Runner headless server as a Linux system service.
The packaged airunner-headless.service file is a relocatable template. Use
deployment/systemd/install.sh to render it with the actual bundle root,
Python executable, and runtime data directories for the current install.
This surface is primarily for the distributed daemon install mode. The
normal entry point is:
./deployment/install_distributed.sh --role daemon --systemd
That command creates the daemon venv first, then calls this renderer with the
resolved install root and Python path. Invoke deployment/systemd/install.sh
directly only when you are manually rendering the service for a bundle or a
custom venv layout.
Install Layout
Linux desktop bundles and distributed daemon installs are expected to keep the AIRunner install root separate from the writable runtime data root.
- Install root: the installed application directory, for example
~/.local/airunner,~/.local/airunner/distributed/daemon, or/opt/airunner - Install Python: one of
<install>/venv/bin/python,<install>/.venv/bin/python, or<install>/bin/python - Runtime data root:
~/.local/share/airunnerunlessAIRUNNER_DATA_DIRoverrides it - Runtime configs:
<data>/runtime/configs - Runtime logs:
<data>/runtime/logs - Runtime sockets:
<data>/runtime/sockets - Runtime cache:
<data>/cache - Models:
<data>/models
The desktop launchers created by the top-level installer export
AIRUNNER_BUNDLE_ROOT, AIRUNNER_PYTHON, and the standardized runtime
directory variables so the daemon and sidecars can discover the bundle and
runtime roots predictably after relocation.
The distributed daemon installer passes the same resolved install root and
Python path through AIRUNNER_INSTALL_ROOT, AIRUNNER_TEMPLATE_ROOT, and
AIRUNNER_PYTHON before this renderer writes the systemd unit.
Systemd Service Setup (Ubuntu/Debian)
The rendered airunner-headless.service file allows AI Runner to run as a
background service that starts automatically at system boot.
Installation Steps
-
Render and install the service template:
sudo bash deployment/systemd/install.sh -
Optional overrides before rendering:
AIRUNNER_BUNDLE_ROOT=/path/to/bundleAIRUNNER_PYTHON=/path/to/pythonAIRUNNER_DATA_DIR=/path/to/runtime-data
-
Reload systemd to recognize the new service:
sudo systemctl daemon-reload -
Enable the service to start at boot:
sudo systemctl enable airunner-headless -
Start the service:
sudo systemctl start airunner-headless
Service Management
Check service status:
sudo systemctl status airunner-headless
View service logs:
# View recent logs
sudo journalctl -u airunner-headless -n 100
# Follow logs in real-time
sudo journalctl -u airunner-headless -f
# View logs since last boot
sudo journalctl -u airunner-headless -b
Stop the service:
sudo systemctl stop airunner-headless
Restart the service:
sudo systemctl restart airunner-headless
Disable auto-start at boot:
sudo systemctl disable airunner-headless
Reload service after editing config:
sudo systemctl daemon-reload
sudo systemctl restart airunner-headless
Troubleshooting
Service fails to start:
- Check logs:
sudo journalctl -u airunner-headless -n 100 - Verify the rendered Python path exists under your bundle root
- Verify the runtime data directory exists and has correct permissions
- Test manually from the bundle root with the rendered Python path
Permission issues:
# Ensure the service user can access the runtime data directory
sudo chown -R airunner:airunner ~/.local/share/airunner
# Check if user can write to runtime logs
ls -la ~/.local/share/airunner/runtime/
Service won't stop:
# Force stop
sudo systemctl kill airunner-headless
# Check for lingering processes
ps aux | grep airunner
Configuration
The service is configured with:
- Auto-restart: Service will automatically restart if it crashes
- Restart delay: 10 seconds between restart attempts
- File limits: Increased to 65536 for handling many connections
- Local-only bind defaults: The packaged unit binds the daemon to
127.0.0.1 - Runtime directories: Runtime config, logs, sockets, cache, and model roots live under
~/.local/share/airunner - Sandboxing: The service uses
NoNewPrivileges,PrivateTmp,ProtectSystem=full,ProtectHome=read-only, and a restricted writable path - Logging: By default the daemon logs to stdout/stderr only, so systemd captures everything in
journalctl; runtime log files under~/.local/share/airunner/runtime/logsare only written whenAIRUNNER_SAVE_LOG_TO_FILE=1
Environment Variables
The service sets these environment variables:
AIRUNNER_HEADLESS=1- Run in headless mode (no GUI)AIRUNNER_LLM_ON=1- Enable LLM serviceAIRUNNER_RUNTIME_BIND_HOST=127.0.0.1- Keep managed runtimes on loopback by defaultAIRUNNER_BUNDLE_ROOT- Resolved install root for the rendered bundleAIRUNNER_PYTHON- Resolved bundle Python executableAIRUNNER_DAEMON_CONFIG- Standard daemon config pathPATH- Prefers the rendered bundle'sbindirectory
The standardized runtime layout is:
~/.local/share/airunner/runtime/configsfor daemon and sidecar config files~/.local/share/airunner/runtime/logsfor daemon and sidecar logs~/.local/share/airunner/runtime/socketsfor local socket-style discovery paths~/.local/share/airunner/cachefor runtime-owned caches~/.local/share/airunner/modelsfor default model storage
To add more environment variables, edit the service file and add lines like:
Environment="YOUR_VAR=value"
Testing the HTTP Server
Once the service is running, test it:
# Health check
curl http://localhost:8080/health
# Test LLM endpoint
curl -X POST http://localhost:8080/llm \
-H "Content-Type: application/json" \
-d '{
"prompt": "Hello",
"action": "CHAT",
"stream": false,
"llm_request": {
"max_new_tokens": 50
}
}'
Integration with BookSite
Once the service is running, you can use the BookSite classification:
cd /path/to/airunner/booksite
./manage.py ai_process_books --books 535
The Django app will automatically connect to http://localhost:8080 and use the RAG tools.
Uninstallation
To remove the service:
# Stop and disable
sudo systemctl stop airunner-headless
sudo systemctl disable airunner-headless
# Remove service file
sudo rm /etc/systemd/system/airunner-headless.service
# Reload systemd
sudo systemctl daemon-reload