Linux Server Setup - Production-Ready Configuration
This guide walks through setting up Update-Watcher on a Linux production server with proper security boundaries. The result is a dedicated system user with minimal permissions that runs automated update checks on a daily schedule.
Step 1: Create a Dedicated System User
Create a system user with no login shell and a home directory for storing state:
sudo useradd -r -s /usr/sbin/nologin -m -d /var/lib/update-watcher update-watcher| Flag | Purpose |
|---|---|
-r | Create a system account (low UID, no aging). |
-s /usr/sbin/nologin | Prevent interactive login. |
-m -d /var/lib/update-watcher | Create a home directory for the user. |
Step 2: Configuration Directory and Permissions
Create the configuration directory and set ownership:
sudo mkdir -p /etc/update-watcher
sudo chown update-watcher:update-watcher /etc/update-watcher
sudo chmod 755 /etc/update-watcherIf a configuration file already exists, move it and set restrictive permissions:
sudo mv config.yaml /etc/update-watcher/config.yaml
sudo chown update-watcher:update-watcher /etc/update-watcher/config.yaml
sudo chmod 600 /etc/update-watcher/config.yaml600 permission ensures only the update-watcher user can read the file, which is important because it may contain webhook URLs, API tokens, and SMTP credentials.Step 3: Log File Setup (Optional)
If you want persistent logging beyond cron mail:
sudo touch /var/log/update-watcher.log
sudo chown update-watcher:update-watcher /var/log/update-watcher.log
sudo chmod 644 /var/log/update-watcher.logThen configure the log file path in your config:
settings:
log_file: "/var/log/update-watcher.log"Step 4: Sudoers Configuration
Most system package manager checkers need sudo to refresh package lists. Grant the update-watcher user passwordless sudo for only the specific commands it needs.
Create a sudoers drop-in file:
sudo visudo -f /etc/sudoers.d/update-watcherAdd the rules for your distribution’s package manager. Only include the section for the package manager(s) you use.
APT (Debian, Ubuntu)
update-watcher ALL=(ALL) NOPASSWD: /usr/bin/apt-get updateDNF (Fedora, RHEL, Rocky, AlmaLinux)
update-watcher ALL=(ALL) NOPASSWD: /usr/bin/dnf check-update
update-watcher ALL=(ALL) NOPASSWD: /usr/bin/dnf updateinfoPacman (Arch Linux, Manjaro)
update-watcher ALL=(ALL) NOPASSWD: /usr/bin/pacman -SyMultiple Package Managers
If you monitor multiple package managers on the same host (uncommon but possible), combine the rules in a single file:
update-watcher ALL=(ALL) NOPASSWD: /usr/bin/apt-get update
update-watcher ALL=(ALL) NOPASSWD: /usr/bin/snap refresh --listsudo visudo -c -f /etc/sudoers.d/update-watcherStep 5: Docker Access
If you are using the Docker checker to monitor running containers, add the update-watcher user to the docker group:
sudo usermod -aG docker update-watcher/var/run/docker.sock) without requiring sudo. The Docker checker queries image digests to detect newer versions but never pulls images or modifies containers.Step 6: WordPress and Web Project Access
If you are monitoring WordPress sites or web projects, the update-watcher user needs read access to the project directories. Add the user to the web server group:
sudo usermod -aG www-data update-watcherOn some distributions, the web server group may be nginx, apache, or http instead of www-data. Check with:
stat -c '%G' /var/wwwEnsure the project directories and wp-config.php are group-readable:
sudo chmod -R g+r /var/www/mysiteStep 7: Cron Scheduling
Install a cron job under the dedicated user:
sudo crontab -u update-watcher -eAdd the following entry:
# update-watcher: daily update check
0 7 * * * /usr/local/bin/update-watcher run --quiet --as-service-userAlternatively, use the built-in cron management while running as the service user:
sudo -u update-watcher update-watcher install-cronFor more scheduling options including twice-daily runs and logging, see Cron Scheduling.
Summary Table
| Resource | Path | Permissions | Owner |
|---|---|---|---|
| Binary | /usr/local/bin/update-watcher | 755 | root:root |
| Config directory | /etc/update-watcher/ | 755 | update-watcher:update-watcher |
| Config file | /etc/update-watcher/config.yaml | 600 | update-watcher:update-watcher |
| Log file | /var/log/update-watcher.log | 644 | update-watcher:update-watcher |
| Home directory | /var/lib/update-watcher/ | 700 | update-watcher:update-watcher |
| Sudoers drop-in | /etc/sudoers.d/update-watcher | 440 | root:root |
Security Notes
- No inbound ports – Update-Watcher does not listen on any ports. All network activity is outbound HTTPS to notification services and the GitHub API.
- Read-only operations – Checkers never install updates, pull Docker images, or modify your system. They only query for available updates.
- Minimal sudo – The sudoers configuration grants access only to the specific package manager commands needed for refreshing package lists.
- Secret protection – The config file (which may contain webhook URLs, API tokens, and credentials) is readable only by the
update-watcheruser (chmod 600).
Verifying the Setup
Run a test check as the service user to verify everything works:
sudo -u update-watcher update-watcher run --verbose --notify=falseCheck each component:
# Verify config is readable
sudo -u update-watcher update-watcher validate
# Verify status
sudo -u update-watcher update-watcher status
# Verify cron is installed
sudo crontab -u update-watcher -lRelated
- macOS Setup – Setup guide for macOS.
- Cron Scheduling – Detailed cron options and logging.
- Configuration – Full YAML configuration reference.
- Security Best Practices – Additional hardening guidance.