From 0bcc97a819d6578d41754512376b31fff66b1bce Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 26 Jul 2026 11:37:47 +0300 Subject: forgejo: reach git+ssh from off-LAN via a relayd TCP relay on 2022 The NodePort is LAN-only, so the advertised clone URL (ssh://git@r0.lan.buetow.org:30222/...) did not work from outside. Add a plain TCP relay on the gateways forwarding 2022 to NodePort 30222, and have Forgejo advertise code.f3s.buetow.org:2022. Port 2022 rather than 22: the gateways run their own sshd on port 2, so 22 was in fact free, but leaving the forge off the default port keeps it clear of the mass scanning that port attracts. That is noise reduction and not security -- the real protection is that Forgejo's SSH does key-only auth for git operations and offers no shell. 2222 would have been the conventional choice but dserver (DTail) already holds it on the gateways; verified 2022 free on both. The relay carries no "protocol" line, so relayd forwards the stream untouched. TLS must not be involved: SSH secures its own transport and the client verifies Forgejo's host key at the far end. A dedicated table keeps the health check on the SSH port, since the web UI can be up while SSH is not. Co-Authored-By: Claude Opus 5 --- f3s/forgejo/README.md | 18 ++++++++++++- f3s/forgejo/helm-chart/templates/deployment.yaml | 17 +++++++----- frontends/etc/relayd.conf.tpl | 34 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/f3s/forgejo/README.md b/f3s/forgejo/README.md index 9758b29..70e6133 100644 --- a/f3s/forgejo/README.md +++ b/f3s/forgejo/README.md @@ -112,10 +112,26 @@ just create-admin # HTTPS git clone https://code.f3s.buetow.org//.git -# SSH (NodePort; LAN only unless you forward it) +# SSH, from anywhere -- relayd listens on 2022 and TCP-forwards to the NodePort +git clone ssh://git@code.f3s.buetow.org:2022//.git + +# SSH direct to a node, bypassing the gateways (LAN only) git clone ssh://git@r0.lan.buetow.org:30222//.git ``` +Port 2022 rather than 22 keeps the forge away from the mass scanning the default +port attracts; 2222 was unavailable, dserver (DTail) already uses it on the +gateways. To administer blowfish/fishfinger, SSH is on port 2 as usual. + +To use the short `git@code.f3s.buetow.org:user/repo.git` form, put the port in +`~/.ssh/config`: + +``` +Host code.f3s.buetow.org + Port 2022 + User git +``` + ## Operations ```sh diff --git a/f3s/forgejo/helm-chart/templates/deployment.yaml b/f3s/forgejo/helm-chart/templates/deployment.yaml index ba19dfa..73c5704 100644 --- a/f3s/forgejo/helm-chart/templates/deployment.yaml +++ b/f3s/forgejo/helm-chart/templates/deployment.yaml @@ -96,15 +96,18 @@ spec: value: "true" - name: FORGEJO__server__SSH_LISTEN_PORT value: "2222" - # SSH_DOMAIN is deliberately NOT code.f3s.buetow.org: that name resolves - # to the OpenBSD gateways, which forward 443 only, and *.f3s.lan points - # at the CARP storage VIP rather than a k3s node. Advertise a node that - # actually answers on the NodePort, so the clone URLs Forgejo renders - # are ones that work. + # relayd listens on 2022 on the gateways and TCP-forwards to NodePort + # 30222, so git+ssh works from off-LAN (see relay "forgejo_ssh4" in + # frontends/etc/relayd.conf.tpl). Not 22: that keeps the forge clear of + # the constant scanning on the default port. Not 2222 either -- dserver + # already holds that on the gateways. + # + # SSH_PORT is what Forgejo advertises in clone URLs (2022, via relayd); + # SSH_LISTEN_PORT above is what the container actually binds (2222). - name: FORGEJO__server__SSH_DOMAIN - value: "r0.lan.buetow.org" + value: "code.f3s.buetow.org" - name: FORGEJO__server__SSH_PORT - value: "30222" + value: "2022" # Behind relayd -> Traefik, Forgejo's default trusts only 127.0.0.0/8, # so every request would be attributed to the Traefik pod IP: real client diff --git a/frontends/etc/relayd.conf.tpl b/frontends/etc/relayd.conf.tpl index 02b4887..8a53ed3 100644 --- a/frontends/etc/relayd.conf.tpl +++ b/frontends/etc/relayd.conf.tpl @@ -48,6 +48,15 @@ table { 192.168.2.132 } +# Forgejo git+ssh backends (NodePort 30222 on the k3s nodes, over WireGuard). +# Separate table from so the health check tracks the SSH port specifically: +# the web UI can be up while the built-in SSH server is not. +table { + 192.168.2.120 + 192.168.2.121 + 192.168.2.122 +} + # Local OpenBSD httpd table { 127.0.0.1 @@ -234,6 +243,31 @@ relay "gemini6" { forward to 127.0.0.1 port 11965 } +# Forgejo git+ssh. +# +# Port 2022, deliberately not 22: leaving the forge off the default port keeps +# it out of the way of the mass scanners that hammer 22 continuously. That is +# noise reduction, not security -- the actual protection is that Forgejo's SSH +# server does key-only auth for git operations and offers no shell. +# +# 2222 was the obvious alternative but is already taken here by dserver (DTail). +# +# Plain TCP relay: no "protocol" line, so relayd forwards the stream untouched. +# TLS is not involved and must not be -- SSH does its own transport security, +# and the client verifies Forgejo's own host key at the far end. +# +# Only the gateway currently holding the code.f3s.buetow.org address actually +# receives connections; the other listens harmlessly. +relay "forgejo_ssh4" { + listen on <%= $ipv4address->($hostname) %> port 2022 + forward to port 30222 check tcp +} + +relay "forgejo_ssh6" { + listen on <%= $ipv6address->($hostname) %> port 2022 + forward to port 30222 check tcp +} + relay "f3s_static_proxy4" { listen on 127.0.0.1 port 18080 forward to port 80 check tcp -- cgit v1.2.3