diff options
Diffstat (limited to 'terranix')
| -rw-r--r-- | terranix/README.md | 21 | ||||
| -rw-r--r-- | terranix/cloud.nix | 7 | ||||
| -rw-r--r-- | terranix/cloudflare/default.nix | 10 | ||||
| -rw-r--r-- | terranix/cloudflare/dns.nix | 110 | ||||
| -rw-r--r-- | terranix/cloudflare/pages_domains.nix | 32 | ||||
| -rw-r--r-- | terranix/cloudflare/pages_projects.nix | 60 | ||||
| -rw-r--r-- | terranix/cloudflare/ruleset.nix | 29 | ||||
| -rw-r--r-- | terranix/cloudflare/tls.nix | 15 | ||||
| -rw-r--r-- | terranix/cloudflare/tunnels.nix | 14 | ||||
| -rw-r--r-- | terranix/default.nix | 9 | ||||
| -rw-r--r-- | terranix/tailscale/acl.nix | 51 | ||||
| -rw-r--r-- | terranix/tailscale/default.nix | 13 | ||||
| -rw-r--r-- | terranix/tailscale/devices.nix | 20 | ||||
| -rw-r--r-- | terranix/tailscale/dns.nix | 5 | ||||
| -rw-r--r-- | terranix/tailscale/tags.nix | 21 | ||||
| -rw-r--r-- | terranix/vars.nix | 10 | ||||
| -rw-r--r-- | terranix/versions.nix | 14 |
17 files changed, 441 insertions, 0 deletions
diff --git a/terranix/README.md b/terranix/README.md new file mode 100644 index 0000000..dd2edd0 --- /dev/null +++ b/terranix/README.md @@ -0,0 +1,21 @@ +# ./terranix/ + +## cloudflare/ + +DNS, Workers/Pages, Tunnels, etc through [Cloudflare](https://cloudflare.com/) + +## tailscale/ + +Secure, remote access via [tailscale](https://tailscale.com/) + +## cloud.nix + +[Cloud backend for OpenTofu state](https://opentofu.org/docs/language/settings/tf-cloud/) + +## vars.nix + +Shared variable definitions + +## versions.nix + +[Provider configuration](https://opentofu.org/docs/language/providers/configuration/) diff --git a/terranix/cloud.nix b/terranix/cloud.nix new file mode 100644 index 0000000..5ee0113 --- /dev/null +++ b/terranix/cloud.nix @@ -0,0 +1,7 @@ +{ + terraform.cloud = { + hostname = "app.terraform.io"; + organization = "getchoo"; + workspaces.name = "flake"; + }; +} diff --git a/terranix/cloudflare/default.nix b/terranix/cloudflare/default.nix new file mode 100644 index 0000000..a8f6d43 --- /dev/null +++ b/terranix/cloudflare/default.nix @@ -0,0 +1,10 @@ +{ + imports = [ + ./dns.nix + ./pages_domains.nix + ./pages_projects.nix + ./ruleset.nix + ./tls.nix + ./tunnels.nix + ]; +} diff --git a/terranix/cloudflare/dns.nix b/terranix/cloudflare/dns.nix new file mode 100644 index 0000000..335562d --- /dev/null +++ b/terranix/cloudflare/dns.nix @@ -0,0 +1,110 @@ +{ lib, ... }: +let + mkRecord = + { + name, + content, + type, + zone_id, + }: + { + inherit + name + content + type + zone_id + ; + ttl = 1; + } + // lib.optionalAttrs (type != "TXT") { proxied = true; }; + + zones = { + getchoo_com = lib.tfRef "var.getchoo_com_zone_id"; + }; + inherit (zones) getchoo_com; + + atlas_tunnel = + lib.tfRef "data.cloudflare_zero_trust_tunnel_cloudflared.atlas-nginx.id" + ".cfargotunnel.com"; + + pagesSubdomainFor = project: lib.tfRef "resource.cloudflare_pages_project.${project}.subdomain"; + blockEmailSpoofingFor = + domain: + let + zone_id = zones.${domain}; + in + { + "${domain}_dmarc" = { + name = "_dmarc"; + content = "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s;"; + type = "TXT"; + inherit zone_id; + }; + + "${domain}_domainkey" = { + name = "*._domainkey"; + content = "v=DKIM1; p="; + type = "TXT"; + inherit zone_id; + }; + + "${domain}_email" = { + name = "@"; + content = "v=spf1 -all"; + type = "TXT"; + inherit zone_id; + }; + }; +in +{ + resource.cloudflare_zone_dnssec = { + getchoo_com_dnssec = { + zone_id = getchoo_com; + }; + }; + + resource.cloudflare_record = + lib.mapAttrs (_: mkRecord) { + getchoo_com_website = { + name = "@"; + content = pagesSubdomainFor "personal_website"; + type = "CNAME"; + zone_id = getchoo_com; + }; + + getchoo_com_www = { + name = "www"; + content = "getchoo.com"; + type = "CNAME"; + zone_id = getchoo_com; + }; + + getchoo_com_api = { + name = "api"; + content = pagesSubdomainFor "teawie_api"; + type = "CNAME"; + zone_id = getchoo_com; + }; + + getchoo_com_miniflux = { + name = "miniflux"; + content = atlas_tunnel; + type = "CNAME"; + zone_id = getchoo_com; + }; + + getchoo_com_git = { + name = "git"; + content = atlas_tunnel; + type = "CNAME"; + zone_id = getchoo_com; + }; + + getchoo_com_keyoxide = { + name = "@"; + content = "$argon2id$v=19$m=512,t=256,p=1$AlA6W5fP7J14zMsw0W5KFQ$EQz/NCE0/TQpE64r2Eo/yOpjtMZ9WXevHsv3YYP7CXg"; + type = "TXT"; + zone_id = getchoo_com; + }; + } + // blockEmailSpoofingFor "getchoo_com"; +} diff --git a/terranix/cloudflare/pages_domains.nix b/terranix/cloudflare/pages_domains.nix new file mode 100644 index 0000000..531b2de --- /dev/null +++ b/terranix/cloudflare/pages_domains.nix @@ -0,0 +1,32 @@ +{ lib, ... }: +let + setDomainsFor = + { + account_id, + project, + domains, + }: + lib.listToAttrs ( + map (domain: { + name = "${project}_${builtins.replaceStrings [ "." ] [ "_" ] domain}"; + value = { + inherit account_id; + project_name = lib.tfRef "resource.cloudflare_pages_project.${project}.name"; + inherit domain; + }; + }) domains + ); +in +{ + resource.cloudflare_pages_domain = + setDomainsFor { + account_id = lib.tfRef "var.account_id"; + project = "personal_website"; + domains = [ "getchoo.com" ]; + } + // setDomainsFor { + account_id = lib.tfRef "var.account_id"; + project = "teawie_api"; + domains = [ "api.getchoo.com" ]; + }; +} diff --git a/terranix/cloudflare/pages_projects.nix b/terranix/cloudflare/pages_projects.nix new file mode 100644 index 0000000..4c0b076 --- /dev/null +++ b/terranix/cloudflare/pages_projects.nix @@ -0,0 +1,60 @@ +{ lib, ... }: +let + getGitHubRepo = + { owner, repo_name }: + { + type = "github"; + config = { + inherit owner repo_name; + production_branch = "main"; + }; + }; +in +{ + resource.cloudflare_pages_project = { + personal_website = { + account_id = lib.tfRef "var.account_id"; + name = "getchoo-website"; + production_branch = "main"; + + source = getGitHubRepo { + owner = "getchoo"; + repo_name = "website"; + }; + + build_config = { + build_caching = true; + build_command = "./build-site.sh"; + destination_dir = "/dist"; + }; + + deployment_configs = + let + environment_variables = { + ZOLA_VERSION = "0.19.2"; + }; + in + { + production = [ { inherit environment_variables; } ]; + preview = [ { inherit environment_variables; } ]; + }; + }; + + teawie_api = { + account_id = lib.tfRef "var.account_id"; + name = "teawie-api"; + production_branch = "main"; + + source = getGitHubRepo { + owner = "getchoo"; + repo_name = "teawieAPI"; + }; + + build_config = { + build_caching = true; + build_command = "pnpm run lint && pnpm run build"; + destination_dir = "/dist"; + }; + }; + }; +} diff --git a/terranix/cloudflare/ruleset.nix b/terranix/cloudflare/ruleset.nix new file mode 100644 index 0000000..98364d9 --- /dev/null +++ b/terranix/cloudflare/ruleset.nix @@ -0,0 +1,29 @@ +{ lib, ... }: +{ + resource.cloudflare_ruleset = { + getchoo_com_redirects = { + kind = "zone"; + name = "default"; + phase = "http_request_dynamic_redirect"; + zone_id = lib.tfRef "var.getchoo_com_zone_id"; + + rules = [ + { + action = "redirect"; + action_parameters = { + from_value = { + preserve_query_string = false; + status_code = 301; + target_url = { + value = "https://www.youtube.com/watch?v=RvVdFXOFcjw"; + }; + }; + }; + description = "funny"; + enabled = true; + expression = "(http.request.uri.path eq \"/hacks\" and http.host eq \"getchoo.com\")"; + } + ]; + }; + }; +} diff --git a/terranix/cloudflare/tls.nix b/terranix/cloudflare/tls.nix new file mode 100644 index 0000000..77450ad --- /dev/null +++ b/terranix/cloudflare/tls.nix @@ -0,0 +1,15 @@ +{ lib, ... }: +let + baseSettings = { + always_use_https = "on"; + ssl = "strict"; + }; +in +{ + resource.cloudflare_zone_settings_override = { + getchoo_com_settings = { + zone_id = lib.tfRef "var.getchoo_com_zone_id"; + settings = baseSettings; + }; + }; +} diff --git a/terranix/cloudflare/tunnels.nix b/terranix/cloudflare/tunnels.nix new file mode 100644 index 0000000..717a887 --- /dev/null +++ b/terranix/cloudflare/tunnels.nix @@ -0,0 +1,14 @@ +{ lib, ... }: +{ + data.cloudflare_zero_trust_tunnel_cloudflared = lib.genAttrs [ "atlas-nginx" ] (name: { + inherit name; + account_id = lib.tfRef "var.account_id"; + }); + + resource.cloudflare_authenticated_origin_pulls = { + getchoo_com_origin = { + zone_id = lib.tfRef "var.getchoo_com_zone_id"; + enabled = true; + }; + }; +} diff --git a/terranix/default.nix b/terranix/default.nix new file mode 100644 index 0000000..d7c7778 --- /dev/null +++ b/terranix/default.nix @@ -0,0 +1,9 @@ +{ + imports = [ + ./cloudflare + ./tailscale + ./cloud.nix + ./vars.nix + ./versions.nix + ]; +} diff --git a/terranix/tailscale/acl.nix b/terranix/tailscale/acl.nix new file mode 100644 index 0000000..80e3537 --- /dev/null +++ b/terranix/tailscale/acl.nix @@ -0,0 +1,51 @@ +{ lib, ... }: +{ + resource.tailscale_acl.default = { + acl = toString ( + builtins.toJSON { + tagOwners = + let + me = [ "getchoo@github" ]; + tags = map (name: "tag:${name}") [ + "server" + "personal" + ]; + in + lib.genAttrs tags (_: me); + + acls = + let + mkAcl = action: src: dst: { inherit action src dst; }; + in + [ + (mkAcl "accept" [ "tag:personal" ] [ "*:*" ]) + (mkAcl "accept" [ "tag:server" ] [ "tag:server:*" ]) + ]; + + ssh = + let + mkSshAcl = action: src: dst: users: { + inherit + action + src + dst + users + ; + }; + in + [ + (mkSshAcl "accept" [ "tag:personal" ] + [ + "tag:server" + "tag:personal" + ] + [ + "autogroup:nonroot" + "root" + ] + ) + ]; + } + ); + }; +} diff --git a/terranix/tailscale/default.nix b/terranix/tailscale/default.nix new file mode 100644 index 0000000..b370b34 --- /dev/null +++ b/terranix/tailscale/default.nix @@ -0,0 +1,13 @@ +{ lib, ... }: +{ + imports = [ + ./acl.nix + ./devices.nix + ./dns.nix + ./tags.nix + ]; + + provider.tailscale = { + tailnet = lib.tfRef "var.tailnet"; + }; +} diff --git a/terranix/tailscale/devices.nix b/terranix/tailscale/devices.nix new file mode 100644 index 0000000..625c56e --- /dev/null +++ b/terranix/tailscale/devices.nix @@ -0,0 +1,20 @@ +{ lib, ... }: +{ + data.tailscale_device = + let + toDevices = + devices: + lib.genAttrs devices (name: { + name = "${name}.tailc59d6.ts.net"; + wait_for = "60s"; + }); + in + toDevices [ + "atlas" + "caroline" + "glados" + "glados-wsl" + "glados-windows" + "iphone-14" + ]; +} diff --git a/terranix/tailscale/dns.nix b/terranix/tailscale/dns.nix new file mode 100644 index 0000000..320a24b --- /dev/null +++ b/terranix/tailscale/dns.nix @@ -0,0 +1,5 @@ +{ + resource.tailscale_dns_preferences.default = { + magic_dns = true; + }; +} diff --git a/terranix/tailscale/tags.nix b/terranix/tailscale/tags.nix new file mode 100644 index 0000000..3e82dbb --- /dev/null +++ b/terranix/tailscale/tags.nix @@ -0,0 +1,21 @@ +{ lib, ... }: +{ + resource.tailscale_device_tags = + let + getDeviceID = device: lib.tfRef "data.tailscale_device.${device}.id"; + toTags = n: v: { device_id = getDeviceID n; } // v; + + tags = lib.genAttrs [ + "server" + "personal" + ] (n: [ "tag:${n}" ]); + in + builtins.mapAttrs toTags { + atlas.tags = tags.server; + caroline.tags = tags.personal; + glados.tags = tags.personal; + glados-wsl.tags = tags.personal; + glados-windows.tags = tags.personal; + iphone-14.tags = tags.personal; + }; +} diff --git a/terranix/vars.nix b/terranix/vars.nix new file mode 100644 index 0000000..afee9de --- /dev/null +++ b/terranix/vars.nix @@ -0,0 +1,10 @@ +{ + variable = { + # cloudflare + getchoo_com_zone_id.default = "5ab8019935bfb8838a820aa68250eb77"; + account_id.default = "44c47ae2d55db34c1bf2f378ea8202f1"; + + # tailscale + tailnet.default = "getchoo.github"; + }; +} diff --git a/terranix/versions.nix b/terranix/versions.nix new file mode 100644 index 0000000..6ac0b3e --- /dev/null +++ b/terranix/versions.nix @@ -0,0 +1,14 @@ +{ lib, ... }: +{ + terraform.required_providers = + let + registry = "registry.terraform.io"; + + fmtSource = _: value: lib.recursiveUpdate value { source = "${registry}/${value.source}"; }; + in + lib.mapAttrs fmtSource { + cloudflare.source = "cloudflare/cloudflare"; + + tailscale.source = "tailscale/tailscale"; + }; +} |
