From 2571930efab1ba464a61a72653b2a31e325db6b9 Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Tue, 7 Jul 2026 14:11:31 -0400 Subject: [PATCH 1/2] Local change dump --- ai/compose.yml | 90 ++++++++++++++++-------------------- ai/hermes/Dockerfile | 28 +---------- authentification/compose.yml | 2 +- backup/compose.yml | 52 ++++++++++----------- cloudstorage/compose.yml | 5 +- coms/compose.yml | 2 +- finance/compose.yml | 3 +- homeautomation/compose.yml | 17 +++---- homepage/compose.yml | 3 +- network/compose.yml | 12 ++--- passwordmanager/compose.yml | 7 +-- tak/compose.yml | 3 +- versioncontrol/compose.yml | 3 +- vpn/compose.yml | 28 +++++++++-- 14 files changed, 125 insertions(+), 130 deletions(-) diff --git a/ai/compose.yml b/ai/compose.yml index 3bae744..cd78971 100755 --- a/ai/compose.yml +++ b/ai/compose.yml @@ -1,29 +1,5 @@ services: - # webui: - # image: ghcr.io/open-webui/open-webui:main - # volumes: - # - /mnt/HoardingCow_docker_data/Ollama/open-webui:/app/backend/data - # restart: always - # environment: - # - OLLAMA_API_BASE_URL=http://ollama:11434/api - # networks: - # - ai_net - # - ai_backend - # labels: - # - "traefik.enable=true" - - # # Router for HTTP + redirection to HTTPS - # - "traefik.http.routers.webui-http.rule=Host(`ai.lazyworkhorse.net`)" - # - "traefik.http.routers.webui-http.entrypoints=web" - # - "traefik.http.routers.webui-http.middlewares=redirect-to-https" - - # # Router for HTTPS with TLS - # - "traefik.http.routers.webui-https.rule=Host(`ai.lazyworkhorse.net`)" - # - "traefik.http.routers.webui-https.entrypoints=websecure" - # - "traefik.http.routers.webui-https.tls=true" - # - "traefik.http.routers.webui-https.tls.certresolver=njalla" - hermes: build: context: ./hermes @@ -31,12 +7,14 @@ services: - default container_name: hermes entrypoint: ["/bin/bash", "-c", - "bash /opt/data/hermes-tools/install.sh && bash /usr/local/bin/run-multi-gateways.sh && exec /usr/bin/tini -g -- /opt/hermes/docker/entrypoint.sh \"$@\"", + "bash /usr/local/bin/run-multi-gateways.sh && exec /usr/bin/tini -g -- /opt/hermes/docker/entrypoint.sh \"$@\"", "hermes-entrypoint"] restart: always # Gateway run enables the internal API server on port 8642 command: gateway run environment: + - HERMES_UID=10000 + - HERMES_GID=10000 - OLLAMA_HOST=http://ollama:11434 - HERMES_DASHBOARD=1 # Multi-profile: comma-separated list of profiles to run as gateways. @@ -59,10 +37,7 @@ services: - TZ=America/Montreal volumes: - /mnt/HoardingCow_docker_data/Hermes/data:/opt/data - # Syncthing-shared org files — read-only view of user's agenda - - /mnt/HoardingCow_docker_data/Syncthing/telos-ro:/opt/data/telos-ro:ro - # Syncthing-shared inbox — write tasks here, they sync to user's laptop - - /mnt/HoardingCow_docker_data/Syncthing/telos-rw:/opt/data/telos-rw:rw + - /mnt/HoardingCow_docker_data/Hermes/Syncthing/ExoKortex:/opt/data/ExoKortex devices: - /dev/kfd:/dev/kfd - /dev/dri:/dev/dri @@ -109,24 +84,29 @@ services: - "21027:21027/udp" environment: - TZ=America/Montreal + - PUID=10000 + - PGID=10000 volumes: - - /mnt/HoardingCow_docker_data/Syncthing/config:/var/syncthing/config - - /mnt/HoardingCow_docker_data/Syncthing/telos-ro:/telos-ro - - /mnt/HoardingCow_docker_data/Syncthing/telos-rw:/telos-rw + - /mnt/HoardingCow_docker_data/Hermes/Syncthing/config:/var/syncthing/config + - /mnt/HoardingCow_docker_data/Hermes/Syncthing/ExoKortex:/ExoKortex networks: - ai_backend - ai_net labels: - "traefik.enable=true" + - "traefik.docker.network=ai_net" + - "traefik.http.routers.syncthing-http.rule=Host(`syncthing.lazyworkhorse.net`)" - "traefik.http.routers.syncthing-http.entrypoints=web" - "traefik.http.routers.syncthing-http.middlewares=redirect-to-https" + - "traefik.http.routers.syncthing-https.rule=Host(`syncthing.lazyworkhorse.net`)" - "traefik.http.routers.syncthing-https.entrypoints=websecure" - "traefik.http.routers.syncthing-https.tls=true" - "traefik.http.routers.syncthing-https.tls.certresolver=njalla" - - "traefik.http.services.syncthing.loadbalancer.server.port=8384" + - "traefik.http.routers.syncthing-https.middlewares=hermes-auth" + - "traefik.http.services.syncthing.loadbalancer.server.port=8384" ollama: build: @@ -203,10 +183,8 @@ services: # Service Loadbalancer (nginx port) - "traefik.http.services.honcho.loadbalancer.server.port=80" depends_on: - honcho-db: - condition: service_healthy - honcho-redis: - condition: service_healthy + - honcho-db + - honcho-redis honcho-db: image: pgvector/pgvector:pg15 @@ -225,11 +203,6 @@ services: - ./honcho/init-db.sql:/docker-entrypoint-initdb.d/init.sql:ro networks: - ai_backend - healthcheck: - test: ["CMD-SHELL", "pg_isready -U honcho -d honcho"] - interval: 5s - timeout: 5s - retries: 5 honcho-redis: image: redis:8 @@ -241,15 +214,10 @@ services: - /mnt/HoardingCow_docker_data/Honcho/redis:/data networks: - ai_backend - healthcheck: - test: ["CMD-SHELL", "redis-cli ping"] - interval: 5s - timeout: 5s - retries: 5 networks: ai_net: - external: true + driver: bridge name: ai_net ai_backend: driver: bridge @@ -257,7 +225,7 @@ networks: volumes: honcho_data: - external: true + driver: bridge name: honcho_data # llama_cpp_devstral: @@ -348,6 +316,30 @@ volumes: # - /mnt/HoardingCow_docker_data/vllm/models:/root/.cache/huggingface # restart: unless-stopped + # webui: + # image: ghcr.io/open-webui/open-webui:main + # volumes: + # - /mnt/HoardingCow_docker_data/Ollama/open-webui:/app/backend/data + # restart: always + # environment: + # - OLLAMA_API_BASE_URL=http://ollama:11434/api + # networks: + # - ai_net + # - ai_backend + # labels: + # - "traefik.enable=true" + + # # Router for HTTP + redirection to HTTPS + # - "traefik.http.routers.webui-http.rule=Host(`ai.lazyworkhorse.net`)" + # - "traefik.http.routers.webui-http.entrypoints=web" + # - "traefik.http.routers.webui-http.middlewares=redirect-to-https" + + # # Router for HTTPS with TLS + # - "traefik.http.routers.webui-https.rule=Host(`ai.lazyworkhorse.net`)" + # - "traefik.http.routers.webui-https.entrypoints=websecure" + # - "traefik.http.routers.webui-https.tls=true" + # - "traefik.http.routers.webui-https.tls.certresolver=njalla" + # n8n: # image: n8nio/n8n:latest # container_name: n8n diff --git a/ai/hermes/Dockerfile b/ai/hermes/Dockerfile index 368efca..8459749 100644 --- a/ai/hermes/Dockerfile +++ b/ai/hermes/Dockerfile @@ -9,26 +9,6 @@ # ---------- Base: official Hermes image (system deps, npm, uv, Playwright) ---------- FROM nousresearch/hermes-agent:latest -# ---------- Overlay our forked source ---------- -# Uses SSH agent forwarding from the build host (no key baked into image). -# --exclude node_modules/.venv keeps the base image's pre-built layers intact. -# Only the Python source, web UI source, and config change. -RUN --mount=type=ssh \ - mkdir -p /root/.ssh && \ - ssh-keyscan -p 2222 code.lazyworkhorse.net >> /root/.ssh/known_hosts 2>/dev/null && \ - cd /tmp && \ - GIT_SSH_COMMAND='ssh -p 2222 -o StrictHostKeyChecking=no' \ - git clone --depth 1 --branch main \ - git@code.lazyworkhorse.net:gortium/hermes-agent.git fork && \ - rm -rf fork/node_modules fork/.venv fork/.git && \ - cp -a fork/. /opt/hermes/ && \ - rm -rf /tmp/fork /root/.ssh/ - -# ---------- Reinstall Python package (editable) ---------- -# Picks up source changes from our fork. -RUN . /opt/hermes/.venv/bin/activate && \ - uv pip install --no-cache-dir --no-deps -e /opt/hermes - # ---------- Extra system deps ---------- USER root RUN apt-get update && \ @@ -43,12 +23,6 @@ RUN apt-get update && \ # ---------- UV ---------- COPY --chmod=0755 --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/ -# ---------- Matrix bridge + extra pip deps ---------- -# Previously installed inline at container startup and persisted via volume mount. -# Now baked into the image so the fragile venv volume mount can be removed. -RUN . /opt/hermes/.venv/bin/activate && \ - uv pip install --no-cache-dir 'mautrix[encryption]' openai - WORKDIR /opt/hermes # ---------- Matrix bridge + extra pip deps ---------- @@ -100,4 +74,4 @@ ENV CHROME_EXECUTABLE=/opt/hermes/.playwright/chromium/chrome-linux/chrome USER root RUN chown -R hermes:hermes /opt/hermes/tools /opt/hermes/toolsets.py -VOLUME [ "/opt/data" ] \ No newline at end of file +VOLUME [ "/opt/data" ] diff --git a/authentification/compose.yml b/authentification/compose.yml index c50c795..7542e44 100644 --- a/authentification/compose.yml +++ b/authentification/compose.yml @@ -32,5 +32,5 @@ services: networks: auth_net: - external: true + driver: bridge name: auth_net diff --git a/backup/compose.yml b/backup/compose.yml index 990efc4..c78f8f9 100644 --- a/backup/compose.yml +++ b/backup/compose.yml @@ -68,33 +68,33 @@ services: labels: - "traefik.enable=false" # Internal only, accessed by restic-browser - restic-browser: - image: embergarage/restic-browser:latest - container_name: restic-browser - restart: always - environment: - - TZ=America/Montreal - - RESTIC_REPOSITORY=http://restic-server:8080 - - RESTIC_PASSWORD=${RESTIC_PASSWORD} - networks: - - backup_net - labels: - - "traefik.enable=true" - # 1. HTTP to HTTPS Redirect - - "traefik.http.routers.restic-browser-http.rule=Host(`backup.lazyworkhorse.net`)" - - "traefik.http.routers.restic-browser-http.entrypoints=web" - - "traefik.http.routers.restic-browser-http.middlewares=redirect-to-https@docker" - - # 2. HTTPS Configuration - - "traefik.http.routers.restic-browser.rule=Host(`backup.lazyworkhorse.net`)" - - "traefik.http.routers.restic-browser.entrypoints=websecure" - - "traefik.http.routers.restic-browser.tls=true" - - "traefik.http.routers.restic-browser.tls.certresolver=njalla" - - # 3. Backend Service Config - - "traefik.http.services.restic-browser.loadbalancer.server.port=8000" +# restic-browser: +# image: mazzolino/restic-browser:latest +# container_name: restic-browser +# restart: always +# environment: +# - TZ=America/Montreal +# - RESTIC_REPOSITORY=http://restic-server:8080 +# - RESTIC_PASSWORD=${RESTIC_PASSWORD} +# networks: +# - backup_net +# labels: +# - "traefik.enable=true" +# # 1. HTTP to HTTPS Redirect +# - "traefik.http.routers.restic-browser-http.rule=Host(`backup.lazyworkhorse.net`)" +# - "traefik.http.routers.restic-browser-http.entrypoints=web" +# - "traefik.http.routers.restic-browser-http.middlewares=redirect-to-https@docker" +# +# # 2. HTTPS Configuration +# - "traefik.http.routers.restic-browser.rule=Host(`backup.lazyworkhorse.net`)" +# - "traefik.http.routers.restic-browser.entrypoints=websecure" +# - "traefik.http.routers.restic-browser.tls=true" +# - "traefik.http.routers.restic-browser.tls.certresolver=njalla" +# +# # 3. Backend Service Config +# - "traefik.http.services.restic-browser.loadbalancer.server.port=8000" networks: backup_net: - external: true + driver: bridge name: backup_net diff --git a/cloudstorage/compose.yml b/cloudstorage/compose.yml index a5c1114..c2475a2 100644 --- a/cloudstorage/compose.yml +++ b/cloudstorage/compose.yml @@ -6,6 +6,7 @@ services: restart: always networks: - cloud_net + - cloud_internal environment: - PUID=1000 - PGID=1000 @@ -51,7 +52,7 @@ services: container_name: nextcloud_cron restart: always networks: - - cloud_net + - cloud_internal entrypoint: /cron.sh volumes: - /mnt/HoardingCow_docker_data/NextCloud/data:/var/www/html:rw @@ -75,7 +76,7 @@ services: networks: cloud_net: - external: true + driver: bridge name: cloud_net cloud_internal: driver: bridge diff --git a/coms/compose.yml b/coms/compose.yml index 34897c0..74d6454 100644 --- a/coms/compose.yml +++ b/coms/compose.yml @@ -103,7 +103,7 @@ services: networks: coms_net: - external: true + driver: bridge name: coms_net coms_backend: driver: bridge diff --git a/finance/compose.yml b/finance/compose.yml index 9f4eeab..8cabc18 100644 --- a/finance/compose.yml +++ b/finance/compose.yml @@ -37,4 +37,5 @@ services: networks: finance_net: - external: true + driver: bridge + name: finance_net diff --git a/homeautomation/compose.yml b/homeautomation/compose.yml index 1bcb5ee..b0792ea 100644 --- a/homeautomation/compose.yml +++ b/homeautomation/compose.yml @@ -12,8 +12,8 @@ services: volumes: - /mnt/HoardingCow_docker_data/Home_Assistant:/config:rw networks: - - home_auto_net - - home_auto_backend + - home_net + - home_backend labels: - "traefik.enable=true" @@ -34,7 +34,7 @@ services: volumes: - /mnt/HoardingCow_docker_data/Mosquitto:/mosquitto networks: - - home_auto_backend + - home_backend # ports: # - 1883:1883 # - 9001:9001 @@ -43,7 +43,7 @@ services: image: registry.gitlab.com/hydroqc/hydroqc2mqtt:1.3.0 restart: always networks: - - home_auto_backend + - home_backend environment: MQTT_USERNAME: hass MQTT_PASSWORD: ${MQTT_PASSWORD} @@ -88,8 +88,9 @@ services: # restart: unless-stopped networks: - home_auto_net: - external: true - home_auto_backend: + home_net: driver: bridge - name: home_auto_backend + name: home_net + home_backend: + driver: bridge + name: home_backend diff --git a/homepage/compose.yml b/homepage/compose.yml index 58b07bf..6a799de 100644 --- a/homepage/compose.yml +++ b/homepage/compose.yml @@ -38,4 +38,5 @@ services: networks: homepage_net: - external: true + driver: bridge + name: homepage_net diff --git a/network/compose.yml b/network/compose.yml index ef6360f..c78dab3 100644 --- a/network/compose.yml +++ b/network/compose.yml @@ -36,9 +36,9 @@ services: - cloud_net - coms_net - finance_net - - home_auto_net + - home_net - homepage_net - - passman_net + - pass_net - tak_net - vc_net @@ -99,15 +99,15 @@ networks: finance_net: driver: bridge name: finance_net - home_auto_net: + home_net: driver: bridge - name: home_auto_net + name: home_net homepage_net: driver: bridge name: homepage_net - passman_net: + pass_net: driver: bridge - name: passman_net + name: pass_net tak_net: driver: bridge name: tak_net diff --git a/passwordmanager/compose.yml b/passwordmanager/compose.yml index a02f33c..6270114 100644 --- a/passwordmanager/compose.yml +++ b/passwordmanager/compose.yml @@ -13,7 +13,7 @@ services: volumes: - /mnt/HoardingCow_docker_data/BitWarden/data:/data:rw networks: - - passman_net + - pass_net restart: always labels: - "traefik.enable=true" @@ -32,5 +32,6 @@ services: # Internal service - "traefik.http.services.pass.loadbalancer.server.port=80" networks: - passman_net: - external: true + pass_net: + driver: bridge + name: pass_net diff --git a/tak/compose.yml b/tak/compose.yml index 708bd37..2031b50 100644 --- a/tak/compose.yml +++ b/tak/compose.yml @@ -92,7 +92,8 @@ services: networks: tak_net: - external: true + driver: bridge + name: tak_net tak_backend: driver: bridge name: tak_backend diff --git a/versioncontrol/compose.yml b/versioncontrol/compose.yml index 01007ff..bde0e62 100644 --- a/versioncontrol/compose.yml +++ b/versioncontrol/compose.yml @@ -61,4 +61,5 @@ services: networks: vc_net: - external: true + driver: bridge + name: vc_net diff --git a/vpn/compose.yml b/vpn/compose.yml index cd14f27..670a6ff 100644 --- a/vpn/compose.yml +++ b/vpn/compose.yml @@ -12,7 +12,7 @@ services: - SYS_MODULE environment: - WG_HOST=vpn.lazyworkhorse.net - - PASSWORD=${WG_PASSWORD} + - PASSWORD_HASH=${WG_PASSWORD_HASH} - WG_PORT=51820 - WG_DEFAULT_ADDRESS=10.8.0.x - WG_DEFAULT_DNS=1.1.1.1,8.8.8.8 @@ -22,7 +22,6 @@ services: - UI_CHART_TYPE=0 ports: - "51820:51820/udp" - - "51821:51821/tcp" volumes: - /mnt/HoardingCow_docker_data/WireGuard:/etc/wireguard:rw sysctls: @@ -31,8 +30,31 @@ services: restart: unless-stopped networks: - vpn_net + labels: + - "traefik.enable=true" + + # HTTP → HTTPS redirect + - "traefik.http.routers.wireguard-http.rule=Host(vpn.lazyworkhorse.net)" + - "traefik.http.routers.wireguard-http.entrypoints=web" + - "traefik.http.routers.wireguard-http.middlewares=redirect-to-https" + - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" + + # HTTPS router — protégé par Authelia + - "traefik.http.routers.wireguard-https.rule=Host(vpn.lazyworkhorse.net)" + - "traefik.http.routers.wireguard-https.entrypoints=websecure" + - "traefik.http.routers.wireguard-https.tls=true" + - "traefik.http.routers.wireguard-https.tls.certresolver=njalla" + - "traefik.http.routers.wireguard-https.middlewares=wireguard-auth" + + # Authelia forwardAuth + - "traefik.http.middlewares.wireguard-auth.forwardauth.address=http://authelia:9091/api/verify?rd=https://auth.lazyworkhorse.net/" + - "traefik.http.middlewares.wireguard-auth.forwardauth.trustforwardheader=true" + - "traefik.http.middlewares.wireguard-auth.forwardauth.authresponseheaders=X-Forwarded-User,X-Forwarded-Groups" + + # Port interne du web UI wg-easy + - "traefik.http.services.wireguard.loadbalancer.server.port=51821" networks: vpn_net: - external: true + driver: bridge name: vpn_net -- 2.49.1 From 54e06613960446e593c170581cc263d3999538bc Mon Sep 17 00:00:00 2001 From: Hermes Date: Tue, 7 Jul 2026 14:58:44 -0400 Subject: [PATCH 2/2] fix: add missing USER hermes at end of Dockerfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Dockerfile was switching to USER root for the final chown but never switched back to USER hermes. This caused ALL container processes to run as root (uid 0) instead of the hermes user (uid 10000). The entrypoint's gosu privilege drop only caught the main exec chain, leaving backgrounded subprocesses (dashboard PTY sessions, workers with start_new_session=True) running as root — creating files owned by root in ExoKortex and breaking Syncthing sync. Adding USER hermes at the end ensures the container runs unprivileged and ALL child processes inherit uid 10000 from the start. --- ai/hermes/Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ai/hermes/Dockerfile b/ai/hermes/Dockerfile index 8459749..8cf1e6d 100644 --- a/ai/hermes/Dockerfile +++ b/ai/hermes/Dockerfile @@ -75,3 +75,8 @@ USER root RUN chown -R hermes:hermes /opt/hermes/tools /opt/hermes/toolsets.py VOLUME [ "/opt/data" ] + +# Switch to the hermes user so the container runs unprivileged. +# All child processes inherit this user — no more orphan root processes +# that escape gosu privilege drops in the entrypoint. +USER hermes -- 2.49.1