Actions
39 actions, callable from the panel, the command palette and the API as
POST /api/v1/a/<id>. Internal actions used between modules are not listed.
| Action | What it does | Risk | Preview |
|---|---|---|---|
security.firewall.get | Show the firewall (read) | low | No dry run |
security.firewall.presets | List firewall presets (read) | low | No dry run |
security.firewall.apply | Apply a firewall ruleset | high | |
security.firewall.cluster | Open the ports the cluster needs | high | |
security.firewall.confirm | Confirm the applied ruleset | medium | No dry run |
security.firewall.rollback | Roll the firewall back | medium | No dry run |
security.firewall.history | Firewall versions (read) | low | No dry run |
security.ban.add | Ban an IP | medium | No dry run |
security.ban.remove | Remove a ban | medium | No dry run |
security.ban.list | List bans (read) | low | No dry run |
security.allow.add | Allow-list an IP | medium | No dry run |
security.allow.remove | Remove an allow-list entry | medium | No dry run |
security.allow.list | List allow-listed IPs (read) | low | No dry run |
security.lockdown.enable | Lockdown the server | critical | |
security.lockdown.disable | End lockdown | high | No dry run |
security.geo.update | Update the country database | medium | No dry run |
security.crowdsec.install | Install CrowdSec | high | No dry run |
security.crowdsec.status | CrowdSec status (read) | low | No dry run |
security.crowdsec.decisions | List CrowdSec decisions (read) | low | No dry run |
security.crowdsec.unblock | Unblock an IP in CrowdSec | medium | No dry run |
security.crowdsec.configure | CrowdSec settings and allow-list | medium | No dry run |
security.scan.run | Scan for malware | low | No dry run |
security.findings.list | List malware findings (read) | low | No dry run |
security.quarantine.move | Quarantine a finding | medium | No dry run |
security.quarantine.restore | Restore a quarantined file | medium | No dry run |
security.quarantine.delete | Delete a quarantined file | medium | No dry run |
security.yara.set | Add or remove a YARA rule file | high | No dry run |
security.integrity.baseline | Record the integrity baseline | medium | No dry run |
security.integrity.check | Check file integrity | low | No dry run |
security.updates.configure | Configure unattended updates | high | No dry run |
security.updates.run | Run security updates now | high | No dry run |
security.updates.status | Update status (read) | low | No dry run |
security.updates.health_watch | Check service health now | low | No dry run |
security.hardening.check | Check the hardening profile (read) | low | No dry run |
security.hardening.fix | Apply the hardening profile | medium | |
security.ports.audit | Audit open ports (read) | low | No dry run |
security.score.get | Security score | low | No dry run |
security.score.fix | Apply score fixes | high | |
security.events.list | Security events (read) | low | No dry run |
Permissions and limits
Permissions
security.viewView server security statesecurity.firewall.manageManage the firewallsecurity.ban.manageBan, unban and allow-list IPssecurity.lockdownEnable lockdownsecurity.crowdsec.manageManage CrowdSec / fail2bansecurity.scan.runRun malware scans and view findingssecurity.scan.manageQuarantine, restore and delete findingssecurity.scan.adminManage YARA rulessecurity.integrity.manageFile integrity baseline and checkssecurity.updates.manageUnattended updates and health watchsecurity.hardening.manageHardening profilesecurity.score.viewSee the security scoresecurity.plan.applyApply score fixessecurity.events.viewView security events
Plan limits
security.ip_rulesBan and allow-list entriessecurity.scans_per_dayMalware scans per daysecurity.quarantine_mbQuarantine size
Engineering notes
Generated from modules/security/docs.md at build d90e9e2. These are the notes the engineers keep
next to the code: precise, technical, and honest about what is not done yet.
Agent code: internal/agent/security{,_fw,_cs,_scan,_sys}.go; op types sdk/agentop/security.go. WAF per site comes with the web module.
What works (lab w4-04, Ubuntu 24.04 containers, see docs/tasks/w4/w4-04-security.handover.md)
- Firewall: one
table inet respirecloud, rendered fromFWConfig(RenderNft, every token validated; nothing else is ever flushed), loaded atomically (nft -cfirst, thennft -f). Default-deny input; always open: loopback, established, protect_ips (admin IP is added automatically), ssh + panel ports. Presets web/mail/dns/ssh/panel/db-remote, custom allow/deny/rate_limit rules, SYN-rate and conn-count limits, ICMP limit, country block/allow-only from the DB-IP lite CSV (security.geo.update), outbound 25/465/587 blocked for uid 1000-59999 (hosting accounts). Allow/deny sets take IP/CIDR; temp bans have a TTL (kernel set timeout) and are re-added after a reload. - Anti-lockout: every apply arms a rollback (default 60 s, 10-3600). State is on disk (
/var/lib/respirecloud/security/fw/), so an agent restart keeps the timer; after a reboot the last confirmed ruleset is reloaded when the agent starts.firewall.confirmcancels it,firewall.rollbackrestores the previous ruleset now. The module notices an automatic rollback (1-min schedule /firewall.get) and emitssecurity.firewall.reverted. Versions are never reused.security.reconcile(15 min) reapplies the confirmed config if the table vanished. - Lockdown: protect IPs only (+ optional mail/dns) for a TTL, needs step-up; the TTL is the same rollback timer;
lockdown.disableends it. - CrowdSec (packagecloud repo, engine + nftables bouncer) with collections, journald acquisition for sshd/postfix/dovecot, nginx logs.
The local API is pinned to 127.0.0.1:18080 (8080 is too often taken).
share=false(default) sets an empty Central API credentials path: no signals out, no community list in; local bans still work.trust_private=falseremoves the RFC 1918 whitelist parser (labs). Allow-list = parser whitelist + our nft allow set. Decisions list / unblock; fail2ban (nftables banaction) is the fallback driver. - Malware: ClamAV (
clamscan, plus a localrc-signatures.ndbwith EICAR so it works before freshclam) and YARA (built-in rules in/var/lib/respirecloud/security/yara/, custom files viasecurity.yara.set, compiled-checked). Runs undersystemd-runinrc-security-scan.slice(CPUQuota 50 %, CPU/IO weight 20, Nice 19). Findings table, quarantine vault (root 0700, blob mode 000, openat2 BENEATH|NO_SYMLINKS so a user cannot redirect the move), restore (original owner/mode, refuses to overwrite), delete. Scheduled every 6 h. - Integrity: SHA-256/mode/owner baseline of /etc /usr/bin /usr/sbin (noisy files excluded), hourly diff, event on change; re-approved
automatically after
updates.runupgraded packages. - Updates:
updates.configure(unattended-upgrades, class security|all, reboot never|needed) andupdates.run. The health watch runs inside the agent (works with the control plane down): every 15 s each watched unit that was up and is not gets one restart; eventsservice_failed/recoveredare drained by the module every minute. Lab: nginx stopped, active again in <10 s. - Hardening: 15 sysctl + 4 file-permission checks, dry-run diff, fix writes
/etc/sysctl.d/60-respirecloud-hardening.conf. - Ports audit: listeners with process, exposed (non-loopback and accepted by our ruleset), expected.
- Score (0-100, server): firewall 25, CrowdSec 15, SSH 15 (password auth off 8, root login not yes 7), updates 10, malware scan <7 d and no
open findings 10, integrity 5, hardening 10, ports 10. Account score: scan recency 50 + no open findings 50. History (90 d) in
score_history;score.fixreturns a reviewed plan (dry run) and runs the suggested fixes;security.score.droppedon a drop of 10+. - Events: every ban, detection, firewall change, update result, lockdown lands in
events(+ live stream); users see only their account's.
Not done / next
WAF, bot challenge, rate limits per site, geo per site (web module). Rootkit scan, real-time fanotify scan, CVE feed, per-node role targeting and automatic node-to-node ports (cluster: today add an allow rule for the NATS port 4222 of enrolled nodes), SSH port change (files module), PDF/HTML report, UI bundle. fail2ban fallback is implemented but was not run in the lab.