Compare commits

...

24 Commits

Author SHA1 Message Date
1eacc3cd8e fix(paperclip): force Traefik to use ai_net network for routing
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
2026-05-18 22:13:59 -04:00
bce403232a Revert custom Dockerfile - not needed, adapter installs on persistent volume
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
The Hermes adapter can be installed once via Paperclip's adapter
management API and persists on the Docker volume across restarts.
No custom Dockerfile or build step required.
2026-05-18 18:38:17 -04:00
37bf43c3ea feat: add custom Dockerfile with Hermes adapter baked in
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
Creates ai/paperclip/ with:
- Dockerfile: extends upstream paperclip image, pre-installs
  hermes-paperclip-adapter@0.3.0 npm package as seed data
- docker-entrypoint.sh: seeds the adapter plugin on first boot
  if the persistent volume is empty, then runs original startup

This ensures the Hermes adapter is available on first boot without
requiring network access — no npm install needed at runtime. The
adapter persists on the Docker volume across restarts.
2026-05-18 18:37:31 -04:00
563ccc5632 feat: add Paperclip agent orchestrator to AI compose stack
Some checks failed
Build Hermes agent / build (pull_request) Has been cancelled
Build ollama (gfx906) / build (pull_request) Has been cancelled
Paperclip (ghcr.io/paperclipai/paperclip:v2026.517.0) is an open-source
agent management dashboard. Adds paperclip-db (PostgreSQL 17) and
paperclip services with Traefik reverse proxy on
paperclip.lazyworkhorse.net.

Requires .env: PAPERCLIP_DB_PASSWORD, PAPERCLIP_AUTH_SECRET.
2026-05-18 18:17:15 -04:00
8d1ae7e632 Remove the unsuported gitea action off 2026-05-13 13:11:11 -04:00
29ae32a1c5 Merge pull request 'fix: use ln -sf instead of update-alternatives --set for iptables-nft' (#28) from fix/vpn-iptables-nft-v3 into master
Reviewed-on: #28
2026-05-13 16:59:50 +00:00
8dff094768 fix: use ln -sf instead of update-alternatives --set
update-alternatives --set fails because the base image only registers
iptables-legacy as an alternative. The iptables-nft binary (/usr/sbin/iptables-nft)
exists but isn't in the alternatives database. Direct ln -sf bypasses this.
2026-05-13 12:58:43 -04:00
ec08f5eb5d Merge pull request 'fix: remove apk add iptables-nft — built-in on Alpine 3.18+' (#27) from fix/vpn-iptables-nft-v2 into master
Reviewed-on: #27
2026-05-13 16:49:23 +00:00
611e96b306 fix: remove apk add iptables-nft — built-in on Alpine 3.18+
In Alpine 3.18+, the 'iptables' package IS the nftables variant.
iptables-nft is not a separate package. The binary is already in
the base image — only need to flip update-alternatives.
2026-05-13 12:48:51 -04:00
f184ed957c Merge pull request 'fix: update wg-easy to official ghcr image with iptables-nft' (#26) from fix/vpn-iptables-nft-upstream into master
Reviewed-on: #26
2026-05-13 16:37:35 +00:00
2bf31c7ccc fix: update wg-easy to official ghcr image with iptables-nft
- Switch FROM weejewel/wg-easy:latest (4yr old, Alpine 3.11) to
  ghcr.io/wg-easy/wg-easy:latest (actively maintained, Alpine krypton)
- Use update-alternatives instead of raw ln -sf to flip iptables
  from legacy to nftables backend
- Fix compose build context: ./vpn -> . (Dockerfile was at same level)

The weejewel/wg-easy image lacked iptables-nft package in Alpine 3.11.
The new official image has it available, we just flip the alternatives.
The old ln -sf approach was fragile across Alpine versions.
2026-05-13 12:30:15 -04:00
f44f93e35a Merge pull request 'fix: add Himalaya email CLI to Hermes Docker image' (#25) from fix/himalaya-email-cli into master
Some checks failed
Build Hermes agent / build (push) Has been cancelled
Reviewed-on: #25
2026-05-13 15:03:40 +00:00
4cdd157e3f Merge pull request 'fix: add iptables-nft to wg-easy for nftables-only kernels' (#24) from fix/wg-easy-iptables-nft into master
Reviewed-on: #24
2026-05-13 15:03:25 +00:00
3ba0345887 Merge pull request 'feat: install custom Hermes tools at startup, remove deprecated fix-permissions.sh' (#23) from feat/hermes-custom-tools-startup into master
Some checks failed
Build Hermes agent / build (push) Failing after 2s
Build ollama (gfx906) / build (push) Failing after 2s
Reviewed-on: #23
2026-05-13 13:52:36 +00:00
27571ddb3f feat: add Himalaya email CLI to Hermes Docker image
Some checks failed
Build Hermes agent / build (pull_request) Failing after 2s
2026-05-12 18:09:40 -04:00
5e242eb946 fix: add iptables-nft to wg-easy for nftables-only kernels
wg-easy's Alpine wg-quick uses legacy iptables which requires the
iptable_nat kernel module. On NixOS kernels compiled without legacy
netfilter modules, the container crashes in a restart loop:

  iptables v1.8.3 (legacy): can't initialize iptables table 'nat'
  Table does not exist (do you need to insmod?)

Fix: build a custom image that installs Alpine's iptables-nft package
and symlinks iptables -> iptables-nft (nftables backend).
2026-05-12 14:52:33 -04:00
e607982b21 refactor: chown tools dir at build time instead of root at runtime
Some checks failed
Build Hermes agent / build (pull_request) Failing after 3s
Build ollama (gfx906) / build (pull_request) Failing after 2s
2026-05-12 14:47:34 -04:00
4627199217 feat: install custom tools at startup, remove deprecated fix-permissions.sh
Some checks failed
Build Hermes agent / build (pull_request) Failing after 41m55s
Build ollama (gfx906) / build (pull_request) Failing after 2s
2026-05-12 13:38:26 -04:00
3611d645db Merge pull request 'feat: add Gitea Actions CI workflows for Docker builds' (#21) from feat/gitea-actions into master
Reviewed-on: #21
2026-05-11 02:39:02 +00:00
99ac8b5dcd Merge pull request 'feat: add act_runner and enable Gitea Actions' (#22) from feat/act-runner into master
Reviewed-on: #22
2026-05-11 02:38:41 +00:00
b517a65393 fix: add nixos-builder label for NixOS CI builds 2026-05-10 22:15:44 -04:00
61a59dfac1 Merge pull request 'feat: update Hermes Dockerfile to build from forked source (gortium/hermes-agent)' (#20) from feat/hermes-fork-dockerfile into master
Reviewed-on: #20
2026-05-11 02:07:41 +00:00
34b1cb83a0 feat: add Gitea Actions workflows for ollama and hermes Docker builds 2026-05-10 21:33:10 -04:00
46241d10c5 feat: update Hermes Dockerfile to build from forked source
- Switch Dockerfile to clone from gortium/hermes-agent (Gitea fork)
- Add SSH agent forwarding for private repo clone at build time
- Set CHROME_EXECUTABLE for Playwright Chromium
- Remove patch_tts_tool.py (Piper patch now in fork source)
- Enable Gitea Actions in versioncontrol compose
2026-05-10 17:55:17 -04:00
9 changed files with 282 additions and 90 deletions

View File

@@ -0,0 +1,31 @@
name: Build Hermes agent
on:
pull_request:
branches: [ master ]
paths:
- 'ai/hermes/**'
- 'ai/compose.yml'
push:
branches: [ master ]
paths:
- 'ai/hermes/**'
- 'ai/compose.yml'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
run: |
git clone -b "${{ github.head_ref || github.ref_name }}" \
https://gitea:${{ secrets.GITHUB_TOKEN }}@code.lazyworkhorse.net/gortium/compose.git .
git log --oneline -3
- name: Build hermes image
run: |
cd ai
docker compose build hermes 2>&1
- name: Verify image
run: |
docker run --rm ai-hermes /opt/hermes/.venv/bin/python --version 2>&1

View File

@@ -0,0 +1,31 @@
name: Build ollama (gfx906)
on:
pull_request:
branches: [ master ]
paths:
- 'ai/ollama/**'
- 'ai/compose.yml'
push:
branches: [ master ]
paths:
- 'ai/ollama/**'
- 'ai/compose.yml'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
run: |
git clone -b "${{ github.head_ref || github.ref_name }}" \
https://gitea:${{ secrets.GITHUB_TOKEN }}@code.lazyworkhorse.net/gortium/compose.git .
git log --oneline -3
- name: Build ollama image
run: |
cd ai
docker compose build ollama --no-cache 2>&1
- name: Verify version
run: |
docker run --rm ollama/ollama:rocm-gfx906 ollama --version 2>&1

View File

@@ -26,8 +26,14 @@ services:
# - "traefik.http.routers.webui-https.tls.certresolver=njalla" # - "traefik.http.routers.webui-https.tls.certresolver=njalla"
hermes: hermes:
build: ./hermes build:
context: ./hermes
ssh:
- default
container_name: hermes container_name: hermes
entrypoint: ["/bin/bash", "-c",
"bash /opt/data/hermes-tools/install.sh && exec /usr/bin/tini -g -- /opt/hermes/docker/entrypoint.sh \"$@\"",
"hermes-entrypoint"]
restart: always restart: always
# Gateway run enables the internal API server on port 8642 # Gateway run enables the internal API server on port 8642
command: gateway run command: gateway run
@@ -90,6 +96,62 @@ services:
- "303" - "303"
- "26" - "26"
paperclip-db:
image: postgres:17-alpine
container_name: paperclip-db
restart: always
environment:
POSTGRES_USER: paperclip
POSTGRES_PASSWORD: ${PAPERCLIP_DB_PASSWORD:?PAPERCLIP_DB_PASSWORD must be set}
POSTGRES_DB: paperclip
healthcheck:
test: ["CMD-SHELL", "pg_isready -U paperclip -d paperclip"]
interval: 5s
timeout: 5s
retries: 10
volumes:
- /mnt/HoardingCow_docker_data/Paperclip/pgdata:/var/lib/postgresql/data
networks:
- ai_backend
paperclip:
image: ghcr.io/paperclipai/paperclip:v2026.517.0
container_name: paperclip
restart: always
ports:
- "127.0.0.1:3100:3100"
environment:
- HOST=0.0.0.0
- PORT=3100
- SERVE_UI=true
- DATABASE_URL=postgres://paperclip:${PAPERCLIP_DB_PASSWORD}@paperclip-db:5432/paperclip
- BETTER_AUTH_SECRET=${PAPERCLIP_AUTH_SECRET:?PAPERCLIP_AUTH_SECRET must be set}
- PAPERCLIP_PUBLIC_URL=https://paperclip.lazyworkhorse.net
- PAPERCLIP_DEPLOYMENT_MODE=authenticated
- PAPERCLIP_DEPLOYMENT_EXPOSURE=private
volumes:
- /mnt/HoardingCow_docker_data/Paperclip/data:/paperclip
depends_on:
paperclip-db:
condition: service_healthy
networks:
- ai_net
- ai_backend
labels:
- "traefik.enable=true"
- "traefik.docker.network=ai_net"
- "traefik.http.routers.paperclip-http.rule=Host(`paperclip.lazyworkhorse.net`)"
- "traefik.http.routers.paperclip-http.entrypoints=web"
- "traefik.http.routers.paperclip-http.middlewares=redirect-to-https"
- "traefik.http.routers.paperclip-https.rule=Host(`paperclip.lazyworkhorse.net`)"
- "traefik.http.routers.paperclip-https.entrypoints=websecure"
- "traefik.http.routers.paperclip-https.tls=true"
- "traefik.http.routers.paperclip-https.tls.certresolver=njalla"
- "traefik.http.services.paperclip.loadbalancer.server.port=3100"
networks: networks:
ai_net: ai_net:
external: true external: true

View File

@@ -1,50 +1,59 @@
# 1. On récupère la version la plus récente d'UV # syntax=docker/dockerfile:1
FROM ghcr.io/astral-sh/uv:latest AS uv_source # Hermes Agent -- custom fork build
# Builds on top of official image + overlays our forked source from Gitea.
# Requires Docker BuildKit. Pass SSH agent for git clone:
# docker compose build hermes
# Or manually:
# DOCKER_BUILDKIT=1 docker build --ssh default -t hermes-agent:custom .
# 2. Image officielle Hermes Agent de NousResearch # ---------- Base: official Hermes image (system deps, npm, uv, Playwright) ----------
# Contient déjà: Python, Node.js, npm, Playwright/Chromium, venv, tts_tool.py, etc.
FROM nousresearch/hermes-agent:latest FROM nousresearch/hermes-agent:latest
# ---------- System dependencies ---------- # ---------- Overlay our forked source ----------
# The official hermes-agent image already has: git, curl, ffmpeg, python3, # Uses SSH agent forwarding from the build host (no key baked into image).
# gcc, build-essential, openssh-client, procps, tini, ripgrep, docker-cli, # --exclude node_modules/.venv keeps the base image's pre-built layers intact.
# libportaudio2, ca-certificates, etc. # Only the Python source, web UI source, and config change.
# RUN --mount=type=ssh \
# These extras we need to add back: mkdir -p /root/.ssh && \
# - poppler-utils, imagemagick (PDF/image processing) ssh-keyscan -p 2222 code.lazyworkhorse.net >> /root/.ssh/known_hosts 2>/dev/null && \
# - texlive-* (LaTeX typesetting for reports) cd /tmp && \
# - qemu-user-static, binfmt-support (QEMU cross-compilation) GIT_SSH_COMMAND='ssh -p 2222 -o StrictHostKeyChecking=no' \
# - emacs-nox (text editing in container) git clone --depth 1 --branch main \
git@code.lazyworkhorse.net:gortium/hermes-agent.git fork && \
rsync -a --delete fork/ /opt/hermes/ \
--exclude node_modules \
--exclude .venv \
--exclude .git && \
rm -rf /tmp/fork /root/.ssh/
# ---------- Rebuild web UI ----------
# Source files changed; node_modules (from base image) reused.
RUN cd /opt/hermes && npm run build
# ---------- 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 USER root
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y --no-install-recommends \ apt-get install -y --no-install-recommends \
libportaudio2 \ libportaudio2 ca-certificates poppler-utils imagemagick \
ca-certificates \ texlive-latex-base texlive-latex-extra texlive-fonts-recommended \
poppler-utils \ texlive-xetex texlive-science \
imagemagick \ qemu-user-static binfmt-support emacs-nox && \
texlive-latex-base \
texlive-latex-extra \
texlive-fonts-recommended \
texlive-xetex \
texlive-science \
qemu-user-static \
binfmt-support \
emacs-nox && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# ---------- UV (hyperfast pip alternative) ---------- # ---------- UV ----------
COPY --chmod=0755 --from=uv_source /uv /usr/local/bin/ COPY --chmod=0755 --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/
WORKDIR /opt/hermes # ---------- Piper TTS ----------
# ---------- Piper TTS dans le venv existant ----------
# Le venv de l'image de base est root-owned, on doit installer en root aussi
RUN . /opt/hermes/.venv/bin/activate && \ RUN . /opt/hermes/.venv/bin/activate && \
uv pip install --no-cache-dir piper-tts sounddevice numpy uv pip install --no-cache-dir piper-tts sounddevice numpy && \
mkdir -p /opt/hermes/.venv/share/piper/voices
# ---------- Télécharger la voix Piper Ryan (high quality) ---------- RUN /opt/hermes/.venv/bin/python3 /dev/stdin << 'PYEOF'
RUN mkdir -p /opt/hermes/.venv/share/piper/voices && \
/opt/hermes/.venv/bin/python3 /dev/stdin << 'PYEOF'
import urllib.request import urllib.request
base = '/opt/hermes/.venv/share/piper/voices' base = '/opt/hermes/.venv/share/piper/voices'
url = 'https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/ryan/high/en_US-ryan-high.onnx' url = 'https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/ryan/high/en_US-ryan-high.onnx'
@@ -52,22 +61,33 @@ urllib.request.urlretrieve(url, base + '/en_US-ryan-high.onnx')
urllib.request.urlretrieve(url + '.json', base + '/en_US-ryan-high.onnx.json') urllib.request.urlretrieve(url + '.json', base + '/en_US-ryan-high.onnx.json')
PYEOF PYEOF
# ---------- Patch tts_tool.py: remplacer Edge TTS par Piper ---------- # ---------- Install Himalaya email CLI ----------
# Edge TTS appelle les serveurs Microsoft — on ne veut jamais ça. RUN /opt/hermes/.venv/bin/python3 /dev/stdin << 'PYEOF'
# Piper roule localement sur CPU, aucun cloud, aucune donnée qui sort. import urllib.request, tarfile, os, shutil
COPY patch_tts_tool.py /tmp/patch_tts_tool.py url = 'https://github.com/pimalaya/himalaya/releases/download/v1.2.0/himalaya.x86_64-linux.tgz'
RUN /opt/hermes/.venv/bin/python3 /tmp/patch_tts_tool.py && rm /tmp/patch_tts_tool.py tgz = '/tmp/himalaya.tgz'
urllib.request.urlretrieve(url, tgz)
with tarfile.open(tgz) as t:
t.extractall('/tmp')
shutil.move('/tmp/himalaya', '/usr/local/bin/himalaya')
os.chmod('/usr/local/bin/himalaya', 0o755)
os.remove(tgz)
print('himalaya v1.2.0 installed')
PYEOF
# ---------- Install himalaya-ro wrapper ----------
COPY --chmod=0755 himalaya-ro.sh /usr/local/bin/himalaya-ro
# ---------- Runtime ---------- # ---------- Runtime ----------
# Retour à l'utilisateur non-root pour la sécurité
USER hermes USER hermes
ENV HERMES_HOME=/opt/data ENV HERMES_HOME=/opt/data
ENV PATH="/opt/data/.local/bin:${PATH}" ENV PATH="/opt/data/.local/bin:${PATH}"
# Point browser tool to Playwright's Chromium (already in base image)
ENV CHROME_EXECUTABLE=/opt/hermes/.playwright/chromium/chrome-linux/chrome
VOLUME [ "/opt/data" ] # Ensure tools directory and toolsets.py are writable by the hermes runtime user
# so custom tools can be injected from the persistent volume at startup.
RUN chown -R hermes:hermes /opt/hermes/tools /opt/hermes/toolsets.py
# Script de réparation des permissions + patch TTS au démarrage VOLUME [ "/opt/data" ]
COPY --chmod=0755 fix-permissions.sh /opt/hermes/fix-permissions.sh
ENTRYPOINT [ "/usr/bin/tini", "-g", "--", "/opt/hermes/fix-permissions.sh" ]

View File

@@ -1,38 +0,0 @@
#!/bin/bash
# Startup permission fix + TTS patch.
# Runs as root before the entrypoint drops to the hermes user.
set -e
HERMES_HOME="${HERMES_HOME:-/opt/data}"
# Fix ownership on critical writable directories
chown -R hermes:hermes \
"$HERMES_HOME/sessions" \
"$HERMES_HOME/checkpoints" \
"$HERMES_HOME/skills" \
"$HERMES_HOME/memories" \
"$HERMES_HOME/workspace" \
"$HERMES_HOME/pastes" \
"$HERMES_HOME/logs" \
"$HERMES_HOME/cron" \
"$HERMES_HOME/plans" \
"$HERMES_HOME/hooks" \
"$HERMES_HOME/cache" \
2>/dev/null || true
# Fix data volume root ownership
if [ "$(stat -c %u "$HERMES_HOME" 2>/dev/null)" != "$(id -u hermes)" ]; then
chown hermes:hermes "$HERMES_HOME" 2>/dev/null || true
fi
# ---------- Patch tts_tool.py: replace Edge TTS with Piper ----------
# Fallback runtime patch in case the volume's site-packages differ from the image.
# Idempotent: if already patched, the script does nothing.
PATCH_SCRIPT="/opt/hermes/patch_tts_tool.py"
if [ -f "$PATCH_SCRIPT" ]; then
echo "Applying TTS patch (Piper only, no Edge fallback)..."
/opt/hermes/.venv/bin/python3 "$PATCH_SCRIPT" 2>&1 || true
fi
# Chain to the official Hermes entrypoint
exec /opt/hermes/docker/entrypoint.sh "$@"

73
ai/hermes/himalaya-ro.sh Normal file
View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────
# himalaya-ro — Read-only wrapper for himalaya
#
# Blocks destructive commands and logs audit trail.
# Pass-through for read-only commands (list, read, search).
#
# Usage: himalaya-ro [options] <command> [args...]
#
# Install: place in PATH before the real himalaya, or use
# `ln -sf himalaya-ro /usr/local/bin/himalaya`
# ─────────────────────────────────────────────────────────────
set -o pipefail
# ── Configuration ───────────────────────────────────────────
HIMALAYA_BIN="${HIMALAYA_BIN:-/usr/local/bin/himalaya}"
AUDIT_LOG="${HIMALAYA_AUDIT_LOG:-/var/log/himalaya-audit.log}"
# ── Destructive commands we block ──────────────────────────
BLOCKED_CMDS=(
"message move"
"message delete"
"message copy"
"flag add"
"flag remove"
"folder create"
"folder delete"
"folder rename"
"template send"
"account configure"
"account delete"
)
# ── Determine the subcommand being invoked ─────────────────
# Strip leading options (--account, --output, etc.) to find the verb
ARGS=()
SKIP_NEXT=false
for arg in "$@"; do
if $SKIP_NEXT; then
SKIP_NEXT=false
continue
fi
if [[ "$arg" == --* ]]; then
case "$arg" in
--account|--output|--page|--page-size|--folder|--color|--format)
SKIP_NEXT=true ;;
esac
continue
fi
ARGS+=("$arg")
done
# Build subcommand string and check against blocklist
CMD_STR=""
for ((i=0; i<${#ARGS[@]}; i++)); do
if [ -z "$CMD_STR" ]; then
CMD_STR="${ARGS[$i]}"
else
CMD_STR="$CMD_STR ${ARGS[$i]}"
fi
for blocked in "${BLOCKED_CMDS[@]}"; do
if [[ "$CMD_STR" == "$blocked" ]]; then
TS=$(date '+%Y-%m-%d %H:%M:%S')
echo "[AUDIT] $TS BLOCKED: himalaya $*" >> "$AUDIT_LOG"
echo "ERROR: Command 'himalaya $CMD_STR ...' is blocked by read-only policy." >&2
echo " Audit log: $AUDIT_LOG" >&2
exit 100
fi
done
done
# ── Allow pass-through ─────────────────────────────────────
exec "$HIMALAYA_BIN" "$@"

View File

@@ -8,9 +8,10 @@ services:
- USER_GID=1000 - USER_GID=1000
- GITEA__server__ROOT_URL=https://code.lazyworkhorse.net - GITEA__server__ROOT_URL=https://code.lazyworkhorse.net
- GITEA__actions__ENABLED=true - GITEA__actions__ENABLED=true
- GITEA__actions__DEFAULT_ACTIONS_URL=off
- SSH_PORT=2222 - SSH_PORT=2222
- SSH_LISTEN_PORT=2222 - SSH_LISTEN_PORT=2222
# Enable Gitea Actions (act_runner required on host)
- GITEA__actions__ENABLED=true
volumes: volumes:
- /mnt/HoardingCow_docker_data/Gitea:/data - /mnt/HoardingCow_docker_data/Gitea:/data
networks: networks:
@@ -49,7 +50,7 @@ services:
- GITEA_INSTANCE_URL=https://code.lazyworkhorse.net - GITEA_INSTANCE_URL=https://code.lazyworkhorse.net
- GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN} - GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_TOKEN}
- GITEA_RUNNER_NAME=ai-host-runner - GITEA_RUNNER_NAME=ai-host-runner
- GITEA_RUNNER_LABELS=ubuntu-latest:docker://catthehacker/ubuntu:full-22.04 - GITEA_RUNNER_LABELS=ubuntu-latest:docker://catthehacker/ubuntu:full-22.04,nixos-builder:docker://nixos/nix
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
networks: networks:

9
vpn/Dockerfile Normal file
View File

@@ -0,0 +1,9 @@
# Custom wg-easy with iptables-nft (nftables-backed iptables)
# Fixes crash-loop when host kernel lacks legacy iptable_nat module.
FROM ghcr.io/wg-easy/wg-easy:latest
# The upstream image registers only iptables-legacy with update-alternatives.
# iptables-nft binary exists but isn't registered as an alternative key.
# Override the alternatives-managed symlinks directly.
RUN ln -sf /usr/sbin/iptables-nft /usr/sbin/iptables && \
ln -sf /usr/sbin/ip6tables-nft /usr/sbin/ip6tables

View File

@@ -2,7 +2,10 @@ version: "3.8"
services: services:
wireguard: wireguard:
image: weejewel/wg-easy:latest build:
context: .
dockerfile: Dockerfile
image: wg-easy-iptables-nft:latest
container_name: wireguard container_name: wireguard
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN