From c3a377a265d2ca92b8823be281fa0e487d30692b Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 18 Feb 2026 15:12:32 +0800 Subject: switch to rocky linux 10, add --init for zombie reaping, fix NAT setup - base image alpine -> rockylinux:10 (cgit/fcgiwrap from EPEL) - drop spawn-fcgi, use fcgiwrap -s directly - add --init to reap zombie sshd-auth processes (PID exhaustion fix) - replace ip addr/route networking with nft DNAT/SNAT/FORWARD rules - add FORWARD accept rule that was missing for inbound DNAT traffic --- Caddyfile | 6 +++--- Dockerfile | 10 ++++++---- entrypoint.sh | 5 +++-- sshd_config | 2 +- start_container.sh | 21 ++++++++++++++++----- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Caddyfile b/Caddyfile index b783e7b..7458b93 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,18 +1,18 @@ {$DOMAIN} { handle {$CGIT_CSS} { - root * /usr/share/webapps/cgit + root * /usr/share/cgit file_server } handle {$CGIT_LOGO} { - root * /usr/share/webapps/cgit + root * /usr/share/cgit file_server } handle { reverse_proxy unix/{$FCGI_SOCK} { transport fastcgi { - env SCRIPT_FILENAME /usr/share/webapps/cgit/cgit.cgi + env SCRIPT_FILENAME /var/www/cgi-bin/cgit env QUERY_STRING {query} env HTTP_HOST {host} env PATH_INFO {path} diff --git a/Dockerfile b/Dockerfile index 86352b4..65ead86 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,16 @@ -FROM alpine:latest +FROM rockylinux:10 -RUN apk add --no-cache \ +RUN dnf install -y epel-release && \ + dnf copr enable -y @caddy/caddy && \ + dnf install -y \ caddy \ cgit \ git \ fcgiwrap \ - spawn-fcgi \ gettext \ openssl \ - openssh-server + openssh-server \ + && dnf clean all COPY cgitrc.template /etc/cgitrc.template COPY Caddyfile /etc/caddy/Caddyfile diff --git a/entrypoint.sh b/entrypoint.sh index 3e2dcc0..ba24e29 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash set -e # Check cert matches domain, else clear and renew @@ -21,7 +21,8 @@ chmod 700 /git/.ssh chmod 600 /git/.ssh/authorized_keys /usr/sbin/sshd -spawn-fcgi -s ${FCGI_SOCK} /usr/bin/fcgiwrap +fcgiwrap -s unix:${FCGI_SOCK} & +sleep 0.5 chmod 666 ${FCGI_SOCK} exec caddy run --config /etc/caddy/Caddyfile --adapter caddyfile diff --git a/sshd_config b/sshd_config index 5d31e36..0270433 100644 --- a/sshd_config +++ b/sshd_config @@ -7,4 +7,4 @@ AuthorizedKeysFile /git/.ssh/authorized_keys MaxStartups 3:50:10 # Kill unauthenticated connections after 15 seconds LoginGraceTime 15 -Subsystem sftp /usr/lib/ssh/sftp-server +Subsystem sftp /usr/libexec/openssh/sftp-server diff --git a/start_container.sh b/start_container.sh index 2299390..f93f5df 100755 --- a/start_container.sh +++ b/start_container.sh @@ -29,6 +29,7 @@ podman build -t cgit "$(dirname "$0")" # Run container podman run -d \ + --init \ --name ${CONTAINER_NAME} \ --network ${NETWORK} \ --ip ${PRIVATE_IP} \ @@ -39,11 +40,21 @@ podman run -d \ -v /git:/git \ localhost/cgit -# Setup public IP +# Setup public IP via DNAT/SNAT sleep 2 -# Get the container's network interface name (e.g. eth0) -IFACE=$(podman exec ${CONTAINER_NAME} sh -c "ip -o link | grep -v lo | head -1 | cut -d: -f2 | tr -d ' ' | cut -d@ -f1") -podman exec ${CONTAINER_NAME} ip addr add ${PUBLIC_IP}/32 dev ${IFACE} -ip route add ${PUBLIC_IP}/32 via ${PRIVATE_IP} +OIFACE=$(ip route show default | awk '{print $5; exit}') +BRIDGE=$(podman network inspect ${NETWORK} 2>/dev/null | python3 -c "import json,sys; print(json.load(sys.stdin)[0]['network_interface'])") + +# Clean up any stale rules for this IP +nft -a list chain ip nat PREROUTING 2>/dev/null | grep "daddr ${PUBLIC_IP} " | grep -oP 'handle \K\d+' | while read h; do nft delete rule ip nat PREROUTING handle "$h"; done +nft -a list chain ip nat POSTROUTING 2>/dev/null | grep "snat to ${PUBLIC_IP}" | grep -oP 'handle \K\d+' | while read h; do nft delete rule ip nat POSTROUTING handle "$h"; done +nft -a list chain inet netavark FORWARD 2>/dev/null | grep "daddr ${PRIVATE_IP} " | grep -oP 'handle \K\d+' | while read h; do nft delete rule inet netavark FORWARD handle "$h"; done +nft -a list chain ip nat POSTROUTING 2>/dev/null | grep "daddr ${PRIVATE_IP}.*masquerade" | grep -oP 'handle \K\d+' | while read h; do nft delete rule ip nat POSTROUTING handle "$h"; done +ip route del ${PUBLIC_IP} 2>/dev/null || true + +nft add rule ip nat PREROUTING ip daddr ${PUBLIC_IP} dnat to ${PRIVATE_IP} +nft add rule ip nat POSTROUTING ip saddr ${PRIVATE_IP} oifname ${OIFACE} snat to ${PUBLIC_IP} +nft insert rule inet netavark FORWARD ip daddr ${PRIVATE_IP} oifname ${BRIDGE} accept +nft add rule ip nat POSTROUTING ip saddr ${PRIVATE_SUBNET} ip daddr ${PRIVATE_IP} oifname ${BRIDGE} masquerade echo "Running at https://${DOMAIN}/" -- cgit