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