feat(gitea): forge locale (postgres, admin, Pangolin SSO)
Instance gitea sur tower avec base postgres (rôle gitea en peer auth), compte admin créé une seule fois par un oneshot idempotent avec le mot de passe de secrets/gitea.yml (sops). Exposition gitea.marcpartensky.com via newt/Pangolin, et assertion pour que le port HTTP local reste fermé.
This commit is contained in:
@@ -40,3 +40,7 @@ creation_rules:
|
||||
key_groups:
|
||||
- age:
|
||||
- *tower
|
||||
- path_regex: secrets/gitea\.yml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *tower
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
admin_password: ENC[AES256_GCM,data:l8q9fUM2fIXWkQ8Ksa/5eIRlJ9quguCa8Vrlxw==,iv:Jzc7EUewIkZMMk+CK4dOjnh2v3EbF2cb/Rxt5lH5N1w=,tag:XYpjRMD60zZHcH7al7sYPg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPK2lDZFl1K2JZR3FjREVm
|
||||
aFgydTJGZStOQ211WXV3NHRJWWpIV1o1eEdzClVpVzJKc0ZPa2lNMUwzdU14NEpo
|
||||
YlVBN2haRkVHOW1tVFVLK0dFcE00M0EKLS0tIDVuMTZxTkRlUlYwV1ZXWXZPcXpL
|
||||
U1RmRE1QTlRWSW5VUDNMVExpb0dZbTQK81XPcL83RImGfvLO6G7lm6bYnmxzGBbk
|
||||
OVa9r9zSKYfNHItDAlNZUQ5r0X8cUS0aqcdytMhd13M2ZbQ46G5SLw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1usm3v0ugducrzcwud60dda7xfnj49fdhecj7kcsfm7dzwzrzeyqq2jc2hm
|
||||
lastmodified: "2026-09-26T23:29:26Z"
|
||||
mac: ENC[AES256_GCM,data:9j0rXRhhuvpL7dVQATVW4pTlLwt/rOxgP6BgApM/lrWtgpuZzvTSc51D0lcuS3sAA1YXEGAu/d657W+NHESUKVks3xA0bSYAYMT/sfWeYtMZFlFpi7GxMxXSGjSYgxoAsy1bUopemeGzdYJ3qW5EVbe+Kf/qBQVhc+q6E0QfGrY=,iv:nbdqtNrz0MfmDHvQe3FftaNfkxLeODnJITafneX5tjE=,tag:9UFwVIIMvY8Ej+/lc81sIA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.3
|
||||
@@ -44,6 +44,7 @@
|
||||
./zitadel-mcp
|
||||
./roku
|
||||
./codeberg-mcp
|
||||
./gitea
|
||||
# ./kanidm
|
||||
# ./syncserver
|
||||
# ./newt # attendre maj flakes
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# services/gitea/default.nix
|
||||
# Instance Gitea (forge git auto-hébergée) sur git.marcpartensky.com.
|
||||
#
|
||||
# Écoute en loopback (127.0.0.1:3001), exposée uniquement via le blueprint
|
||||
# Pangolin/newt (SSO devant, comme hermes-webui/hermes-dashboard). Base
|
||||
# postgres locale via socket unix (peer auth, pas de secret DB nécessaire :
|
||||
# services.gitea.database.createDatabase=true crée le rôle "gitea" et se
|
||||
# connecte par défaut sur /run/postgresql avec le user système "gitea").
|
||||
#
|
||||
# Inscription publique désactivée (DISABLE_REGISTRATION) : le compte admin
|
||||
# "marc" est créé une fois par un oneshot idempotent (gitea-admin-init) via
|
||||
# la CLI, mot de passe dans secrets/gitea.yml (sops, clé admin_password).
|
||||
#
|
||||
# SSH désactivé pour ce premier déploiement (DISABLE_SSH) : le serveur SSH
|
||||
# intégré de Gitea entrerait en conflit avec le sshd de tower, et newt 1.12.4
|
||||
# ne supporte pas le mode de ressource "ssh" de Pangolin (exige > 1.13). Clone
|
||||
# HTTPS uniquement pour l'instant (token d'accès personnel Gitea).
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
sops.secrets."gitea/admin_password" = {
|
||||
key = "admin_password";
|
||||
sopsFile = ../../secrets/gitea.yml;
|
||||
owner = "gitea";
|
||||
};
|
||||
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
appName = "Gitea de marc";
|
||||
database.type = "postgres";
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = "git.marcpartensky.com";
|
||||
ROOT_URL = "https://git.marcpartensky.com/";
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
HTTP_PORT = 3001;
|
||||
DISABLE_SSH = true;
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
};
|
||||
# Pangolin/newt tunnelent en local : gitea verrait toute requête
|
||||
# publique comme venant de 127.0.0.1. Rien de sensible n'est protégé
|
||||
# par une IP ici (cf. piège jellyfin), mais ça évite un signal trompeur
|
||||
# dans les logs d'audit gitea.
|
||||
security = {
|
||||
REVERSE_PROXY_TRUSTED_PROXIES = "127.0.0.1";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Compte admin créé une seule fois (idempotent : gitea refuse silencieusement
|
||||
# de recréer un username existant, `|| true` avale l'erreur sans faire
|
||||
# échouer l'unité). Même environnement que gitea.service (module nixpkgs).
|
||||
systemd.services.gitea-admin-init = {
|
||||
description = "Crée le compte admin Gitea (idempotent)";
|
||||
after = ["gitea.service" "postgresql.service"];
|
||||
requires = ["gitea.service"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
environment = {
|
||||
USER = config.services.gitea.user;
|
||||
HOME = config.services.gitea.stateDir;
|
||||
GITEA_WORK_DIR = config.services.gitea.stateDir;
|
||||
GITEA_CUSTOM = config.services.gitea.customDir;
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
User = config.services.gitea.user;
|
||||
Group = config.services.gitea.group;
|
||||
};
|
||||
script = ''
|
||||
${config.services.gitea.package}/bin/gitea admin user create \
|
||||
--username marc \
|
||||
--password "$(cat ${config.sops.secrets."gitea/admin_password".path})" \
|
||||
--email marc.partensky@proton.me \
|
||||
--admin --must-change-password=false || true
|
||||
'';
|
||||
};
|
||||
|
||||
# Ressource publique Pangolin, appliquée par le site qui porte le blueprint
|
||||
# (tower) : `site` omis volontairement, cf. services/newt. Schéma
|
||||
# `proxy-resources` + `protocol` (celui vérifié fonctionnel côté hermes-webui
|
||||
# / hermes-dashboard sur ce contrôleur Pangolin, cf. selfhosted-remote-access
|
||||
# / references/pangolin-blueprint.md).
|
||||
services.newt.blueprint.proxy-resources.gitea = {
|
||||
name = "Gitea";
|
||||
protocol = "http";
|
||||
full-domain = "git.marcpartensky.com";
|
||||
auth.sso-enabled = true;
|
||||
targets = [
|
||||
{
|
||||
hostname = "127.0.0.1";
|
||||
port = config.services.gitea.settings.server.HTTP_PORT;
|
||||
method = "http";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Garde-fou : le port HTTP local ne doit jamais être ouvert sur le LAN.
|
||||
assertions = [
|
||||
{
|
||||
assertion = !(lib.elem config.services.gitea.settings.server.HTTP_PORT config.networking.firewall.allowedTCPPorts);
|
||||
message = "gitea : le port HTTP local ne doit pas être ouvert au firewall (exposition uniquement via Pangolin/newt).";
|
||||
}
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user