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