fix: deployment corrections from independent review

Six fixes addressing operational correctness on a real Debian host:

1. Ownership after git operations: chown -R zopu:zopu on the checkout
   after clone/update/rollback before running bun install/build as the
   service user. .env kept at 0600 with explicit chmod after each
   operation.

2. sudo replaced with runuser: minimal Debian does not include sudo.
   runuser is part of util-linux (essential) and always available.
   All three scripts (bootstrap, update, rollback) now use runuser -u.

3. cron.d entry fixed: /etc/cron.d format requires a username field.
   Added ${SERVICE_USER} between the time fields and the command path.

4. Firewall: added explicit `ufw allow in on tailscale0` rule so the
   deny-incoming default does not block Tailscale private-overlay
   reachability. Removed inaccurate claim that direct private IP works
   by default; documented that an explicit per-interface rule is needed.

5. SupplementaryGroups=docker added to zopu-agent.service: the Orb
   sandbox runtime lives in the agent process, not just the daemon.

6. zopu-health.service: added Environment=ENV_FILE=__INSTALL_DIR__/.env
   so health-check.sh sources the correct .env at custom install paths.

Verified Flue build output: bun run build:agents produces
packages/agents/dist/server.mjs (confirmed by running the build).
Agent unit ExecStart path is correct.

Validated: bash -n on all 6 shell scripts; mocked health-check smoke
against live RivetKit engine on port 6420; systemd unit structural
checks. No JS/TS/agent files changed.
This commit is contained in:
-Puter
2026-07-24 20:49:54 +05:30
parent 8f0b915f4b
commit 113c755e23
6 changed files with 90 additions and 25 deletions

View File

@@ -8,6 +8,8 @@
#
# .env is gitignored and is never touched by git operations. It survives
# updates and rollbacks unchanged.
#
# Must be run as root (uses runuser to build as the service user).
set -euo pipefail
@@ -21,6 +23,10 @@ NC='\033[0m'
log() { echo -e "${GREEN}[rollback]${NC} $*"; }
err() { echo -e "${RED}[rollback]${NC} $*" >&2; }
run_as_service() {
runuser -u "$SERVICE_USER" -- "$@"
}
cd "$INSTALL_DIR"
# Determine target
@@ -51,21 +57,26 @@ echo "$CURRENT_SHA" > "${INSTALL_DIR}/.pre-rollback-sha"
# Checkout target
git checkout "$ROLLBACK_SHA"
# Confirm .env is intact
# Restore ownership of the checkout to the service user after git operations
log "Setting ownership of checkout to $SERVICE_USER..."
chown -R "$SERVICE_USER":"$SERVICE_USER" "$INSTALL_DIR"
# Confirm .env is intact and has correct permissions
if [[ -f "${INSTALL_DIR}/.env" ]]; then
log ".env preserved."
chmod 600 "${INSTALL_DIR}/.env"
else
err ".env is missing! Restore it from backup before starting services."
fi
log "Running bun install..."
sudo -u "$SERVICE_USER" bun install
run_as_service bun install
log "Building daemon..."
sudo -u "$SERVICE_USER" bun run build:daemon
run_as_service bun run build:daemon
log "Building agent service..."
sudo -u "$SERVICE_USER" bun run build:agents
run_as_service bun run build:agents
log "Restarting services..."
systemctl restart zopu-daemon

View File

@@ -12,6 +12,8 @@
#
# .env is gitignored and is never touched by git operations. It survives
# updates and rollbacks unchanged.
#
# Must be run as root (uses runuser to build as the service user).
set -euo pipefail
@@ -28,6 +30,10 @@ log() { echo -e "${GREEN}[update]${NC} $*"; }
warn() { echo -e "${YELLOW}[update]${NC} $*"; }
err() { echo -e "${RED}[update]${NC} $*" >&2; }
run_as_service() {
runuser -u "$SERVICE_USER" -- "$@"
}
cd "$INSTALL_DIR"
# Record current commit for rollback
@@ -55,22 +61,27 @@ fi
NEW_SHA=$(git rev-parse HEAD)
log "Now at: ${NEW_SHA:0:12}"
# Confirm .env is intact
# Restore ownership of the checkout to the service user after git operations
log "Setting ownership of checkout to $SERVICE_USER..."
chown -R "$SERVICE_USER":"$SERVICE_USER" "$INSTALL_DIR"
# Confirm .env is intact and has correct permissions
if [[ -f "${INSTALL_DIR}/.env" ]]; then
log ".env preserved."
chmod 600 "${INSTALL_DIR}/.env"
else
err ".env is missing! Restore it from backup before starting services."
fi
# Install and build
log "Running bun install..."
sudo -u "$SERVICE_USER" bun install
run_as_service bun install
log "Building daemon binary..."
sudo -u "$SERVICE_USER" bun run build:daemon
run_as_service bun run build:daemon
log "Building agent service..."
sudo -u "$SERVICE_USER" bun run build:agents
run_as_service bun run build:agents
# Graceful restart: daemon first (owns RivetKit engine), then agent
log "Restarting services..."