From 808bccf0a2665dadd303e309d9f061c360723e8b Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 10:29:45 -0300 Subject: [PATCH 1/9] Add Tailscale tailnet DNS configuration via Terranix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Configure global DNS nameservers for the Tailscale tailnet, setting trantor as the primary DNS server with Cloudflare as fallback. This enables custom DNS resolution across the entire tailnet. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- terranix/cloudflare/baduhai.dev.nix | 77 +++++++++++++++++++++++++++++ terranix/tailscale/tailnet.nix | 43 ++++++++++++++++ terranixConfigurations.nix | 8 +++ 3 files changed, 128 insertions(+) diff --git a/terranix/cloudflare/baduhai.dev.nix b/terranix/cloudflare/baduhai.dev.nix index e69de29..56d25ad 100644 --- a/terranix/cloudflare/baduhai.dev.nix +++ b/terranix/cloudflare/baduhai.dev.nix @@ -0,0 +1,77 @@ +# Required environment variables: +# CLOUDFLARE_API_TOKEN - API token with "Edit zone DNS" permissions +# TF_VAR_zone_id - Zone ID for baduhai.dev (find in Cloudflare dashboard) +# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage +# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage + +{ config, ... }: + +{ + terraform.required_providers.cloudflare = { + source = "cloudflare/cloudflare"; + version = "~> 5.0"; + }; + + terraform.backend.s3 = { + bucket = "terraform-state"; + key = "cloudflare/baduhai.dev.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + + variable = { + zone_id = { + description = "Cloudflare zone ID for baduhai.dev"; + type = "string"; + sensitive = true; + }; + }; + + data = { + terraform_remote_state.trantor = { + backend = "s3"; + config = { + bucket = "terraform-state"; + key = "oci/trantor.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + }; + }; + + resource = { + cloudflare_record.root = { + zone_id = config.variable.zone_id; + name = "@"; + type = "A"; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip.value"; + proxied = true; + }; + + cloudflare_record.www = { + zone_id = config.variable.zone_id; + name = "www"; + type = "A"; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip.value"; + proxied = true; + }; + + cloudflare_record.wildcard = { + zone_id = config.variable.zone_id; + name = "*"; + type = "A"; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip.value"; + proxied = true; + }; + }; +} diff --git a/terranix/tailscale/tailnet.nix b/terranix/tailscale/tailnet.nix index e69de29..929e79b 100644 --- a/terranix/tailscale/tailnet.nix +++ b/terranix/tailscale/tailnet.nix @@ -0,0 +1,43 @@ +# Required environment variables: +# TAILSCALE_API_KEY - Tailscale API key with appropriate permissions +# TAILSCALE_TAILNET - Your tailnet name (e.g., "user@example.com" or "example.org.github") +# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage +# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage + +{ config, ... }: + +{ + terraform.required_providers.tailscale = { + source = "tailscale/tailscale"; + version = "~> 0.17"; + }; + + terraform.backend.s3 = { + bucket = "terraform-state"; + key = "tailscale/tailnet.tfstate"; + region = "auto"; + endpoint = "https://fcdf920bde00c3d013ee541f984da70e.r2.cloudflarestorage.com"; + skip_credentials_validation = true; + skip_metadata_api_check = true; + skip_region_validation = true; + skip_requesting_account_id = true; + use_path_style = true; + }; + + variable = { + trantor_tailscale_ip = { + default = "100.108.5.90"; + type = "string"; + }; + }; + + resource = { + tailscale_dns_nameservers.global = { + nameservers = [ + config.variable.trantor_tailscale_ip.default + "1.1.1.1" + "1.0.0.1" + ]; + }; + }; +} diff --git a/terranixConfigurations.nix b/terranixConfigurations.nix index fc84f17..12c90d1 100644 --- a/terranixConfigurations.nix +++ b/terranixConfigurations.nix @@ -14,6 +14,14 @@ modules = [ ./terranix/oci/trantor.nix ]; terraformWrapper.package = pkgs.opentofu; }; + cloudflare-baduhaidev = { + modules = [ ./terranix/cloudflare/baduhai.dev.nix ]; + terraformWrapper.package = pkgs.opentofu; + }; + tailscale-tailnet = { + modules = [ ./terranix/tailscale/tailnet.nix ]; + terraformWrapper.package = pkgs.opentofu; + }; }; }; } From 1b1d7896e6c9fbe87d64ea02b5adbc89b34bd685 Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 10:29:54 -0300 Subject: [PATCH 2/9] Document required environment variables for OCI configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation about required OCI and AWS credentials for the trantor configuration, clarifying that ~/.oci/config can be used as an alternative to environment variables. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- terranix/oci/trantor.nix | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/terranix/oci/trantor.nix b/terranix/oci/trantor.nix index 2037d87..bb06585 100644 --- a/terranix/oci/trantor.nix +++ b/terranix/oci/trantor.nix @@ -1,3 +1,13 @@ +# Required environment variables: +# instead of OCI variables, ~/.oci/config may also be used +# OCI_TENANCY_OCID - Oracle tenancy OCID (or use TF_VAR_* to override variables) +# OCI_USER_OCID - Oracle user OCID +# OCI_FINGERPRINT - API key fingerprint +# OCI_PRIVATE_KEY_PATH - Path to OCI API private key +# AWS variables are required +# AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage +# AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage + { config, ... }: { From 1921aad1bdd51292baaf18187106b42a874aa28c Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 10:30:02 -0300 Subject: [PATCH 3/9] Update Cloudflare DNS configuration with explicit zone ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace sensitive zone_id variable with hardcoded value and update DNS record configuration to use cloudflare_dns_record resource type. Disable proxying and set explicit TTL for better control over DNS propagation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- terranix/cloudflare/baduhai.dev.nix | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/terranix/cloudflare/baduhai.dev.nix b/terranix/cloudflare/baduhai.dev.nix index 56d25ad..b74484c 100644 --- a/terranix/cloudflare/baduhai.dev.nix +++ b/terranix/cloudflare/baduhai.dev.nix @@ -1,6 +1,5 @@ # Required environment variables: # CLOUDFLARE_API_TOKEN - API token with "Edit zone DNS" permissions -# TF_VAR_zone_id - Zone ID for baduhai.dev (find in Cloudflare dashboard) # AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage # AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage @@ -26,9 +25,8 @@ variable = { zone_id = { - description = "Cloudflare zone ID for baduhai.dev"; + default = "c63a8332fdddc4a8e5612ddc54557044"; type = "string"; - sensitive = true; }; }; @@ -50,28 +48,31 @@ }; resource = { - cloudflare_record.root = { - zone_id = config.variable.zone_id; + cloudflare_dns_record.root = { + zone_id = config.variable.zone_id.default; name = "@"; type = "A"; - content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip.value"; - proxied = true; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; + proxied = false; + ttl = 3600; }; - cloudflare_record.www = { - zone_id = config.variable.zone_id; + cloudflare_dns_record.www = { + zone_id = config.variable.zone_id.default; name = "www"; type = "A"; - content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip.value"; - proxied = true; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; + proxied = false; + ttl = 3600; }; - cloudflare_record.wildcard = { - zone_id = config.variable.zone_id; + cloudflare_dns_record.wildcard = { + zone_id = config.variable.zone_id.default; name = "*"; type = "A"; - content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip.value"; - proxied = true; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; + proxied = false; + ttl = 3600; }; }; } From 14c4440dd1fa31f0589ed6c3a8f91cfa6fab2f20 Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 10:34:57 -0300 Subject: [PATCH 4/9] forgejo: disable singup; document root password --- hosts/trantor/forgejo.nix | 1 + secrets/forgejo-root-password.age | Bin 0 -> 465 bytes secrets/secrets.nix | 5 +++++ 3 files changed, 6 insertions(+) create mode 100644 secrets/forgejo-root-password.age diff --git a/hosts/trantor/forgejo.nix b/hosts/trantor/forgejo.nix index c11573e..a89526d 100644 --- a/hosts/trantor/forgejo.nix +++ b/hosts/trantor/forgejo.nix @@ -24,6 +24,7 @@ in log.LEVEL = "Warn"; mailer.ENABLED = false; actions.ENABLED = false; + service.DISABLE_REGISTRATION = true; }; }; diff --git a/secrets/forgejo-root-password.age b/secrets/forgejo-root-password.age new file mode 100644 index 0000000000000000000000000000000000000000..90be612af57adcc9b8db836f5f02ed55ff0377b3 GIT binary patch literal 465 zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCUlPD{zlPge*@GRiN@ zHVXH)D2u9$DhM{M@-y(LEGW&3(66X4_6rKl3(GSP49cuB_T(z{3yw514D|_h%SlNs ztnlzRGPg7fb#pc;&#KTb&aTSNkF+R{NHj0fH$k_}A~M)9vs|Gf%AnB8#VIu0(=EKn zqd;5R$EncB)6_WIH7YgS$uuv|JkKPoB0xVl!-6X{#XrN(AS=QnDX*%+G$hC@E6*`M zG^jYpJU3t4Ei=p2FW0!ZJkLGQ&jQ`Hz!Kv?ZAXQaLU)6RLf5nsSAYG)l3YhW-w59b zzyEz)TZU*ATZz{cZdy`tCv literal 0 HcmV?d00001 diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 84b14d6..a90cd74 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -27,4 +27,9 @@ in rotterdam-user alexandria ]; + "forgejo-root-password.age".publicKeys = [ + io-user + rotterdam-user + trantor + ]; } From 6f1aca7b01a825e71bb7db10e9968ade435e57b0 Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 11:11:55 -0300 Subject: [PATCH 5/9] Configure Forgejo OAuth2 and disable public registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add OAuth2 client configuration to enable auto-registration via SSO with Kanidm, while disabling direct public registration. Users can now authenticate through the identity provider with automatic account creation and avatar syncing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- hosts/trantor/forgejo.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hosts/trantor/forgejo.nix b/hosts/trantor/forgejo.nix index a89526d..9688458 100644 --- a/hosts/trantor/forgejo.nix +++ b/hosts/trantor/forgejo.nix @@ -25,6 +25,12 @@ in mailer.ENABLED = false; actions.ENABLED = false; service.DISABLE_REGISTRATION = true; + oauth2_client = { + ENABLE_AUTO_REGISTRATION = true; + UPDATE_AVATAR = true; + ACCOUNT_LINKING = "login"; + USERNAME = "preferred_username"; + }; }; }; From 878c4aa3ea7d8c642c2979895c33bf533094f54f Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 11:12:06 -0300 Subject: [PATCH 6/9] Add public visibility flags to service definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mark services as public or private to control external access: - Public: vaultwarden, forgejo, nextcloud - Private: kanidm, jellyfin This enables proper routing and firewall configuration based on intended service visibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- shared/services.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shared/services.nix b/shared/services.nix index 8870258..ebd51de 100644 --- a/shared/services.nix +++ b/shared/services.nix @@ -8,6 +8,7 @@ name = "kanidm"; domain = "auth.baduhai.dev"; host = "alexandria"; + public = false; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 8443; @@ -16,6 +17,7 @@ name = "vaultwarden"; domain = "pass.baduhai.dev"; host = "alexandria"; + public = true; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 8222; @@ -24,6 +26,7 @@ name = "forgejo"; domain = "git.baduhai.dev"; host = "trantor"; + public = true; tailscaleIP = "100.108.5.90"; port = 3000; } @@ -31,6 +34,7 @@ name = "nextcloud"; domain = "cloud.baduhai.dev"; host = "alexandria"; + public = true; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 443; @@ -39,6 +43,7 @@ name = "jellyfin"; domain = "jellyfin.baduhai.dev"; host = "alexandria"; + public = false; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 8096; From ad9d565a8f365d2530b0889edb15613dc6ea330a Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 11:20:21 -0300 Subject: [PATCH 7/9] Route DNS based on service visibility flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace wildcard DNS with dynamic service-based routing that reads from shared/services.nix. Public services (forgejo, vaultwarden, nextcloud) point to trantor's public IP for external access, while private services (kanidm, jellyfin) point to tailscale IPs for internal-only access. This provides granular control over service exposure without manual DNS management. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- shared/services.nix | 2 - terranix/cloudflare/baduhai.dev.nix | 74 +++++++++++++++++++---------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/shared/services.nix b/shared/services.nix index ebd51de..d267792 100644 --- a/shared/services.nix +++ b/shared/services.nix @@ -8,7 +8,6 @@ name = "kanidm"; domain = "auth.baduhai.dev"; host = "alexandria"; - public = false; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 8443; @@ -43,7 +42,6 @@ name = "jellyfin"; domain = "jellyfin.baduhai.dev"; host = "alexandria"; - public = false; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 8096; diff --git a/terranix/cloudflare/baduhai.dev.nix b/terranix/cloudflare/baduhai.dev.nix index b74484c..3a5e6ee 100644 --- a/terranix/cloudflare/baduhai.dev.nix +++ b/terranix/cloudflare/baduhai.dev.nix @@ -3,7 +3,38 @@ # AWS_ACCESS_KEY_ID - Cloudflare R2 access key for state storage # AWS_SECRET_ACCESS_KEY - Cloudflare R2 secret key for state storage -{ config, ... }: +{ config, lib, ... }: + +let + inherit (import ../../shared/services.nix) services; + + # Helper to extract subdomain from full domain (e.g., "git.baduhai.dev" -> "git") + getSubdomain = domain: lib.head (lib.splitString "." domain); + + # Generate DNS records for services + # Public services point to trantor's public IP + # Private services point to their tailscale IP + mkServiceRecords = lib.listToAttrs ( + lib.imap0 (i: svc: + let + subdomain = getSubdomain svc.domain; + targetIP = if svc.public or false + then config.data.terraform_remote_state.trantor "outputs.instance_public_ip" + else svc.tailscaleIP; + in { + name = "service_${toString i}"; + value = { + zone_id = config.variable.zone_id.default; + name = subdomain; + type = "A"; + content = targetIP; + proxied = false; + ttl = 3600; + }; + } + ) services + ); +in { terraform.required_providers.cloudflare = { @@ -48,31 +79,24 @@ }; resource = { - cloudflare_dns_record.root = { - zone_id = config.variable.zone_id.default; - name = "@"; - type = "A"; - content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; - proxied = false; - ttl = 3600; - }; + cloudflare_dns_record = mkServiceRecords // { + root = { + zone_id = config.variable.zone_id.default; + name = "@"; + type = "A"; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; + proxied = false; + ttl = 3600; + }; - cloudflare_dns_record.www = { - zone_id = config.variable.zone_id.default; - name = "www"; - type = "A"; - content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; - proxied = false; - ttl = 3600; - }; - - cloudflare_dns_record.wildcard = { - zone_id = config.variable.zone_id.default; - name = "*"; - type = "A"; - content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; - proxied = false; - ttl = 3600; + www = { + zone_id = config.variable.zone_id.default; + name = "www"; + type = "A"; + content = config.data.terraform_remote_state.trantor "outputs.instance_public_ip"; + proxied = false; + ttl = 3600; + }; }; }; } From cd17bf25617f3922b7ccbdfd5a1bfdb9b7b10002 Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 12:36:43 -0300 Subject: [PATCH 8/9] only forgejo is public for now --- shared/services.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/shared/services.nix b/shared/services.nix index d267792..44f9208 100644 --- a/shared/services.nix +++ b/shared/services.nix @@ -16,7 +16,6 @@ name = "vaultwarden"; domain = "pass.baduhai.dev"; host = "alexandria"; - public = true; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 8222; @@ -33,7 +32,6 @@ name = "nextcloud"; domain = "cloud.baduhai.dev"; host = "alexandria"; - public = true; lanIP = "192.168.15.142"; tailscaleIP = "100.76.19.50"; port = 443; From f1b6be6f3ff1311d7041b194ebdd3956a70fb71d Mon Sep 17 00:00:00 2001 From: William Date: Sun, 9 Nov 2025 13:00:17 -0300 Subject: [PATCH 9/9] Add fail2ban configuration for SSH and Forgejo on Trantor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Configure fail2ban with progressive ban times (1h base, up to 10000h max) - Add SSH jail with password authentication disabled - Add Forgejo jail using systemd journal backend - Ignore private networks and Tailscale IPs - Set Forgejo to 10 retries per hour, 15min initial ban 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- hosts/trantor/fail2ban.nix | 43 +++++++++++++++++++++++++ hosts/trantor/forgejo.nix | 65 ++++++++++++++++++++++++-------------- hosts/trantor/openssh.nix | 23 ++++++++++++++ 3 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 hosts/trantor/fail2ban.nix create mode 100644 hosts/trantor/openssh.nix diff --git a/hosts/trantor/fail2ban.nix b/hosts/trantor/fail2ban.nix new file mode 100644 index 0000000..4ef1bbc --- /dev/null +++ b/hosts/trantor/fail2ban.nix @@ -0,0 +1,43 @@ +{ config, pkgs, ... }: + +{ + services.fail2ban = { + enable = true; + maxretry = 5; + ignoreIP = [ + "127.0.0.0/8" + "::1" + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + "100.64.0.0/10" + ]; + + bantime = "1h"; + bantime-increment = { + enable = true; + multipliers = "1 2 4 8 16 32 64"; + maxtime = "10000h"; + overalljails = true; + }; + + jails.forgejo = { + settings = { + enabled = true; + filter = "forgejo"; + backend = "systemd"; + maxretry = 10; + findtime = "1h"; + bantime = "15m"; + }; + }; + }; + + # Custom fail2ban filter for Forgejo using systemd journal + environment.etc."fail2ban/filter.d/forgejo.local".text = pkgs.lib.mkDefault (pkgs.lib.mkAfter '' + [Definition] + journalmatch = _SYSTEMD_UNIT=forgejo.service + failregex = Failed authentication attempt for .+ from :\d+: + ignoreregex = + ''); +} diff --git a/hosts/trantor/forgejo.nix b/hosts/trantor/forgejo.nix index 9688458..227bcb4 100644 --- a/hosts/trantor/forgejo.nix +++ b/hosts/trantor/forgejo.nix @@ -9,33 +9,50 @@ let inherit (utils) mkNginxVHosts; in { - services.forgejo = { - enable = true; - repositoryRoot = "/data/forgejo"; - settings = { - session.COOKIE_SECURE = true; - server = { - PROTOCOL = "http+unix"; - DOMAIN = "git.baduhai.dev"; - ROOT_URL = "https://git.baduhai.dev"; - OFFLINE_MODE = true; # disable use of CDNs - SSH_DOMAIN = "baduhai.dev"; + services = { + forgejo = { + enable = true; + repositoryRoot = "/data/forgejo"; + settings = { + session.COOKIE_SECURE = true; + server = { + PROTOCOL = "http+unix"; + DOMAIN = "git.baduhai.dev"; + ROOT_URL = "https://git.baduhai.dev"; + OFFLINE_MODE = true; # disable use of CDNs + SSH_DOMAIN = "baduhai.dev"; + }; + log.LEVEL = "Warn"; + mailer.ENABLED = false; + actions.ENABLED = false; + service.DISABLE_REGISTRATION = true; + oauth2_client = { + ENABLE_AUTO_REGISTRATION = true; + UPDATE_AVATAR = true; + ACCOUNT_LINKING = "login"; + USERNAME = "preferred_username"; + }; }; - log.LEVEL = "Warn"; - mailer.ENABLED = false; - actions.ENABLED = false; - service.DISABLE_REGISTRATION = true; - oauth2_client = { - ENABLE_AUTO_REGISTRATION = true; - UPDATE_AVATAR = true; - ACCOUNT_LINKING = "login"; - USERNAME = "preferred_username"; + }; + nginx.virtualHosts = mkNginxVHosts { + domains."git.baduhai.dev".locations."/".proxyPass = + "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/"; + }; + fail2ban.jails.forgejo = { + settings = { + enabled = true; + filter = "forgejo"; + logpath = "${config.services.forgejo.stateDir}/log/forgejo.log"; + maxretry = 10; + findtime = "1h"; + bantime = "15m"; }; }; }; - services.nginx.virtualHosts = mkNginxVHosts { - domains."git.baduhai.dev".locations."/".proxyPass = - "http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/"; - }; + environment.etc."fail2ban/filter.d/forgejo.conf".text = '' + [Definition] + failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from + ignoreregex = + ''; } diff --git a/hosts/trantor/openssh.nix b/hosts/trantor/openssh.nix new file mode 100644 index 0000000..51d8795 --- /dev/null +++ b/hosts/trantor/openssh.nix @@ -0,0 +1,23 @@ +{ ... }: + +{ + services = { + openssh = { + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + }; + }; + fail2ban.jails.sshd = { + settings = { + enabled = true; + port = "ssh"; + filter = "sshd"; + logpath = "/var/log/auth.log"; + maxretry = 5; + findtime = "10m"; + bantime = "1h"; + }; + }; + }; +}