Running on servers
A server has no desktop and no one to click a dialog, and its code lives in /srv, /var/www or /opt rather than in a home folder. Server mode installs the guard for that: a system service that starts at boot, runs as root, watches those folders and logs to the system journal.
| Desktop install | Server install (--server) |
|
|---|---|---|
| Starts | when you sign in | at boot |
| Service | per-user service | systemd system service (Linux) |
| Needs | no administrator rights | sudo |
| Dialogs and desktop notifications | yes | none: nothing waits for a click |
| Editor hardening | yes | skipped: there is no editor |
| Watches | project folders under your home | /srv, /var/www, /opt, /usr/local/src (those that exist), or --roots |
| Settings, quarantine, history | ~/.pushwarden |
/var/lib/pushwarden |
| Logs | ~/.pushwarden/guard.log |
journalctl -u pushwarden-guard and guard.log |
Everything else is the same: real-time file protection, the 5-second process and network check, the 6-hour full sweep, the generic rules, reversible quarantine and the signed self-update.
Install
With the one-line installer, run as root:
curl -fsSL https://pushwarden.com/install.sh | \
sudo PUSHWARDEN_SERVER=1 PUSHWARDEN_ROOTS="/srv /var/www" sh
Or download the release program (see Installation) and run it:
sudo ./pushwarden install --server --roots /srv/sites --webhook https://hooks.slack.com/services/T000/B000/XXXX
Add --dry-run first to see everything it would write without changing anything. As a normal user, install --server refuses and tells you to use sudo.
What it does:
- Copies the program to
/usr/local/lib/pushwarden/and links it as/usr/local/bin/pushwarden. - Writes
/etc/systemd/system/pushwarden-guard.service, enables it and starts it. It restarts if it stops, and also after a reboot. - Saves the server settings in
/var/lib/pushwarden/config.json: no dialogs, no desktop notifications, and the folders above to watch. Folders you already chose are never replaced when you run it again. - Runs a first scan that only reports; the guard’s start-up sweep then applies the policy below.
- Blocks the PolinRider command servers at the firewall, as root, unless you pass
--no-block-c2. See Blocking C2 servers.
| Option | Effect |
|---|---|
--server |
the server install described here |
--report-only |
with --server: report malware and never move or change a file |
--roots DIR |
folder to watch, repeatable; replaces the default list |
--webhook URL |
send each alert to Slack, Discord, Teams or your own endpoint |
--no-kill |
never kill processes automatically |
--deep |
also scan node_modules and vendor (slow) |
--dry-run |
show what would be done and change nothing |
The installer’s environment variables are PUSHWARDEN_SERVER=1, PUSHWARDEN_REPORT_ONLY=1, PUSHWARDEN_ROOTS and PUSHWARDEN_WEBHOOK.
What it may change
By default an infected file is moved to quarantine the moment it is written, and a process that carries a strict campaign marker is killed. Every change is copied first and can be undone with sudo pushwarden history --restore PATH.
For a production server where nothing should be touched without a person deciding, install with --report-only, or change it later:
sudo pushwarden config --set action=report
sudo systemctl restart pushwarden-guard
The guard reads its settings when it starts, so restart it after a change. In report-only mode the alert says what was found and why; you act with scan --fix or history when you have looked.
Day to day
Use sudo: as root, pushwarden works on the server’s data in /var/lib/pushwarden, while an ordinary user has a separate ~/.pushwarden for their own scans.
sudo pushwarden status # score, whether the guard is running, the latest sweep
sudo pushwarden alerts # recent alerts with the reason for each
sudo pushwarden history # everything it found and did
sudo pushwarden history --restore /srv/sites/app/index.js
journalctl -u pushwarden-guard -f # live log
The activity record /var/lib/pushwarden/journal.jsonl is one JSON object per line, ready for a log shipper or a SIEM; pushwarden history --json prints it too.
Alerts
With no desktop, alerts go to the log and to the places you configure: a webhook (--webhook, or config --set webhook_url=...). See Team reporting.
Updates
The guard runs as root, so its signed self-update works: it replaces the program in /usr/local/lib/pushwarden/ and restarts itself, and rolls back if the new version does not start. To update by hand: sudo pushwarden update.
PushWarden Pro on a server
Put the key in /etc/pushwarden/environment (the installer creates the file, readable only by root):
PUSHWARDEN_LICENSE_KEY=PW-XXXXX-XXXXX-XXXXX-XXXXX
Then sudo systemctl restart pushwarden-guard. The guard activates the key once and confirms it about daily. Each server uses one of the key’s devices; see Free and Pro.
Without a background service
For a server where you do not want a daemon, or for a pipeline, scan on a schedule. scan --ci prints no colour, never asks, and exits 1 when something is found:
# /etc/cron.d/pushwarden: every night at 03:15; the JSON report is kept and cron mails the output
15 3 * * * root pushwarden scan --ci --no-system --json /var/log/pushwarden-scan.json /srv /var/www
For build servers and pull requests see CI and automation.
In a container
installers/docker/Dockerfile builds an image that scans folders you mount (make docker-pushwarden builds it). It is not published to a registry yet.
docker run --rm -v /srv:/scan:ro pushwarden # scan, read-only; exit code 1 when infected
docker run --rm --user root -v /srv:/scan -v pushwarden-data:/data \
pushwarden scan --ci --no-system --fix /scan # quarantine what it finds
Remove it
sudo pushwarden uninstall # stop and remove the service
sudo pushwarden uninstall --unblock # also remove the firewall block
sudo pushwarden uninstall --purge # also delete /var/lib/pushwarden (settings, quarantine, history)
Limits
- The system service is Linux only. On macOS and Windows,
install --serverapplies the headless settings and the usual per-user service. - The service runs as root, so it can read and quarantine files anywhere. A dedicated service account is not available yet.