This repository has been archived on 2026-09-17. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
nixos-config/hosts/blunix/localServices/forgejo.nix
pijukka 355b42e78e ssh: pin forgejo's port-2222 host key globally
Der Pin lag in den Dienstmodulen (hosts/{blunix,pinix}/localServices/
forgejo.nix). Auf pinix verschwand er dadurch mit der Reduktion am
12.09.2026, die forgejo.nix auskommentiert hat -- seitdem scheitert dort
jedes `git fetch` an "Host key verification failed". tnix hatte den Pin
nie, konnte also ebenfalls nicht mit Forgejo sprechen.

Es ist eine Client-Eigenschaft, keine Server-Eigenschaft: jeder Host, der
das Repo klont, braucht sie -- auch die, die Forgejo nicht betreiben.
Deshalb in globalServices, mit blunix als zusaetzlichem Hostnamen neben
der Tailnet-IP, weil die Remote-URL ssh://forgejo@blunix:2222/ lautet.

Key verifiziert am 12.09.2026: /var/lib/forgejo/data/ssh/gitea.rsa.pub auf
blunix, gelesen ueber die bereits gepinnte Port-22-Verbindung, Fingerprint
SHA256:WQro5SOdplFhw8FcMZJBjhYNrOOXCF13Z6oe57NiRXY -- identisch mit dem
ssh-keyscan von tnix und mit dem bisher hinterlegten Schluessel.

Getestet: switch auf tnix, danach `git fetch origin` erfolgreich.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ML1tzf3RKWwetud5S4TRAn
2026-09-12 13:41:29 +02:00

146 lines
7.1 KiB
Nix

{ config, pkgs, ...}:
let
forgejoBackgroundCss = pkgs.runCommand "forgejo-0ff-space-background.css" { } ''
cat ${../../globalServices/branding/0ff-space-background.css} \
${./branding/forgejo-theme-override.css} \
> "$out"
'';
in
{
# Der known-hosts-Pin fuer Forgejos eingebetteten SSH-Server (Port 2222)
# steht jetzt in hosts/globalServices/forgejo-known-host.nix: ihn braucht
# jeder Host, der das Repo klont, nicht nur der, der den Dienst betreibt.
services.forgejo= {
enable = true;
lfs.enable = true;
dump.enable = true;
settings = {
service = {
ENABLE_INTERNAL_SIGNIN = true;
DISABLE_REGISTRATION = false;
ALLOW_ONLY_INTERNAL_REGISTRATION = false;
ENABLE_REGISTRATION = true;
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
#ENABLE_AUTO_REGISTRATION=true;
# Reduce platform-y surface area: this instance is a personal code
# showcase today, maybe a handful of collaborators later, not a
# forge for teams/CI. Issues, pull requests, and wiki stay on.
DISABLE_ORGANIZATION_CREATION = true;
};
log.level = "Debug";
# Instance-wide kill switch for mirror sync: the only mirror that
# exists today (nixos-config -> Codeberg push mirror) fails on every
# run ("branch master is the default branch and cannot be deleted",
# see docs/research/full-system-aufit.md, Executive Summary point 3
# -- not docs/review/reviewer-systemaudit-2026-09-01.md, an unrelated
# earlier audit a prior commit here mistakenly cited).
# This is a deliberate "disable, don't repair" -- it would also stop
# any future pull/push mirror on this instance, acceptable since none
# else exists yet.
mirror.DISABLED = true;
repository = {
ENABLE_PUSH_CREATE_USER = true;
DISABLED_REPO_UNITS = "repo.projects,repo.packages,repo.actions";
};
pwa = {
ENABLE_STANDALONE = true;
};
server = {
START_SSH_SERVER = true;
SSH_PORT = 2222;
# Bind only the Tailnet interface -- no public exposure, and no
# Traefik TCP passthrough needed since Forgejo now runs on the same
# host as Traefik (unlike the old pinix setup, which needed a
# passthrough to reach across the Tailnet).
SSH_LISTEN_HOST = config.tailnetIPs.blunix;
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 3000;
DOMAIN = "git.${config.domain}";
ROOT_URL = "https://git.${config.domain}/";
TRUSTED_PROXIES = "127.0.0.1";
LANDING_PAGE = "login";
# Forgejo's default (6h) made the robots.txt fix (see this file's
# tmpfiles.rules) invisible to an external reader's own cache for up
# to 6h after deploy -- verified live 2026-09-11, "private" cache
# semantics meant it wasn't even a shared/CDN caching problem to fix
# server-side, just this TTL being longer than useful whenever a
# static override here actually changes.
STATIC_CACHE_TIME = "5m";
};
session = {
PROVIDER = "file";
COOKIE_SECURE = true;
};
security = {
LOGIN_REMEMBER_DAYS = 10;
REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.1";
};
# Forgejo calls out to webhook receivers on both blunix itself
# (website/launcher/tasks auto-pull, co-located now) and pinix
# (wiki-update, gitpull-calendar-web -- receiver stays on pinix).
# "external" alone does NOT cover Tailnet (100.64.0.0/10) addresses --
# found the hard way: the tasks auto-pull hook was silently denied
# ("webhook can only call allowed HTTP servers") until both Tailnet
# IPs were listed explicitly.
webhook.ALLOWED_HOST_LIST = "external,127.0.0.1,${config.tailnetIPs.blunix},${config.tailnetIPs.pinix}";
oauth2_client = {
# Never use auto account linking with this, otherwise users cannot change
# their new user name and they could potentially overtake other users accounts
# by setting their email address to an existing account.
# With "login" linking the user must choose a non-existing username first or login
# with the existing account to link.
ACCOUNT_LINKING = "login";
USERNAME = "nickname";
# This does not mean that you cannot register via oauth, but just that there should
# be a confirmation dialog shown to the user before the account is actually created.
# This dialog allows changing user name and email address before creating the account.
ENABLE_AUTO_REGISTRATION = false;
REGISTER_EMAIL_CONFIRM = false;
UPDATE_AVATAR = true;
};
};
};
systemd.tmpfiles.rules = [
"d /var/lib/forgejo/custom/public 0750 forgejo forgejo -"
"d /var/lib/forgejo/custom/public/assets 0755 forgejo forgejo -"
"d /var/lib/forgejo/custom/public/assets/img 0755 forgejo forgejo -"
# L+ (symlink, unconditionally relinked), not C+ (copy): C+ only forces
# an overwrite when the source is a directory -- for a single regular
# file it silently degrades to "copy only if the destination doesn't
# already exist yet", so a changed source would stop reaching disk
# after the very first deploy. Found the hard way on pinix: the
# background CSS below kept serving stale content across two redeploys
# with different store paths until the destination was deleted by hand.
"L+ /var/lib/forgejo/custom/public/assets/img/logo.svg - forgejo forgejo - ${./branding/spiral-v2.svg}"
"L+ /var/lib/forgejo/custom/public/assets/img/logo.png - forgejo forgejo - ${./branding/spiral-v2-512.png}"
"L+ /var/lib/forgejo/custom/public/assets/img/apple-touch-icon.png - forgejo forgejo - ${./branding/spiral-v2-192.png}"
"L+ /var/lib/forgejo/custom/public/assets/img/favicon.svg - forgejo forgejo - ${./branding/spiral-v2.svg}"
"L+ /var/lib/forgejo/custom/public/assets/img/favicon.png - forgejo forgejo - ${./branding/spiral-v2-192.png}"
"d /var/lib/forgejo/custom/public/assets/css 0755 forgejo forgejo -"
"L+ /var/lib/forgejo/custom/public/assets/css/0ff-space-background.css - forgejo forgejo - ${forgejoBackgroundCss}"
# Overrides Forgejo's built-in default robots.txt -- see the file's own
# header comment for why (/*/*/src/ and /*/*/raw/ were blocking an
# external reader from actually reading any file content, verified
# live 2026-09-11, once git.0ff.space went external).
"L+ /var/lib/forgejo/custom/public/robots.txt - forgejo forgejo - ${./branding/forgejo-robots.txt}"
"d /var/lib/forgejo/custom/templates 0750 forgejo forgejo -"
"d /var/lib/forgejo/custom/templates/custom 0750 forgejo forgejo -"
# header.tmpl is Forgejo's documented <head> extension point -- included
# verbatim on every page, which is how the background stylesheet above
# actually gets linked in (the public/assets tree above is only served
# statically, nothing references it on its own).
"L+ /var/lib/forgejo/custom/templates/custom/header.tmpl - forgejo forgejo - ${./branding/forgejo-header.tmpl}"
];
systemd.services.forgejo.restartTriggers = [
./branding/spiral-v2.svg
./branding/spiral-v2-192.png
./branding/spiral-v2-512.png
forgejoBackgroundCss
./branding/forgejo-header.tmpl
./branding/forgejo-robots.txt
];
}