# umbrella A safety-critical game server admin daemon written in C11. Monitors multiple server processes via log file tailing, RCON, and A2S probing, and exposes a Unix socket for CLI clients to attach, send commands, and receive real-time output. ## Features - Live log tailing via inotify with symlink resolution - Pluggable per-unit output filters (any stdin→stdout executable) - RCON command dispatch (Valve protocol) - A2S health probing (Valve UDP) - systemd unit state queries over D-Bus - Ring buffer — 500 lines × 1024 bytes per unit, replayed on attach - Reload without restart via SIGHUP ## Build ```bash # Dependencies: libyaml-dev, libsystemd-dev make sudo make install ``` Compiler flags: `-Wall -Wextra -Wpedantic -std=c11 -D_GNU_SOURCE -O2` ## Install layout | Path | Purpose | |------|---------| | `/usr/local/sbin/umbrella` | Daemon | | `/usr/local/bin/umbrella-cli` | CLI client | | `/etc/umbrella/umbrella.conf` | Daemon config | | `/etc/umbrella/units/*.yaml` | Unit descriptors | | `/usr/lib/umbrella/filters/` | Bundled log filters | | `/run/umbrella/umbrella.sock` | Unix socket | | `/run/umbrella/umbrella.pid` | PID file | | `/var/log/umbrella/umbrella.log` | Daemon log | ## Unit descriptor format ```yaml name: tf2 # used in CLI commands display: "TF2 — novemen" service: tf2-server.service # systemd unit for state queries console: type: rcon # rcon | stdin host: 127.0.0.1 port: 27015 password_env: TF_RCON_PASSWORD # or: password: plaintext health: type: a2s # a2s | tcp | none host: 127.0.0.1 port: 27015 timeout_ms: 5000 logs: - /path/to/logs/current.log # up to 4 paths; symlinks resolved # Optional filter — any executable reading stdin, writing stdout log_filter: /usr/lib/umbrella/filters/source.py broadcast_cmd: "say {msg}" # template for !broadcast actions: update: /path/to/update.sh restart: /usr/bin/systemctl restart tf2-server.service ``` ## Bundled filters | Filter | Targets | |--------|---------| | `source.py` | TF2, GMod, CS2 — strips `server_cvar`/stuck spam, strips timestamp prefix | | `minecraft.py` | vanilla/Paper/Spigot — strips keepAlive/autosave noise, strips `[HH:MM:SS] [thread]` prefix | | `terraria.py` | vanilla/tModLoader — strips blank lines and mod-loading spam | Custom filters: any executable at any path that reads stdin and flushes stdout after each write works. Python, shell, compiled binary — anything. ## Log file setup srcds and most dedicated servers create new log files per session. Point `logs:` at a stable symlink and update it on each server start: ```bash # In your startup script / ExecStartPre: ln -sf /srv/game/logs/L0222000.log /srv/game/logs/current.log # Then SIGHUP umbrella so it re-resolves the symlink: kill -HUP $(cat /run/umbrella/umbrella.pid) ``` With `sv_log_onefile 1` (Source engine), the log file is fixed for the server's lifetime, so the symlink only needs updating on restarts. ## CLI usage ```bash umbrella-cli list umbrella-cli status umbrella-cli attach # live output; Ctrl+D to detach umbrella-cli tail # dump ring buffer and exit umbrella-cli input # send RCON command or stdin line umbrella-cli action # run a named action script umbrella-cli broadcast # send to all units' broadcast_cmd ``` ## Reload ```bash kill -HUP $(cat /run/umbrella/umbrella.pid) ``` Reloads unit YAML files, restarts log tails and filter subprocesses. Running processes are not touched.