fix: install chrony for host NTP and enable pic.service on cold install
Unit Tests / test (push) Successful in 12m0s

Root-cause fix for ACME failures caused by clock drift breaking TOTP
during DDNS registration: install and start chrony (all supported package
managers) before the setup wizard runs, so the host clock is accurate from
day one.

Also enables and starts the pic systemd unit at the end of a cold install —
previously the unit file was written but never activated, so the stack would
not survive a reboot without a manual `systemctl enable --now pic`.

Makefile uninstall hardened: `disable --now` instead of bare `disable` so the
running unit is stopped before the unit file is removed; daemon-reload called
afterwards to flush the stale unit; and all lingering cell-* containers
(tor/sshuttle/redsocks/store services) are now force-removed so subsequent
reinstalls start from a clean Docker state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 09:38:03 -04:00
parent aa1e5c41ec
commit a9c7235347
2 changed files with 40 additions and 2 deletions
+7 -2
View File
@@ -182,6 +182,7 @@ uninstall:
echo "Stopping containers and removing images..."; \ echo "Stopping containers and removing images..."; \
for f in data/api/services/*/docker-compose.yml; do [ -f "$$f" ] && PUID=$$(id -u) PGID=$$(id -g) docker compose -f "$$f" down 2>/dev/null || true; done; \ for f in data/api/services/*/docker-compose.yml; do [ -f "$$f" ] && PUID=$$(id -u) PGID=$$(id -g) docker compose -f "$$f" down 2>/dev/null || true; done; \
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile core down --rmi all 2>/dev/null || true; \ PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile core down --rmi all 2>/dev/null || true; \
docker ps -aq --filter "name=cell-" | xargs -r docker rm -f 2>/dev/null || true; \
docker network rm cell-network 2>/dev/null || true; \ docker network rm cell-network 2>/dev/null || true; \
echo "Deleting config/ and data/..."; \ echo "Deleting config/ and data/..."; \
sudo rm -rf config/ data/; \ sudo rm -rf config/ data/; \
@@ -191,14 +192,18 @@ uninstall:
echo "Stopping and removing containers (keeping images and data)..."; \ echo "Stopping and removing containers (keeping images and data)..."; \
for f in data/api/services/*/docker-compose.yml; do [ -f "$$f" ] && PUID=$$(id -u) PGID=$$(id -g) docker compose -f "$$f" down 2>/dev/null || true; done; \ for f in data/api/services/*/docker-compose.yml; do [ -f "$$f" ] && PUID=$$(id -u) PGID=$$(id -g) docker compose -f "$$f" down 2>/dev/null || true; done; \
PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile core down 2>/dev/null || true; \ PUID=$$(id -u) PGID=$$(id -g) $(DCF) --profile core down 2>/dev/null || true; \
docker ps -aq --filter "name=cell-" | xargs -r docker rm -f 2>/dev/null || true; \
echo "Done. Images, config/ and data/ are untouched. Run 'make start' to bring it back up."; \ echo "Done. Images, config/ and data/ are untouched. Run 'make start' to bring it back up."; \
;; \ ;; \
*) \ *) \
echo "Cancelled."; \ echo "Cancelled."; \
;; \ ;; \
esac esac
@-sudo systemctl disable pic 2>/dev/null || true @if command -v systemctl >/dev/null 2>&1; then \
@-sudo rm -f /etc/systemd/system/pic.service sudo systemctl disable --now pic 2>/dev/null || true; \
sudo rm -f /etc/systemd/system/pic.service; \
sudo systemctl daemon-reload 2>/dev/null || true; \
fi
@-sudo rm -f /opt/pic/.installed @-sudo rm -f /opt/pic/.installed
@echo "Note: Data volumes were not deleted. To remove all data, manually delete config/ and data/." @echo "Note: Data volumes were not deleted. To remove all data, manually delete config/ and data/."
+33
View File
@@ -157,6 +157,17 @@ case "$PKG_MANAGER" in
log_warn "docker-compose-plugin not available; falling back to standalone docker-compose" log_warn "docker-compose-plugin not available; falling back to standalone docker-compose"
sudo apt-get install -y -qq docker-compose 2>&1 | grep -v "^$" | sed 's/^/ /' || true sudo apt-get install -y -qq docker-compose 2>&1 | grep -v "^$" | sed 's/^/ /' || true
fi fi
# Ensure host clock is synchronised before DDNS/TOTP registration.
# chrony is preferred; the service name differs by distro (chrony on Debian, chronyd on some Ubuntu).
sudo apt-get install -y -qq chrony 2>&1 | grep -v "^$" | sed 's/^/ /' || true
if sudo systemctl enable --now chrony >/dev/null 2>&1; then
log_ok "Host NTP (chrony) enabled and started"
elif sudo systemctl enable --now chronyd >/dev/null 2>&1; then
log_ok "Host NTP (chronyd) enabled and started"
else
log_warn "Could not start chrony — verify host clock is accurate before running the setup wizard"
fi
;; ;;
dnf) dnf)
@@ -168,6 +179,11 @@ case "$PKG_MANAGER" in
log_warn "docker compose plugin not found; installing docker-compose-plugin..." log_warn "docker compose plugin not found; installing docker-compose-plugin..."
sudo dnf install -y -q docker-compose-plugin 2>&1 | sed 's/^/ /' || true sudo dnf install -y -q docker-compose-plugin 2>&1 | sed 's/^/ /' || true
fi fi
sudo dnf install -y -q chrony 2>&1 | sed 's/^/ /' || true
sudo systemctl enable --now chronyd >/dev/null 2>&1 \
&& log_ok "Host NTP (chronyd) enabled and started" \
|| log_warn "Could not start chronyd — verify host clock is accurate before running the setup wizard"
;; ;;
apk) apk)
@@ -175,6 +191,12 @@ case "$PKG_MANAGER" in
sudo rc-update add docker default >/dev/null 2>&1 || true sudo rc-update add docker default >/dev/null 2>&1 || true
sudo service docker start >/dev/null 2>&1 || true sudo service docker start >/dev/null 2>&1 || true
sudo apk add --quiet chrony 2>&1 | sed 's/^/ /' || true
sudo rc-update add chronyd default >/dev/null 2>&1 || true
sudo service chronyd start >/dev/null 2>&1 \
&& log_ok "Host NTP (chronyd) enabled and started" \
|| log_warn "Could not start chronyd — verify host clock is accurate before running the setup wizard"
;; ;;
esac esac
@@ -269,6 +291,17 @@ fi
log_ok "Core services started" log_ok "Core services started"
# Enable and start the pic systemd unit so the stack survives a reboot.
# Skipped on Alpine (OpenRC) and on systems without systemd.
if command -v systemctl >/dev/null 2>&1; then
sudo systemctl daemon-reload 2>/dev/null || true
if sudo systemctl enable --now pic 2>/dev/null; then
log_ok "systemd unit pic.service enabled and started"
else
log_warn "Could not enable pic.service — run: sudo systemctl enable --now pic"
fi
fi
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Step 7 — Health check + print wizard URL # Step 7 — Health check + print wizard URL
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------