Nix-Vibe public snapshot (squashed history)
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
{ config
|
||||
, pkgs
|
||||
, lib
|
||||
, ...
|
||||
}:
|
||||
|
||||
# Gitea git server, publicly exposed through an external reverse proxy.
|
||||
#
|
||||
# Topology:
|
||||
# internet -> gitea.edley.me -> external reverse proxy (TLS terminator)
|
||||
# -> Tailscale -> homeserver-1:port (Gitea, plain HTTP behind the proxy)
|
||||
#
|
||||
# Hardening posture (public instance):
|
||||
# - HTTPS only (DISABLE_SSH) so there is no second public port to forward.
|
||||
# - Invite-only: registration disabled, everything hidden behind sign-in.
|
||||
# - The firewall admits ONLY the proxy's Tailscale IP; no other tailnet
|
||||
# node (or the LAN) can reach Gitea directly.
|
||||
# - X-Forwarded-* headers are trusted only from that proxy IP.
|
||||
# - PUBLIC_URL_DETECTION = never pins all generated URLs to ROOT_URL
|
||||
# (no Host-header hijacking).
|
||||
# - OpenID disabled, migrations disabled (SSRF reduction), argon2 password
|
||||
# hashing, 12-char minimum password, git hooks disabled.
|
||||
{
|
||||
options.services.gitea-server = {
|
||||
enable = lib.mkEnableOption "Gitea git server";
|
||||
|
||||
port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 3000;
|
||||
description = "Port Gitea listens on. Firewalled to the reverse proxy only.";
|
||||
};
|
||||
|
||||
domain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "gitea.edley.me";
|
||||
description = "Public domain name of the instance.";
|
||||
};
|
||||
|
||||
proxyIp = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "Tailscale IP of the external reverse proxy allowed to reach Gitea.";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf config.services.gitea-server.enable {
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
stateDir = "/data/gitea";
|
||||
appName = "gitea: Git with a cup of tea";
|
||||
database = {
|
||||
type = "postgres";
|
||||
createDatabase = true;
|
||||
name = "gitea";
|
||||
user = "gitea";
|
||||
};
|
||||
dump = {
|
||||
enable = true;
|
||||
interval = "daily";
|
||||
type = "tar.zst";
|
||||
};
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = config.services.gitea-server.domain;
|
||||
ROOT_URL = "https://${config.services.gitea-server.domain}/";
|
||||
HTTP_ADDR = "0.0.0.0";
|
||||
HTTP_PORT = config.services.gitea-server.port;
|
||||
DISABLE_SSH = true;
|
||||
PUBLIC_URL_DETECTION = "never";
|
||||
MINIMUM_KEY_SIZE_CHECK = true;
|
||||
};
|
||||
session = {
|
||||
COOKIE_SECURE = true;
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = true;
|
||||
REQUIRE_SIGNIN_VIEW = true;
|
||||
SHOW_REGISTRATION_BUTTON = false;
|
||||
};
|
||||
security = {
|
||||
REVERSE_PROXY_TRUSTED_PROXIES = config.services.gitea-server.proxyIp;
|
||||
REVERSE_PROXY_LIMIT = 1;
|
||||
MIN_PASSWORD_LENGTH = 12;
|
||||
PASSWORD_HASH_ALGO = "argon2";
|
||||
DISABLE_GIT_HOOKS = true;
|
||||
};
|
||||
openid = {
|
||||
ENABLE_OPENID_SIGNIN = false;
|
||||
ENABLE_OPENID_SIGNUP = false;
|
||||
};
|
||||
repository = {
|
||||
DISABLE_MIGRATIONS = true;
|
||||
};
|
||||
other = {
|
||||
SHOW_FOOTER_VERSION = false;
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# The external proxy (TLS terminator for gitea.edley.me) connects over
|
||||
# Tailscale. Admit ONLY its address on the Gitea port; the default input
|
||||
# policy drops everything else. Update proxyIp when the proxy changes.
|
||||
networking.firewall.extraInputRules = ''
|
||||
ip saddr ${config.services.gitea-server.proxyIp} tcp dport ${toString config.services.gitea-server.port} accept
|
||||
'';
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user