diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..02277bc --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,7 @@ +keys: + - &primary age156gze6ecg8xpgg3gc049tqprts5dl5apr7020cu70ukpsta3qvpsldd6kh +creation_rules: + - path_regex: secrets/.*$ + key_groups: + - age: + - *primary diff --git a/deemz.org/configuration.nix b/deemz.org/configuration.nix index 52b0dc4..31fc91e 100644 --- a/deemz.org/configuration.nix +++ b/deemz.org/configuration.nix @@ -2,14 +2,37 @@ # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running ‘nixos-help’). -{ config, pkgs, icomidal, ... }: +{ config, pkgs, sops-nix, icomidal, ... }: let secrets = import ../secrets.nix; in { imports = [ # Include the results of the hardware scan. ./hardware-configuration.nix + sops-nix.nixosModules.sops ]; + sops.defaultSopsFile = ./secrets/secrets.yaml; + sops.defaultSopsFormat = "yaml"; + sops.age.keyFile = "/home/maestro/.config/sops/age/keys.txt"; + + sops.secrets."nginx-users" = { + owner = "nginx"; + group = "nginx"; + sopsFile = ./secrets/nginx-users; + }; + sops.secrets."duckdns_token" = { + owner = "duckdns"; + }; + sops.secrets."cloudflare_zone_id" = { + owner = "cloudflare-dns"; + }; + sops.secrets."cloudflare_dns_record_id" = { + owner = "cloudflare-dns"; + }; + sops.secrets."cloudflare_api_token" = { + owner = "cloudflare-dns"; + }; + hardware.firmware = [ ( pkgs.runCommand "edid.bin" { } '' @@ -230,10 +253,10 @@ let secrets = import ../secrets.nix; in enable = true; systemCronJobs = [ # Update DuckDNS - use 'journalctl -e' to see logged output (should log 'OK' every 5 minutes) - "*/5 * * * * duckdns curl 'https://www.duckdns.org/update?domains=mstro&token=${secrets.duckdns_token}&ip=' | systemd-cat -t 'duckdns'" + "*/5 * * * * duckdns curl 'https://www.duckdns.org/update?domains=mstro&token=$(cat ${config.sops.secrets.duckdns_token.path})&ip=' | systemd-cat -t 'duckdns'" # Update CloudFlare DNS - "*/1 * * * * cloudflare-dns curl --request PUT --url https://api.cloudflare.com/client/v4/zones/${secrets.cloudflare_zone_id}/dns_records/${secrets.cloudflare_dns_record_id} --header 'Content-Type: application/json' --header 'Authorization: Bearer ${secrets.cloudflare_api_token}' --data '{ \"comment\": \"Domain verification record\", \"name\": \"@\", \"proxied\": false, \"settings\": {}, \"tags\": [], \"ttl\": 60, \"content\": \"'$(curl https://ipinfo.io/ip)'\", \"type\": \"A\" }' | jq -r '.success' | systemd-cat -t 'cloudflare-dns'" + "*/1 * * * * cloudflare-dns curl --request PUT --url https://api.cloudflare.com/client/v4/zones/$(cat ${config.sops.secrets.cloudflare_zone_id.path})/dns_records/$(cat ${config.sops.secrets.cloudflare_dns_record_id.path}) --header 'Content-Type: application/json' --header 'Authorization: Bearer $(cat ${config.sops.secrets.cloudflare_api_token.path})' --data '{ \"comment\": \"Domain verification record\", \"name\": \"@\", \"proxied\": false, \"settings\": {}, \"tags\": [], \"ttl\": 60, \"content\": \"'$(curl https://ipinfo.io/ip)'\", \"type\": \"A\" }' | jq -r '.success' | systemd-cat -t 'cloudflare-dns'" ]; }; @@ -264,12 +287,12 @@ let secrets = import ../secrets.nix; in # NGINX services.nginx = let - userlist = secrets.nginx_userlist; + userlistFile = config.sops.secrets."nginx-users".path; commonConfig = { root = "/schijf"; locations."/" = { - basicAuth = userlist; + basicAuthFile = userlistFile; extraConfig = '' autoindex on; add_header Cache-Control max-age=172800; @@ -294,12 +317,14 @@ let secrets = import ../secrets.nix; in }; locations."/transmission/web/" = { - basicAuth = userlist; + basicAuthFile = userlistFile; + #basicAuth = userlist; proxyPass = "http://127.0.0.1:9091/transmission/web/"; proxyWebsockets = true; }; locations."/transmission/rpc" = { - basicAuth = userlist; + #basicAuth = userlist; + basicAuthFile = userlistFile; proxyPass = "http://127.0.0.1:9091/transmission/rpc"; proxyWebsockets = true; }; diff --git a/flake.lock b/flake.lock index 78b6df5..a69b7a1 100644 --- a/flake.lock +++ b/flake.lock @@ -130,7 +130,28 @@ "icomidal": "icomidal", "mtl-aas": "mtl-aas", "nixpkgs-stable": "nixpkgs-stable", - "nixpkgs-unstable": "nixpkgs-unstable" + "nixpkgs-unstable": "nixpkgs-unstable", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs-stable" + ] + }, + "locked": { + "lastModified": 1763023272, + "narHash": "sha256-TCVNCn/GcKhwm+WlSJEZEPW4ISQdU9ICIU3lTiOLBYc=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "b80c966e70fa0615352c9596315678df1de75801", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" } }, "uv2nix": { diff --git a/flake.nix b/flake.nix index 329a43e..43d0338 100644 --- a/flake.nix +++ b/flake.nix @@ -4,6 +4,10 @@ inputs = { nixpkgs-stable.url = "github:nixos/nixpkgs?ref=nixos-25.05"; nixpkgs-unstable.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + sops-nix = { + url = "github:Mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs-stable"; + }; icomidal = { url = "git+https://deemz.org/git/joeri/icomidal"; inputs.nixpkgs.follows = "nixpkgs-stable"; @@ -14,7 +18,7 @@ }; }; - outputs = { self, nixpkgs-stable, nixpkgs-unstable, icomidal, mtl-aas }: + outputs = { self, nixpkgs-stable, nixpkgs-unstable, sops-nix, icomidal, mtl-aas }: let system = "x86_64-linux"; in { @@ -34,6 +38,7 @@ mtl-aas=mtl-aas.packages.${system}.default; mtlAasHost = "deemz.org"; mtlAasBaseUrl = "/apis/mtl-aas/"; + sops-nix = sops-nix; }; modules = [ ./deemz.org/configuration.nix diff --git a/secrets/nginx-users b/secrets/nginx-users new file mode 100644 index 0000000..2e2aa3a --- /dev/null +++ b/secrets/nginx-users @@ -0,0 +1,14 @@ +{ + "data": "ENC[AES256_GCM,data:vobRo+g4doHaXCSd5YLF/hmIrTDM/uMXDQ3s2guCTxU4hAAHczzIhbdwIkQBWRI=,iv:Zg7yLzY6xHDNrIH1mp+yYjc86aFT0FN7Z+WQ6Fw0foo=,tag:lSGhRH5jXRkgbsweS4Xb5g==,type:str]", + "sops": { + "age": [ + { + "recipient": "age156gze6ecg8xpgg3gc049tqprts5dl5apr7020cu70ukpsta3qvpsldd6kh", + "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFUFpaNzBWeEc0M0kxbGYz\nY3MwOUVsSjRYUEc3YTN1a2ZJdGlQcXB5R0I0Ck1hQWR1cUFhNWxSb2NYcG1kTG9S\naGQxNjEvRy9MaWpjL09KUTI1akVLd0UKLS0tIDNVYnBEL1lWZFQ4NFRtb05kZEk0\ncXRhTzMrSEpNVFlKMEoxbGx4d2J2UGcKNW/9gFikfgFwpH5J7whVWYfjj38io/Tt\n03R35Xt8igkaR6zMUBVCWYlK8gTvNcXLIzwhd4InyY3e6WNQ5gXniA==\n-----END AGE ENCRYPTED FILE-----\n" + } + ], + "lastmodified": "2025-11-13T13:57:32Z", + "mac": "ENC[AES256_GCM,data:gcfYnQ18CCFPYSTSsYAvnHL3AcIDVaUs/gkvCE+cNse7z8VbuRN8PKUhCziqA0/ubENcg0oFMmd1Bzh1PR16FF/uFaKfssTr3HTyygwDYlFpIVbHcAhi1Sx9clQRojVAWOadYbYOfWOiKau+kh0u7uUs+JoKErM48ooDu4KTaow=,iv:X21Y+pIoazeA6PhvhM+xr0klUPLpHDBRUiK6RLrBJJ0=,tag:fcJiC+GIEEsik1SJkl7ovA==,type:str]", + "version": "3.11.0" + } +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..d037d6c --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,19 @@ +duckdns_token: ENC[AES256_GCM,data:0baTWilND6Sz7G2tcrVivLuHEfWVZdDF0MMEKL3GdI42zN6J,iv:TUJfxWmFVsRIz4YGh/l618S33w0hK/gndDl7qRIvXj8=,tag:godLQL7pcg0dBJpt4ar5oQ==,type:str] +cloudflare_zone_id: ENC[AES256_GCM,data:M16f9pPua1jTSeaI+QTuyonkm07b4QtJyLwq46BHVnQ=,iv:hHiiLeDYBJyKsaT4pNtAm2OACHLxXhSP4ccCsPARuqE=,tag:eYcVhdNblYDTsVgmLqRFRA==,type:str] +cloudflare_dns_record_id: ENC[AES256_GCM,data:uWmc89xaIa9MjuvGge3aIDFdXxYzVWmZRf+JV/t89+o=,iv:+4RyCvqEjryw2vO15hETkbvJUT3KleKN1lu2zRATS+s=,tag:BPCb1gd/4gdMokPtn3SZng==,type:str] +cloudflare_api_token: ENC[AES256_GCM,data:8CnqBvjbvD741TRJ9QD4ZSwcIyS7uzgSSGsISq1+w4Llmuh+K2npYQ==,iv:7CqdNAWfvLYJPtk4L8G+HbYoBf5cmxeQ8sRD0uFl4AM=,tag:mbcCNlEOgNC5e/SWIaGP/w==,type:str] +sops: + age: + - recipient: age156gze6ecg8xpgg3gc049tqprts5dl5apr7020cu70ukpsta3qvpsldd6kh + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNd1c0bG9xdmdkRzlhbjZ1 + VEZtemZmcUp4L0V3Z3hJUXd2R2xoZjdEaHk0CmNpRlpza2cyVUFZMDVSNW05bmc0 + b053UU42QWlkVEQwUVBaeDJLNlMwRjQKLS0tIDlPT2UzK2xHZGxrRERJVlZzNFZU + MzJQK1JxT3NtdXQvRVN5Y1dZT0V1MGcKAkdsMIcS9C9VIWVPWIMv3dZC0gTlSBD3 + tf3xQh6MS2DiIqgxoG+ijRpkWKkraianlD4oZRh8mWHew9g3/IK4yw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2025-11-13T14:07:01Z" + mac: ENC[AES256_GCM,data:MA++TKCts2zWSEYTDoNF/lnyxa4TEEb1h1iOn0OctHv9vAaVHCwmkE5bjUfddakRa3zIMZ4nXX0bS1jOa1BYMfvVAYmwviyFejx6lsCZ4/6b9ptK5aO0nwlFZy7WDIIWb7AHdTTGInSU0JQx6emPzUXzsfjfOPAvImLTjhrsqmc=,iv:hM6MkmEb8Mrk8UouzLtECafocFo3yDK7c4iyTWDLe5A=,tag:8kA9j27kBRO3UubRNVKBlw==,type:str] + unencrypted_suffix: _unencrypted + version: 3.11.0