From a94ba0499d0a3d0efc60f8693bdef8d1cae6319e Mon Sep 17 00:00:00 2001
From: prescientmoon <git@moonythm.dev>
Date: Wed, 11 Sep 2024 16:30:19 +0200
Subject: [PATCH] Set up forgejo ssh

---
 home/features/cli/ssh.nix                |   6 +-
 hosts/nixos/common/global/ports.nix      |   1 +
 hosts/nixos/lapetus/services/forgejo.nix |  10 ++-
 modules/nixos/cloudflared.nix            | 101 ++++++++++++++---------
 4 files changed, 75 insertions(+), 43 deletions(-)

diff --git a/home/features/cli/ssh.nix b/home/features/cli/ssh.nix
index 9f6de78..472ee0f 100644
--- a/home/features/cli/ssh.nix
+++ b/home/features/cli/ssh.nix
@@ -1,5 +1,9 @@
-{ config, ... }:
+{ pkgs, lib, ... }:
 {
   programs.ssh.enable = true;
   satellite.persistence.at.state.apps.ssh.directories = [ ".ssh" ];
+
+  # This allows me to push/pull to my forgejo server via SSH.
+  # See the docs for more details: https://developers.cloudflare.com/cloudflare-one/tutorials/gitlab/#configuring-ssh
+  programs.ssh.matchBlocks."ssh.git.moonythm.dev".proxyCommand = "${lib.getExe pkgs.cloudflared} access ssh --hostname %h";
 }
diff --git a/hosts/nixos/common/global/ports.nix b/hosts/nixos/common/global/ports.nix
index f16797b..49bbaee 100644
--- a/hosts/nixos/common/global/ports.nix
+++ b/hosts/nixos/common/global/ports.nix
@@ -24,5 +24,6 @@
     jupyterhub = 8420;
     guacamole = 8421;
     syncthing = 8422;
+    forgejo-ssh = 8423;
   };
 }
diff --git a/hosts/nixos/lapetus/services/forgejo.nix b/hosts/nixos/lapetus/services/forgejo.nix
index d645cec..49137bb 100644
--- a/hosts/nixos/lapetus/services/forgejo.nix
+++ b/hosts/nixos/lapetus/services/forgejo.nix
@@ -7,6 +7,10 @@
   };
 
   satellite.cloudflared.at.git.port = config.satellite.ports.forgejo;
+  satellite.cloudflared.at."ssh.git" = {
+    protocol = "ssh";
+    port = config.satellite.ports.forgejo-ssh;
+  };
 
   services.forgejo = {
     enable = true;
@@ -29,6 +33,8 @@
         HTTP_PORT = config.satellite.cloudflared.at.git.port;
         ROOT_URL = config.satellite.cloudflared.at.git.url;
         LANDING_PAGE = "prescientmoon"; # Make my profile the landing page
+        SSH_DOMAIN = config.satellite.cloudflared.at."ssh.git".host;
+        SSH_PORT = config.satellite.ports.forgejo-ssh;
       };
 
       cron.ENABLED = true;
@@ -45,9 +51,7 @@
       repository = {
         DISABLE_STARS = true;
         DISABLED_REPO_UNITS = "";
-        DEFAULT_REPO_UNITS = lib.strings.concatStringsSep "," [
-          "repo.code"
-        ];
+        DEFAULT_REPO_UNITS = lib.strings.concatStringsSep "," [ "repo.code" ];
       };
     };
   };
diff --git a/modules/nixos/cloudflared.nix b/modules/nixos/cloudflared.nix
index 765c28d..69a5d25 100644
--- a/modules/nixos/cloudflared.nix
+++ b/modules/nixos/cloudflared.nix
@@ -1,5 +1,6 @@
 { config, lib, ... }:
-let cfg = config.satellite.cloudflared;
+let
+  cfg = config.satellite.cloudflared;
 in
 {
   options.satellite.cloudflared = {
@@ -17,52 +18,74 @@ in
     at = lib.mkOption {
       description = "List of hosts to set up ingress rules for";
       default = { };
-      type = lib.types.attrsOf (lib.types.submodule ({ name, config, ... }: {
-        options = {
-          subdomain = lib.mkOption {
-            description = ''
-              Subdomain to use for host generation. 
-              Only required if `host` is not set manually.
-            '';
-            type = lib.types.str;
-            default = name;
-          };
+      type = lib.types.attrsOf (
+        lib.types.submodule (
+          { name, config, ... }:
+          {
+            options = {
+              subdomain = lib.mkOption {
+                description = ''
+                  Subdomain to use for host generation.
+                  Only required if `host` is not set manually.
+                '';
+                type = lib.types.str;
+                default = name;
+              };
 
-          port = lib.mkOption {
-            description = "Localhost port to point the tunnel at";
-            type = lib.types.port;
-          };
+              port = lib.mkOption {
+                description = "Localhost port to point the tunnel at";
+                type = lib.types.port;
+              };
 
-          host = lib.mkOption {
-            description = "Host to direct traffic from";
-            type = lib.types.str;
-            default = "${config.subdomain}.${cfg.domain}";
-          };
+              host = lib.mkOption {
+                description = "Host to direct traffic from";
+                type = lib.types.str;
+                default = "${config.subdomain}.${cfg.domain}";
+              };
 
-          url = lib.mkOption {
-            description = "External https url used to access this host";
-            type = lib.types.str;
-          };
-        };
+              protocol = lib.mkOption {
+                description = "The protocol to redirect traffic through";
+                type = lib.types.str;
+                default = "http";
+              };
 
-        config.url = "https://${config.host}";
-      }));
+              url = lib.mkOption {
+                description = "External https url used to access this host";
+                type = lib.types.str;
+              };
+            };
+
+            config.url = "https://${config.host}";
+          }
+        )
+      );
     };
   };
 
-  config.services.cloudflared.tunnels.${cfg.tunnel}.ingress = lib.attrsets.mapAttrs'
-    (_: { port, host, ... }: {
+  config.services.cloudflared.tunnels.${cfg.tunnel}.ingress = lib.attrsets.mapAttrs' (
+    _:
+    {
+      port,
+      host,
+      protocol,
+      ...
+    }:
+    {
       name = host;
-      value = "http://localhost:${toString port}";
-    })
-    cfg.at;
+      value = "${protocol}://localhost:${toString port}";
+    }
+  ) cfg.at;
 
   config.satellite.dns.records =
-    let mkDnsRecord = { subdomain, ... }: {
-      type = "CNAME";
-      at = subdomain;
-      zone = cfg.domain;
-      value = "${cfg.tunnel}.cfargotunnel.com.";
-    };
-    in lib.attrsets.mapAttrsToList (_: mkDnsRecord) cfg.at;
+    let
+      mkDnsRecord =
+        { subdomain, ... }:
+        {
+          type = "CNAME";
+          at = subdomain;
+          zone = cfg.domain;
+          value = "${cfg.tunnel}.cfargotunnel.com.";
+        };
+    in
+    lib.attrsets.mapAttrsToList (_: mkDnsRecord) cfg.at;
 }