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.services.dns.zones.${config.networking.domain}.records = [ 87 { 88 name = "git"; 89 type = "CNAME"; 90 data = "vps"; 91 } 92 ]; 93 94 # proxy port 22 on ethernet interface to internal gitea ssh server 95 # openssh server remains accessible on port 22 via vpn(s) 96 97 # allow forwarding 98 boot.kernel.sysctl = { 99 "net.ipv4.ip_forward" = 1; 100 "net.ipv6.conf.all.forwarding" = 1; 101 }; 102 103 networking.firewall = { 104 allowedTCPPorts = [ 105 22 106 cfg.gitea.sshPort 107 ]; 108 extraCommands = '' 109 # proxy all traffic on public interface to the gitea SSH server 110 iptables -A PREROUTING -t nat -i ${config.eilean.publicInterface} -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 111 ip6tables -A PREROUTING -t nat -i ${config.eilean.publicInterface} -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 112 113 # proxy locally originating outgoing packets 114 iptables -A OUTPUT -d ${config.eilean.serverIpv4} -t nat -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 115 ip6tables -A OUTPUT -d ${config.eilean.serverIpv6} -t nat -p tcp --dport 22 -j REDIRECT --to-port ${builtins.toString cfg.gitea.sshPort} 116 ''; 117 }; 118 119 services.gitea.settings.server = { 120 START_SSH_SERVER = true; 121 SSH_LISTEN_PORT = cfg.gitea.sshPort; 122 }; 123 }; 124}