WorkWarden is a Fedora GNOME-focused self-control service for separating a personal Linux account from a restricted work account.
The project installs exactly one custom systemd service:
workwarden.service
The runtime is written in C++20 and does not require Python. One binary handles the daemon, PAM quota checks, configuration reads, time tracking, logging, application restrictions, and network policy orchestration.
Status: early Fedora-only release. Test on a non-critical machine before wider use.
Default configuration assumes:
- personal account:
amir - work account:
amir-work
Features:
- blocks selected executables for
amir-work, including terminal execution - prevents
amir-workfrom usingsuto switch torootoramir - removes
amir-workfromwheel; sudo remains an explicit allow-list you control - can block
pkexecandrun0foramir-work - redirects normal DNS from
amir-workto a filtered local resolver - blocks both IPv4 and IPv6 DNS answers for configured domains
- blocks DNS-over-TLS on port 853 for
amir-work - leaves
amirnetwork access unrestricted - limits
amirto a daily quota and a per-session quota - warns before the quota expires and can power off or terminate the session
- blocks new GDM/TTY login to
amirafter the daily quota is exhausted - keeps
amir-worklogin available after the personal quota is exhausted - writes structured JSONL events to
/var/log/workwarden/events.log - retains raw DNS and sudo logs in the same log directory
The current release intentionally targets Fedora GNOME and relies on Fedora's systemd, PAM, auditd, SELinux policy, nftables, systemd-resolved layout, and dnsmasq.
workwarden.service
│
C++20 workwarden binary
│
┌──────────────────┼───────────────────┐
│ │ │
App ACLs DNS child Time quota
│ dnsmasq │
amir-work │ amir
│ nftables │
│ UID DNS redirect │
└──────────── event logger ──────────────┘
│
PAM pam-check
The installed executable is:
/usr/libexec/workwarden/workwarden
Systemd runs:
/usr/libexec/workwarden/workwarden daemon
PAM calls the same binary:
/usr/libexec/workwarden/workwarden pam-check
sudo dnf install gcc-c++ cmake make
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallelOr:
make buildKeep a root-capable terminal/TTY available during the first migration. The installer changes PAM and DNS/NSS configuration.
Review the config first:
nano config/workwarden.tomlThen:
sudo ./scripts/install.shThe installer builds the C++ binary and removes the old custom units:
workguard-apps.service
workguard-dns.service
workguard-network.service
workguard-time.service
amir-workguard.service
It deliberately preserves your existing /etc/sudoers.d/amir-work allow-list.
Installed configuration:
/etc/workwarden/config.toml
Example:
[users]
personal = "amir"
work = "amir-work"
su_admin_group = "workwarden-su"
[apps]
blocked = [
"/usr/bin/Telegram",
"/usr/bin/pkexec",
"/usr/bin/run0",
]
[network]
enabled = true
dns_port = 53053
upstream_dns = ["1.1.1.1", "8.8.8.8"]
blocked_domains = ["instagram.com", "reddit.com"]
[time]
enabled = true
daily_limit_seconds = 7200
session_limit_seconds = 1800
warning_before_seconds = 300
action = "poweroff"After changing app, network, or time configuration:
sudo systemctl restart workwarden.serviceEdit blocked_domains:
sudo nano /etc/workwarden/config.toml
sudo systemctl restart workwarden.serviceWorkWarden intentionally does not overwrite an existing sudo allow-list:
sudo visudo -f /etc/sudoers.d/amir-work
sudo visudo -cf /etc/sudoers.d/amir-work/var/log/workwarden/events.log
/var/log/workwarden/dns.log
/var/log/workwarden/sudo.log
events.log is JSON Lines and is rotated by the C++ daemon.
Example:
{"time":"2026-08-11T15:30:00+01:00","level":"INFO","event":"DOMAIN_BLOCKED","message":"Blocked DNS query","user":"amir-work","domain":"instagram.com"}Follow events:
sudo tail -f /var/log/workwarden/events.logThis is a self-control boundary, not a hostile-user security sandbox. The personal/root administrator can always alter the machine. The restricted work account is intentionally denied obvious privilege-switching paths and receives only the sudo commands you explicitly allow.
DNS filtering covers normal DNS and blocks DNS-over-TLS (853). DNS-over-HTTPS, VPNs, proxies, manually supplied IPs, and other tunneling methods are not comprehensively blocked in this release.
make lint
sudo ./scripts/test.shSee docs/TESTING.md for the manual account tests.
sudo ./scripts/uninstall.shThe uninstaller restores the PAM/NSS/resolver files captured by the installer and preserves user-managed sudo policy plus state/log files for inspection.
MIT.