Fix functional bugs found in service audit

wg-easy: PASSWORD env var removed in v14+; generate bcrypt hash at install
  time via 'docker run wg-easy wgpw' and write PASSWORD_HASH instead.

ntfy: write config/server.yml with base-url, cache-file, auth-file, and
  behind-proxy:true so push notification links work when behind Caddy.
  auth-default-access: deny-all (require topic auth).

mealie: BASE_URL was hardcoded to http://localhost:9925; email links and
  OAuth redirects broke when served via Caddy. Now computed from SITE_DOMAIN
  and written to .env so it's easy to update.

nextcloud: add OVERWRITEPROTOCOL=https, OVERWRITECLIURL, TRUSTED_PROXIES to
  .env so share links and internal redirects use https:// behind Caddy.

onlyoffice: Caddy's default X-Frame-Options: SAMEORIGIN header blocked
  OnlyOffice from being embedded as an iframe in Nextcloud. Override it in
  the Caddy site block to allow framing.

vaultwarden: remove exposed port 3012 (WebSocket — not needed since v1.29+,
  all handled on port 80). Publish port 8888 for direct host access instead.
  Remove WEBSOCKET_ENABLED=true (ignored in current versions).

https://claude.ai/code/session_014CCYqVwW6d6f5dw1qRokYt
This commit is contained in:
Claude
2026-06-08 19:13:09 +00:00
parent 551c254b89
commit e95e82be2f
6 changed files with 72 additions and 12 deletions
+21 -5
View File
@@ -181,13 +181,26 @@ install_wg-easy() {
cd "$WGEASY_DIR" || return 1
# Auto-detect public IP as default for WG_HOST
local PUBLIC_IP WG_HOST WG_PASSWORD
local PUBLIC_IP WG_HOST WG_PASSWORD WG_PASSWORD_HASH
PUBLIC_IP=$(curl -s --connect-timeout 5 ifconfig.me 2>/dev/null || echo "your-public-ip")
WG_PASSWORD=$(openssl rand -base64 16 | tr -dc 'a-zA-Z0-9' | head -c 16)
prompt_text "Public IP or hostname for VPN [$PUBLIC_IP]:" "$PUBLIC_IP" WG_HOST
cat > docker-compose.yml << 'WGEASY_COMPOSE'
# wg-easy v14+ requires PASSWORD_HASH (bcrypt). Generate via docker.
log_info "Generating bcrypt password hash (requires Docker)..."
WG_PASSWORD_HASH=$(docker run --rm ghcr.io/wg-easy/wg-easy:latest wgpw "$WG_PASSWORD" 2>/dev/null \
| grep -oP '\$2[ab]\$[^\s]+' | head -1)
if [[ -z "$WG_PASSWORD_HASH" ]]; then
log_warning "Could not generate bcrypt hash — falling back to plaintext PASSWORD env var."
log_warning "If wg-easy fails to start, run: docker run --rm ghcr.io/wg-easy/wg-easy wgpw 'yourpassword'"
log_warning "Then set PASSWORD_HASH in docker-compose.yml and remove PASSWORD."
fi
# Escape $ in hash for docker-compose env (bcrypt hashes contain $$)
local WG_HASH_ESCAPED="${WG_PASSWORD_HASH//\$/\$\$}"
cat > docker-compose.yml << WGEASY_COMPOSE
name: wg-easy
services:
@@ -203,8 +216,8 @@ services:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
environment:
- WG_HOST=${WG_HOST}
- PASSWORD=${WG_PASSWORD}
- WG_HOST=\${WG_HOST}
- PASSWORD_HASH=${WG_HASH_ESCAPED:-\${WG_PASSWORD}}
- WG_DEFAULT_DNS=1.1.1.1
volumes:
- ./config:/etc/wireguard
@@ -217,11 +230,12 @@ services:
networks:
caddy_net:
external: true
name: ${CADDY_NET:-caddy_net}
name: \${CADDY_NET:-caddy_net}
WGEASY_COMPOSE
cat > .env << WGEASY_ENV
WG_HOST=$WG_HOST
# Plain-text password — used only if PASSWORD_HASH could not be generated above
WG_PASSWORD=$WG_PASSWORD
CADDY_NET=$SITE_CADDY_NET
WGEASY_ENV
@@ -270,6 +284,8 @@ MD
echo ""
echo " Web UI: http://localhost:51821"
echo " Password: $WG_PASSWORD (saved in .env)"
[[ -n "$WG_PASSWORD_HASH" ]] && echo " Auth: bcrypt hash configured (v14+ compatible)" \
|| echo " Auth: WARNING — bcrypt hash generation failed; see README"
echo " Router: forward UDP 51820 → this server for external VPN access"
echo ""
}