summaryrefslogtreecommitdiff
path: root/terranix
diff options
context:
space:
mode:
Diffstat (limited to 'terranix')
-rw-r--r--terranix/README.md21
-rw-r--r--terranix/cloud.nix7
-rw-r--r--terranix/cloudflare/default.nix10
-rw-r--r--terranix/cloudflare/dns.nix110
-rw-r--r--terranix/cloudflare/pages_domains.nix32
-rw-r--r--terranix/cloudflare/pages_projects.nix60
-rw-r--r--terranix/cloudflare/ruleset.nix29
-rw-r--r--terranix/cloudflare/tls.nix15
-rw-r--r--terranix/cloudflare/tunnels.nix14
-rw-r--r--terranix/default.nix9
-rw-r--r--terranix/tailscale/acl.nix51
-rw-r--r--terranix/tailscale/default.nix13
-rw-r--r--terranix/tailscale/devices.nix20
-rw-r--r--terranix/tailscale/dns.nix5
-rw-r--r--terranix/tailscale/tags.nix21
-rw-r--r--terranix/vars.nix10
-rw-r--r--terranix/versions.nix14
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";
+ };
+}