marreta: content-cleaning proxy on Dankclaw, gluetun netns, guard-chained
Deploy manualdousuario/marreta (Laravel / serversideup php:8.4-fpm-nginx) as a rootless Quadlet pair (marreta + marreta-browser/Lightpanda), both joining gluetun's netns so all fetch egress exits the same ProtonVPN tunnel as SearXNG. - marreta relocated to NGINX_HTTP_PORT=8085 (netns already has searxng on 8080); gluetun publishes 8082:8085; Caddy dials 192.168.0.143:8082. - Guard chain: marreta.franksdank.cloud -> Anubis :8923 -> Authentik -> post-auth :8017 @marreta -> 8082. Access = any authenticated user. - Secrets seeded to /home/dank/Containers/marreta/env (0600) from MARRETA_APP_KEY / MARRETA_ADMIN_EMAIL / MARRETA_ADMIN_PASSWORD. - deploy-plan.py: marreta joins the gluetun netns family. - New seam tests/marreta_quadlet.bats (17 contracts); scoping test updated for the widened netns family. Doc: Dankclaw/Marreta.md + index + log.
This commit is contained in:
+13
-4
@@ -23,6 +23,7 @@ SERVICE_ORDER = (
|
||||
"gluetun",
|
||||
"searxng-valkey",
|
||||
"searxng",
|
||||
"marreta",
|
||||
"pihole",
|
||||
"open-webui",
|
||||
"gitea-postgres",
|
||||
@@ -67,6 +68,7 @@ DANKCLAW_SERVICES = {
|
||||
"gluetun",
|
||||
"searxng-valkey",
|
||||
"searxng",
|
||||
"marreta",
|
||||
"pihole",
|
||||
"open-webui",
|
||||
"gitea-postgres",
|
||||
@@ -279,15 +281,22 @@ def services_for_path(path: str, target: str) -> set[str]:
|
||||
if len(parts) >= 4 and parts[2] == "quadlet":
|
||||
name = parts[3]
|
||||
if name == "gluetun.container":
|
||||
# SearXNG shares Gluetun's network namespace. A Gluetun
|
||||
# recreation requires both units to be restarted.
|
||||
_add(services, "gluetun", "searxng")
|
||||
# SearXNG and Marreta (+ its browser companion) share
|
||||
# Gluetun's network namespace. A Gluetun recreation
|
||||
# tears the netns down, so every sharer must restart.
|
||||
_add(services, "gluetun", "searxng", "marreta")
|
||||
elif name == "searxng.container":
|
||||
_add(services, "searxng")
|
||||
elif name == "searxng-valkey.container":
|
||||
_add(services, "searxng-valkey", "searxng")
|
||||
elif name == "searxng.network":
|
||||
_add(services, "gluetun", "searxng-valkey", "searxng")
|
||||
_add(services, "gluetun", "searxng-valkey", "searxng", "marreta")
|
||||
return services
|
||||
if len(parts) >= 2 and parts[1] == "marreta":
|
||||
# One deployable owns both the app and its browser companion;
|
||||
# both live in gluetun's netns. A change to either unit selects
|
||||
# the marreta service, which restarts browser-then-app.
|
||||
_add(services, "marreta")
|
||||
return services
|
||||
if len(parts) >= 2 and parts[1] == "pihole":
|
||||
_add(services, "pihole")
|
||||
|
||||
@@ -89,7 +89,7 @@ service_is_allowed() {
|
||||
dankclaw:loki|dankclaw:alloy|dankclaw:node-exporter|\
|
||||
dankclaw:authentik-postgres|dankclaw:authentik-server|\
|
||||
dankclaw:authentik-worker|dankclaw:authentik-outpost|dankclaw:authentik-outpost-ldap|dankclaw:anubis|\
|
||||
dankclaw:caddy|dankclaw:homepage|dankclaw:seerr|\
|
||||
dankclaw:caddy|dankclaw:homepage|dankclaw:seerr|dankclaw:marreta|\
|
||||
dankclaw:frank-large|\
|
||||
dankserver:romm-mariadb|dankserver:romm-redis|dankserver:romm|\
|
||||
dankserver:copyparty|dankserver:jellyfin|dankserver:calibre-web|dankserver:plex|dankserver:tautulli|\
|
||||
@@ -508,6 +508,38 @@ deploy_searxng_valkey() {
|
||||
systemctl --user restart searxng-valkey.service searxng.service
|
||||
}
|
||||
|
||||
# Marreta's secrets are seeded into a per-service env file under the deploy
|
||||
# user's home (rootless-readable), following the grafana convention rather
|
||||
# than the /opt/searxng one, so the rootless unit can read it without any
|
||||
# ownership gymnastics. Only the three MARRETA_* values are copied; the
|
||||
# quadlet maps them to the app's APP_KEY / ADMIN_EMAIL / ADMIN_PASSWORD.
|
||||
seed_marreta_env() {
|
||||
local dest=/home/dank/Containers/marreta/env
|
||||
mkdir -p /home/dank/Containers/marreta
|
||||
if [[ ! -f "$dest" ]]; then
|
||||
awk -F= '/^MARRETA_APP_KEY=/ || /^MARRETA_ADMIN_EMAIL=/ || /^MARRETA_ADMIN_PASSWORD=/ { print }' \
|
||||
dankclaw/.env > "$dest"
|
||||
chmod 600 "$dest"
|
||||
fi
|
||||
local var
|
||||
for var in MARRETA_APP_KEY MARRETA_ADMIN_EMAIL MARRETA_ADMIN_PASSWORD; do
|
||||
grep -q "^${var}=." "$dest" \
|
||||
|| { echo "marreta env missing ${var}; set it in dankclaw/.env" >&2; return 1; }
|
||||
done
|
||||
}
|
||||
|
||||
deploy_marreta() {
|
||||
seed_marreta_env
|
||||
install_quadlet marreta dankclaw/marreta/quadlet marreta
|
||||
install_quadlet marreta-browser dankclaw/marreta/quadlet marreta-browser
|
||||
systemctl --user daemon-reload
|
||||
# Both containers share gluetun's netns; the tunnel must be up first.
|
||||
systemctl --user start gluetun.service
|
||||
# Browser before app: marreta drives the CDP endpoint on loopback.
|
||||
systemctl --user restart marreta-browser.service
|
||||
systemctl --user restart marreta.service
|
||||
}
|
||||
|
||||
deploy_open_webui() {
|
||||
install_quadlet open-webui dankclaw/open-webui/quadlet open-webui
|
||||
mkdir -p /home/dank/Containers/open-webui/data
|
||||
@@ -1153,6 +1185,7 @@ deploy_service() {
|
||||
;;
|
||||
anubis) deploy_anubis ;;
|
||||
seerr) deploy_seerr ;;
|
||||
marreta) deploy_marreta ;;
|
||||
frank-large) deploy_llm_large ;;
|
||||
frank-small) deploy_llm_small ;;
|
||||
hermes|hermes-dashboard|hermes-webui) deploy_hermes ;;
|
||||
|
||||
Reference in New Issue
Block a user