Updated code to configure Forgejo to have two DNS names, one for git and for ssh.
Some checks failed
deploy / deploy (push) Has been cancelled
Some checks failed
deploy / deploy (push) Has been cancelled
This commit is contained in:
parent
1250c9cef6
commit
d59f463d3d
9 changed files with 97 additions and 10 deletions
|
|
@ -771,6 +771,14 @@ the native install needs, `terraform apply -target=module.forgejo`,
|
|||
Ansible deliberately does not do — moving repository data, and the DNS/SSH-port
|
||||
cutover.
|
||||
|
||||
Note Forgejo needs **two** DNS names, not one: `FORGEJO_DOMAIN` for the web
|
||||
side, pointing at whatever terminates HTTPS in front of it, and
|
||||
`FORGEJO_SSH_DOMAIN` for git-over-SSH, pointing at the container itself. SSH
|
||||
has no SNI, so a reverse proxy can't route it by hostname the way it routes
|
||||
HTTP — the split is forced by the protocol. See
|
||||
`src/forgejo/ansible/proxmox/README.md` for the alternative (a layer-4 TCP
|
||||
proxy) and why it isn't used here.
|
||||
|
||||
## Deploying one platform, one host, one stack
|
||||
|
||||
`playbooks/deploy.yml` runs everything; `playbooks/unraid.yml`,
|
||||
|
|
|
|||
|
|
@ -18,8 +18,14 @@
|
|||
# off nas2, which is no longer a machine that can be read from.
|
||||
#
|
||||
# Also note SSH clone URLs move from port 2222 to 22 (see FORGEJO_SSH_PORT in
|
||||
# src/forgejo/ansible/proxmox/vars.yml): existing remotes need editing, and
|
||||
# git.turtlesystems.uk has to resolve to this container.
|
||||
# src/forgejo/ansible/proxmox/vars.yml): existing remotes need editing.
|
||||
#
|
||||
# They also move to a different *hostname*. HTTP for git.turtlesystems.uk is
|
||||
# proxied by Caddy, which is a different machine and has no sshd, so SSH is
|
||||
# advertised as src.turtlesystems.uk instead (FORGEJO_SSH_DOMAIN, same file) —
|
||||
# and it is that name, not the web one, that has to resolve to `ansible_host`
|
||||
# below. SSH has no SNI, so this split is forced by the protocol rather than
|
||||
# being a Caddy shortcoming; the reasoning is in vars.yml.
|
||||
|
||||
# The address Terraform assigns this guest (build/config/terraform/main.tf).
|
||||
# Pinned here rather than left to DNS: the API-backed dynamic inventory
|
||||
|
|
|
|||
|
|
@ -192,11 +192,25 @@ gives back every file and no issues, pull requests, users or permissions.
|
|||
|
||||
Last, once the above is verified:
|
||||
|
||||
- Point `git.turtlesystems.uk` at this container.
|
||||
- **SSH clone URLs move from port 2222 to 22.** The Unraid stack published
|
||||
2222 to dodge the host's own sshd; this container has its own IP and uses
|
||||
its own sshd, with Forgejo managing the `git` user's `authorized_keys`.
|
||||
Every existing remote needs editing — there is no redirect for this.
|
||||
- Point `git.turtlesystems.uk` at whatever terminates HTTPS for it — the Caddy
|
||||
reverse proxy at 192.168.50.51, which proxies through to this container's
|
||||
`FORGEJO_HTTP_PORT`.
|
||||
- Point `src.turtlesystems.uk` at this container (192.168.50.52). This is the
|
||||
name in `FORGEJO_SSH_DOMAIN`, and the one SSH clone URLs use.
|
||||
- **SSH clone URLs move from port 2222 to 22, and onto their own hostname.**
|
||||
The Unraid stack published 2222 to dodge the host's own sshd; this container
|
||||
has its own IP and uses its own sshd, with Forgejo managing the `git` user's
|
||||
`authorized_keys`. Every existing remote needs editing — there is no
|
||||
redirect for this.
|
||||
|
||||
The two hostnames are not redundancy. An SSH client sends a version banner
|
||||
and nothing identifying the host it meant — there is no equivalent of TLS
|
||||
SNI — so a reverse proxy cannot route SSH by name the way it routes HTTP.
|
||||
The web name therefore has to point at the proxy and the SSH name at
|
||||
Forgejo. Collapsing them into one would mean putting a layer-4 TCP proxy on
|
||||
the proxy's port 22 (Caddy can, via the third-party `caddy-l4` module, at
|
||||
the cost of a custom binary and of losing client IPs on SSH), not
|
||||
configuring the hostname more cleverly.
|
||||
- The Forgejo Actions runner registration is tied to the instance. Re-register
|
||||
it against the new host, or CI stops running (`.forgejo/workflows/`).
|
||||
|
||||
|
|
|
|||
|
|
@ -79,6 +79,21 @@ editing `FORGEJO_RELEASE` and redeploying.
|
|||
the `git` user's `authorized_keys` rather than running its own server. This
|
||||
changes the SSH clone URLs Forgejo advertises, so existing remotes need
|
||||
updating after a migration.
|
||||
- **SSH is on its own hostname** (`FORGEJO_SSH_DOMAIN` =
|
||||
`src.turtlesystems.uk`), separate from the web one (`FORGEJO_DOMAIN` =
|
||||
`git.turtlesystems.uk`, which resolves to the Caddy reverse proxy). Not a
|
||||
redundancy and not a Caddy limitation: SSH has no SNI — the client sends a
|
||||
version banner and nothing naming the host it meant — so no reverse proxy
|
||||
can route SSH by hostname the way it routes HTTP. The web name has to point
|
||||
at whatever terminates TLS and the SSH name at whatever runs sshd, and here
|
||||
those are different machines. One name is possible only by putting a
|
||||
layer-4 TCP proxy on the proxy's port 22 (Caddy's third-party `caddy-l4`
|
||||
module does this) and accepting a custom Caddy build plus every SSH
|
||||
connection appearing to originate from the proxy.
|
||||
|
||||
Both names must therefore exist in DNS, and the failure mode of getting
|
||||
this wrong is quiet: web logins work, and only `git push` breaks, with a
|
||||
connection refused against a host that has no sshd.
|
||||
- **`INSTALL_LOCK = true`.** `app.ini` is rendered in full from Vault, so the
|
||||
web installer is skipped entirely. Nothing is left for Forgejo to generate
|
||||
on first boot — which is why `LFS_JWT_SECRET` has to exist in Vault here
|
||||
|
|
|
|||
|
|
@ -28,8 +28,14 @@ HTTP_PORT = {{ app_config.FORGEJO_HTTP_PORT }}
|
|||
APP_DATA_PATH = {{ app_config.FORGEJO_DATA_PATH }}
|
||||
{# The container's own sshd serves git over SSH, so Forgejo only advertises
|
||||
the address and manages the git user's authorized_keys. On Unraid this was
|
||||
Forgejo's built-in server behind a published Docker port. #}
|
||||
SSH_DOMAIN = {{ app_config.FORGEJO_DOMAIN }}
|
||||
Forgejo's built-in server behind a published Docker port.
|
||||
|
||||
FORGEJO_SSH_DOMAIN, not FORGEJO_DOMAIN: SSH reaches this container
|
||||
directly while HTTP goes through a reverse proxy, so the two names resolve
|
||||
to different machines. Rendering the web domain here advertises clone URLs
|
||||
pointing at the proxy, which has no sshd — see ../vars.yml for why the
|
||||
protocol leaves no other option. #}
|
||||
SSH_DOMAIN = {{ app_config.FORGEJO_SSH_DOMAIN }}
|
||||
SSH_PORT = {{ app_config.FORGEJO_SSH_PORT }}
|
||||
START_SSH_SERVER = false
|
||||
DISABLE_SSH = false
|
||||
|
|
|
|||
|
|
@ -27,6 +27,25 @@ env_defaults:
|
|||
# SSH clone URLs Forgejo advertises — see README.md in this directory.
|
||||
FORGEJO_SSH_PORT: "22"
|
||||
|
||||
# Git over SSH lands on this container directly; the web side does not. HTTP
|
||||
# is proxied by Caddy at 192.168.50.51, which is what git.turtlesystems.uk
|
||||
# (FORGEJO_DOMAIN) resolves to — and Caddy speaks HTTP, so port 22 there is
|
||||
# closed. Pointing the SSH clone URLs at the web domain therefore advertises
|
||||
# a host with no sshd on it, which is exactly what this override exists to
|
||||
# avoid.
|
||||
#
|
||||
# Splitting the names is not a workaround for a Caddy limitation; it is
|
||||
# forced by the protocol. An SSH client sends a version banner and nothing
|
||||
# else — no equivalent of TLS SNI — so no proxy can tell which backend a
|
||||
# connection was meant for. The alternatives are a layer-4 TCP proxy on
|
||||
# port 22 (Caddy can do this via the third-party `caddy-l4` module, at the
|
||||
# cost of a custom binary and of every SSH connection appearing to come from
|
||||
# the proxy's address) or giving Forgejo its own name, as here.
|
||||
#
|
||||
# Keep in step with the A record: src.turtlesystems.uk must resolve to this
|
||||
# container's `ansible_host` in host_vars/forgejo.yml (192.168.50.52).
|
||||
FORGEJO_SSH_DOMAIN: src.turtlesystems.uk
|
||||
|
||||
# No `unraid_shared` Docker network here to resolve `shared-postgres`
|
||||
# through, so the shared Postgres is reached over the LAN, at the address of
|
||||
# the LXC running it. Keep in step with `ip_address` on the `postgres`
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ FORGEJO_HTTP_PORT=3000
|
|||
FORGEJO_SSH_PORT=2222
|
||||
FORGEJO_DOMAIN=git.example.internal
|
||||
FORGEJO_ROOT_URL=http://git.example.internal:3000/
|
||||
# The host SSH clone URLs point at. Same as FORGEJO_DOMAIN unless a reverse
|
||||
# proxy fronts the web side, in which case that name has no sshd behind it.
|
||||
FORGEJO_SSH_DOMAIN=git.example.internal
|
||||
DB_HOST=shared-postgres
|
||||
DB_NAME=forgejo
|
||||
DB_USER=forgejo
|
||||
|
|
|
|||
|
|
@ -27,7 +27,12 @@ services:
|
|||
FORGEJO__database__PASSWD: ${DB_PASSWORD}
|
||||
FORGEJO__server__DOMAIN: ${FORGEJO_DOMAIN}
|
||||
FORGEJO__server__ROOT_URL: ${FORGEJO_ROOT_URL}
|
||||
FORGEJO__server__SSH_DOMAIN: ${FORGEJO_DOMAIN}
|
||||
# Its own variable rather than ${FORGEJO_DOMAIN}: the SSH clone URLs need
|
||||
# a name that resolves to whatever is actually listening for SSH, which
|
||||
# is not the web domain wherever a reverse proxy terminates HTTP. Equal
|
||||
# to FORGEJO_DOMAIN by default in ../../common/vars.yml, so this is a
|
||||
# no-op until a platform overrides it.
|
||||
FORGEJO__server__SSH_DOMAIN: ${FORGEJO_SSH_DOMAIN}
|
||||
FORGEJO__server__SSH_PORT: ${FORGEJO_SSH_PORT}
|
||||
# Fixed rather than left to be auto-generated, so recreating the
|
||||
# container from a fresh volume doesn't invalidate sessions/tokens.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,17 @@ env_defaults:
|
|||
FORGEJO_SSH_PORT: "2222"
|
||||
FORGEJO_DOMAIN: git.turtlesystems.uk
|
||||
FORGEJO_ROOT_URL: "https://git.turtlesystems.uk"
|
||||
|
||||
# The hostname Forgejo puts in the SSH clone URLs it advertises, kept
|
||||
# separate from FORGEJO_DOMAIN because the two need not resolve to the same
|
||||
# machine. SSH carries no hostname in its handshake — there is no SNI — so a
|
||||
# reverse proxy cannot route it by name the way it routes HTTP. A deployment
|
||||
# that terminates TLS on a proxy in front of Forgejo therefore has the web
|
||||
# domain pointing at the proxy and the SSH domain pointing at Forgejo
|
||||
# itself. Defaulted to FORGEJO_DOMAIN here, which is correct whenever
|
||||
# nothing sits in front; the platform that needs them to differ overrides it
|
||||
# (see ../ansible/proxmox/vars.yml).
|
||||
FORGEJO_SSH_DOMAIN: git.turtlesystems.uk
|
||||
DB_NAME: forgejo
|
||||
DB_USER: forgejo
|
||||
# DB_PASSWORD, SECRET_KEY, INTERNAL_TOKEN, JWT_SECRET are secrets — sourced
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue