Systemd Services¶
Target Audience: Administrators Difficulty: Beginner Prerequisites: Basic Linux systemd knowledge
Overview¶
A standard MultiFlexi installation runs three continuously-running background services and one periodic maintenance timer managed by systemd:
Service / Timer unit |
Purpose |
|---|---|
|
Enqueues jobs based on RunTemplate schedules |
|
Executes queued jobs |
|
Triggers jobs in response to external events |
|
Periodic maintenance — cleanup, retention, schedule integrity, credential health checks |
All run as the multiflexi system user and load their configuration from /etc/multiflexi/multiflexi.env.
Checking Service Status¶
# Status of all services at a glance
systemctl status multiflexi-scheduler multiflexi-executor multiflexi-eventor
# Detailed status with recent log lines
systemctl status multiflexi-executor -l
# HouseKeeper timer — next scheduled run
systemctl list-timers multiflexi-housekeeper
Starting and Stopping Services¶
# Start
sudo systemctl start multiflexi-scheduler
sudo systemctl start multiflexi-executor
sudo systemctl start multiflexi-eventor
# Stop
sudo systemctl stop multiflexi-executor
# Restart (e.g. after configuration change)
sudo systemctl restart multiflexi-executor
# Reload (re-reads the env file without interrupting running jobs — executor only)
sudo systemctl reload multiflexi-executor
# Trigger an immediate HouseKeeper run without waiting for the timer
sudo systemctl start multiflexi-housekeeper.service
Enabling / Disabling on Boot¶
Services are enabled at boot by default after installation. To manage this:
# Enable (start at boot)
sudo systemctl enable multiflexi-executor
# Disable
sudo systemctl disable multiflexi-eventor
Viewing Logs¶
All services log to the systemd journal.
# Live log tail
sudo journalctl -u multiflexi-executor -f
# All services together
sudo journalctl -u multiflexi-scheduler -u multiflexi-executor -u multiflexi-eventor \
-u multiflexi-housekeeper -f
# Last 100 lines
sudo journalctl -u multiflexi-executor -n 100
# Logs since last boot
sudo journalctl -u multiflexi-executor -b
# Logs between timestamps
sudo journalctl -u multiflexi-executor --since "2025-01-01 08:00" --until "2025-01-01 10:00"
Service Details¶
multiflexi-scheduler¶
Scans RunTemplates in the database and creates Job records when a scheduled run time is due. Runs continuously as a simple PHP daemon.
Binary:
/usr/lib/multiflexi-scheduler/daemon.phpRestarts automatically: yes (
Restart=always, 10 s delay)No memory ceiling (scheduler is lightweight)
multiflexi-executor¶
Picks up pending Job records, resolves environment variables, runs the job via the configured executor module, and stores results + artifacts.
Binary:
/usr/share/multiflexi-executor/daemon.phpMemory ceiling: 2 GB (
MemoryMax=2G) — restarts automatically if exceededSoft memory warning: 1800 MB (
MULTIFLEXI_MEMORY_LIMIT_MB=1800)Restarts automatically: yes (
Restart=always, 10 s delay)
multiflexi-eventor¶
Monitors configured event sources and enqueues jobs in response to external triggers (files, webhooks, queue messages).
Binary:
/usr/lib/multiflexi-eventor/daemon.phpMemory ceiling: 1 GB (
MemoryMax=1G)Restarts automatically: yes (
Restart=always, 10 s delay)
Note
If you do not use event-driven job triggering, multiflexi-eventor can be disabled:
sudo systemctl disable --now multiflexi-eventor
multiflexi-housekeeper¶
Periodic maintenance timer that runs once per hour. Cleans orphaned jobs and broken schedule entries, finalizes stale Tasks, enforces data retention policies, prunes the log table, recalculates RunTemplate job counters, and checks credential health.
Package:
multiflexi-housekeeperTimer:
multiflexi-housekeeper.timer(OnCalendar=hourly,Persistent=true)Service:
multiflexi-housekeeper.service(Type=oneshot)Binary:
/usr/lib/multiflexi-housekeeper/housekeeper.phpJitter: up to 5 minutes (
RandomizedDelaySec=300) — prevents thundering-herd on multi-server deploymentsDry-run:
sudo -u multiflexi multiflexi-housekeeper --dry-run
Note
The HouseKeeper uses a timer unit, not a continuously-running service.
systemctl status multiflexi-housekeeper.service shows the result of the last
run; systemctl list-timers multiflexi-housekeeper shows the next scheduled run.
See HouseKeeper — Periodic Maintenance for full configuration reference and troubleshooting.
Node-RED bridge¶
multiflexi-eventor can forward webhook change events and finished jobs to a
Node-RED HTTP-in endpoint. The bridge is optional and disabled by default.
You are prompted for the bridge settings when the package is installed (debconf). To reconfigure them later, run:
sudo dpkg-reconfigure multiflexi-eventor
The answers are written to /etc/multiflexi/multiflexi.env:
NODERED_WEBHOOK_URL: Node-RED HTTP-in endpoint URL. Leave empty to disable the bridge.
NODERED_TOKEN: Optional shared secret sent as the
X-MultiFlexi-Tokenheader.NODERED_FORWARD_CHANGES: Forward incoming webhook changes in addition to finished jobs (default:
true).
You can also set these variables directly in /etc/multiflexi/multiflexi.env
and restart the service.
Node-RED catalog feed¶
Beyond forwarding events, multiflexi-eventor can publish the MultiFlexi
configuration catalog — every company, every enabled run-template and every
credential — to the node-red-contrib-multiflexi catalog node. The
catalog node then builds one Node-RED palette node per entity, each carrying the
same icon it has in MultiFlexi.
Set these in /etc/multiflexi/multiflexi.env:
NODERED_CATALOG_URL: HTTP-in URL of the catalog node (e.g.
http://node-red:1880/multiflexi-catalog). Use a path distinct fromNODERED_WEBHOOK_URL. Leave empty to disable the feed.NODERED_CATALOG_INTERVAL: How often (seconds) to republish the catalog. The payload is content-hashed, so an unchanged catalog is not resent (default:
300).
The NODERED_TOKEN shared secret, when set, is also sent with the catalog push.
Icons are not embedded in the push. The catalog node fetches each entity’s
icon from the MultiFlexi web image endpoints — appimage.php (apps),
companylogo.php and credentialimage.php — which are public (no login).
On the catalog node, set App URL (MULTIFLEXI_APP_URL, default
/multiflexi/) to where the MultiFlexi web UI is reachable from Node-RED.
The node-red-contrib-multiflexi package also ships a systemd drop-in that
adds /usr/share/node-red to the Node-RED service NODE_PATH.
Exposing the editor over HTTPS¶
Do not link users to the unencrypted :1880 port. Instead, reverse-proxy the
Node-RED editor under a path on the existing HTTPS vhost (for example
https://multiflexi.example.com/node-red/). Tell Node-RED its base path so its
assets and admin API resolve behind the proxy, in settings.js:
httpAdminRoot: '/node-red',
Then add an Apache reverse proxy (enable proxy, proxy_http,
proxy_wstunnel and rewrite):
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/node-red/comms(.*)$ ws://127.0.0.1:1880/node-red/comms$1 [P,L]
ProxyPass /node-red/ http://127.0.0.1:1880/node-red/
ProxyPassReverse /node-red/ http://127.0.0.1:1880/node-red/
The catalog HTTP-in node stays on the local port (its httpNodeRoot is left at
/), so NODERED_CATALOG_URL keeps pointing at http://127.0.0.1:1880/....
The vitexus.multiflexi Ansible multiflexi_server role configures all of
this automatically via multiflexi_server_nodered_http_root (default
/node-red).
Protect the editor with a login (adminAuth in settings.js). Generate a
bcrypt password hash with node-red-admin hash-pw and add a user:
adminAuth: {
type: "credentials",
users: [{ username: "demo", password: "$2b$12$...", permissions: "*" }]
},
The Ansible role creates this demo user automatically
(multiflexi_server_nodered_admin_user / _admin_password_hash /
_admin_permissions; default demo with full access — use read for a
read-only demo).
Configuration File¶
All services share /etc/multiflexi/multiflexi.env. After editing this file, restart the affected services:
sudo systemctl restart multiflexi-scheduler multiflexi-executor multiflexi-eventor
The HouseKeeper reads the env file at the start of each timer-triggered run, so no
restart is needed for multiflexi-housekeeper — the next run picks up the changes
automatically.
See Configuration for the full list of configuration variables.
Troubleshooting Service Issues¶
Service fails to start¶
# Check the last start attempt
sudo journalctl -u multiflexi-executor -n 50
# Verify the env file is readable
sudo -u multiflexi cat /etc/multiflexi/multiflexi.env
# Check PHP syntax
php -l /usr/share/multiflexi-executor/daemon.php
Service keeps restarting¶
Usually caused by a database connection failure or missing PHP extension.
# Watch restart loop
sudo journalctl -u multiflexi-executor -f
# Test database connectivity
php -r "new PDO('mysql:host=127.0.0.1;dbname=multiflexi', 'user', 'pass');"
Jobs are not being executed¶
Verify the executor is running:
systemctl status multiflexi-executorVerify the scheduler is running:
systemctl status multiflexi-schedulerCheck for pending jobs in the database:
multiflexi-cli job:list --status=pendingCheck executor logs for errors:
journalctl -u multiflexi-executor -n 200
See Also¶
Execution Architecture — How the daemons interact
HouseKeeper — Periodic Maintenance — HouseKeeper periodic maintenance reference
Configuration — Environment variables
Troubleshooting — General troubleshooting guide
Docker Deployment — Running services in Docker Compose