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