fix: systemd tangle-deploy missing ob-shell, add OIDC proxy, chmod fix
- Replaced stale /usr/local/bin/tangle-deploy (no (require 'ob-shell)) with correct repo version — was writing crowdsecLapiKey: nil every 5min - Added chmod +x to tangle-deploy.sh so git pull doesn't strip exec bit - Added oidc-rewrite-proxy.py and oidc-proxy.service as tangle targets - Documented Gitea OIDC discovery rewrite fix - Added systemd unit detection to tangle-deploy restart logic - Updated changelog
This commit is contained in:
@@ -70,6 +70,7 @@ if [ ! -f "$ORG_FILE" ]; then
|
|||||||
echo "ERROR: $ORG_FILE not found in $REPO_DIR"
|
echo "ERROR: $ORG_FILE not found in $REPO_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
chmod +x "$0"
|
||||||
echo "=== Tangling $ORG_FILE ==="
|
echo "=== Tangling $ORG_FILE ==="
|
||||||
emacs --batch -Q --load /usr/share/emacs/28.2/lisp/org/org-loaddefs.el \
|
emacs --batch -Q --load /usr/share/emacs/28.2/lisp/org/org-loaddefs.el \
|
||||||
--eval "(require 'org)" \
|
--eval "(require 'org)" \
|
||||||
@@ -84,6 +85,10 @@ if [ -f /docker/appdata/traefik/traefik.yaml ] || \
|
|||||||
echo 'Traefik config changed -- restarting...'
|
echo 'Traefik config changed -- restarting...'
|
||||||
docker compose up -d traefik
|
docker compose up -d traefik
|
||||||
fi
|
fi
|
||||||
|
if [ -f /etc/systemd/system/oidc-proxy.service ]; then
|
||||||
|
echo 'Systemd unit changed -- reloading...'
|
||||||
|
systemctl daemon-reload
|
||||||
|
fi
|
||||||
if [ -f /docker/compose/docker-compose.yaml ]; then
|
if [ -f /docker/compose/docker-compose.yaml ]; then
|
||||||
echo 'Docker compose changed -- restarting all services'
|
echo 'Docker compose changed -- restarting all services'
|
||||||
docker compose up -d 2>&1 | tail -5
|
docker compose up -d 2>&1 | tail -5
|
||||||
@@ -1238,6 +1243,101 @@ services:
|
|||||||
- traefik.http.services.gitea.loadbalancer.server.port=3000
|
- traefik.http.services.gitea.loadbalancer.server.port=3000
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
*** Gitea OIDC — Discovery Rewrite Proxy
|
||||||
|
|
||||||
|
Gitea's OIDC provider uses Authentik's auto-discovery URL to fetch
|
||||||
|
endpoint metadata. The discovery document returned by Authentik contains
|
||||||
|
internal Docker hostnames (like =http://authentik:9000/=) which the
|
||||||
|
browser cannot resolve. Gitea's =openidConnect= provider in v1.25.5 does
|
||||||
|
not support =CustomURLMapping= (confirmed from source
|
||||||
|
=providers_openid.go= — =CreateGothProvider= ignores the field), so the
|
||||||
|
redirect URLs must be rewritten externally.
|
||||||
|
|
||||||
|
The fix is a small HTTP proxy at =172.28.10.1:9122= (the Docker bridge
|
||||||
|
gateway) that intercepts the discovery request, fetches the real document
|
||||||
|
from Authentik at =172.28.10.33:9000=, and rewrites all internal URLs to
|
||||||
|
=https://auth.gharbeia.net=.
|
||||||
|
|
||||||
|
The proxy runs as a systemd service on production-1:
|
||||||
|
|
||||||
|
#+BEGIN_SRC ini :tangle /etc/systemd/system/oidc-proxy.service
|
||||||
|
[Unit]
|
||||||
|
Description=OIDC discovery rewrite proxy for Gitea
|
||||||
|
After=network-online.target docker.service
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/bin/python3 /docker/compose/oidc-rewrite-proxy.py
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
User=root
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
The proxy lives at =/docker/compose/oidc-rewrite-proxy.py= on production-1:
|
||||||
|
|
||||||
|
#+BEGIN_SRC python :tangle /docker/compose/oidc-rewrite-proxy.py
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
\"\"\"Minimal OIDC discovery rewrite proxy for Gitea's openidConnect provider.
|
||||||
|
|
||||||
|
Listens on 0.0.0.0:9122. Rewrites internal Authentik URLs to the public
|
||||||
|
HTTPS URL so Gitea redirects browsers to auth.gharbeia.net.
|
||||||
|
\"\"\"
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||||
|
from urllib.request import urlopen, Request
|
||||||
|
|
||||||
|
UPSTREAM = "http://172.28.10.33:9000"
|
||||||
|
PUBLIC = "https://auth.gharbeia.net"
|
||||||
|
DISCOVERY_PATH = "/application/o/gitea-oidc/.well-known/openid-configuration"
|
||||||
|
|
||||||
|
|
||||||
|
class RewriteHandler(BaseHTTPRequestHandler):
|
||||||
|
def do_GET(self):
|
||||||
|
if self.path != DISCOVERY_PATH:
|
||||||
|
self.send_response(404)
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(b"Not found")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
upstream_url = f"{UPSTREAM}{DISCOVERY_PATH}"
|
||||||
|
req = Request(upstream_url, headers={"Accept": "application/json"})
|
||||||
|
with urlopen(req, timeout=5) as resp:
|
||||||
|
body = resp.read().decode()
|
||||||
|
body = body.replace(UPSTREAM, PUBLIC)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-Type", "application/json")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(body.encode())
|
||||||
|
except Exception as e:
|
||||||
|
self.send_response(502)
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(f"Proxy error: {e}".encode())
|
||||||
|
|
||||||
|
def log_message(self, format, *args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
server = HTTPServer(("0.0.0.0", 9122), RewriteHandler)
|
||||||
|
print("OIDC rewrite proxy listening on :9122", flush=True)
|
||||||
|
server.serve_forever()
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
The systemd service is tangled from the block above. After deploying, enable
|
||||||
|
with =systemctl enable --now oidc-proxy=.
|
||||||
|
|
||||||
|
Gitea's =OpenIDConnectAutoDiscoveryURL= in the database was updated to point
|
||||||
|
at the proxy:
|
||||||
|
|
||||||
|
: http://172.28.10.1:9122/application/o/gitea-oidc/.well-known/openid-configuration
|
||||||
|
|
||||||
** Infrastructure Services
|
** Infrastructure Services
|
||||||
|
|
||||||
Core data and networking services that everything depends on.
|
Core data and networking services that everything depends on.
|
||||||
@@ -1632,6 +1732,23 @@ wp-config: =/docker/appdata/khaledfahmy-site/html/wp-config.php=
|
|||||||
- Created infrastructure.org as source of truth
|
- Created infrastructure.org as source of truth
|
||||||
- Added Forward Auth to internal LAN routers
|
- Added Forward Auth to internal LAN routers
|
||||||
|
|
||||||
|
** [2026-06-06 Sat] Systemd tangle-deploy fixed — ob-shell, chmod, OIDC proxy
|
||||||
|
- Replaced stale /usr/local/bin/tangle-deploy (missing (require 'ob-shell))
|
||||||
|
with the correct repo version. Every 5-minute systemd timer cycle was
|
||||||
|
writing crowdsecLapiKey: nil because it couldn't evaluate the sh code block.
|
||||||
|
- Added chmod +x "$0" to tangle-deploy.sh so git pull doesn't strip the
|
||||||
|
executable bit, keeping cron + systemd reliable.
|
||||||
|
- Created and deployed oidc-rewrite-proxy.py: a discovery rewrite proxy that
|
||||||
|
intercepts Gitea's OIDC metadata request and rewrites internal
|
||||||
|
http://authentik:9000 URLs to https://auth.gharbeia.net.
|
||||||
|
- Registered oidc-proxy as a systemd service on production-1 (port 9122).
|
||||||
|
- Updated Gitea's OpenIDConnectAutoDiscoveryURL in the database to point
|
||||||
|
at the proxy (http://172.28.10.1:9122/...).
|
||||||
|
- Reverted Gitea's CustomURLMapping to {} (confirmed unused by source code).
|
||||||
|
- Fixed qBittorrent v5.2.1 persistent password — old PBKDF2 hash was not
|
||||||
|
recognized by the v5 upgrade. Set new password hash in config, updated
|
||||||
|
Sonarr and Radarr download client credentials via API.
|
||||||
|
|
||||||
** [2026-06-02 Tue] Gluetun port cleanup — only downloaders behind VPN
|
** [2026-06-02 Tue] Gluetun port cleanup — only downloaders behind VPN
|
||||||
- Removed 20+ stale port mappings from gluetun (services migrated off VPN)
|
- Removed 20+ stale port mappings from gluetun (services migrated off VPN)
|
||||||
- Updated all internal router URLs: standalone services now referenced by
|
- Updated all internal router URLs: standalone services now referenced by
|
||||||
|
|||||||
Reference in New Issue
Block a user