fix: proper workflow — deploy Zoraxy minimal, upload certs, stop, write configs, restart

This commit is contained in:
Claus Lohmar 2026-07-07 19:17:54 +01:00
parent f44041f0d5
commit 48241364aa

196
deploy.sh
View file

@ -149,10 +149,10 @@ if [ "$GREENFIELD" = true ]; then
echo "[INFO] Version: $(cat $TARGET_DIR/VERSION)"
fi
# Write configs before starting Zoraxy (BoltDB must not be locked)
echo "[*] Writing configuration files..."
# --- Phase 1: Deploy Zoraxy with minimal config to get CSRF access ---
echo "[*] Phase 1: Deploying Zoraxy for configuration..."
# Write ACME config
# Write ACME config + BoltDB (before Zoraxy starts, db not locked)
mkdir -p "$TARGET_DIR/config/zoraxy/conf"
cat > "$TARGET_DIR/config/zoraxy/conf/acme_conf.json" <<EOF
{
@ -164,181 +164,119 @@ if [ "$GREENFIELD" = true ]; then
}
EOF
# Write admin + ZorxAuth to BoltDB (Zoraxy not running, db not locked)
if [ -f "$TOOL_BIN" ]; then
# Create the data directory and an empty database
mkdir -p "$TARGET_DIR/data/zoraxy"
touch "$TARGET_DIR/data/zoraxy/sys.db"
"$TOOL_BIN" db --db "$TARGET_DIR/data/zoraxy/sys.db" \
--set "system:admin:{\"username\":\"${ADMIN_USERNAME:-master}\"}" 2>&1 || true
"$TOOL_BIN" db --db "$TARGET_DIR/data/zoraxy/sys.db" \
--set "zorxauth:options:{\"enable_auth_gateway\":true,\"sso_redirect_url\":\"https://app.${DOMAIN}/\"}" 2>&1 || true
--set "zorxauth:options:{\"enable_auth_gateway\":true,\"sso_redirect_url\":\"https://${APP_SUB}.${DOMAIN}/\"}" 2>&1 || true
echo " [OK] Admin + ZorxAuth written to BoltDB"
fi
# Deploy Zoraxy
# Start Zoraxy (no custom proxy configs yet — CSRF will work)
cp compose/zoraxy.yaml "$TARGET_DIR/compose/zoraxy.yaml"
podman rm -f zoraxy 2>/dev/null || true
podman-compose -f "$TARGET_DIR/compose/zoraxy.yaml" up -d 2>&1 || echo "[WARN] Zoraxy deploy had issues"
# Generate Zoraxy proxy configs
echo "[*] Generating Zoraxy proxy configs..."
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/app.$DOMAIN.config" <<ZORAXY_APP
# Wait for Zoraxy to be ready
for i in $(seq 1 15); do
if curl -sf --max-time 3 "http://127.0.0.1:8000/api/auth/userCount" > /dev/null 2>&1; then break; fi
sleep 2
done
# --- Phase 2: Upload certificates via API (no proxy rules to interfere) ---
echo "[*] Phase 2: Registering certificates..."
CERTS_DIR="$TARGET_DIR/config/zoraxy/conf/certs"
for SUB in $APP_SUB $DNS_SUB $WWW_SUB; do
FQDN="${SUB}.${DOMAIN}"
CRT_FILE="$CERTS_DIR/${FQDN}.crt"
[ -f "$CRT_FILE" ] || continue
for TRY in 1 2 3; do
rm -f /tmp/zc.txt
PAGE=$(curl -s --max-time 5 -c /tmp/zc.txt "http://127.0.0.1:8000/login.html" 2>&1)
TOKEN=$(echo "$PAGE" | grep 'zoraxy.csrf.Token' | sed 's/.*content="//;s/".*//')
[ -z "$TOKEN" ] && sleep 2 && continue
R=$(curl -s --max-time 5 -b /tmp/zc.txt -X POST \
-H "X-CSRF-Token: $TOKEN" \
-H "Referer: http://127.0.0.1:8000/login.html" \
"http://127.0.0.1:8000/api/cert/upload?ktype=pub&domain=$FQDN" \
--data-binary "@$CRT_FILE" 2>&1) || true
if echo "$R" | grep -qi '"success"\|"ok"\|^{}$'; then
echo " [OK] Cert registered: $FQDN"
break
fi
sleep 2
done
done
# --- Phase 3: Stop Zoraxy, write custom configs ---
echo "[*] Phase 3: Writing custom proxy configs..."
podman stop zoraxy 2>/dev/null || true
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/${APP_SUB}.$DOMAIN.config" <<ZORAXY_APP
{
"ProxyType": 1,
"RootOrMatchingDomain": "${APP_SUB}.$DOMAIN",
"ActiveOrigins": [{
"OriginIpOrDomain": "127.0.0.1:9000",
"RequireTLS": false,
"Weight": 1,
"MaxConn": 0
}],
"Disabled": false,
"AuthenticationProvider": {"AuthMethod": 0}
"ActiveOrigins": [{"OriginIpOrDomain": "127.0.0.1:9000", "RequireTLS": false, "Weight": 1, "MaxConn": 0}],
"Disabled": false, "AuthenticationProvider": {"AuthMethod": 0}
}
ZORAXY_APP
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/$DNS_SUB.$DOMAIN.config" <<ZORAXY_DNS
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/${DNS_SUB}.$DOMAIN.config" <<ZORAXY_DNS
{
"ProxyType": 1,
"RootOrMatchingDomain": "${DNS_SUB}.$DOMAIN",
"ActiveOrigins": [{
"OriginIpOrDomain": "127.0.0.1:8000",
"RequireTLS": false,
"Weight": 1,
"MaxConn": 0
}],
"Disabled": false,
"AuthenticationProvider": {"AuthMethod": 0}
"ActiveOrigins": [{"OriginIpOrDomain": "127.0.0.1:8000", "RequireTLS": false, "Weight": 1, "MaxConn": 0}],
"Disabled": false, "AuthenticationProvider": {"AuthMethod": 0}
}
ZORAXY_DNS
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/$WWW_SUB.$DOMAIN.config" <<ZORAXY_WWW
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/${WWW_SUB}.$DOMAIN.config" <<ZORAXY_WWW
{
"ProxyType": 1,
"RootOrMatchingDomain": "${WWW_SUB}.$DOMAIN",
"ActiveOrigins": [{
"OriginIpOrDomain": "127.0.0.1:9000",
"RequireTLS": false,
"Weight": 1,
"MaxConn": 0
}],
"Disabled": false,
"AuthenticationProvider": {"AuthMethod": 0}
"ActiveOrigins": [{"OriginIpOrDomain": "127.0.0.1:9000", "RequireTLS": false, "Weight": 1, "MaxConn": 0}],
"Disabled": false, "AuthenticationProvider": {"AuthMethod": 0}
}
ZORAXY_WWW
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/auth.$DOMAIN.config" <<ZORAXY_AUTH
cat > "$TARGET_DIR/config/zoraxy/conf/proxy/${AUTH_SUB}.$DOMAIN.config" <<ZORAXY_AUTH
{
"ProxyType": 1,
"RootOrMatchingDomain": "${AUTH_SUB}.$DOMAIN",
"ActiveOrigins": [{
"OriginIpOrDomain": "127.0.0.1:5489",
"RequireTLS": false,
"Weight": 1,
"MaxConn": 0
}],
"Disabled": false,
"AuthenticationProvider": {"AuthMethod": 0}
"ActiveOrigins": [{"OriginIpOrDomain": "127.0.0.1:5489", "RequireTLS": false, "Weight": 1, "MaxConn": 0}],
"Disabled": false, "AuthenticationProvider": {"AuthMethod": 0}
}
ZORAXY_AUTH
chattr -R +i "$TARGET_DIR/config/zoraxy/conf/proxy/" 2>/dev/null || true
# Copy landing page
# Copy landing page + launcher config
cp -r config/www/* "$TARGET_DIR/config/zoraxy/www/html/"
# Copy launcher config
cp -r config/nextworkspace/* "$TARGET_DIR/config/nextworkspace/"
# Generate apps.yaml
echo "[*] Generating apps.yaml..."
cat > "$TARGET_DIR/config/nextworkspace/apps.yaml" <<EOF
apps:
- name: "OpenCloud"
subtitle: "File Storage"
path: "/cloud"
upstream: "http://127.0.0.1:9100"
icon: "cloud"
- name: "Euro Office"
subtitle: "Collaborative Suite"
path: "/office"
upstream: "http://127.0.0.1:9200"
icon: "office"
- name: "ERPNext"
subtitle: "Enterprise ERP"
path: "/erp"
upstream: "http://127.0.0.1:9300"
icon: "erp"
- name: "Matrix Chat"
subtitle: "Team Communication"
path: "/chat"
upstream: "http://127.0.0.1:9400"
icon: "chat"
- name: "Jitsi"
subtitle: "Video Conferencing"
path: "/meet"
upstream: "http://127.0.0.1:9500"
icon: "video"
- name: "Webmail"
subtitle: "Email Client"
path: "/mail"
upstream: "http://127.0.0.1:9600"
icon: "mail"
- name: "AI Chat"
subtitle: "Open WebUI"
path: "/ai"
upstream: "http://127.0.0.1:9700"
icon: "bot"
- name: "Portainer"
subtitle: "Container Management"
path: "/admin"
upstream: "http://127.0.0.1:9800"
icon: "admin"
- name: "OpenCloud" subtitle: "File Storage" path: "/cloud" upstream: "http://127.0.0.1:9100" icon: "cloud"
- name: "Euro Office" subtitle: "Collaborative Suite" path: "/office" upstream: "http://127.0.0.1:9200" icon: "office"
- name: "ERPNext" subtitle: "Enterprise ERP" path: "/erp" upstream: "http://127.0.0.1:9300" icon: "erp"
- name: "Matrix Chat" subtitle: "Team Communication" path: "/chat" upstream: "http://127.0.0.1:9400" icon: "chat"
- name: "Jitsi" subtitle: "Video Conferencing" path: "/meet" upstream: "http://127.0.0.1:9500" icon: "video"
- name: "Webmail" subtitle: "Email Client" path: "/mail" upstream: "http://127.0.0.1:9600" icon: "mail"
- name: "AI Chat" subtitle: "Open WebUI" path: "/ai" upstream: "http://127.0.0.1:9700" icon: "bot"
- name: "Portainer" subtitle: "Container Management" path: "/admin" upstream: "http://127.0.0.1:9800" icon: "admin"
EOF
# Upload certs to Zoraxy via API (needed to register them in sys.db)
echo "[*] Registering certificates in Zoraxy..."
# Wait for Zoraxy to be ready
for i in $(seq 1 15); do
if curl -sf --max-time 3 "http://127.0.0.1:8000/api/auth/userCount" > /dev/null 2>&1; then
break
fi
sleep 2
done
# Remove stale proxy.old dirs created by Zoraxy
rm -rf "$TARGET_DIR/config/zoraxy/conf/proxy.old" "$TARGET_DIR/config/zoraxy/conf/proxy-314.old" "$TARGET_DIR/config/zoraxy/conf/proxy-321.old" 2>/dev/null || true
CERTS_DIR="$TARGET_DIR/config/zoraxy/conf/certs"
for SUB in $APP_SUB $DNS_SUB $WWW_SUB; do
FQDN="${SUB}.${DOMAIN}"
CRT_FILE="$CERTS_DIR/${FQDN}.crt"
[ -f "$CRT_FILE" ] || continue
# Three retries with fresh CSRF each time
for TRY in 1 2 3; do
rm -f /tmp/zc.txt
PAGE=$(curl -s --max-time 5 -c /tmp/zc.txt "http://127.0.0.1:8000/login.html" 2>&1)
TOKEN=$(echo "$PAGE" | grep 'zoraxy.csrf.Token' | sed 's/.*content="//;s/".*//')
if [ -z "$TOKEN" ]; then
echo " Retry $TRY for $FQDN (no CSRF token in page)"
sleep 2
continue
fi
echo " Debug: token=${TOKEN:0:20}..."
R=$(curl -s --max-time 5 -b /tmp/zc.txt -X POST \
-H "X-CSRF-Token: $TOKEN" \
-H "Referer: http://127.0.0.1:8000/login.html" \
-H "Origin: http://127.0.0.1:8000" \
"http://127.0.0.1:8000/api/cert/upload?ktype=pub&domain=$FQDN" \
--data-binary "@$CRT_FILE" 2>&1) || true
if echo "$R" | grep -qi '"success"\|"ok"\|^{}$'; then
echo " [OK] Cert registered: $FQDN"
break
else
echo " Retry $TRY for $FQDN: $(echo $R | head -c 100)"
sleep 2
fi
done
done
echo " [*] Certificate registration complete"
# --- Phase 4: Start Zoraxy with all configs ---
echo "[*] Phase 4: Starting Zoraxy with custom configs..."
podman start zoraxy 2>/dev/null || podman-compose -f "$TARGET_DIR/compose/zoraxy.yaml" up -d 2>&1 || true
sleep 2
# Write systemd service
echo "[*] Writing systemd service..."