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}