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