RoamSwitch Server Edition Operations Manual
Official installation, deployment, and operational reference for Cloud VPS (AWS, GCP, Azure, Linode, DigitalOcean), bare-metal data centers, and container hosts.
1. Overview & Requirements
RoamSwitch Server Edition is a headless (zero GUI dependencies) autonomous defense and integrity monitoring suite designed for Linux servers exposed to the public Internet.
Unlike the client edition which dynamically switches profiles based on Wi-Fi state, the server edition enforces Inbound Default Drop, critical path File Integrity Monitoring (FIM), preventive kernel LPE mitigation (Frag Gap), eBPF runtime threat detection, SSH lockout prevention, and automated multi-channel emergency alerts (Telegram / LINE / Webhook).
System Requirements
- Supported Distributions: Ubuntu 22.04 / 24.04 LTS, Debian 12+, AlmaLinux / Rocky Linux / RHEL 9+, Fedora 39+, openSUSE Leap 15.5+, Raspberry Pi OS (64-bit)
- Architectures:
x86_64(amd64) oraarch64(arm64) - Kernel: Linux 5.10+ (
nftables,cgroups v2, eBPF BTF recommended) - Footprint: 20–30 MB resident memory, <0.1% CPU during idle/normal workloads
2. Installation Procedures
Using the official signed repositories ensures automatic dependency resolution and seamless updates via your standard system package manager.
2.1 APT (Ubuntu / Debian / Raspberry Pi OS)
# 1. Register the repository signing key
curl -fsSL https://lafine.net/apt/roamswitch-archive-keyring.asc \
| sudo gpg --dearmor -o /usr/share/keyrings/roamswitch-archive-keyring.gpg
# 2. Add the repository
echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/roamswitch-archive-keyring.gpg] https://lafine.net/apt stable main" \
| sudo tee /etc/apt/sources.list.d/roamswitch.list
# 3. Install
sudo apt update && sudo apt install roamswitch-server
2.2 DNF / RPM (Fedora / RHEL / AlmaLinux / Rocky Linux)
# 1. Import the GPG key
sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch
# 2. Add the repository config file
sudo curl -fsSL -o /etc/yum.repos.d/roamswitch.repo https://lafine.net/rpm/fedora/roamswitch.repo
# 3. Install
sudo dnf install roamswitch-server
2.3 openSUSE (zypper)
sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch
sudo zypper addrepo https://lafine.net/rpm/opensuse/roamswitch.repo
sudo zypper refresh && sudo zypper install roamswitch-server
roamswitch) and Server Edition (roamswitch-server) declare reciprocal package conflicts. Always select roamswitch-server on headless server environments.3. Initial Setup & Service Verification
3.1 Service Status
Following installation, roamswitch-server.service starts immediately and is enabled at system boot.
sudo systemctl status roamswitch-server.service
3.2 Interactive Setup Wizard
Run the interactive setup wizard to configure ports, maintenance source IPs, notification channels and the containment action (press Enter to accept each default).
sudo roamswitch server setup
- Ports: enter the SSH maintenance ports (default
22) and the public service ports (default80,443), each comma-separated. - Maintenance source IPs: SSH bastion / monitoring IPs or CIDRs (e.g.
203.0.113.50/32); leave blank to allow SSH from any source. - Notification channels: enable Telegram bot, LINE Messaging API and/or a generic webhook (Slack / Discord / Teams).
- Response to a critical eBPF event: choose
isolate(isolate host),freeze(freeze the process) oralert_only(notify only). After saving, you are prompted to send a test notification and restart the service. - Automatic kernel CVE data updates (default
n): choose whether to anonymously fetch the kernel CVE database used by the container-isolation audit from lafine.net once a day (no query string, cookies, or identifying headers). The audit itself still runs against the embedded baseline if left disabled. This is the one exception to Server Edition's zero-network-code policy, and it defaults to off (opt-in). - File Scan Guard settings: choose whether to enable virus scanning for mail relays, shared folders and upload destinations (§13), and set the target directories. Optional, off by default.
- Resource Guard settings: enable the resource-exhaustion guard that detects sustained RSS growth (memory leaks/DoS) or crash loops in network-exposed services.
- Overview of always-on core protections: displays the core defenses that run at all times regardless of the wizard — inbound default-drop, FIM, eBPF integration, and so on (no input required).
- Investigation-agent hand-off (investigation) settings: choose whether to automatically delegate first-pass investigation — for critical eBPF events, or Critical-Path FIM / dependency-lockfile tampering detections, whenever they were judged notify-only — to an external AI agent CLI (Claude Code / agy / Codex CLI / OpenCode, or a custom command) (§10.1). Off by default.
-100 (e.g. -1001234567890). Confirm the correct value from the "chat":{"id":...} field in curl -s "https://api.telegram.org/bot<token>/getUpdates".3.3 30-Item Server Security Audit
sudo roamswitch status --server
Performs an instantaneous 30-check audit of firewall rules, Frag Gap mitigation, Yama LSM restrictions, permissions, and Docker port exposure, producing a 0–100 security score and grade (S to C).
4. Firewall & Port Rules
/etc/roamswitch/server.conf is forced to 0600 permissions (root read/write only). The format is flat key=value; section headers such as [network] are ignored.
# --- Firewall ---
ssh_ports=22 # SSH management port (kept even during emergency isolation)
allowed_ports=80,443 # Public service ports
whitelist_ips=203.0.113.10/32 # Maintenance source IP / CIDR (blank = allow all, formerly admin_source_ips)
protect_docker_ports=true # DOCKER-USER protection (blocks containers from bypassing the firewall)
preserve_ssh_on_isolation=true # Preserve the SSH management path even during emergency isolation (false = full cutoff)
# --- eBPF runtime guard ---
action_on_critical=isolate # isolate | freeze (SIGSTOP + network cutoff) | alert_only
ebpf_socket_path=/run/roamswitch/events.sock
# --- Egress / C2 blocking & DNS sinkhole ---
egress_ip_blocklist_enabled=true # Default true. Harmless until a feed is populated (blocks nothing)
dns_sinkhole_enabled=false # Default false (to avoid breaking internal DNS / split-horizon setups)
dns_sinkhole_provider=quad9 # quad9 | cloudflare | adguard | cleanbrowsing
# --- Container-isolation CVE data (opt-in) ---
cve_kernel_map_updates_enabled=false # Default false. The sole external-communication exception (once a day, anonymous)
# --- Notifications ---
telegram_enabled=false
telegram_bot_token=
telegram_chat_id=
line_enabled=false
webhook_enabled=false
webhook_url=
# --- System ---
language=ja
fim_check_interval_secs=300 # Formerly named scan_interval
After editing the file directly, restart the service to apply the changes (roamswitch-server has no reload):
sudo roamswitch server restart
4.1 Per-Severity Policy (guard.yaml, optional)
If action_on_critical alone isn't granular enough, create /etc/roamswitch/guard.yaml (a template ships at /etc/roamswitch/guard.yaml.example). When absent, an equivalent policy is synthesized automatically from server.conf's action_on_critical, so existing deployments are unaffected.
policies:
on_warning:
action: log_and_notify
on_critical:
server_action: isolate_process
kill_process: true
fallback_to_host_isolation_after_retries: 3 # Auto-escalates to host isolation if the same process recurs
on_emergency:
action: isolate_host_all
kill_process: true
server_safeguards:
maintenance_ssh_ports: [22]
safety_timer_secs: 300 # Auto-restores after this many seconds post-isolation if no ack arrives (0 disables)
Safety timer: once a host isolation (Air-Gap) fires, the administrator investigates and then acknowledges it with the command below. If no acknowledgment arrives within safety_timer_secs, RoamSwitch automatically restores network access so a false positive can't leave the server cut off indefinitely.
sudo roamswitch server ack
4.2 Egress / C2 Blocking and DNS Sinkhole
With egress_ip_blocklist_enabled=true (default), outbound connections to known-malicious IPs are blocked via nftables. The feed at /var/lib/roamswitch/threatfeed/malicious_ips.txt (managed by the update mechanism) is used first, falling back to the empty package-shipped seed (/usr/share/roamswitch/threatfeed/) — so the default of true blocks nothing until a feed is actually populated.
Setting dns_sinkhole_enabled=true forces resolution through a filtering DNS resolver (Quad9 / Cloudflare / AdGuard / CleanBrowsing), blocking known-malicious domain resolution. It defaults to false since it can break internal DNS or split-horizon setups.
4.3 Incoming-Port-Scan-Detection Guard
Detects source IPs that connected to many distinct ports in a short time, by correlating nftables log rules with journald (enabled by default). High-confidence scan sources can be auto-blocked for a set duration. When used alongside RoamSwitch Sensor (a different feature from §10.1 — full-port audit probes from a paired Sensor are excluded as a false-positive mitigation), the Sensor's own IP is automatically excluded.
# --- Incoming port-scan detection (enabled by default) ---
port_scan_detect_enabled=true # false to disable
port_scan_detect_min_distinct_ports=15 # Judged a scan when connections reach this many distinct ports
port_scan_detect_window_secs=300 # Aggregation window for detection (seconds)
port_scan_block_enabled=true # Auto-blocks the detected scan source IP
port_scan_block_duration_secs=600 # Duration of the automatic block (seconds)
You can review detection history with the roamswitch port-scan command.
5. SSH Lockout Prevention Failsafe
Accidental lockout via firewall misconfiguration is an intolerable operational disaster. RoamSwitch Server Edition incorporates multi-tiered safeguards:
- ESTABLISHED / RELATED Unconditional Pass: Active sessions are never dropped during rule reloads.
- SSH Preservation on Air-Gap: Even under hostile attack containment,
preserve_ssh_on_isolation = truemaintains administrative access from authorized CIDRs for investigation. - Atomic nftables Loading with Rollback: Rule syntax errors instantly trigger a zero-downtime rollback to the preceding verified ruleset.
6. Container Protection (Docker / Podman)
Docker's default behavior creates custom iptables rules that bypass standard host firewalls, exposing container ports (e.g. -p 8080:8080) directly to the Internet.
When protect_docker_ports=true (default), RoamSwitch inserts inspection rules at the head of the DOCKER-USER chain so container-bound traffic also obeys the allowed_ports and whitelist_ips policy, reliably preventing accidental exposure of dev database containers and the like.
In addition, a real-time guard watches docker events and notifies you the moment a container starts with --privileged or a /var/run/docker.sock bind-mount — a container-escape risk. No configuration needed, always on, and notify-only (no automatic blocking).
7. Critical Path File Integrity Monitoring (FIM)
Monitors 150+ essential binaries (/bin/login, /usr/bin/sudo, /usr/sbin/sshd), auth configurations (/etc/shadow, /etc/pam.d/), and systemd units using SHA-256 hashes.
7.1 Manual Hash Verification
sudo roamswitch fim verify
7.2 Event-Driven Detection (Instant)
Monitored files are individually watched via fanotify (FAN_CLASS_NOTIF, write-completion events), so tampering is re-hashed and detected the instant it happens rather than waiting for the next periodic scan. The periodic scan (default fim_check_interval_secs=300 seconds) remains as a backstop for any missed events.
7.3 Automatic Baseline Sync on OS Updates
On Debian / Ubuntu, package installation auto-configures the DPkg::Post-Invoke hook at /etc/apt/apt.conf.d/99roamswitch-fim. On Fedora / RHEL / Rocky / AlmaLinux / openSUSE, a systemd.path unit (roamswitch-fim-update.path) watching /var/lib/rpm plays the same role.
This means that when an administrator runs sudo apt upgrade (or dnf upgrade / zypper update) and binaries are legitimately updated, RoamSwitch detects it automatically and quietly re-syncs the hash baseline (preventing false-positive alerts). To sync manually:
sudo roamswitch fim update
8. eBPF Runtime Guard & Falco / Tetragon Integration
Hooks into kernel-space eBPF events to detect Frag Gap kernel privilege escalation, container escapes, and unauthorized reverse shells. The default sensor is Falco (JSONL over a UNIX domain socket). Selecting sensor.type: tetragon in guard.yaml lets you use Cilium Tetragon as the sensor instead — it simply subscribes to Tetragon's native gRPC API over the same UNIX socket, adding no new listening port.
8.1 Anti-Bloat Architecture
Traditional security agents suffer from severe syslog explosion and disk wear. RoamSwitch connects directly to Falco via a dedicated UNIX domain socket (/run/roamswitch/events.sock):
- Bundled
/etc/falco/config.d/99-roamswitch-optimized.yamlstreams events directly into the daemon with zero disk I/O. /etc/logrotate.d/roamswitch-falcoensures clean daily rotation for any fallback file outputs.
8.2 Autonomous Containment
Upon detecting a critical attack, RoamSwitch immediately issues SIGSTOP to freeze the offending process PID and applies nftables Air-Gap isolation.
9. Emergency Alerts (Telegram / LINE / Webhook)
Dispatches immediate alerts to external notification channels when port anomalies, FIM tampering, or eBPF containment events occur:
[notifications]
language = ja
# Telegram: bot token and chat ID
telegram_bot_token = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ"
telegram_chat_id = "-1001234567890"
# LINE: Messaging API channel access token and user ID
line_channel_access_token = "YOUR_LINE_ACCESS_TOKEN"
line_user_id = "U1234567890abcdef1234567890abcdef"
# Generic webhook (Slack, Discord, Teams, your own monitoring platform)
webhook_url = "https://hooks.slack.com/services/T00/B00/XXXXX"
Even without any of these external channels configured, every alert sent is also kept locally for the past 7 days. Check it with roamswitch notifications.
10. AI Agent / MCP Integration (Model Context Protocol)
RoamSwitch Server Edition includes roamswitch-mcp, allowing AI agents (Claude, Gemini, Cursor) to monitor infrastructure health and posture.
Configuration Example (`claude_desktop_config.json`)
{
"mcpServers": {
"roamswitch": {
"command": "/usr/bin/roamswitch-mcp",
"args": []
}
}
}
10.1 Investigation-Agent Hand-off (investigation — delegating first-pass automated investigation to an AI agent)
While §10's roamswitch-mcp serves queries from a human's AI client, investigation hand-off is a separate mechanism where the daemon itself autonomously launches an external AI agent CLI, triggered by a detection event. It targets critical eBPF events that were judged notify-only (did not trigger automatic isolation or process freezing), plus Critical-Path FIM and dependency-lockfile tampering detections. When enabled, the daemon first generates a local heuristic first-pass triage report (likelihood of false positive, reasoning, suggested next steps), then launches the configured AI agent CLI as a subprocess with that report attached, delegating further investigation and summarization. Off by default.
# Append to /etc/roamswitch/guard.yaml (a separate file from server.conf)
investigation:
enabled: true
command: "claude" # "claude" | "agy" | "codex" | "opencode" | any custom command
args: ["-p"] # The prompt is automatically appended as the final argument
timeout_secs: 180
The same settings can also be configured from the interactive wizard of sudo roamswitch server setup (§3.2, final step). Choose from presets for Claude Code (claude -p), agy (agy -p --dangerously-skip-permissions), Codex CLI (codex exec), OpenCode (opencode run), or a custom command. On a re-run, the matching preset is auto-selected based on the saved configuration.
--dangerously-skip-permissions, raises the risk that malicious input causes the agent to take unintended actions. The wizard displays this warning when agy is selected. In environments with an untrusted log-input path, we recommend a tool configuration that does not skip permission checks.The investigation hand-off is never invoked while the network is cut off (e.g. during an active Air-Gap, or any state equivalent to isolate_host_all).
11. CLI Command Cheat Sheet
| Command | Privileges | Description |
|---|---|---|
sudo roamswitch status --server |
root | Display 30-item server posture score & check breakdown |
sudo roamswitch ports |
root | Audit open listening ports and bound processes |
sudo roamswitch fim verify |
root | Verify SHA-256 integrity of critical path system files |
roamswitch notifications |
User | Shows the notification history (every alert sent) from the past 7 days |
sudo roamswitch server setup |
root | Launch interactive initial configuration wizard |
sudo roamswitch fim update |
root | Refresh FIM SHA-256 baseline database |
sudo roamswitch server config set <key> <value> |
root | Change and persist a single setting (see §4 for the key list) |
sudo roamswitch airgap enable / disable |
root | Manually trigger / release the Air-Gap emergency cut-off |
sudo roamswitch emergency-restore |
Root | Disarm all eBPF / firewall isolation and restore the initial baseline |
roamswitch port-scan |
User | Shows the incoming-port-scan-detection guard's (§4.3) detection history (source IP, whether it was auto-blocked, and block duration) |
roamswitch sensor [key|list|pair|unpair|request-audit|results] |
User / root | Pairing-code-based mutual trust with RoamSwitch Sensor. pair --addr <ip> --code <code> to pair, request-audit to request an active vulnerability audit (fetch the result with results). Requires sensor_pairing_enabled: true (off by default). See the Sensor Manual for details |
12. Troubleshooting & FAQ
Q1. Will RoamSwitch unexpectedly disconnect my SSH session?
No. RoamSwitch unconditionally allows established ESTABLISHED/RELATED states and ssh_ports (default 22). Even during an Air-Gap isolation triggered by a serious attack, preserve_ssh_on_isolation=true (default) keeps your admin session alive.
Q2. How do I regain access if accidentally locked out?
Log in through your cloud provider's web console (VNC / serial), then run sudo roamswitch emergency-restore to disarm the isolation, or sudo systemctl stop roamswitch-server to stop the service.
Q3. How do I expose ports for newly added web services (e.g. Nginx)?
Run sudo roamswitch server config set allowed_ports 80,443,3000 (or edit /etc/roamswitch/server.conf directly), then run sudo roamswitch server restart.
13. File Scan Guard (protecting mail relays, shared folders, and upload endpoints)
An optional feature relevant only if this host has a directory that stores files for others — a mail relay, a Samba/NFS share, a file upload endpoint. The embedded YARA engine always scans clamav_scan_dirs with no external dependency; setting clamav_enabled=true adds ClamAV as a second opinion. Confirmed threats are automatically quarantined to /var/lib/roamswitch/quarantine and the operator is notified.
# --- File Scan Guard (ClamAV, opt-in) ---
# The embedded YARA engine always scans clamav_scan_dirs unconditionally.
clamav_enabled=false # true enables additional inspection via clamdscan
clamav_scan_dirs= # Absolute paths to scan (comma-separated)
clamav_scan_interval_secs=86400 # Scan interval (seconds, minimum 3600)
clamav_freshclam_interval_secs=7200 # Signature DB auto-update interval (seconds, minimum 1800)
Also configurable via the interactive sudo roamswitch server setup wizard; check its configuration and quarantine status via the get_file_scan_guard_status MCP tool.
14. Log Audit (Log Pattern Anomaly Detection & Notification)
A periodic journalctl scan turns log messages into templates to detect new patterns (log shapes never seen before) and frequency anomalies (a statistical spike, Z-score > 3.0). This is a lightweight mechanism that needs no extra daemon or external dependency, so it's enabled by default. Detections are sent through the same notification channels as File Scan Guard and FIM (Telegram / LINE / Webhook). Any API keys or tokens that might appear in a log line are automatically masked before being included in the notification.
# --- Log Audit (enabled by default) ---
log_audit_enabled=true # false to disable
log_audit_interval_secs=1800 # Scan interval in seconds (minimum 300)
This can also be configured from the interactive sudo roamswitch server setup wizard, and the latest detection results can be checked via the roamswitch audit-logs CLI command or the audit_security_logs MCP tool.