Systemd Service
Run Dwaar as a managed systemd service on Linux. Systemd handles process supervision, automatic restarts, journal logging, and capability grants — so Dwaar can bind ports 80 and 443 without running as root.
Quick Start
Section titled “Quick Start”# Copy the unit filesudo cp /usr/share/dwaar/dwaar.service /etc/systemd/system/dwaar.service
# Reload unit definitionssudo systemctl daemon-reload
# Enable on boot and start nowsudo systemctl enable --now dwaar
# Confirm it is runningsudo systemctl status dwaarUnit File
Section titled “Unit File”[Unit]Description=Dwaar reverse proxyDocumentation=https://dwaar.dev/docsAfter=network-online.targetWants=network-online.target
[Service]Type=simpleExecStart=/usr/local/bin/dwaar --config /etc/dwaar/DwaarfileExecReload=/bin/kill -HUP $MAINPIDRestart=on-failureRestartSec=5sTimeoutStartSec=30sTimeoutStopSec=60s
# Run as a dedicated non-root userUser=dwaarGroup=dwaar
# Working directory and environmentWorkingDirectory=/etc/dwaarEnvironmentFile=-/etc/dwaar/dwaar.env
# Grant permission to bind privileged ports without rootAmbientCapabilities=CAP_NET_BIND_SERVICECapabilityBoundingSet=CAP_NET_BIND_SERVICE
# PID file (written by Pingora when --daemon is used)PIDFile=/run/dwaar/dwaar.pidRuntimeDirectory=dwaarRuntimeDirectoryMode=0750
[Install]WantedBy=multi-user.targetSave this to /etc/systemd/system/dwaar.service then run systemctl daemon-reload.
Capabilities
Section titled “Capabilities”Dwaar binds ports 80 and 443 by default. On Linux, binding ports below 1024 requires either root or CAP_NET_BIND_SERVICE.
| Setting | Value | Effect |
|---|---|---|
AmbientCapabilities | CAP_NET_BIND_SERVICE | Grants the capability to the process at exec time |
CapabilityBoundingSet | CAP_NET_BIND_SERVICE | Prevents any other capability from being added |
User | dwaar | Process runs as a non-root user |
Create the service account before starting the unit:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin dwaarIf you bind only to ports above 1024 (e.g. behind a load balancer), remove both AmbientCapabilities and CapabilityBoundingSet from the unit file.
Log Integration
Section titled “Log Integration”Dwaar writes structured JSON logs to stdout. Systemd captures stdout automatically and routes it to the journal.
View live logs:
journalctl -u dwaar -fView logs since last boot:
journalctl -u dwaar -bFilter by priority (errors only):
journalctl -u dwaar -p errExport as JSON for log shippers:
journalctl -u dwaar -o json | jq .To persist logs across reboots, ensure /var/log/journal exists:
sudo mkdir -p /var/log/journalsudo systemd-tmpfiles --create --prefix /var/log/journalReload
Section titled “Reload”Send SIGHUP to trigger a zero-disruption config reload. The config watcher re-reads the Dwaarfile, recompiles routes, and swaps in new upstream pools without restarting the process or dropping connections.
# Via systemctl (preferred)sudo systemctl reload dwaar
# Via the CLIdwaar reload
# Directly (sends SIGHUP)sudo kill -HUP $(cat /run/dwaar/dwaar.pid)The ExecReload line in the unit file maps systemctl reload to SIGHUP:
ExecReload=/bin/kill -HUP $MAINPIDHardening
Section titled “Hardening”Apply these systemd security directives to reduce the attack surface. Add them to the [Service] section.
[Service]# FilesystemProtectSystem=strictProtectHome=trueReadWritePaths=/etc/dwaar /var/log/dwaar /run/dwaar /etc/dwaar/certs /etc/dwaar/acme
# Privilege escalationNoNewPrivileges=trueSecureBits=keep-caps
# Kernel and system callsProtectKernelTunables=trueProtectKernelModules=trueProtectKernelLogs=trueProtectControlGroups=trueRestrictAddressFamilies=AF_INET AF_INET6 AF_UNIXRestrictNamespaces=trueLockPersonality=trueMemoryDenyWriteExecute=trueRestrictRealtime=trueRestrictSUIDSGID=true
# DevicesPrivateDevices=true
# Temporary filesystemPrivateTmp=true| Directive | What it prevents |
|---|---|
ProtectSystem=strict | Mounts /, /usr, /boot read-only |
ProtectHome=true | Blocks access to all home directories |
NoNewPrivileges=true | Prevents setuid/setgid escalation |
PrivateDevices=true | Hides all device nodes except pseudo-devices |
PrivateTmp=true | Isolates /tmp and /var/tmp |
MemoryDenyWriteExecute=true | Blocks JIT and shellcode injection |
RestrictAddressFamilies | Limits sockets to IPv4, IPv6, and Unix |
Complete Example
Section titled “Complete Example”Production-ready unit file with all hardening options applied:
[Unit]Description=Dwaar reverse proxyDocumentation=https://dwaar.dev/docsAfter=network-online.targetWants=network-online.target
[Service]Type=simpleExecStart=/usr/local/bin/dwaar --config /etc/dwaar/DwaarfileExecReload=/bin/kill -HUP $MAINPIDRestart=on-failureRestartSec=5sTimeoutStartSec=30sTimeoutStopSec=60s
User=dwaarGroup=dwaarWorkingDirectory=/etc/dwaarEnvironmentFile=-/etc/dwaar/dwaar.env
AmbientCapabilities=CAP_NET_BIND_SERVICECapabilityBoundingSet=CAP_NET_BIND_SERVICE
PIDFile=/run/dwaar/dwaar.pidRuntimeDirectory=dwaarRuntimeDirectoryMode=0750
# HardeningProtectSystem=strictProtectHome=trueReadWritePaths=/etc/dwaar /var/log/dwaar /run/dwaar /etc/dwaar/certs /etc/dwaar/acmeNoNewPrivileges=trueSecureBits=keep-capsProtectKernelTunables=trueProtectKernelModules=trueProtectKernelLogs=trueProtectControlGroups=trueRestrictAddressFamilies=AF_INET AF_INET6 AF_UNIXRestrictNamespaces=trueLockPersonality=trueMemoryDenyWriteExecute=trueRestrictRealtime=trueRestrictSUIDSGID=truePrivateDevices=truePrivateTmp=true
[Install]WantedBy=multi-user.targetVerify the security score with:
systemd-analyze security dwaarA well-hardened unit scores below 4.0 (SAFE).
Related
Section titled “Related”- Docker — running Dwaar in a container
- Zero-Downtime Upgrades — upgrading the binary without dropping connections
- Installation — binary installation options