diff --git a/ops/nixos/bvm-forgejo/default.nix b/ops/nixos/bvm-forgejo/default.nix index cb42b5575b..d3ab29ab22 100644 --- a/ops/nixos/bvm-forgejo/default.nix +++ b/ops/nixos/bvm-forgejo/default.nix @@ -9,6 +9,7 @@ let in { imports = [ ../lib/bvm.nix + ../lib/pomerium.nix ]; # Networking! @@ -40,8 +41,8 @@ in { allowedUDPPorts = [ 443 ]; }; }; - #my.ip.tailscale = "100.94.23.105"; - #my.ip.tailscale6 = "fd7a:115c:a1e0:ab12:4843:cd96:625e:1769"; + my.ip.tailscale = "100.103.26.78"; + my.ip.tailscale6 = "fd7a:115c:a1e0::8d01:1a4e"; services.openssh.ports = [ 20022 ]; my.deploy.args = "-p 20022"; @@ -51,8 +52,8 @@ in { services.postfix = { enable = true; - domain = "hg.lukegb.com"; - hostname = "hg.lukegb.com"; + domain = "git.lukegb.com"; + hostname = "git.lukegb.com"; extraConfig = '' milter_protocol = 2 milter_default_action = accept @@ -63,9 +64,76 @@ in { }; services.opendkim = { enable = true; - domains = "csl:hg.lukegb.com"; + domains = "csl:git.lukegb.com"; selector = "bvm-forgejo"; }; + services.pomerium = { + settings = { + services = "proxy"; + autocert = true; + routes = [{ + from = "https://git.lukegb.com"; + to = "http://localhost:3000"; + pass_identity_headers = true; + remove_request_headers = [ + "X-WebAuth-User" + "X-WebAuth-Email" + "X-WebAuth-FullName" + ]; + }]; + }; + }; + + environment.systemPackages = with pkgs; [ forgejo-cli forgejo ]; + services.forgejo = { + enable = true; + lfs.enable = true; + package = pkgs.forgejo; + secrets = let + customDir = config.services.forgejo.customDir; + in { + storage.MINIO_SECRET_ACCESS_KEY = "${customDir}/conf/s3_secret_key"; + }; + settings = { + server = { + DOMAIN = "git.lukegb.com"; + ROOT_URL = "https://git.lukegb.com/"; + }; + session = { + COOKIE_SECURE = true; + }; + storage = { + STORAGE_TYPE = "minio"; + MINIO_ENDPOINT = "objdump.zxcvbnm.ninja"; + MINIO_BUCKET = "lukegb-forgejo"; + MINIO_LOCATION = "london"; + MINIO_USE_SSL = true; + MINIO_BUCKET_LOOKUP = "dns"; + MINIO_ACCESS_KEY_ID = "AKIALUKEGBFORGEJO000"; + }; + security = { + COOKIE_REMEMBER_NAME = "forgejo_remember_me"; + REVERSE_PROXY_AUTHENTICATION_EMAIL = "X-Pomerium-Claim-Email"; + }; + service = { + DISABLE_REGISTRATION = true; + ENABLE_REVERSE_PROXY_AUTHENTICATION = true; + ENABLE_REVERSE_PROXY_EMAIL = true; + }; + mailer = { + ENABLED = true; + PROTOCOL = "smtp"; + SMTP_ADDR = "localhost"; + SMTP_PORT = 25; + FROM = "lukegb.com Forgejo "; + }; + cron = { + ENABLED = true; + }; + log.LEVEL = "Trace"; + }; + }; + system.stateVersion = "24.11"; } diff --git a/ops/nixos/etheroute-lon01/default.nix b/ops/nixos/etheroute-lon01/default.nix index 06d7a80443..9ea2f0bd5d 100644 --- a/ops/nixos/etheroute-lon01/default.nix +++ b/ops/nixos/etheroute-lon01/default.nix @@ -7,6 +7,7 @@ imports = [ ../lib/bgp.nix ../lib/zfs.nix + ../lib/pomerium.nix ../totoro/barf.nix # eww ]; @@ -270,41 +271,18 @@ bind = "127.0.0.1"; }; services.pomerium = { - enable = true; - secretsFile = config.my.vault.secrets.pomerium.path; - settings = { - address = ":443"; - http_redirect_addr = ":80"; - dns_lookup_family = "AUTO"; - - idp_provider = "google"; - idp_client_id = "136257844546-qsa6hi1oqqoq2bnt93deo4e70ggbn1p8.apps.googleusercontent.com"; - idp_request_params = { - hd = "lukegb.com"; - login_hint = "lukegb@lukegb.com"; - }; - - jwt_claims_headers = [ - "email" - "user" - ]; - - timeout_read = "0"; # We have some long-lived connections... - timeout_write = "0"; - timeout_idle = "0"; - - forward_auth_url = "https://fwdauth.int.lukegb.com"; - authenticate_service_url = "https://auth.int.lukegb.com"; - signout_redirect_url = "https://logged-out.int.lukegb.com"; - certificates = [ { cert = "/var/lib/acme/lukegb.com/fullchain.pem"; key = "/var/lib/acme/lukegb.com/privkey.pem"; } ]; - policy = let + routes = let baseConfig = { - allowed_domains = [ "lukegb.com" ]; + policy = [{ + allow.and = [{ + domain.is = "lukegb.com"; + }]; + }]; pass_identity_headers = true; timeout = "30s"; }; @@ -319,7 +297,7 @@ } // extraConfig); public = extraConfig: { allow_public_unauthenticated_access = true; - allowed_domains = null; + policy = null; } // extraConfig; in [ (service "localhost:12001" "barf.lukegb.com" (public {})) @@ -384,6 +362,20 @@ allow_websockets = true; timeout = "0"; }) + + # These services are included for policy reasons only. + # They have their own reverse proxy instances. + (service "localhost:3000" "git.lukegb.com" { + policy = [{ + allow.not = [{ + http_path.starts_with = "/user/login"; + }]; + } { + allow.and = [{ + domain.is = "lukegb.com"; + }]; + }]; + }) ]; }; }; @@ -403,19 +395,6 @@ ]; reloadOrRestartUnits = [ "pomerium.service" ]; }; - my.vault.secrets.pomerium = { - template = '' - {{ with secret "kv/apps/pomerium" }} - COOKIE_SECRET={{ .Data.data.cookieSecret }} - SHARED_SECRET={{ .Data.data.sharedSecret }} - IDP_CLIENT_SECRET={{ .Data.data.idpClientSecret }} - SIGNING_KEY={{ .Data.data.signingKey }} - IDP_SERVICE_ACCOUNT={{ .Data.data.googleServiceAccount }} - {{ end }} - ''; - group = "root"; - reloadOrRestartUnits = [ "pomerium.service" ]; - }; users.groups.acme = {}; system.stateVersion = "22.11"; diff --git a/ops/nixos/lib/coredns/zones/db.as205479.net b/ops/nixos/lib/coredns/zones/db.as205479.net index d2c5ebd0eb..1a26903766 100644 --- a/ops/nixos/lib/coredns/zones/db.as205479.net +++ b/ops/nixos/lib/coredns/zones/db.as205479.net @@ -3,7 +3,7 @@ ; SPDX-License-Identifier: Apache-2.0 ; MNAME RNAME SERIAL REFRESH RETRY EXPIRE TTL -@ 600 IN SOA frantech-lux01.as205479.net. hostmaster.lukegb.com. 59 600 450 3600 300 +@ 600 IN SOA frantech-lux01.as205479.net. hostmaster.lukegb.com. 60 600 450 3600 300 ; NB: this are also glue records in Google Domains. $INCLUDE tmpl.ns @@ -101,6 +101,8 @@ bvm-logger.int 3600 IN A 100.68.134.82 bvm-logger.int 3600 IN AAAA fd7a:115c:a1e0:ab12:4843:cd96:6244:8652 bvm-paperless.int 3600 IN A 100.85.236.121 bvm-paperless.int 3600 IN AAAA fd7a:115c:a1e0:ab12:4843:cd96:6255:ec79 +bvm-forgejo.int 3600 IN A 100.103.26.78 +bvm-forgejo.int 3600 IN AAAA fd7a:115c:a1e0::8d01:1a4e mac-mini.int 3600 IN A 100.91.188.84 mac-mini.int 3600 IN AAAA fd7a:115c:a1e0:ab12:4843:cd96:625b:bc54 diff --git a/ops/nixos/lib/pomerium.nix b/ops/nixos/lib/pomerium.nix new file mode 100644 index 0000000000..d4040405a6 --- /dev/null +++ b/ops/nixos/lib/pomerium.nix @@ -0,0 +1,61 @@ +{ config, ... }: + +{ + services.pomerium = { + enable = true; + secretsFile = config.my.vault.secrets.pomerium.path; + + settings = { + address = ":443"; + grpc_address = ":5443"; + http_redirect_addr = ":80"; + dns_lookup_family = "AUTO"; + + idp_provider = "google"; + idp_client_id = "136257844546-qsa6hi1oqqoq2bnt93deo4e70ggbn1p8.apps.googleusercontent.com"; + idp_request_params = { + hd = "lukegb.com"; + login_hint = "lukegb@lukegb.com"; + }; + + jwt_claims_headers = [ + "email" + "user" + ]; + + # Note autocert = true; not set here. + autocert_ca = "https://dv.acme-v02.api.pki.goog/directory"; + autocert_email = "acme@lukegb.com"; + autocert_must_staple = true; + autocert_dir = "/var/lib/pomerium/autocert"; + + grpc_insecure = true; + + timeout_read = "0"; # We have some long-lived connections... + timeout_write = "0"; + timeout_idle = "0"; + + forward_auth_url = "https://fwdauth.int.lukegb.com"; + authenticate_service_url = "https://auth.int.lukegb.com"; + signout_redirect_url = "https://logged-out.int.lukegb.com"; + authorize_service_url = "http://etheroute-lon01.int.as205479.net:5443"; + databroker_service_url = "http://etheroute-lon01.int.as205479.net:5443"; + }; + }; + + my.vault.secrets.pomerium = { + template = '' + {{ with secret "kv/apps/pomerium" }} + COOKIE_SECRET={{ .Data.data.cookieSecret }} + SHARED_SECRET={{ .Data.data.sharedSecret }} + IDP_CLIENT_SECRET={{ .Data.data.idpClientSecret }} + SIGNING_KEY={{ .Data.data.signingKey }} + IDP_SERVICE_ACCOUNT={{ .Data.data.googleServiceAccount }} + AUTOCERT_EAB_KEY_ID={{ .Data.data.eabKeyID }} + AUTOCERT_EAB_MAC_KEY={{ .Data.data.eabMacKey }} + {{ end }} + ''; + group = "root"; + reloadOrRestartUnits = [ "pomerium.service" ]; + }; +} diff --git a/ops/vault/cfg/config.nix b/ops/vault/cfg/config.nix index f5213f859c..1445a695ae 100644 --- a/ops/vault/cfg/config.nix +++ b/ops/vault/cfg/config.nix @@ -78,6 +78,7 @@ my.apps.bsky-pds = {}; my.servers.etheroute-lon01.apps = [ "pomerium" ]; + my.servers.bvm-forgejo.apps = [ "pomerium" ]; my.servers.howl.apps = [ "nixbuild" ]; my.servers.porcorosso.apps = [ "quotesdb" "nixbuild" ]; my.servers.nausicaa.apps = [ "quotesdb" "nixbuild" "hacky-vouchproxy" "hackyplayer" "emfminiserv" ];