Running as a service
For a machine you actually want monitored, the agent should start at boot and restart if it stops.
Watchtower does not ship a service installer. There is no .msi, no systemd
unit, and no launchd plist in the box — you write the service definition
yourself using the examples below.
A proper installer is planned. Until then, the one thing you must get right is
WT_CREDENTIAL_PATH.
Set the credential path explicitly
This is the part that catches people.
The default credential location is derived from the home directory of the user running the agent. A service account has a different home directory, or none — so without an explicit path the credential lands somewhere unexpected, and in the worst case in whatever directory the service happened to start in.
Pick a system path and set it:
| Platform | Suggested path |
|---|---|
| Linux | /var/lib/wt-agent/credential.json |
| Windows | C:\ProgramData\wt-agent\credential.json |
| macOS | /Library/Application Support/wt-agent/credential.json |
Create the directory, make the service account its owner, and keep it unreadable by other users. The agent writes the file owner-only, but it cannot fix a directory that is open to everyone.
Linux (systemd)
/etc/systemd/system/wt-agent.service:
[Unit]
Description=Watchtower agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=wt-agent
Environment=WT_APP_URL=https://watchtower.page
Environment=WT_BROKER_URL=wss://broker.watchtower.page/ws
Environment=WT_CREDENTIAL_PATH=/var/lib/wt-agent/credential.json
EnvironmentFile=/etc/wt-agent/env
ExecStart=/usr/local/bin/wt-agent
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Put the API key in /etc/wt-agent/env, readable only by root, so it is not
visible in the unit file or in systemctl show:
WT_API_KEY=wt_your_key_here
Then:
sudo useradd --system --no-create-home wt-agent
sudo mkdir -p /var/lib/wt-agent && sudo chown wt-agent:wt-agent /var/lib/wt-agent && sudo chmod 700 /var/lib/wt-agent
sudo chmod 600 /etc/wt-agent/env
sudo systemctl daemon-reload
sudo systemctl enable --now wt-agent
sudo journalctl -u wt-agent -f
Windows
The agent is a console program, not a native Windows service, so it needs a wrapper. NSSM is the usual choice:
nssm install WatchtowerAgent "C:\Program Files\Watchtower\wt-agent.exe"
nssm set WatchtowerAgent AppEnvironmentExtra WT_APP_URL=https://watchtower.page WT_BROKER_URL=wss://broker.watchtower.page/ws WT_CREDENTIAL_PATH=C:\ProgramData\wt-agent\credential.json WT_API_KEY=wt_your_key_here
nssm set WatchtowerAgent Start SERVICE_AUTO_START
nssm start WatchtowerAgent
Create C:\ProgramData\wt-agent\ first and restrict it to the account the
service runs as. Note that environment variables set this way are readable by
anyone who can read the service configuration — on a shared machine, prefer
running the agent once interactively to register it, then removing WT_API_KEY
from the service definition entirely. The credential is all it needs after that.
macOS (launchd)
/Library/LaunchDaemons/page.watchtower.agent.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>page.watchtower.agent</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/wt-agent</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>WT_APP_URL</key>
<string>https://watchtower.page</string>
<key>WT_BROKER_URL</key>
<string>wss://broker.watchtower.page/ws</string>
<key>WT_CREDENTIAL_PATH</key>
<string>/Library/Application Support/wt-agent/credential.json</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
sudo launchctl load /Library/LaunchDaemons/page.watchtower.agent.plist
Register the machine once by running the agent manually with WT_API_KEY set
before loading the daemon, so the key never has to appear in the plist.
Registering first, then running as a service
The cleanest pattern on any platform:
- Run the agent once by hand, with
WT_API_KEYandWT_CREDENTIAL_PATHset to the system path, as the account the service will use. - Confirm the machine appears in the console and the credential file exists.
- Configure the service without
WT_API_KEY, pointing at the sameWT_CREDENTIAL_PATH.
The key never lands in a service definition, and the service starts with a credential already in place.