From 6641f21dd29c04e787813cfeb71fc393cd2a8812 Mon Sep 17 00:00:00 2001 From: MickLesk Date: Sun, 3 May 2026 21:21:28 +0200 Subject: [PATCH] fix(pangolin): pin version, drop manual SQL, use upstream migrator Pangolin updates regularly broke (last: #14147 networkId/defaultNetworkId) because ct/pangolin.sh ran 'drizzle-kit push --force' against the live schema, which prompts interactively when columns look like renames. Pangolin already ships a versioned, idempotent migration runner (server/setup/migrationsSqlite.ts -> dist/migrations.mjs) that the official Docker image executes on every container start via 'npm run start'. Use the same mechanism instead of fighting drizzle-kit: - ct/pangolin.sh: PANGOLIN_VERSION=1.18.2 pin, remove ~80 lines of manual sqlite3 ALTER/CREATE pre-migration hacks, replace 'drizzle-kit push --force' with 'node dist/migrations.mjs'. - install/pangolin-install.sh: pin same PANGOLIN_VERSION, add ExecStartPre=node dist/migrations.mjs to pangolin.service so the DB is migrated automatically on every (re)start, matching Docker semantics. Closes #14147 --- ct/pangolin.sh | 45 +++++++++++++------------------------ install/pangolin-install.sh | 4 +++- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/ct/pangolin.sh b/ct/pangolin.sh index c135645dd..b96b4ddcb 100644 --- a/ct/pangolin.sh +++ b/ct/pangolin.sh @@ -6,6 +6,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV # Source: https://pangolin.net/ | Github: https://github.com/fosrl/pangolin APP="Pangolin" +PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.2}" var_tags="${var_tags:-proxy}" var_cpu="${var_cpu:-2}" var_ram="${var_ram:-4096}" @@ -33,7 +34,7 @@ function update_script() { NODE_VERSION="24" setup_nodejs - if check_for_gh_release "pangolin" "fosrl/pangolin"; then + if check_for_gh_release "pangolin" "fosrl/pangolin" "$PANGOLIN_VERSION" "Pinned to a tested release because Pangolin's schema changes have repeatedly broken unattended updates. To try a newer version at your own risk, run: 'export PANGOLIN_VERSION=' and re-run update. If it breaks, please open an issue at https://github.com/community-scripts/ProxmoxVE/issues with the error log."; then msg_info "Stopping Service" systemctl stop pangolin systemctl stop gerbil @@ -41,9 +42,13 @@ function update_script() { msg_info "Creating backup" tar -czf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin config + if [[ -f /opt/pangolin/config/db/db.sqlite ]]; then + cp -a /opt/pangolin/config/db/db.sqlite \ + "/opt/pangolin/config/db/db.sqlite.pre-${PANGOLIN_VERSION}-$(date +%Y%m%d-%H%M%S).bak" + fi msg_ok "Created backup" - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION" CLEAN_INSTALL=1 fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64" msg_info "Updating Pangolin" @@ -67,36 +72,16 @@ function update_script() { rm -f /opt/pangolin_config_backup.tar.gz msg_ok "Restored config" - msg_info "Running database migrations" - cd /opt/pangolin - - # Pre-apply potentially destructive schema changes safely so drizzle-kit - # does not recreate tables (which would delete all rows). - local DB="/opt/pangolin/config/db/db.sqlite" - if [[ -f "$DB" ]]; then - sqlite3 "$DB" "ALTER TABLE 'orgs' ADD COLUMN 'settingsLogRetentionDaysConnection' integer DEFAULT 0 NOT NULL;" 2>/dev/null || true - sqlite3 "$DB" "ALTER TABLE 'clientSitesAssociationsCache' ADD COLUMN 'isJitMode' integer DEFAULT 0 NOT NULL;" 2>/dev/null || true - sqlite3 "$DB" "ALTER TABLE 'userOrgs' ADD COLUMN 'pamUsername' text;" 2>/dev/null || true - - # Create new role-mapping tables and migrate data before drizzle-kit - # drops the roleId columns from userOrgs and userInvites. - sqlite3 "$DB" "CREATE TABLE IF NOT EXISTS 'userOrgRoles' ( - 'userId' text NOT NULL REFERENCES 'user'('id') ON DELETE CASCADE, - 'orgId' text NOT NULL REFERENCES 'orgs'('orgId') ON DELETE CASCADE, - 'roleId' integer NOT NULL REFERENCES 'roles'('roleId') ON DELETE CASCADE, - UNIQUE('userId', 'orgId', 'roleId') - );" 2>/dev/null || true - sqlite3 "$DB" "INSERT OR IGNORE INTO 'userOrgRoles' (userId, orgId, roleId) SELECT userId, orgId, roleId FROM 'userOrgs' WHERE roleId IS NOT NULL;" 2>/dev/null || true - - sqlite3 "$DB" "CREATE TABLE IF NOT EXISTS 'userInviteRoles' ( - 'inviteId' text NOT NULL REFERENCES 'userInvites'('inviteId') ON DELETE CASCADE, - 'roleId' integer NOT NULL REFERENCES 'roles'('roleId') ON DELETE CASCADE, - PRIMARY KEY('inviteId', 'roleId') - );" 2>/dev/null || true - sqlite3 "$DB" "INSERT OR IGNORE INTO 'userInviteRoles' (inviteId, roleId) SELECT inviteId, roleId FROM 'userInvites' WHERE roleId IS NOT NULL;" 2>/dev/null || true + if ! grep -q '^ExecStartPre=/usr/bin/node dist/migrations.mjs' /etc/systemd/system/pangolin.service 2>/dev/null; then + msg_info "Adding migration step to pangolin.service" + sed -i '/^ExecStart=\/usr\/bin\/node --enable-source-maps dist\/server.mjs/i ExecStartPre=/usr/bin/node dist/migrations.mjs' /etc/systemd/system/pangolin.service + systemctl daemon-reload + msg_ok "Updated pangolin.service" fi - ENVIRONMENT=prod $STD npx drizzle-kit push --force --config drizzle.sqlite.config.ts + msg_info "Running database migrations" + cd /opt/pangolin + ENVIRONMENT=prod $STD node dist/migrations.mjs msg_ok "Ran database migrations" msg_info "Updating Badger plugin version" diff --git a/install/pangolin-install.sh b/install/pangolin-install.sh index b522551ac..1ccd52c0b 100644 --- a/install/pangolin-install.sh +++ b/install/pangolin-install.sh @@ -22,7 +22,8 @@ $STD apt install -y \ msg_ok "Installed Dependencies" NODE_VERSION="24" setup_nodejs -fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" +PANGOLIN_VERSION="${PANGOLIN_VERSION:-1.18.2}" +fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" "$PANGOLIN_VERSION" fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64" fetch_and_deploy_gh_release "traefik" "traefik/traefik" "prebuild" "latest" "/usr/bin" "traefik_v*_linux_amd64.tar.gz" @@ -204,6 +205,7 @@ User=root Environment=NODE_ENV=production Environment=ENVIRONMENT=prod WorkingDirectory=/opt/pangolin +ExecStartPre=/usr/bin/node dist/migrations.mjs ExecStart=/usr/bin/node --enable-source-maps dist/server.mjs Restart=always RestartSec=10