Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions packaging/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,17 @@ install -m 644 "$SCRIPT_DIR/pimonitor-apt-update.service" /etc/systemd/system/pi
install -m 644 "$SCRIPT_DIR/pimonitor-apt-update.timer" /etc/systemd/system/pimonitor-apt-update.timer

# Capture this before daemon-reload/enable so an upgrade of an already-running
# service is detected: 'enable --now' is a no-op when the unit is already
# active, which would otherwise leave the old binary running until an
# unrelated reboot/restart.
# service/timer is detected: 'enable --now' is a no-op when the unit is
# already active, which would otherwise leave the old binary/schedule loaded
# until an unrelated reboot/restart.
SERVICE_WAS_ACTIVE=0
if systemctl is-active --quiet pimonitor.service; then
SERVICE_WAS_ACTIVE=1
fi
TIMER_WAS_ACTIVE=0
if systemctl is-active --quiet pimonitor-apt-update.timer; then
TIMER_WAS_ACTIVE=1
fi

systemctl daemon-reload

Expand All @@ -100,9 +104,15 @@ if [[ "$SERVICE_WAS_ACTIVE" -eq 1 ]]; then
echo "pimonitor.service was already running; restarting to pick up the new binary/unit..."
systemctl restart pimonitor.service
fi
if [[ "$TIMER_WAS_ACTIVE" -eq 1 ]]; then
echo "pimonitor-apt-update.timer was already active; restarting to pick up any schedule change..."
systemctl restart pimonitor-apt-update.timer
fi

echo "Running an initial apt cache refresh so the update count isn't empty on first view..."
systemctl start pimonitor-apt-update.service || true
if ! systemctl start pimonitor-apt-update.service; then
echo "warning: initial apt cache refresh failed; check 'systemctl status pimonitor-apt-update.service'" >&2
fi

echo
echo "Done. Check status with:"
Expand Down
34 changes: 34 additions & 0 deletions packaging/pimonitor-apt-update.service
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,37 @@ Type=oneshot
# This is the only part of PiMonitor that touches apt with write intent;
# the main pimonitor.service never runs this itself and never needs root.
ExecStart=/usr/bin/apt-get update

# Hardening. apt-get update needs root (to write the package lists/cache
# and to drop privileges to the _apt sandbox user for the actual network
# fetch) so this can't be locked down as tightly as pimonitor.service, but
# the following cheap directives still apply.
NoNewPrivileges=true
# strict (not full) so ReadWritePaths= below actually confines writes
# instead of being a no-op - traced (strace) against a live 'apt-get
# update': the only write-mode opens are under /var/lib/apt/lists (index
# files) and /tmp (apt-key's gpg homedir, already covered by PrivateTmp).
# /var/cache/apt is included for portability across apt versions that
# rebuild pkgcache.bin here. Nothing is written under /var/log/apt - that's
# only touched by install/remove, not update.
ProtectSystem=strict
ReadWritePaths=/var/lib/apt /var/cache/apt
ProtectHome=true
PrivateTmp=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectControlGroups=true

# Trimmed from the default (full) capability set for root. Verified against
# a live 'apt-get update' run: apt drops to the _apt user for the actual
# download (CAP_SETUID/CAP_SETGID), then chowns/chmods the fetched index
# files (CAP_CHOWN/CAP_FOWNER) and needs CAP_DAC_OVERRIDE to replace
# lock/partial files it doesn't own as _apt. Dropping any one of these five
# makes apt-get update fail outright or silently leave files root-owned
# instead of _apt-owned.
CapabilityBoundingSet=CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_SETGID CAP_SETUID

# The 6-hourly refresh shouldn't compete with foreground workloads on slow
# SD cards.
Nice=19
IOSchedulingClass=idle
Loading