diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..c0dd061 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,7 @@ +keys: + - &server age1xhpcja6q6us9r44qvwxeqdq4y03n8l9xlq68uumew6gzm2tshgwq4ufd2l +creation_rules: + - path_regex: secrets/[^/]+\.(yaml|json|env|ini)$ + key_groups: + - age: + - *server diff --git a/nixos/configuration.nix b/nixos/configuration.nix index d058109..fc15434 100644 --- a/nixos/configuration.nix +++ b/nixos/configuration.nix @@ -17,6 +17,10 @@ programs.fish.enable = true; programs.tmux.enable = true; + programs.neovim = { + enable = true; + defaultEditor = true; + }; # Set your time zone. time.timeZone = "Europe/London"; @@ -34,7 +38,8 @@ shell = pkgs.fish; extraGroups = [ "wheel" ]; openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJFUwk54CNtSLUyXSTLsIs5KXgEsjOgE4HGlA4FacKjV syed@tardis" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJFUwk54CNtSLUyXSTLsIs5KXgEsjOgE4HGlA4FacKjV syed@tardis # msi laptop" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILMeU7L0yQ4+O1GME4D4UM4f6nqua+pWt/zdsMvyHV94 u0_a309@localhost # mobile" ]; packages = with pkgs; []; }; @@ -42,11 +47,12 @@ # List packages installed in system profile. # You can use https://search.nixos.org/ to find more packages (and options). environment.systemPackages = with pkgs; [ + sops + age eza yazi gitui bind - neovim wget curl stow diff --git a/nixos/flake.lock b/nixos/flake.lock index fcfffe6..b4badc7 100644 --- a/nixos/flake.lock +++ b/nixos/flake.lock @@ -16,9 +16,44 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1775888245, + "narHash": "sha256-nwASzrRDD1JBEu/o8ekKYEXm/oJW6EMCzCRdrwcLe90=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "13043924aaa7375ce482ebe2494338e058282925", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "sops-nix": "sops-nix" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1782165805, + "narHash": "sha256-478kKQBvK6SYTOdN2h9jhKJv94nbXRbFMfuL1WshErg=", + "owner": "Mic92", + "repo": "sops-nix", + "rev": "56b24064fdcaedca53553b1a6d607fd23b613a24", + "type": "github" + }, + "original": { + "owner": "Mic92", + "repo": "sops-nix", + "type": "github" } } }, diff --git a/nixos/flake.nix b/nixos/flake.nix index 22aa0be..40989c3 100644 --- a/nixos/flake.nix +++ b/nixos/flake.nix @@ -1,11 +1,21 @@ { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05"; + sops-nix.url = "github:Mic92/sops-nix"; }; - outputs = inputs@{ self, nixpkgs, ... }: { + + outputs = inputs@{ self, nixpkgs, sops-nix, ... }: + let + system = "x86_64-linux"; + in { nixosConfigurations.syedm = nixpkgs.lib.nixosSystem { - modules = [ ./configuration.nix ]; + inherit system; + + modules = [ + ./configuration.nix + sops-nix.nixosModules.sops + ./flakes/cloudflare-ddns.nix + ]; }; }; } - diff --git a/nixos/flakes/cloudfare-ddns.nix b/nixos/flakes/cloudfare-ddns.nix new file mode 100644 index 0000000..3e3a7d0 --- /dev/null +++ b/nixos/flakes/cloudfare-ddns.nix @@ -0,0 +1,42 @@ +{ config, pkgs, ... }: + +let + script = pkgs.substituteAll { + src = ../../scripts/cloudflare-ddns.sh; + + bash = pkgs.bash; + curl = pkgs.curl; + jq = pkgs.jq; + }; + + cloudflare-ddns = pkgs.writeShellScriptBin "cloudflare-ddns" (builtins.readFile script); + +in +{ + environment.systemPackages = [ cloudflare-ddns ]; + + systemd.services.cloudflare-ddns = { + description = "Cloudflare DDNS updater"; + + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + + script = "${cloudflare-ddns}/bin/cloudflare-ddns"; + }; + + systemd.timers.cloudflare-ddns = { + wantedBy = [ "timers.target" ]; + + timerConfig = { + OnBootSec = "2min"; + OnUnitActiveSec = "5min"; + Persistent = true; + }; + }; + + systemd.tmpfiles.rules = [ + "d /var/lib/cloudflare-ddns 0750 root root -" + ]; +} diff --git a/scripts/cloudflare-ddns.sh b/scripts/cloudflare-ddns.sh new file mode 100644 index 0000000..2e98d70 --- /dev/null +++ b/scripts/cloudflare-ddns.sh @@ -0,0 +1,33 @@ +#!@bash@/bin/bash + +source /run/secrets/main.env + +cache=/var/lib/cloudflare-ddns/old_ip +IP=$(@curl@/bin/curl -s 'https://api.ipify.org') +arr=("" "git." "www.") + +if [[ -f "$cache" ]]; then + old_ip=$(cat "$cache") +else + old_ip="" +fi + +if [[ "$IP" != "$old_ip" ]]; then + for sub in "${arr[@]}"; do + RECORD_ID=$(@curl@/bin/curl -s -X GET \ + "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \ + -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + -H "Content-Type: application/json" \ + | @jq@/bin/jq -r ".result[] | select(.name==\"${sub}syedm.dev\" and .type==\"A\") | .id") + + if [ -n "$RECORD_ID" ]; then + @curl@/bin/curl -s -X PUT \ + "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \ + -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"type\":\"A\",\"name\":\"${sub}syedm.dev\",\"content\":\"$IP\",\"ttl\":3600,\"proxied\":false}" + fi + done + + echo "$IP" > "$cache" +fi diff --git a/secrets/main.env b/secrets/main.env new file mode 100644 index 0000000..19168ac --- /dev/null +++ b/secrets/main.env @@ -0,0 +1,8 @@ +CLOUDFLARE_API_TOKEN=ENC[AES256_GCM,data:qUc5v0dwbAedM/uQ1s2A0/c8nU/NipWz79mkAkdm2l/pC+NcmCEhsA==,iv:u/G6hR32Xay8j23XGHcKWnZo/6q9mDfIMQOgG+KMO78=,tag:0hGvWe9Gj0PsYdRqnFKeBA==,type:str] +ZONE_ID=ENC[AES256_GCM,data:o3fUyWND1dE1I5nAiRYKyPZTqCvOTPl/r1i98PC0ZPk=,iv:pXb+IZblnePYmMxr9J4Y7Ie8DdzP0yI5JXRPr2C+kWE=,tag:7cjM891ard+GZoyiCqDoow==,type:str] +sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJVXJaQjU0eEErUU94NG1j\ndllZbjhNcW5qY0pueFJmWkZlb1dPcXBuS1hZCnZSMlJhRzhGWFJSTVNnWndOaHJP\nd3FzQXY5TGoxTmZiVFJhYy83RHI1dGcKLS0tIElGNktpZ0QrWXROcExqZEhPbVN1\nalJPS0tNQXY2N0NrZlNTT3FvMG1tSlkKrX+LWOibAN79q5kQiBqnRHpiGAqej/Co\nFm8GMQKFYK3UJGidIXDz2JfMy5I26kBXKBlup2hGwGIA7veghkskVQ==\n-----END AGE ENCRYPTED FILE-----\n +sops_age__list_0__map_recipient=age1xhpcja6q6us9r44qvwxeqdq4y03n8l9xlq68uumew6gzm2tshgwq4ufd2l +sops_lastmodified=2026-07-02T20:21:19Z +sops_mac=ENC[AES256_GCM,data:BsZxChuzgqTMnSgpRqe1UFqdhXPaA03hXnTXbzuQPal1OCTJ1YIAEbcjvkxf69dQ0zTm68vcl4nV2fS7pLmz5wkexiU5/tfuHEcVhRu1eAtHj5LpR9wBWOoOLH1BkZQWDOWPhCm91+K+3LQZg6dfOj5Vq0ukHHfXwSBPFiAEWcs=,iv:pK0I5ho6cN+lmAnhxugcTRoDZ2IiDyYemxP4jpnpkk0=,tag:MMIy8lPUKhhY2F4JRRN3Lw==,type:str] +sops_unencrypted_suffix=_unencrypted +sops_version=3.13.1