commit 00315a990a8342e58d1fa30e0b74f3427d8e077f Author: Max Koon Date: Fri Aug 15 19:54:31 2025 -0400 feat: inital public commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..202e3a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +**/.terraform/* + +*.tfstate +*.tfstate.* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4581bf0 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "secrets"] + path = secrets + url = ssh://git@ssh.koon.us/max/secrets.git diff --git a/README.md b/README.md new file mode 100644 index 0000000..872d258 --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +

+ +
+
+Koon Family OS +
+

+ +## Post Clone + +When cloning the repo, you have to initalize the secrets submodule. + +``` +git submodule update --init secrets +``` + +## Deploy + +### Ark + +```sh +nix-shell -p neofetch --run "neofetch" + ▗▄▄▄ ▗▄▄▄▄ ▄▄▄▖ admin@ark + ▜███▙ ▜███▙ ▟███▛ --------- + ▜███▙ ▜███▙▟███▛ OS: NixOS 25.11.20250806.c2ae88e (Xantusia) x86_64 + ▜███▙ ▜██████▛ Host: HP 829A + ▟█████████████████▙ ▜████▛ ▟▙ Kernel: 6.12.40 + ▟███████████████████▙ ▜███▙ ▟██▙ Uptime: 12 days, 1 hour, 39 mins + ▄▄▄▄▖ ▜███▙ ▟███▛ Packages: 373 (nix-system), 111 (nix-user) + ▟███▛ ▜██▛ ▟███▛ Shell: bash 5.3.0 + ▟███▛ ▜▛ ▟███▛ Terminal: /dev/pts/0 +▟███████████▛ ▟██████████▙ CPU: Intel i5-6500T (4) @ 3.100GHz +▜██████████▛ ▟███████████▛ GPU: Intel HD Graphics 530 + ▟███▛ ▟▙ ▟███▛ Memory: 2259MiB / 7818MiB + ▟███▛ ▟██▙ ▟███▛ + ▟███▛ ▜███▙ ▝▀▀▀▀ + ▜██▛ ▜███▙ ▜██████████████████▛ + ▜▛ ▟████▙ ▜████████████████▛ + ▟██████▙ ▜███▙ + ▟███▛▜███▙ ▜███▙ + ▟███▛ ▜███▙ ▜███▙ + ▝▀▀▀ ▀▀▀▀▘ ▀▀▀▘ +``` + +```sh +just rebuild-ark +``` + +### Max's Laptop + +```sh +nix-shell -p neofetch --run "neofetch" + ▗▄▄▄ ▗▄▄▄▄ ▄▄▄▖ max@nixos + ▜███▙ ▜███▙ ▟███▛ --------- + ▜███▙ ▜███▙▟███▛ OS: NixOS 25.05.20250807.e728d7a (Warbler) aarch64 + ▜███▙ ▜██████▛ Host: Apple MacBook Pro (14-inch, M2 Pro, 2023) + ▟█████████████████▙ ▜████▛ ▟▙ Kernel: 6.14.8-asahi + ▟███████████████████▙ ▜███▙ ▟██▙ Uptime: 3 days, 2 hours, 11 mins + ▄▄▄▄▖ ▜███▙ ▟███▛ Packages: 1936 (nix-system), 1277 (nix-user) + ▟███▛ ▜██▛ ▟███▛ Shell: bash 5.2.37 + ▟███▛ ▜▛ ▟███▛ Resolution: 3024x1890 +▟███████████▛ ▟██████████▙ DE: Plasma 6.3.6 (Wayland) +▜██████████▛ ▟███████████▛ WM: kwin + ▟███▛ ▟▙ ▟███▛ Icons: breeze [GTK2/3] + ▟███▛ ▟██▙ ▟███▛ Terminal: alacritty + ▟███▛ ▜███▙ ▝▀▀▀▀ CPU: (12) @ 2.424GHz + ▜██▛ ▜███▙ ▜██████████████████▛ Memory: 10290MiB / 15424MiB + ▜▛ ▟████▙ ▜████████████████▛ + ▟██████▙ ▜███▙ + ▟███▛▜███▙ ▜███▙ + ▟███▛ ▜███▙ ▜███▙ + ▝▀▀▀ ▀▀▀▀▘ ▀▀▀▘ +``` + +```sh +just rebuild +``` + diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000..961d245 Binary files /dev/null and b/assets/logo.png differ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..41a353b --- /dev/null +++ b/flake.lock @@ -0,0 +1,367 @@ +{ + "nodes": { + "flake-compat": { + "locked": { + "lastModified": 1688025799, + "narHash": "sha256-ktpB4dRtnksm9F5WawoIkEneh1nrEvuxb5lJFt1iOyw=", + "owner": "nix-community", + "repo": "flake-compat", + "rev": "8bf105319d44f6b9f0d764efa4fdef9f1cc9ba1c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754091436, + "narHash": "sha256-XKqDMN1/Qj1DKivQvscI4vmHfDfvYR2pfuFOJiCeewM=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "67df8c627c2c39c41dbec76a1f201929929ab0bd", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "terranix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1736143030, + "narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1753592768, + "narHash": "sha256-oV695RvbAE4+R9pcsT9shmp6zE/+IZe6evHWX63f2Qg=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "fc3add429f21450359369af74c2375cb34a2d204", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-25.05", + "repo": "home-manager", + "type": "github" + } + }, + "ixx": { + "inputs": { + "flake-utils": [ + "nixvim", + "nuschtosSearch", + "flake-utils" + ], + "nixpkgs": [ + "nixvim", + "nuschtosSearch", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1748294338, + "narHash": "sha256-FVO01jdmUNArzBS7NmaktLdGA5qA3lUMJ4B7a05Iynw=", + "owner": "NuschtOS", + "repo": "ixx", + "rev": "cc5f390f7caf265461d4aab37e98d2292ebbdb85", + "type": "github" + }, + "original": { + "owner": "NuschtOS", + "ref": "v0.0.8", + "repo": "ixx", + "type": "github" + } + }, + "nixos-apple-silicon": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1748659443, + "narHash": "sha256-dav2hzyCmXZ3n6lEZrfZBG51+g6PUhkzRl3d6Ypd9x0=", + "owner": "nix-community", + "repo": "nixos-apple-silicon", + "rev": "3ddc251d2acce5019b0fa770e224d068610a34e4", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-2025-05-30", + "repo": "nixos-apple-silicon", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1748460289, + "narHash": "sha256-7doLyJBzCllvqX4gszYtmZUToxKvMUrg45EUWaUYmBg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "96ec055edbe5ee227f28cdbc3f1ddf1df5965102", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1754563854, + "narHash": "sha256-YzNTExe3kMY9lYs23mZR7jsVHe5TWnpwNrsPOpFs/b8=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "e728d7ae4bb6394bbd19eec52b7358526a44c414", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixvim": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs" + ], + "nuschtosSearch": "nuschtosSearch", + "systems": "systems_2" + }, + "locked": { + "lastModified": 1754262585, + "narHash": "sha256-Yz5dJ0VzGRzSRHdHldsWQbuFYmtP3NWNreCvPfCi9CI=", + "owner": "nix-community", + "repo": "nixvim", + "rev": "ab1b5962e1ca90b42de47e1172e0d24ca80e6256", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "nixos-25.05", + "repo": "nixvim", + "type": "github" + } + }, + "nuschtosSearch": { + "inputs": { + "flake-utils": "flake-utils", + "ixx": "ixx", + "nixpkgs": [ + "nixvim", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1753771532, + "narHash": "sha256-Pmpke0JtLRzgdlwDC5a+aiLVZ11JPUO5Bcqkj0nHE/k=", + "owner": "NuschtOS", + "repo": "search", + "rev": "2a65adaf2c0c428efb0f4a2bc406aab466e96a06", + "type": "github" + }, + "original": { + "owner": "NuschtOS", + "repo": "search", + "type": "github" + } + }, + "plasma-manager": { + "inputs": { + "home-manager": [ + "home-manager" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754501628, + "narHash": "sha256-FExJ54tVB5iu7Dh2tLcyCSWpaV+lmUzzWKZUkemwXvo=", + "owner": "nix-community", + "repo": "plasma-manager", + "rev": "cca090f8115c4172b9aef6c5299ae784bdd5e133", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "plasma-manager", + "type": "github" + } + }, + "root": { + "inputs": { + "home-manager": "home-manager", + "nixos-apple-silicon": "nixos-apple-silicon", + "nixpkgs": "nixpkgs_2", + "nixvim": "nixvim", + "plasma-manager": "plasma-manager", + "sops-nix": "sops-nix", + "terranix": "terranix", + "unstable": "unstable" + } + }, + "sops-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1754328224, + "narHash": "sha256-glPK8DF329/dXtosV7YSzRlF4n35WDjaVwdOMEoEXHA=", + "owner": "mic92", + "repo": "sops-nix", + "rev": "49021900e69812ba7ddb9e40f9170218a7eca9f4", + "type": "github" + }, + "original": { + "owner": "mic92", + "repo": "sops-nix", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "terranix": { + "inputs": { + "flake-parts": "flake-parts_2", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_3" + }, + "locked": { + "lastModified": 1749381683, + "narHash": "sha256-16z7tXZch12SAd3d8tbAiEOamyq3zFbw1oUq/ipmTkM=", + "owner": "terranix", + "repo": "terranix", + "rev": "9d2370279d595be9e728b68d29ff0b546d88e619", + "type": "github" + }, + "original": { + "owner": "terranix", + "repo": "terranix", + "type": "github" + } + }, + "unstable": { + "locked": { + "lastModified": 1754498491, + "narHash": "sha256-erbiH2agUTD0Z30xcVSFcDHzkRvkRXOQ3lb887bcVrs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "c2ae88e026f9525daf89587f3cbee584b92b6134", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..1759e6b --- /dev/null +++ b/flake.nix @@ -0,0 +1,127 @@ +{ + description = "Koon OS"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-25.05"; + + unstable.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + + nixos-apple-silicon.url = + "github:nix-community/nixos-apple-silicon?ref=release-2025-05-30"; + + home-manager = { + url = "github:nix-community/home-manager?ref=release-25.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + plasma-manager = { + url = "github:nix-community/plasma-manager"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.home-manager.follows = "home-manager"; + }; + + nixvim = { + url = "github:nix-community/nixvim?ref=nixos-25.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + sops-nix = { + url = "github:mic92/sops-nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + terranix = { + url = "github:terranix/terranix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { self, nixpkgs, unstable, nixos-apple-silicon, home-manager + , plasma-manager, nixvim, sops-nix, terranix, ... }: { + + packages.aarch64-linux = + let + system = "aarch64-linux"; + + pkgs = import unstable { + inherit system; + config = { + allowUnfree = true; + }; + }; + + terraform = pkgs.terraform.withPlugins (p: [ + p.pocketid + p.local + ]); + terraformConfiguration = terranix.lib.terranixConfiguration { + inherit system; + modules = [ ./infra/config.nix ]; + }; + in { + deploy = pkgs.writeShellScriptBin "deploy" '' + echo Deploying Infrastructure... + + export TF_VAR_pocketid_api_token=$(${pkgs.sops}/bin/sops -d --extract '["pocketid-api-token"]' secrets/secrets.yaml) + + cd infra + + cp ${terraformConfiguration} config.tf.json + + ${terraform}/bin/terraform init + ${terraform}/bin/terraform apply + + rm -f config.tf.json + + echo Done + + echo Encrypting secrets + + cd ../secrets + + ${pkgs.sops}/bin/sops -e -i sops/oauth.yaml + + echo Done + ''; + }; + + nixosConfigurations = { + max = let + system = "aarch64-linux"; + pkgs-unstable = import unstable { inherit system; }; + secrets = import ./secrets; + in nixpkgs.lib.nixosSystem { + inherit system; + specialArgs = { inherit pkgs-unstable secrets; }; + modules = [ + ./host/max/default.nix + nixos-apple-silicon.nixosModules.apple-silicon-support + sops-nix.nixosModules.sops + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + home-manager.extraSpecialArgs = { inherit secrets; }; + home-manager.users.max = { config, pkgs, lib, ... }: { + imports = [ + sops-nix.homeManagerModules.sops + nixvim.homeManagerModules.nixvim + plasma-manager.homeManagerModules.plasma-manager + ./host/max/home.nix # Import your home.nix here + ]; + }; + } + ]; + }; + + ark = let system = "x86_64-linux"; + in unstable.lib.nixosSystem { + inherit system; + modules = [ + ./host/ark/default.nix + sops-nix.nixosModules.sops + ]; + }; + }; + }; +} diff --git a/host/ark/default.nix b/host/ark/default.nix new file mode 100644 index 0000000..bba351f --- /dev/null +++ b/host/ark/default.nix @@ -0,0 +1,62 @@ +{ config, lib, pkgs, ... }: { + imports = [ + ./hardware-configuration.nix + ./options.nix + ../common/core/default.nix + ./user.nix + ./sops.nix + + ./service/audio.nix + ./service/auth.nix + ./service/docs.nix + ./service/git.nix + ./service/home.nix + ./service/photos.nix + ./service/radicale.nix + ./service/wakapi.nix + ]; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.hostName = "ark"; # Define your hostname. + + oauth.name = "KoonFamily"; + oauth.secrets = import ./oauth-secrets.nix; + + security.sudo.wheelNeedsPassword = false; + + services.cloudflared = { + enable = true; + tunnels = { + "91d31395-fbc7-45a1-ae13-148957b32ecd" = { + credentialsFile = config.sops.secrets.tunnel-credentials.path; + ingress = { + "auth.koon.us" = "http://localhost:1411"; + "photos.koon.us" = "http://localhost:2283"; + "home.koon.us" = "http://localhost:8123"; + "docs.koon.us" = "http://localhost:3004"; + "git.koon.us" = "http://localhost:3000"; + "ssh.koon.us" = "ssh://localhost:2222"; + "audio.koon.us" = "http://localhost:8021"; + "radicale.koon.us" = "http://localhost:5232"; + "waka.koon.us" = "http://localhost:3006"; + }; + default = "http_status:404"; + }; + }; + }; + + fileSystems."/mnt/hdd" = { + device = "/dev/sdb"; + fsType = "ext4"; + }; + + services.openssh.enable = true; + + networking.firewall.allowedTCPPorts = [ 8123 22 ]; + + system.stateVersion = "25.05"; # Did you read the comment? +} + diff --git a/host/ark/hardware-configuration.nix b/host/ark/hardware-configuration.nix new file mode 100644 index 0000000..956f4a6 --- /dev/null +++ b/host/ark/hardware-configuration.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = + [ "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/56034a80-72ea-4e67-be41-2e8cb642fb44"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/DE8B-01DE"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.eno1.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = + lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/host/ark/options.nix b/host/ark/options.nix new file mode 100644 index 0000000..c4233cf --- /dev/null +++ b/host/ark/options.nix @@ -0,0 +1,7 @@ +{ lib, ... }: { + options.oauth = { + name = lib.mkOption { type = lib.types.str; }; + secrets = lib.mkOption { type = lib.types.attrs; }; + }; + +} diff --git a/host/ark/service/audio.nix b/host/ark/service/audio.nix new file mode 100644 index 0000000..9840857 --- /dev/null +++ b/host/ark/service/audio.nix @@ -0,0 +1,6 @@ +{ ... }: { + services.audiobookshelf = { + enable = true; + port = 8021; + }; +} diff --git a/host/ark/service/auth.nix b/host/ark/service/auth.nix new file mode 100644 index 0000000..f339e33 --- /dev/null +++ b/host/ark/service/auth.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: { + services.pocket-id = { + enable = true; + settings = { + APP_URL = "https://auth.koon.us"; + TRUST_PROXY = true; + ANALYTICS_DISABLED = true; + + UI_CONFIG_DISABLED = true; + + APP_NAME = config.oauth.name; + }; + }; +} diff --git a/host/ark/service/docs.nix b/host/ark/service/docs.nix new file mode 100644 index 0000000..c3d4084 --- /dev/null +++ b/host/ark/service/docs.nix @@ -0,0 +1,94 @@ +{ config, lib, pkgs, ... }: { + nixpkgs.config.allowUnfree = true; + + services.outline = { + enable = true; + publicUrl = "https://docs.koon.us"; + port = 3004; + forceHttps = true; + storage.storageType = "local"; + logo = "https://i.imgur.com/fKJ1I63.png"; + oidcAuthentication = { + authUrl = "https://auth.koon.us/authorize"; + tokenUrl = "https://auth.koon.us/api/oidc/token"; + userinfoUrl = "https://auth.koon.us/api/oidc/userinfo"; + clientId = ""; + clientSecretFile = config.sops.secrets."docs/clientSecret".path; + scopes = [ "openid" "email" "profile" ]; + usernameClaim = "preferred_username"; + displayName = config.oauth.name; + }; + }; + + systemd.services.outline = { + script = + let + localPostgresqlUrl = "postgres://localhost/outline?host=/run/postgresql"; + cfg = config.services.outline; + in lib.mkForce '' + export SECRET_KEY="$(head -n1 ${lib.escapeShellArg cfg.secretKeyFile})" + export UTILS_SECRET="$(head -n1 ${lib.escapeShellArg cfg.utilsSecretFile})" + ${lib.optionalString (cfg.storage.storageType == "s3") '' + export AWS_SECRET_ACCESS_KEY="$(head -n1 ${lib.escapeShellArg cfg.storage.secretKeyFile})" + ''} + ${lib.optionalString (cfg.slackAuthentication != null) '' + export SLACK_CLIENT_SECRET="$(head -n1 ${lib.escapeShellArg cfg.slackAuthentication.secretFile})" + ''} + ${lib.optionalString (cfg.googleAuthentication != null) '' + export GOOGLE_CLIENT_SECRET="$(head -n1 ${lib.escapeShellArg cfg.googleAuthentication.clientSecretFile})" + ''} + ${lib.optionalString (cfg.azureAuthentication != null) '' + export AZURE_CLIENT_SECRET="$(head -n1 ${lib.escapeShellArg cfg.azureAuthentication.clientSecretFile})" + ''} + ${lib.optionalString (cfg.oidcAuthentication != null) '' + export OIDC_CLIENT_SECRET="$(head -n1 ${lib.escapeShellArg cfg.oidcAuthentication.clientSecretFile})" + export OIDC_CLIENT_ID="$(cat ${config.sops.secrets."docs/clientId".path})" + ''} + ${lib.optionalString (cfg.sslKeyFile != null) '' + export SSL_KEY="$(head -n1 ${lib.escapeShellArg cfg.sslKeyFile})" + ''} + ${lib.optionalString (cfg.sslCertFile != null) '' + export SSL_CERT="$(head -n1 ${lib.escapeShellArg cfg.sslCertFile})" + ''} + ${lib.optionalString (cfg.slackIntegration != null) '' + export SLACK_VERIFICATION_TOKEN="$(head -n1 ${lib.escapeShellArg cfg.slackIntegration.verificationTokenFile})" + ''} + ${lib.optionalString (cfg.smtp != null) '' + export SMTP_PASSWORD="$(head -n1 ${lib.escapeShellArg cfg.smtp.passwordFile})" + ''} + + ${ + if (cfg.databaseUrl == "local") then + '' + export DATABASE_URL=${lib.escapeShellArg localPostgresqlUrl} + export PGSSLMODE=disable + '' + else + '' + export DATABASE_URL=${lib.escapeShellArg cfg.databaseUrl} + '' + } + + ${cfg.package}/bin/outline-server + ''; + }; + # systemd.services.outline = { + # serviceConfig = { + # # Load the client ID from the sops secret file + # ExecStartPre = let + # script = pkgs.writeShellScript "outline-set-oauth" '' + # CLIENT_ID=$(cat ${config.sops.secrets."docs/clientId".path}) + # # Export as environment variable that Outline will use + # echo "OIDC_CLIENT_ID=$CLIENT_ID" >> $RUNTIME_DIRECTORY/env + # ''; + # in "+${script}"; + # + # # Load the environment file + # EnvironmentFile = "-/run/outline/env"; + # }; + # + # # Ensure sops secrets are available before starting + # after = [ "sops-nix.service" ]; + # wants = [ "sops-nix.service" ]; + # }; +} diff --git a/host/ark/service/git.nix b/host/ark/service/git.nix new file mode 100644 index 0000000..7d71782 --- /dev/null +++ b/host/ark/service/git.nix @@ -0,0 +1,111 @@ +{ lib, config, pkgs, ... }: { + services.gitea = { + enable = true; + user = "git"; + group = "git"; + database = { + user = "git"; + name = "git"; + type = "postgres"; + }; + settings = { + server = { + DOMAIN = "git.koon.us"; + ROOT_URL = "https://git.koon.us"; + HTTP_PORT = 3000; + LANDING_PAGE = "/max"; + SSH_DOMAIN = "ssh.koon.us"; + SSH_PORT = 2222; + START_SSH_SERVER = true; + }; + oauth2_client = { + ACCOUNT_LINKING = "auto"; + ENABLE_AUTO_REGISTRATION = true; + UPDATE_AVATAR = true; + USERNAME = "email"; + }; + service = { + DISABLE_REGISTRATION = true; + ENABLE_PASSWORD_SIGNIN_FORM = false; + ENABLE_PASSKEY_AUTHENTICATION = false; + + SHOW_MILESTONES_DASHBOARD_PAGE = false; + }; + "service.explore" = { + DISABLE_USERS_PAGE = true; + DISABLE_ORGANIZATIONS_PAGE = true; + DISABLE_CODE_PAGE = true; + }; + }; + }; + + users.users.git = { + isSystemUser = true; + group = "git"; + home = "/var/lib/gitea"; + description = "Git server (Gitea)"; + createHome = true; + }; + users.groups.git = { }; + + systemd.services.gitea = { + serviceConfig = { + RestartSec = "60"; # Retry every minute + }; + preStart = let + exe = lib.getExe config.services.gitea.package; + + clientIdPath = config.sops.secrets."git/clientId".path; + clientSecretPath = config.sops.secrets."git/clientSecret".path; + + args = lib.escapeShellArgs (lib.concatLists [ + [ "--name" config.oauth.name ] + [ "--provider" "openidConnect" ] + # [ "--key" config.oauth.secrets.git.clientId ] + [ + "--auto-discover-url" + "https://auth.koon.us/.well-known/openid-configuration" + ] + [ "--scopes" "email" ] + [ "--scopes" "profile" ] + [ "--group-claim-name" "groups" ] + [ "--admin-group" "admin" ] + [ "--skip-local-2fa" ] + ]); + in lib.mkAfter '' + CLIENT_ID=$(cat ${clientIdPath}) + CLIENT_SECRET=$(cat ${clientSecretPath}) + + provider_id=$(${exe} admin auth list | ${pkgs.gnugrep}/bin/grep -w '${config.oauth.name}' | cut -f1) + + if [[ -z "$provider_id" ]]; then + ${exe} admin auth add-oauth ${args} --key "$CLIENT_ID" --secret "$CLIENT_SECRET" + else + ${exe} admin auth update-oauth --id "$provider_id" ${args} --key "$CLIENT_ID" --secret "$CLIENT_SECRET" + fi + + mkdir -p /var/lib/gitea/custom/public/assets/img/ + + ln -sf ${ + ./git/assets/img/logo.svg + } /var/lib/gitea/custom/public/assets/img/logo.svg + ln -sf ${ + ./git/assets/img/favicon.svg + } /var/lib/gitea/custom/public/assets/img/favicon.svg + + mkdir -p /var/lib/gitea/custom/templates/base/ + ln -sf ${ + ./git/templates/base/head_navbar.tmpl + } /var/lib/gitea/custom/templates/base/head_navbar.tmpl + ln -sf ${ + ./git/templates/base/footer_content.tmpl + } /var/lib/gitea/custom/templates/base/footer_content.tmpl + + mkdir -p /var/lib/gitea/custom/templates/custom/ + ln -sf ${ + ./git/templates/custom/header.tmpl + } /var/lib/gitea/custom/templates/custom/header.tmpl + + ''; + }; +} diff --git a/host/ark/service/git/assets/css/custom.css b/host/ark/service/git/assets/css/custom.css new file mode 100644 index 0000000..34b5f9b --- /dev/null +++ b/host/ark/service/git/assets/css/custom.css @@ -0,0 +1,15 @@ +/* custom.css */ +:root { + --color-primary: #2e7d32; + --color-primary-dark: #1b5e20; +} + +/* Hide "Powered by Gitea" */ +.footer .ui.container .ui.left { + display: none; +} + +/* Custom header background */ +.ui.top.menu { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +} diff --git a/host/ark/service/git/assets/img/favicon.svg b/host/ark/service/git/assets/img/favicon.svg new file mode 100644 index 0000000..364038c --- /dev/null +++ b/host/ark/service/git/assets/img/favicon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/host/ark/service/git/assets/img/logo.svg b/host/ark/service/git/assets/img/logo.svg new file mode 100644 index 0000000..364038c --- /dev/null +++ b/host/ark/service/git/assets/img/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/host/ark/service/git/templates/base/footer_content.tmpl b/host/ark/service/git/templates/base/footer_content.tmpl new file mode 100644 index 0000000..221452c --- /dev/null +++ b/host/ark/service/git/templates/base/footer_content.tmpl @@ -0,0 +1,3 @@ +
+ © MMXXV Koon Family +
diff --git a/host/ark/service/git/templates/base/head_navbar.tmpl b/host/ark/service/git/templates/base/head_navbar.tmpl new file mode 100644 index 0000000..8043f33 --- /dev/null +++ b/host/ark/service/git/templates/base/head_navbar.tmpl @@ -0,0 +1,190 @@ +{{$notificationUnreadCount := 0}} +{{if and .IsSigned .NotificationUnreadCount}} + {{$notificationUnreadCount = call .NotificationUnreadCount ctx}} +{{end}} +{{$activeStopwatch := NIL}} +{{if and .IsSigned EnableTimetracking .GetActiveStopwatch}} + {{$activeStopwatch = call .GetActiveStopwatch ctx}} +{{end}} + diff --git a/host/ark/service/git/templates/custom/header.tmpl b/host/ark/service/git/templates/custom/header.tmpl new file mode 100644 index 0000000..21e63b1 --- /dev/null +++ b/host/ark/service/git/templates/custom/header.tmpl @@ -0,0 +1,10 @@ + diff --git a/host/ark/service/home.nix b/host/ark/service/home.nix new file mode 100644 index 0000000..85ed873 --- /dev/null +++ b/host/ark/service/home.nix @@ -0,0 +1,28 @@ +{ pkgs, ... }: { + virtualisation.oci-containers = let + hass_config = pkgs.writeText "configuration.yaml" '' + # Discovery + default_config: + + # Web Server configuration + http: + server_host: 127.0.0.1 + use_x_forwarded_for: true + trusted_proxies: 127.0.0.1 + ''; + in { + backend = "podman"; + containers.homeassistant = { + volumes = [ + "home-assistant:/config" + # "/data/docker/hass:/config" + "${hass_config}:/config/configuration.yaml" + # "/run/secrets/home-assistant:/config/secrets.yaml" + ]; + environment.TZ = "America/New_York"; + image = + "ghcr.io/home-assistant/home-assistant:stable"; # Warning: if the tag does not change, the image will not be updated + extraOptions = [ "--network=host" ]; + }; + }; +} diff --git a/host/ark/service/photos.nix b/host/ark/service/photos.nix new file mode 100644 index 0000000..89feb53 --- /dev/null +++ b/host/ark/service/photos.nix @@ -0,0 +1,117 @@ +{ lib, config, pkgs, ... }: { + sops = { + templates = { + "immich-config.json" = { + content = builtins.toJSON { + passwordLogin.enabled = false; + + # We will do this ourselves + backup.database.enabled = false; + + oauth = { + enabled = true; + autoLaunch = true; + autoRegister = true; + buttonText = + lib.strings.concatStrings [ "Login To " config.oauth.name ]; + clientId = config.sops.placeholder."photos/clientId"; + clientSecret = config.sops.placeholder."photos/clientSecret"; + issuerUrl = "https://auth.koon.us/.well-known/openid-configuration"; + }; + }; + owner = config.users.users.immich.name; + mode = "0400"; + restartUnits = [ "immich-server.service" "pocket-id.service" ]; + }; + }; + }; + + services.immich = { + enable = true; + port = 2283; + environment.IMMICH_CONFIG_FILE = config.sops.templates."immich-config.json".path; + accelerationDevices = null; + + machine-learning.environment = { + HF_XET_CACHE = "/var/cache/immich/huggingface-xet"; + }; + + }; + + users.users.immich = { + home = "/var/lib/immich"; + createHome = true; + extraGroups = [ "video" "render" ]; + }; + + hardware.graphics = { + enable = true; + extraPackages = with pkgs; [ intel-media-driver ]; + }; + environment.sessionVariables = { LIBVA_DRIVER_NAME = "iHD"; }; + + services.restic.backups = { + immich-local = { + repository = "/mnt/hdd/restic/immich"; + passwordFile = config.sops.secrets.restic-password.path; + initialize = true; + paths = [ "/var/lib/immich/upload" "/var/backup/immich" ]; + backupPrepareCommand = '' + mkdir -p /var/backup/immich + + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl stop immich-server + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl stop immich-machine-learning + + ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump \ + --clean \ + --if-exists \ + --dbname=immich > /var/backup/immich/postgres.sql + ''; + backupCleanupCommand = '' + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl start immich-server + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl start immich-machine-learning + ''; + }; + immich-remote = { + repository = "rest:http://m1:8000/immich"; + passwordFile = config.sops.secrets.restic-password.path; + initialize = true; + paths = [ "/var/lib/immich/upload" "/var/backup/immich" ]; + backupPrepareCommand = '' + mkdir -p /var/backup/immich + + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl stop immich-server + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl stop immich-machine-learning + + ${pkgs.sudo}/bin/sudo -u postgres ${pkgs.postgresql}/bin/pg_dump \ + --clean \ + --if-exists \ + --dbname=immich > /var/backup/immich/postgres.sql + ''; + backupCleanupCommand = '' + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl start immich-server + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl start immich-machine-learning + ''; + }; + }; + + environment.systemPackages = with pkgs; + let + scripts = with pkgs; { + restore_immich_pg = writeShellScriptBin "restore_immich_pg" '' + ${pkgs.sudo}/bin/sudo -u postgres psql --dbname=immich < /var/backup/immich/postgres.sql + ''; + restore_immich = writeShellScriptBin "restore_immich" '' + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl stop immich-server + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl stop immich-machine-learning + + ${pkgs.sudo}/bin/sudo ${restic}/bin/restic -r /mnt/hdd/restic/immich restore latest --target / + + ${scripts.restore_immich_pg}/bin/restore_immich_pg + + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl start immich-server + ${pkgs.sudo}/bin/sudo ${pkgs.systemd}/bin/systemctl start immich-machine-learning + ''; + }; + in [ scripts.restore_immich_pg scripts.restore_immich ]; +} diff --git a/host/ark/service/radicale.nix b/host/ark/service/radicale.nix new file mode 100644 index 0000000..0a5016e --- /dev/null +++ b/host/ark/service/radicale.nix @@ -0,0 +1,9 @@ +{ ... }: { + services.radicale = { + enable = true; + settings = { + auth.type = "none"; + server.hosts = [ "0.0.0.0:5232" ]; + }; + }; +} diff --git a/host/ark/service/wakapi.nix b/host/ark/service/wakapi.nix new file mode 100644 index 0000000..4289050 --- /dev/null +++ b/host/ark/service/wakapi.nix @@ -0,0 +1,28 @@ +{ config, ... }: +{ + + nixpkgs.overlays = [ + (final: prev: { + wakapi = prev.wakapi.overrideAttrs (oldAttrs: rec { + src = final.fetchFromGitHub { + owner = "k2on"; + repo = "wakapi"; + rev = "theming"; + # hash = ""; + hash = "sha256-mbQ2cA9tbuDA5OXEP+qVfsrBC90budAzWE7x4oN6ypY="; + }; + # vendorHash = final.lib.fakeHash; + vendorHash = "sha256-lb6u9NQbB3bizIRbCRaB7Ngv9T5mAYtSl+g13gL7VEU="; + }); + }) + ]; + + services.wakapi = { + enable = true; + passwordSaltFile = config.sops.secrets."waka-password-salt".path; + settings = { + server.port = 3006; + app.avatar_url_template = "https://auth.koon.us/api/users/fbffa48a-faf7-4230-a89f-0da184f5948c/profile-picture.png"; + }; + }; +} diff --git a/host/ark/sops.nix b/host/ark/sops.nix new file mode 100644 index 0000000..049ad8d --- /dev/null +++ b/host/ark/sops.nix @@ -0,0 +1,50 @@ +{ config, ... }: +{ + sops = { + + defaultSopsFile = ../../secrets/sops/host/ark/default.yaml; + validateSopsFiles = false; + + age.keyFile = "/var/lib/sops-nix/key.txt"; + + secrets = { + "host_age_key" = { + path = "/var/lib/sops-nix/key.txt"; + }; + + "restic-password" = {}; + "tunnel-credentials" = {}; + "admin-password" = {}; + + "waka-password-salt" = { + owner = config.users.users.wakapi.name; + }; + + "photos/clientId" = { + sopsFile = ../../secrets/sops/host/ark/oauth.yaml; + }; + "photos/clientSecret" = { + sopsFile = ../../secrets/sops/host/ark/oauth.yaml; + }; + + "git/clientId" = { + sopsFile = ../../secrets/sops/host/ark/oauth.yaml; + owner = config.services.gitea.user; + }; + "git/clientSecret" = { + sopsFile = ../../secrets/sops/host/ark/oauth.yaml; + owner = config.services.gitea.user; + }; + + "docs/clientId" = { + sopsFile = ../../secrets/sops/host/ark/oauth.yaml; + owner = config.services.outline.user; + }; + "docs/clientSecret" = { + sopsFile = ../../secrets/sops/host/ark/oauth.yaml; + owner = config.services.outline.user; + }; + + }; + }; +} diff --git a/host/ark/user.nix b/host/ark/user.nix new file mode 100644 index 0000000..bcf2d5a --- /dev/null +++ b/host/ark/user.nix @@ -0,0 +1,12 @@ +{ pkgs, config, ... }: { + + sops.secrets.admin-password.neededForUsers = true; + users.mutableUsers = false; + + users.users.admin = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + hashedPasswordFile = config.sops.secrets.admin-password.path; + packages = with pkgs; [ tree vim tmux restic ]; + }; +} diff --git a/host/common/core/default.nix b/host/common/core/default.nix new file mode 100644 index 0000000..0cd2eee --- /dev/null +++ b/host/common/core/default.nix @@ -0,0 +1,9 @@ +{ inputs, ... }: { + time.timeZone = "America/New_York"; + + services.tailscale.enable = true; + + # security.sudo.wheelNeedsPassword = false; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; +} diff --git a/host/common/optional/browser.nix b/host/common/optional/browser.nix new file mode 100644 index 0000000..1080cfe --- /dev/null +++ b/host/common/optional/browser.nix @@ -0,0 +1,63 @@ +{ lib, ... }: { + programs.firefox = let + lock-false = { + Value = false; + Status = "locked"; + }; + lock-true = { + Value = true; + Status = "locked"; + }; + lock-empty-string = { + Value = ""; + Status = "locked"; + }; + in { + enable = true; + policies = { + DisableTelemetry = true; + DisableFirefoxStudies = true; + DontCheckDefaultBrowser = true; + DisablePocket = true; + DisableAccounts = true; + + Preferences = { + "extensions.pocket.enabled" = lock-false; + "browser.topsites.contile.enabled" = lock-false; + "browser.newtabpage.pinned" = lock-empty-string; + "browser.newtabpage.activity-stream.showSponsored" = lock-false; + "browser.newtabpage.activity-stream.system.showSponsored" = lock-false; + "browser.newtabpage.activity-stream.showSponsoredTopSites" = lock-false; + }; + + ExtensionSettings = { + "uBlock0@raymondhill.net" = { + install_url = + "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + installation_mode = "force_installed"; + }; + "{446900e4-71c2-419f-a6a7-df9c091e268b}" = { + install_url = + "https://addons.mozilla.org/firefox/downloads/latest/bitwarden-password-manager/latest.xpi"; + installation_mode = "force_installed"; + }; + "{d7742d87-e61d-4b78-b8a1-b469842139fa}" = { + install_url = + "https://addons.mozilla.org/firefox/downloads/latest/vimium-ff/latest.xpi"; + installation_mode = "force_installed"; + }; + "myallychou@gmail.com" = { + install_url = + "https://addons.mozilla.org/firefox/downloads/latest/youtube-recommended-videos/latest.xpi"; + installation_mode = "force_installed"; + }; + + }; + + UserMessaging = { + UrlbarInterventions = false; + SkipOnboarding = true; + }; + }; + }; +} diff --git a/host/common/optional/desktop.nix b/host/common/optional/desktop.nix new file mode 100644 index 0000000..eb4c1cd --- /dev/null +++ b/host/common/optional/desktop.nix @@ -0,0 +1,28 @@ +{ pkgs, ... }: { + services = { + desktopManager.plasma6.enable = true; + + displayManager.sddm.enable = true; + displayManager.sddm.wayland.enable = true; + }; + + environment.systemPackages = with pkgs; [ + kdePackages.discover # Optional: Install if you use Flatpak or fwupd firmware update sevice + kdePackages.kcalc # Calculator + kdePackages.kcharselect # Tool to select and copy special characters from all installed fonts + kdePackages.kcolorchooser # A small utility to select a color + kdePackages.kolourpaint # Easy-to-use paint program + kdePackages.ksystemlog # KDE SystemLog Application + kdePackages.sddm-kcm # Configuration module for SDDM + kdiff3 # Compares and merges 2 or 3 files or directories + kdePackages.isoimagewriter # Optional: Program to write hybrid ISO files onto USB disks + kdePackages.partitionmanager # Optional Manage the disk devices, partitions and file systems on your computer + kdePackages.merkuro + kdePackages.korganizer + kdePackages.kdepim-addons + hardinfo2 # System information and benchmarks for Linux systems + haruna # Open source video player built with Qt/QML and libmpv + wayland-utils # Wayland utilities + wl-clipboard # Command-line copy/paste utilities for Wayland + ]; +} diff --git a/host/common/optional/email.nix b/host/common/optional/email.nix new file mode 100644 index 0000000..f047774 --- /dev/null +++ b/host/common/optional/email.nix @@ -0,0 +1 @@ +{ ... }: { programs.thunderbird.enable = true; } diff --git a/host/common/optional/fonts.nix b/host/common/optional/fonts.nix new file mode 100644 index 0000000..6501c95 --- /dev/null +++ b/host/common/optional/fonts.nix @@ -0,0 +1,18 @@ +{ pkgs, ... }: { + fonts.packages = with pkgs; [ + monocraft + + (stdenv.mkDerivation { + name = "apple-color-emoji"; + src = fetchurl { + url = + "https://github.com/samuelngs/apple-emoji-linux/releases/download/v17.4/AppleColorEmoji.ttf"; + sha256 = "1wahjmbfm1xgm58madvl21451a04gxham5vz67gqz1cvpi0cjva8"; + }; + dontUnpack = true; + installPhase = '' + install -Dm644 $src $out/share/fonts/truetype/AppleColorEmoji.ttf + ''; + }) + ]; +} diff --git a/host/common/optional/locale.nix b/host/common/optional/locale.nix new file mode 100644 index 0000000..525ce99 --- /dev/null +++ b/host/common/optional/locale.nix @@ -0,0 +1,14 @@ +{ pkgs, ... }: { + i18n.defaultLocale = "en_US.UTF-8"; + i18n.supportedLocales = [ "en_US.UTF-8/UTF-8" "zh_CN.UTF-8/UTF-8" ]; + i18n.inputMethod = { + enabled = "fcitx5"; + fcitx5.addons = with pkgs; [ + # fcitx5-gtk # alternatively, kdePackages.fcitx5-qt + kdePackages.fcitx5-qt # alternatively, kdePackages.fcitx5-qt + fcitx5-chinese-addons # table input method support + fcitx5-nord # a color theme + ]; + }; + +} diff --git a/host/common/optional/yubikey.nix b/host/common/optional/yubikey.nix new file mode 100644 index 0000000..5c35151 --- /dev/null +++ b/host/common/optional/yubikey.nix @@ -0,0 +1,32 @@ +{ lib, pkgs, ... }: +{ + environment.systemPackages = with pkgs; [ + yubioath-flutter # gui + yubikey-manager # `ykman` + pam_u2f # yubikey with sudo + ]; + + services.pcscd.enable = true; + services.udev.packages = [ pkgs.yubikey-personalization ]; + + services.yubikey-agent.enable = true; + + security.pam = { + sshAgentAuth.enable = true; + u2f = { + enable = true; + settings = { + cue = true; + authFile = "/home/max/.config/Yubico/u2f_keys"; + }; + }; + services = { + login.u2fAuth = true; + sudo = { + u2fAuth = true; + sshAgentAuth = true; + }; + }; + + }; +} diff --git a/host/max/default.nix b/host/max/default.nix new file mode 100644 index 0000000..ec97a3a --- /dev/null +++ b/host/max/default.nix @@ -0,0 +1,116 @@ +{ pkgs, config, pkgs-unstable, ... }: { + imports = [ + ./hardware-configuration.nix + ../common/core/default.nix + ./user.nix + ./work.nix + ./sops.nix + + ../common/optional/yubikey.nix + + ../common/optional/browser.nix + ../common/optional/desktop.nix + ../common/optional/fonts.nix + ../common/optional/locale.nix + ../common/optional/email.nix + + ./zero-cache.nix + ]; + services.zero-cache.enable = false; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = false; + + boot.m1n1CustomLogo = ../../assets/logo.png; + + hardware = { + asahi = { + peripheralFirmwareDirectory = ./firmware; + useExperimentalGPUDriver = true; + experimentalGPUInstallMode = "replace"; + setupAsahiSound = true; + }; + }; + + # networking.hostName = "nixos"; # Define your hostname. + # Pick only one of the below networking options. + networking.networkmanager.enable = + true; # Easiest to use and most distros use this by default. + + hardware.bluetooth = { + enable = true; + powerOnBoot = true; + }; + + environment.variables = { + XDG_DATA_HOME = "/home/max/.local/share"; + GSK_RENDERER = "ngl"; + EDITOR = "nvim"; + }; + + programs.wireshark.enable = true; + programs.adb.enable = true; + + programs.kdeconnect.enable = true; + environment.systemPackages = with pkgs; [ + vim + git + wget + + # mpc + gurk-rs + libreoffice-qt + # ncmpcpp + + brave + + signal-desktop + gnupg + + (pass.withExtensions (exts: [ exts.pass-otp ])) + + pinentry + pinentry-curses + pinentry-qt + + zathura + + fzf + ffmpeg + ripgrep + unzip + zbar + tt + sc-im + libqalculate + librespeed-cli + + tea + + kubectl + cloudflared + # gcc + + prismlauncher + + gimp + inkscape + + wireshark + + # arm support + pkgs-unstable.sparrow + ]; + + programs.zsh.enable = true; + + programs.gnupg.agent = { + enable = true; + pinentryPackage = pkgs.pinentry-qt; + enableSSHSupport = true; + }; + + system.stateVersion = "25.05"; + +} diff --git a/host/max/firmware/all_firmware.tar.gz b/host/max/firmware/all_firmware.tar.gz new file mode 100755 index 0000000..a0b04f2 Binary files /dev/null and b/host/max/firmware/all_firmware.tar.gz differ diff --git a/host/max/firmware/kernelcache.release.mac14j b/host/max/firmware/kernelcache.release.mac14j new file mode 100755 index 0000000..9f95e2b Binary files /dev/null and b/host/max/firmware/kernelcache.release.mac14j differ diff --git a/host/max/hardware-configuration.nix b/host/max/hardware-configuration.nix new file mode 100644 index 0000000..0dcaf10 --- /dev/null +++ b/host/max/hardware-configuration.nix @@ -0,0 +1,35 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ "usb_storage" "sdhci_pci" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/664ec8c7-4c36-414c-bf99-c5346a4579dd"; + fsType = "ext4"; + }; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/02E4-1CF8"; + fsType = "vfat"; + options = [ "fmask=0022" "dmask=0022" ]; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.wlan0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; +} diff --git a/host/max/home.nix b/host/max/home.nix new file mode 100644 index 0000000..5288c94 --- /dev/null +++ b/host/max/home.nix @@ -0,0 +1,18 @@ +{ ... }: + +{ + imports = [ + ./home/sops.nix + ./home/ssh.nix + ./home/git.nix + + ./home/browser.nix + ./home/desktop.nix + ./home/nvim.nix + ./home/terminal.nix + ]; + + home.username = "max"; + home.homeDirectory = "/home/max"; + home.stateVersion = "25.05"; +} diff --git a/host/max/home/browser.nix b/host/max/home/browser.nix new file mode 100644 index 0000000..1038302 --- /dev/null +++ b/host/max/home/browser.nix @@ -0,0 +1,57 @@ +{ + programs.firefox = { + enable = true; + profiles = { + personal = { + id = 0; + name = "1. Personal"; + isDefault = true; + settings = { + "browser.search.defaultenginename" = "ddg"; + "browser.search.order.1" = "ddg"; + + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + }; + search = { + force = true; + default = "ddg"; + order = [ "ddg" "google" ]; + }; + userChrome = builtins.readFile ./browser/userChrome.css; + }; + work = { + id = 1; + name = "2. Work"; + settings = { + "browser.search.defaultenginename" = "ddg"; + "browser.search.order.1" = "ddg"; + + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + }; + search = { + force = true; + default = "ddg"; + order = [ "ddg" "google" ]; + }; + userChrome = builtins.readFile ./browser/userChrome.css; + }; + school = { + id = 2; + name = "3. School"; + settings = { + "browser.search.defaultenginename" = "ddg"; + "browser.search.order.1" = "ddg"; + + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + }; + search = { + force = true; + default = "ddg"; + order = [ "ddg" "google" ]; + }; + userChrome = builtins.readFile ./browser/userChrome.css; + }; + + }; + }; +} diff --git a/host/max/home/browser/userChrome.css b/host/max/home/browser/userChrome.css new file mode 100644 index 0000000..da75be5 --- /dev/null +++ b/host/max/home/browser/userChrome.css @@ -0,0 +1,6 @@ +.browserContainer > findbar { + top: 0 !important; + position: fixed !important; + width: 1000px !important; + right: 0 !important; +} diff --git a/host/max/home/desktop.nix b/host/max/home/desktop.nix new file mode 100644 index 0000000..61f21f8 --- /dev/null +++ b/host/max/home/desktop.nix @@ -0,0 +1,15 @@ +{ lib, ... }: { + programs.plasma = { + enable = true; + workspace = { wallpaper = "/home/max/bg.jpg"; }; + + kwin = { virtualDesktops = { number = 9; }; }; + + input = { + keyboard = { + options = [ "caps:escape" ]; + layouts = [ { layout = "us"; } { layout = "cn"; } ]; + }; + }; + }; +} diff --git a/host/max/home/git.nix b/host/max/home/git.nix new file mode 100644 index 0000000..ec16b17 --- /dev/null +++ b/host/max/home/git.nix @@ -0,0 +1,29 @@ +{ lib, ... }: +let + publicGitEmail = "22125083+k2on@users.noreply.github.com"; + publicKey = "/home/max/.ssh/id_maxkey.pub"; +in +{ + programs.git = { + enable = true; + userName = "Max Koon"; + userEmail = publicGitEmail; + extraConfig = { + init.defaultBranch = "main"; + + commit.gpgsign = true; + gpg.format = "ssh"; + user.signing.key = publicKey; + gpg.ssh.allowedSignersFile = "/home/max/.ssh/allowed_signers"; + }; + + signing = { + signByDefault = true; + key = publicKey; + }; + }; + + home.file.".ssh/allowed_signers".text = '' + ${publicGitEmail} ${lib.fileContents ../keys/id_maxkey.pub} + ''; +} diff --git a/host/max/home/nvim.nix b/host/max/home/nvim.nix new file mode 100644 index 0000000..8f8aae2 --- /dev/null +++ b/host/max/home/nvim.nix @@ -0,0 +1,262 @@ +{ pkgs, ... }: { + programs.nixvim = { + enable = true; + + colorschemes.one.enable = true; + + globals = { + mapleader = " "; + maplocalleader = " "; + }; + + clipboard = { + providers.wl-copy.enable = true; + register = "unnamedplus"; + }; + + opts = { + background = "light"; + relativenumber = true; + cursorline = true; + number = true; + + signcolumn = "yes"; + + updatetime = 250; + + list = true; + listchars.__raw = "{ tab = '» ', trail = '·', nbsp = '␣' }"; + + }; + + extraConfigLua = '' + require('stay-centered').setup({ enable = true }) + require('mini.ai').setup() + ''; + + keymaps = [ + { + mode = "n"; + key = ""; + action = "nohlsearch"; + } + { + mode = "n"; + key = "a"; + action.__raw = "function() require'harpoon':list():add() end"; + } + { + mode = "n"; + key = ""; + action.__raw = + "function() require'harpoon'.ui:toggle_quick_menu(require'harpoon':list()) end"; + } + { + mode = "n"; + key = ""; + action.__raw = "function() require'harpoon':list():select(1) end"; + } + { + mode = "n"; + key = ""; + action.__raw = "function() require'harpoon':list():select(2) end"; + } + { + mode = "n"; + key = ""; + action.__raw = "function() require'harpoon':list():select(3) end"; + } + { + mode = "n"; + key = ""; + action.__raw = "function() require'harpoon':list():select(4) end"; + } + + { + mode = "n"; + key = "b"; + action = "Neotree"; + } + { + mode = "n"; + key = "l"; + action = "Neotree reveal"; + } + ]; + + diagnostic.settings.virtual_text = true; + + userCommands.W.command = "w"; + + plugins = { + + sleuth.enable = true; + lastplace.enable = true; + + gitsigns.enable = true; + highlight-colors.enable = true; + todo-comments.enable = true; + # smear-cursor.enable = true; + goyo.enable = true; + + treesitter = { + enable = true; + settings = { + ensureInstalled = + [ "typescript" "rust" "php" "blade" "python" "nix" ]; + + highlight = { enable = true; }; + + indent = { enable = true; }; + }; + }; + + lsp = { + enable = true; + + servers = { + ts_ls.enable = true; + rust_analyzer = { + enable = true; + installCargo = true; + installRustc = true; + }; + clangd.enable = true; + tailwindcss.enable = true; + phpactor.enable = true; + pylsp.enable = true; + pyright.enable = true; + nixd.enable = true; + }; + + keymaps = { + extra = [ + { + mode = "n"; + key = "gd"; + action.__raw = "require('telescope.builtin').lsp_definitions"; + options = { desc = "LSP: [G]oto [D]efinition"; }; + } + { + mode = "n"; + key = "gr"; + action.__raw = "require('telescope.builtin').lsp_references"; + options = { desc = "LSP: [G]oto [R]eferences"; }; + } + ]; + + lspBuf = { + "." = { + mode = [ "n" "x" ]; + action = "code_action"; + desc = "Code action"; + }; + }; + }; + }; + + lazydev.enable = true; + luasnip.enable = true; + + telescope = { + enable = true; + + extensions = { + fzf-native.enable = true; + ui-select.enable = true; + }; + + keymaps = { + "sf" = { + mode = "n"; + action = "find_files"; + options = { desc = "[S]earch [F]iles"; }; + }; + "sk" = { + mode = "n"; + action = "live_grep"; + options = { desc = "[S]earch [S]tring"; }; + }; + }; + settings = { + extensions.__raw = + "{ ['ui-select'] = { require('telescope.themes').get_dropdown() } }"; + }; + }; + + cmp = { + enable = true; + settings = { + snippet = { + expand = '' + function(args) + require('luasnip').lsp_expand(args.body) + end + ''; + }; + + completion = { completeopt = "menu,menuone,noinsert"; }; + formatting = { + format = ''require("nvim-highlight-colors").format''; + }; + mapping = { + "" = "cmp.mapping.confirm { select = true }"; + "" = "cmp.mapping.select_next_item()"; + "" = "cmp.mapping.select_prev_item()"; + "" = "cmp.mapping.select_next_item()"; + "" = "cmp.mapping.select_prev_item()"; + "" = "cmp.mapping.select_next_item()"; + "" = "cmp.mapping.select_prev_item()"; + }; + sources = [ + { + name = "lazydev"; + + group_index = 0; + } + { name = "nvim_lsp"; } + { name = "luasnip"; } + { name = "path"; } + { name = "nvim_lsp_signature_help"; } + ]; + }; + }; + + harpoon = { + enable = true; + settings.settings = { save_on_toggle = true; }; + }; + neo-tree = { + enable = true; + extraOptions = { + filesystem = { + filtered_items = { + visible = true; + }; + }; + }; + }; + wakatime.enable = true; + autoclose.enable = true; + ts-autotag.enable = true; + spider = { + enable = true; + extraOptions = { + subwordMovement = true; + skipInsignificantPunctuation = false; + }; + keymaps = { + motions = { + "w" = "w"; + "e" = "e"; + "b" = "b"; + }; + }; + }; + + }; + + extraPlugins = with pkgs.vimPlugins; [ stay-centered-nvim mini-ai ]; + + }; +} diff --git a/host/max/home/sops.nix b/host/max/home/sops.nix new file mode 100644 index 0000000..7cb30c0 --- /dev/null +++ b/host/max/home/sops.nix @@ -0,0 +1,19 @@ +{ ... }: +{ + sops = { + + age.keyFile = "/home/max/.config/sops/age/keys.txt"; + + defaultSopsFile = ../../../secrets/sops/host/max/default.yaml; + validateSopsFiles = false; + + secrets = { + "ssh_keys/max" = { + path = "/home/max/.ssh/id_maxkey"; + }; + "waka_config" = { + path = "/home/max/.wakatime.cfg"; + }; + }; + }; +} diff --git a/host/max/home/ssh.nix b/host/max/home/ssh.nix new file mode 100644 index 0000000..bf13c78 --- /dev/null +++ b/host/max/home/ssh.nix @@ -0,0 +1,45 @@ +{ ... }: +{ + programs.ssh = { + enable = true; + + extraConfig = '' + Host m1 + HostName m1 + User admin + + Host surface + HostName surface + User admin + + Host ark + HostName ark + User admin + + Host pi + HostName 192.168.0.143 + User admin + + Host ssh.koon.us + HostName ssh.koon.us + ProxyCommand cloudflared access ssh --hostname %h + User git + + AddKeysToAgent yes + ''; + + matchBlocks = { + "git" = { + host = "github.com"; + user = "git"; + identityFile = [ + "~/.ssh/id_maxkey" + ]; + }; + }; + }; + + home.file = { + ".ssh/id_maxkey.pub".source = ../keys/id_maxkey.pub; + }; +} diff --git a/host/max/home/terminal.nix b/host/max/home/terminal.nix new file mode 100644 index 0000000..83b17d5 --- /dev/null +++ b/host/max/home/terminal.nix @@ -0,0 +1,69 @@ +{ pkgs, ... }: { + programs.alacritty = { + enable = true; + theme = "one_light"; + settings = { + font = { + normal.family = "Monocraft"; + size = 10; + }; + }; + }; + + programs.lf = { enable = true; }; + + programs.tmux = { + enable = true; + mouse = true; + keyMode = "vi"; + shell = "${pkgs.zsh}/bin/zsh"; + extraConfig = '' + set -g status-style bg=white + + bind h select-pane -L + bind j select-pane -D + bind k select-pane -U + bind l select-pane -R + ''; + }; + + programs.zsh = { + enable = true; + enableCompletion = true; + autosuggestion = { + enable = true; + highlight = "fg=#bbbbbb"; + }; + syntaxHighlighting.enable = true; + dotDir = ".config/zsh"; + autocd = true; + + # initExtra = builtins.readFile ./zsh-nix-shell.zsh; + + shellAliases = { + ll = "ls -la --color"; + v = "nvim"; + vi = "nvim"; + vim = "nvim"; + + k = "kubectl"; + + tt = "tt --theme one-light -n 10"; + + bible = "nvim ~/bible.txt -R"; + notes = "nvim ~/notes"; + home = "sudo nvim /etc/nixos/home.nix"; + wttr = "curl wttr.in/Clemson"; + + docx-to-pdf = "libreoffice --headless --convert-to pdf"; + }; + + plugins = [{ + name = "vi-mode"; + src = pkgs.zsh-vi-mode; + file = "share/zsh-vi-mode/zsh-vi-mode.plugin.zsh"; + }]; + }; + + programs.starship = { enable = true; }; +} diff --git a/host/max/keys/id_maxkey.pub b/host/max/keys/id_maxkey.pub new file mode 100644 index 0000000..4826bac --- /dev/null +++ b/host/max/keys/id_maxkey.pub @@ -0,0 +1 @@ +sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIMywmwW37vjQSd9lqYh9IhGYce9Bi24sTyG3zffpdaJrAAAABHNzaDo= max@koon diff --git a/host/max/sops.nix b/host/max/sops.nix new file mode 100644 index 0000000..5018a99 --- /dev/null +++ b/host/max/sops.nix @@ -0,0 +1,25 @@ +{ config, lib, ... }: +{ + sops = { + + age.keyFile = if builtins.pathExists /var/lib/sops-nix/key.txt then + "/var/lib/sops-nix/key.txt" + else + "/home/max/.config/sops/age/keys.txt" # temp decrypt key + ; + + defaultSopsFile = ../../secrets/sops/host/max/default.yaml; + validateSopsFiles = false; + + secrets = { + "host_age_key" = { + path = "/var/lib/sops-nix/key.txt"; + }; + "yubico/u2f_keys" = { + owner = config.users.users.max.name; + inherit (config.users.users.max) group; + path = "/home/max/.config/Yubico/u2f_keys"; + }; + }; + }; +} diff --git a/host/max/user.nix b/host/max/user.nix new file mode 100644 index 0000000..ca7dd93 --- /dev/null +++ b/host/max/user.nix @@ -0,0 +1,13 @@ +{ pkgs, config, ... }: { + + sops.secrets.max-password.neededForUsers = true; + users.mutableUsers = false; + + users.users.max = { + isNormalUser = true; + hashedPasswordFile = config.sops.secrets.max-password.path; + extraGroups = [ "wheel" "networkmanager" "video" "wireshark" "kvm" ]; + packages = with pkgs; [ tree ]; + shell = pkgs.zsh; + }; +} diff --git a/host/max/work.nix b/host/max/work.nix new file mode 100644 index 0000000..966f70b --- /dev/null +++ b/host/max/work.nix @@ -0,0 +1,31 @@ +{ config, secrets, ... }: { + + + services.openvpn.servers = { + ris = { + config = "config /etc/openvpn/ris/config.ovpn "; + updateResolvConf = true; + autoStart = false; + }; + }; + + sops.secrets = { + "ris-vpn/key" = { + sopsFile = ../../secrets/sops/host/max/work.yaml; + owner = config.users.users.root.name; + inherit (config.users.users.root) group; + path = "/etc/openvpn/ris/vpnclient.rismedia.com.key"; + }; + }; + + environment.etc."openvpn/ris/config.ovpn" = { + text = secrets.work.ris.vpn.config; + }; + environment.etc."openvpn/ris/vpnclient.rismedia.com.crt" = { + text = secrets.work.ris.vpn.crt; + }; + + networking.extraHosts = '' + ${secrets.work.ris.extraHosts} + ''; +} diff --git a/host/max/zero-cache.nix b/host/max/zero-cache.nix new file mode 100644 index 0000000..90ee2fc --- /dev/null +++ b/host/max/zero-cache.nix @@ -0,0 +1,84 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.services.zero-cache; + inherit (lib) + mkEnableOption + mkIf + ; + + litestream = pkgs.buildGoModule rec { + pname = "litestream-zero"; + version = "0.3.13+z0.0.6"; + + src = pkgs.fetchFromGitHub { + owner = "rocicorp"; + repo = "litestream"; + rev = "zero@v0.0.6"; + sha256 = "sha256-sBKmz2fBoYzYi1kUVeiugLBLPdqHc+fXCBkI8Cttakg="; + }; + + vendorHash = "sha256-PlfDJbhzbH/ZgtQ35KcB6HtPEDTDgss7Lv8BcKT/Dgg="; + + ldflags = [ + "-s" + "-w" + "-X main.Version=${version}" + + # nix does not like to build with this + # "-extldflags '-static'" + + ]; + + doCheck = false; + + tags = [ + "osusergo" + "netgo" + "sqlite_omit_load_extension" + ]; + + subPackages = [ "cmd/litestream" ]; + }; + + zero-cache = pkgs.buildNpmPackage rec { + name = "zero-cache"; + src = pkgs.fetchFromGitHub { + owner = "rocicorp"; + repo = "mono"; + rev = "zero/v0.23.2025081401"; + hash = "sha256-NQcG/vnfUmle/6eNXXmnMqzNvniK8R/mO5RYdMX9pnE="; + }; + + npmDepsHash = "sha256-9vX9eODN8AfcLcMSjm6KzAAUmPIHfe2BILt0juya5us="; + makeCacheWritable = true; + npmFlags = [ "--legacy-peer-deps" ]; + }; + +in +{ + options = { + services.zero-cache = { + enable = mkEnableOption "Zero-cache, the server component of the Zero sync engine."; + }; + }; + + config = mkIf cfg.enable { + systemd.services.zero-cache = { + description = "Zero Cache"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + ExecStart = "${zero-cache}/bin/zero-cache"; + RemainAfterExit = true; + }; + }; + }; +} + diff --git a/infra/.terraform.lock.hcl b/infra/.terraform.lock.hcl new file mode 100644 index 0000000..aa0ed95 --- /dev/null +++ b/infra/.terraform.lock.hcl @@ -0,0 +1,16 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/local" { + version = "2.5.3" + hashes = [ + "h1:6ADVoHtXiWFhClkKa1vnBycJxqnL0GjHMZAQipa4SEU=", + ] +} + +provider "registry.terraform.io/trozz/pocketid" { + version = "0.1.5" + hashes = [ + "h1:egwnwPepmLF/OAE96D7RxGlsXYlUVZi3CuFhAH69iVE=", + ] +} diff --git a/infra/config.nix b/infra/config.nix new file mode 100644 index 0000000..b48da62 --- /dev/null +++ b/infra/config.nix @@ -0,0 +1,93 @@ +{ + terraform = { + required_providers = { + pocketid = { + source = "trozz/pocketid"; + }; + }; + }; + provider.pocketid = { + base_url = "https://auth.koon.us"; + api_token = "\${var.pocketid_api_token}"; + }; + + variable.pocketid_api_token = { + type = "string"; + sensitive = true; + description = "PocketID API token"; + }; + + resource.pocketid_client.photos = { + name = "Photos"; + callback_urls = [ + "https://photos.koon.us/auth/login" + "https://photos.koon.us/user-settings" + "app.immich:///oauth-callback" + ]; + is_public = false; + pkce_enabled = false; + }; + + resource.pocketid_client.git = { + name = "Git"; + callback_urls = [ + "https://git.koon.us/user/oauth2/KoonFamily/callback" + ]; + is_public = false; + pkce_enabled = false; + }; + + resource.pocketid_client.docs = { + name = "Docs"; + callback_urls = [ + "https://docs.koon.us/*" + ]; + is_public = false; + pkce_enabled = false; + }; + + output = { + photos_client_id = { + value = "\${pocketid_client.photos.id}"; + }; + + photos_client_secret = { + value = "\${pocketid_client.photos.client_secret}"; + sensitive = true; + }; + + git_client_id = { + value = "\${pocketid_client.git.id}"; + }; + + git_client_secret = { + value = "\${pocketid_client.git.client_secret}"; + sensitive = true; + }; + + docs_client_id = { + value = "\${pocketid_client.docs.id}"; + }; + + docs_client_secret = { + value = "\${pocketid_client.docs.client_secret}"; + sensitive = true; + }; + }; + + resource.local_file.oauth_config = { + filename = "\${path.module}/../secrets/sops/oauth.yaml"; + content = '' + photos: + clientId: ''${pocketid_client.photos.id} + clientSecret: ''${pocketid_client.photos.client_secret} + git: + clientId: ''${pocketid_client.git.id} + clientSecret: ''${pocketid_client.git.client_secret} + docs: + clientId: ''${pocketid_client.docs.id} + clientSecret: ''${pocketid_client.docs.client_secret} + ''; + file_permission = "0600"; + }; +} diff --git a/justfile b/justfile new file mode 100644 index 0000000..edb98a4 --- /dev/null +++ b/justfile @@ -0,0 +1,31 @@ +default: + @just --list + +list: + @just --list + +add-secrets: + git -C secrets add . + +rebuild: + just add-secrets + + git add . + sudo nixos-rebuild switch --flake '.?submodules=1#max' + +rebuild-ark: + just add-secrets + + git add . + nixos-rebuild --flake '.?submodules=1#ark' --build-host admin@100.98.252.15 --target-host admin@100.98.252.15 --use-remote-sudo --fast switch + +push-secrets: + just add-secrets + + git -C secrets commit + git -C secrets push + +push: + git add . + git commit + git push diff --git a/secrets b/secrets new file mode 160000 index 0000000..7a4d9d5 --- /dev/null +++ b/secrets @@ -0,0 +1 @@ +Subproject commit 7a4d9d5e4783115c397624304930ce1b79422a4c diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..f476c23 --- /dev/null +++ b/shell.nix @@ -0,0 +1,10 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + packages = [ + pkgs.age + pkgs.ssh-to-age + pkgs.sops + pkgs.just + ]; +}