Self-host your own digital island
1{ pkgs, config, lib, ... }: 2 3let 4 cfg = config.eilean; 5 domain = config.networking.domain; 6in { 7 options.eilean.gitea = { 8 enable = lib.mkEnableOption "gitea"; 9 sshPort = lib.mkOption { 10 type = lib.types.int; 11 default = 3001; 12 }; 13 }; 14 15 config = lib.mkIf cfg.gitea.enable { 16 services.nginx = { 17 enable = true; 18 recommendedProxySettings = true; 19 virtualHosts."git.${domain}" = { 20 enableACME = true; 21 forceSSL = true; 22 locations."/" = { 23 proxyPass = "http://localhost:${builtins.toString config.services.gitea.settings.server.HTTP_PORT}/"; 24 }; 25 }; 26 }; 27 28 users.users.git = { 29 description = "Git Service"; 30 home = config.services.gitea.stateDir; 31 useDefaultShell = true; 32 group = "gitea"; 33 isSystemUser = true; 34 }; 35 36 services.gitea = { 37 enable = true; 38 user = "git"; 39 appName = "git | ${domain}"; 40 mailerPasswordFile = "${config.eilean.secretsDir}/email-pswd-unhashed"; 41 settings = { 42 server = { 43 ROOT_URL = "https://git.${domain}/"; 44 DOMAIN = "git.${domain}"; 45 }; 46 mailer = { 47 ENABLED = true; 48 FROM = "git@${domain}"; 49 MAILER_TYPE = "smtp"; 50 HOST = "mail.${domain}:465"; 51 USER = "misc@${domain}"; 52 IS_TLS_ENABLED = true; 53 }; 54 repository.DEFAULT_BRANCH = "main"; 55 service.DISABLE_REGISTRATION = true; 56 #server.HTTP_PORT = 3000; 57 }; 58 database = { 59 type = "postgres"; 60 passwordFile = "${config.eilean.secretsDir}/gitea-db"; 61 user = "git"; 62 name = "git"; 63 #createDatabase = true; 64 #socket = "/run/postgresql"; 65 }; 66 #stateDir = "/var/lib/gitea"; 67 }; 68 69 # https://github.com/NixOS/nixpkgs/issues/103446 70 systemd.services.gitea.serviceConfig = { 71 ReadWritePaths = [ "/var/lib/postfix/queue/maildrop" ]; 72 NoNewPrivileges = lib.mkForce false; 73 PrivateDevices = lib.mkForce false; 74 PrivateUsers = lib.mkForce false; 75 ProtectHostname = lib.mkForce false; 76 ProtectClock = lib.mkForce false; 77 ProtectKernelTunables = lib.mkForce false; 78 ProtectKernelModules = lib.mkForce false; 79 ProtectKernelLogs = lib.mkForce false; 80 RestrictAddressFamilies = lib.mkForce [ ]; 81 LockPersonality = lib.mkForce false; 82 MemoryDenyWriteExecute = lib.mkForce false; 83 RestrictRealtime = lib.mkForce false; 84 RestrictSUIDSGID = lib.mkForce false; 85 SystemCallArchitectures = lib.mkForce ""; 86 SystemCallFilter = lib.mkForce []; 87 }; 88 89 eilean.dns.enable = true; 90 eilean.services.dns.zones.${config.networking.domain}.records = [ 91 { 92 name = "git"; 93 type = "CNAME"; 94 data = "vps"; 95 } 96 ]; 97 98 # proxy port 22 on ethernet interface to internal gitea ssh server 99 # openssh server remains accessible on port 22 via vpn(s) 100 101 # allow forwarding 102 boot.kernel.sysctl = { 103 "net.ipv4.ip_forward" = 1; 104 "net.ipv6.conf.all.forwarding" = 1; 105 }; 106 107 networking.firewall = { 108 allowedTCPPorts = [ 109 22 110 cfg.gitea.sshPort 111 ]; 112 extraCommands = '' 113 # proxy all traffic on public interface to the gitea SSH server 114 iptables -A PREROUTING -t nat -i ${config.eilean.publicInterface} -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 115 ip6tables -A PREROUTING -t nat -i ${config.eilean.publicInterface} -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 116 117 # proxy locally originating outgoing packets 118 iptables -A OUTPUT -d ${config.eilean.serverIpv4} -t nat -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 119 ip6tables -A OUTPUT -d ${config.eilean.serverIpv6} -t nat -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 120 ''; 121 }; 122 123 services.gitea.settings.server = { 124 START_SSH_SERVER = true; 125 SSH_LISTEN_PORT = cfg.gitea.sshPort; 126 }; 127 }; 128}