diff --git a/.gitignore b/.gitignore deleted file mode 100644 index fd099b8..0000000 --- a/.gitignore +++ /dev/null @@ -1,74 +0,0 @@ -### Linux gitignore ### -*~ - -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* - -# Metadata left by Dolphin file manager, which comes with KDE Plasma -.directory - -# Linux trash folder which might appear on any partition or disk -.Trash-* - -# .nfs files are created when an open file is removed but is still being accessed -.nfs* - -# Log files created by default by the nohup command -nohup.out - -### MacOS gitignore ### -# General -.DS_Store -__MACOSX/ -.AppleDouble -.LSOverride -Icon[] - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### Nix gitignore ### -# Ignore build outputs from performing a nix-build or `nix build` command -result -result-* - -# Ignore automatically generated direnv output -.direnv - -### Vim gitignore ### -# Swap -[._]*.s[a-v][a-z] -# comment out the next line if you don't need vector files -!*.svg -[._]*.sw[a-p] -[._]s[a-rt-v][a-z] -[._]ss[a-gi-z] -[._]sw[a-p] - -# Session -Session.vim -Sessionx.vim - -# Temporary -.netrwhist -*~ -# Auto-generated tag files -tags -# Persistent undo -[._]*.un~ diff --git a/README.md b/README.md deleted file mode 100644 index d650f9b..0000000 --- a/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# nix-dotfiles - -System and home configurations for my machines. - -| Machine | Role | OS | Arch | System config tool | Home config tool | -| -------- | --------------- | ------ | ------- | --------------------------- | ---------------- | -| anderson | server | linux | x86_64 | dpkg/Docker (not this repo) | home-manager | -| bosephus | server | linux | x86_64 | NixOS | home-manager | -| mcentire | server | linux | x86_64 | NixOS | home-manager | -| corianne | MacBook | darwin | aarch64 | nix-darwin | home-manager | -| odyssey | workstation | linux | x86_64 | Ansible | home-manager | - -## Quickstart - -### Home dotfiles - -> ![WARNING] -> Fedora systems will set this up automagically via Ansible. Follow the -[Fedora quickstart] instructions. - -Ensure Nix is installed, with the `nix` command and flakes enabled. I try to use -the [Determinate Nix installer] (with upstream Nix) to install Nix with these -options turned on by default. - -```bash -curl -fsSL https://install.determinate.systems/nix | sh -s -- install -``` - -Once Nix is installed, clone the repository to `~/.config/home-manager` and -initiate home-manager. - -```bash -git clone https://code.millironx.com/millironx/nix-dotfiles.git ~/.config/home-manager -nix run home-manager -- switch --flake ~/.config/home-manager#$USER@$(hostname -s) -``` - -In the case that the host has not been assigned a configuration within this repo -yet, pick a hostname with the same system OS, arch, and role as the target -system to get temporary dotfiles up and running. - -```bash -nix run home-manager -- switch --flake ~/.config/home-manager#millironx@anderson -``` - -Once an SSH (with or without GPG) key has been setup and added to the authorized -keys of the git server, switch the upstream to track an authorized (i.e. -read/write) version of the repo. - -```bash -cd ~/.config/home-manager -git remote set-url origin git@code.millironx.com:millironx/nix-dotfiles.git -cd - -``` - -### NixOS - -Switching to a flake-based config requires running as root. All of the following -commands are assumed to be running as root. - -Ensure that the `nix` command and flakes are enabled. - -```bash -sed -i '/^}/i nix.settings.experimental-features = [ "nix-command" "flakes" ];' /etc/nixos/configuration.nix -nixos-rebuild switch -``` - -> ![NOTE] -> To allow secret decryption in the system, the *machine*-specific SSH key must -> be added to the publicKeys attribute of all applicable secrets, and the -> `hardware-configuration.nix` file must be added to git. Copying arbitrary -> strings like SSH keys or disk UUIDs between systems can be painful, so it might -> be worth setting up the [home dotfiles] immediately after enabling flakes, -> then running these steps on the same machine to avoid typos. Alternatively, I -> might someday be smart enough to create an installer CD that automagically -> sets this up for me. - -Get the machine-specific public SSH key. - -```bash -cat /etc/ssh/ssh_host_ed25519_key.pub -``` - -On a separate machine, add the machine's SSH key to `./secrets.nix` and assign -it to any secrets it would need. - -```nix -let - bosephus-host = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxTfeg+GZsfmG8TuEV1xW1gXknAIKzZ3UjZ3guRY+EW root@nixos"; - bosephus-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaDPqRJHoqgY2pseh/mnhjaGWXprHk2s5I52LhHpHcF millironx@bosephus"; - odyssey-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; - - system-administrators = [ - bosephus-millironx - odyssey-millironx - ]; -in { - "secrets/network-information.age".publicKeys = system-administrators - ++ [ bosephus-host ]; -} -``` - -Rekey the secrets, and push the updated secrets to the upstream repo. - -```bash -nix run github:ryantm/agenix -- --rekey -git add secrets.nix secrets/* -git commit -m "added $NEW_HOST to secrets" -git push -``` - -Copy the target machine's `hardware-configuration.nix` file to this repo's -`./systems/linux/hardware-configuration/$NEW_HOST.nix`, and be sure to update -the configuration to import its own `hardware-configuration`. - -```bash -cp /etc/nixos/hardware-configuration.nix ./systems/linux/hardware-configuration/$NEW_HOST.nix -``` - -```nix -{ config, pkgs, ... }: { - imports = [ - ./hardware-configuration/bosephus.nix - ]; -} -``` - -Commit and push the hardware configuration to the upstream repo. - -```bash -git add systems/linux/* -git commit -m "added $NEW_HOST hardware configuration" -git push -``` - -Now switch to the flake by pulling and switching in one step. - - -```bash -nixos-rebuild switch --flake git+https://code.millironx.com/millironx/nix-dotfiles#$(hostname -s) -``` - -### Fedora - -Fedora systems are managed using Ansible. - -TODO - -## Home settings - -TODO - -[determinate nix installer]: https://github.com/DeterminateSystems/nix-installer -[fedora quickstart]: #fedora -[home dotfiles]: #home-dotfiles diff --git a/bin/secret-translator.jl b/bin/secret-translator.jl deleted file mode 100644 index c5dee39..0000000 --- a/bin/secret-translator.jl +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env julia -using TOML: TOML - -@show ENV["PATH"] - -function remove_podman_secrets() - run(`podman secret rm --all`) - return nothing -end #function - -function create_podman_secret(name, secret) - run( - addenv( - `podman secret create --env=true --replace $name SECRET`, - Dict("SECRET" => secret), - ), - ) - return nothing -end #function - -function parse_toml_secrets(file) - foreach(f -> create_podman_secret(f[1], f[2]), TOML.parsefile(file)) - return nothing -end #function - -function main() - remove_podman_secrets() - foreach(parse_toml_secrets, ARGS) - return 0 -end #function - -main() diff --git a/dotfiles/dolphinrc b/dotfiles/dolphinrc new file mode 100644 index 0000000..2f11ee4 --- /dev/null +++ b/dotfiles/dolphinrc @@ -0,0 +1,24 @@ +MenuBar=Disabled + +[DetailsMode] +PreviewSize=16 + +[General] +BrowseThroughArchives=true +EditableUrl=true +GlobalViewProps=false +ShowFullPath=true +ShowStatusBar=FullWidth +ShowZoomSlider=true +Version=202 + + +[KFileDialog Settings] +Places Icons Auto-resize=false +Places Icons Static Size=22 + +[MainWindow] +MenuBar=Disabled + +[PreviewSettings] +Plugins=audiothumbnail,avif,blenderthumbnail,comicbookthumbnail,cursorthumbnail,djvuthumbnail,ebookthumbnail,exrthumbnail,directorythumbnail,fontthumbnail,imagethumbnail,jpegthumbnail,jxl,kraorathumbnail,windowsexethumbnail,windowsimagethumbnail,mobithumbnail,opendocumentthumbnail,gsthumbnail,rawthumbnail,svgthumbnail,gdk-pixbuf-thumbnailer,ffmpegthumbs,gsf-office diff --git a/dotfiles/konsolerc b/dotfiles/konsolerc new file mode 100644 index 0000000..7f417e8 --- /dev/null +++ b/dotfiles/konsolerc @@ -0,0 +1,9 @@ +[Desktop Entry] +DefaultProfile=My Default.profile + +[MainWindow] +StatusBar=Disabled +ToolBarsMovable=Disabled + +[UiSettings] +ColorScheme=Default diff --git a/flake.lock b/flake.lock index 6141529..a1cd1d3 100644 --- a/flake.lock +++ b/flake.lock @@ -14,11 +14,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1762618334, - "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", + "lastModified": 1754433428, + "narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=", "owner": "ryantm", "repo": "agenix", - "rev": "fcdea223397448d35d9b31f798479227e80183f6", + "rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d", "type": "github" }, "original": { @@ -27,6 +27,27 @@ "type": "github" } }, + "crowdsec": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1752497357, + "narHash": "sha256-9epXn1+T6U4Kfyw8B9zMzbERxDB3VfaPXhVebtai6CE=", + "ref": "refs/heads/main", + "rev": "84db7dcea77f7f477d79e69e35fb0bb560232667", + "revCount": 42, + "type": "git", + "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" + }, + "original": { + "type": "git", + "url": "https://codeberg.org/kampka/nix-flake-crowdsec.git" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": [ @@ -48,6 +69,23 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, "home-manager": { "inputs": { "nixpkgs": [ @@ -55,16 +93,16 @@ ] }, "locked": { - "lastModified": 1764613336, - "narHash": "sha256-L979az28t/+SXvYw9qhOno5HLlDwkZOpz6LzCLnjmRM=", + "lastModified": 1756679287, + "narHash": "sha256-Xd1vOeY9ccDf5VtVK12yM0FS6qqvfUop8UQlxEB+gTQ=", "owner": "nix-community", "repo": "home-manager", - "rev": "f3902b5d8767985680875ad86d028371100faeb3", + "rev": "07fc025fe10487dd80f2ec694f1cd790e752d0e8", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-25.11", + "ref": "release-25.05", "repo": "home-manager", "type": "github" } @@ -76,117 +114,59 @@ ] }, "locked": { - "lastModified": 1764161084, - "narHash": "sha256-HN84sByg9FhJnojkGGDSrcjcbeioFWoNXfuyYfJ1kBE=", + "lastModified": 1757432263, + "narHash": "sha256-qHn+/0+IOz5cG68BZUwL9BV3EO/e9eNKCjH3+N7wMdI=", "owner": "LnL7", "repo": "nix-darwin", - "rev": "e95de00a471d07435e0527ff4db092c84998698e", + "rev": "1fef4404de4d1596aa5ab2bd68078370e1b9dcdb", "type": "github" }, "original": { "owner": "LnL7", - "ref": "nix-darwin-25.11", + "ref": "nix-darwin-25.05", "repo": "nix-darwin", "type": "github" } }, - "nix-rosetta-builder": { - "inputs": { - "nixos-generators": "nixos-generators", - "nixpkgs": [ - "nixpkgs-darwin" - ] - }, - "locked": { - "lastModified": 1756177999, - "narHash": "sha256-aSbB7/jrt7ujiJ55f2uGhOo+usGxVSkqbAMVgg2jDls=", - "owner": "cpick", - "repo": "nix-rosetta-builder", - "rev": "ebb7162a975074fb570a2c3ac02bc543ff2e9df4", - "type": "github" - }, - "original": { - "owner": "cpick", - "repo": "nix-rosetta-builder", - "type": "github" - } - }, - "nixlib": { - "locked": { - "lastModified": 1736643958, - "narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" - } - }, - "nixos-generators": { - "inputs": { - "nixlib": "nixlib", - "nixpkgs": [ - "nix-rosetta-builder", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1737057290, - "narHash": "sha256-3Pe0yKlCc7EOeq1X/aJVDH0CtNL+tIBm49vpepwL1MQ=", - "owner": "nix-community", - "repo": "nixos-generators", - "rev": "d002ce9b6e7eb467cd1c6bb9aef9c35d191b5453", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixos-generators", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1764522689, - "narHash": "sha256-SqUuBFjhl/kpDiVaKLQBoD8TLD+/cTUzzgVFoaHrkqY=", + "lastModified": 1757545623, + "narHash": "sha256-mCxPABZ6jRjUQx3bPP4vjA68ETbPLNz9V2pk9tO7pRQ=", "owner": "nixos", "repo": "nixpkgs", - "rev": "8bb5646e0bed5dbd3ab08c7a7cc15b75ab4e1d0f", + "rev": "8cd5ce828d5d1d16feff37340171a98fc3bf6526", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-25.11", + "ref": "nixos-25.05", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-darwin": { "locked": { - "lastModified": 1764572236, - "narHash": "sha256-hLp6T/vKdrBQolpbN3EhJOKTXZYxJZPzpnoZz+fEGlE=", + "lastModified": 1757590060, + "narHash": "sha256-EWwwdKLMZALkgHFyKW7rmyhxECO74+N+ZO5xTDnY/5c=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b0924ea1889b366de6bb0018a9db70b2c43a15f8", + "rev": "0ef228213045d2cdb5a169a95d63ded38670b293", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixpkgs-25.11-darwin", + "ref": "nixpkgs-25.05-darwin", "repo": "nixpkgs", "type": "github" } }, "nixpkgs-unstable": { "locked": { - "lastModified": 1764642553, - "narHash": "sha256-mvbFFzVBhVK1FjyPHZGMAKpNiqkr7k++xIwy+p/NQvA=", + "lastModified": 1757034884, + "narHash": "sha256-PgLSZDBEWUHpfTRfFyklmiiLBE1i1aGCtz4eRA3POao=", "owner": "nixos", "repo": "nixpkgs", - "rev": "f720de59066162ee879adcc8c79e15c51fe6bfb4", + "rev": "ca77296380960cd497a765102eeb1356eb80fed0", "type": "github" }, "original": { @@ -204,11 +184,11 @@ ] }, "locked": { - "lastModified": 1764683664, - "narHash": "sha256-Mr5HKf/bjAJ8H7/H0qJSk2BEV/OILkDIFKrGK0dUVUk=", + "lastModified": 1757647720, + "narHash": "sha256-qf/utP3d1qBDl5R4yWUCt7E7CHTkw2NY8BEsS7lJ0dc=", "owner": "nix-community", "repo": "NUR", - "rev": "b8b40e258cf4c959b06b7322648c87674633629b", + "rev": "ef767aa25f9f917fe25d3848051f0e54ae42349f", "type": "github" }, "original": { @@ -227,11 +207,11 @@ ] }, "locked": { - "lastModified": 1763909441, - "narHash": "sha256-56LwV51TX/FhgX+5LCG6akQ5KrOWuKgcJa+eUsRMxsc=", + "lastModified": 1756632588, + "narHash": "sha256-ydam6eggXf3ZwRutyCABwSbMAlX+5lW6w1SVZQ+kfSo=", "owner": "nix-community", "repo": "plasma-manager", - "rev": "b24ed4b272256dfc1cc2291f89a9821d5f9e14b4", + "rev": "d47428e5390d6a5a8f764808a4db15929347cd77", "type": "github" }, "original": { @@ -242,11 +222,11 @@ }, "quadlet-nix": { "locked": { - "lastModified": 1763141753, - "narHash": "sha256-XAHkOkLEWbRQZ6t/SowwOukrUfIneNQOC/UEQlTaPBU=", + "lastModified": 1754008153, + "narHash": "sha256-MYT1mDtSkiVg343agxgBFsnuNU3xS8vRy399JXX1Vw0=", "owner": "SEIAROTg", "repo": "quadlet-nix", - "rev": "211b5c626cf9ea91403b510e2ac5ca03a7194566", + "rev": "1b2d27d460d8c7e4da5ba44ede463b427160b5c4", "type": "github" }, "original": { @@ -258,9 +238,9 @@ "root": { "inputs": { "agenix": "agenix", + "crowdsec": "crowdsec", "home-manager": "home-manager", "nix-darwin": "nix-darwin", - "nix-rosetta-builder": "nix-rosetta-builder", "nixpkgs": "nixpkgs", "nixpkgs-darwin": "nixpkgs-darwin", "nixpkgs-unstable": "nixpkgs-unstable", @@ -278,11 +258,11 @@ }, "locked": { "dir": "pkgs/firefox-addons", - "lastModified": 1764648280, - "narHash": "sha256-xniOnxIx/qhm+maO4mb9BZ7FytcUhNeTm1Y/QBjNf8o=", + "lastModified": 1757591399, + "narHash": "sha256-OlvNzfsqDok0y5PDY+2dK5T53GsxAdm1YGdYHjxAiHM=", "owner": "rycee", "repo": "nur-expressions", - "rev": "119826bd51ad1a8012e0585f3a073571a35a812e", + "rev": "b7d4f61ce9db44ba82859e15f6e1c175959948e3", "type": "gitlab" }, "original": { @@ -306,6 +286,21 @@ "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" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 3b4f7b7..a5b90d9 100644 --- a/flake.nix +++ b/flake.nix @@ -3,8 +3,8 @@ inputs = { # Specify the source of Home Manager and Nixpkgs. - nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; - nixpkgs-darwin.url = "github:nixos/nixpkgs/nixpkgs-25.11-darwin"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + nixpkgs-darwin.url = "github:nixos/nixpkgs/nixpkgs-25.05-darwin"; nixpkgs-unstable.url = "github:nixos/nixpkgs/nixpkgs-unstable"; # Inputs for both darwin and linux systems @@ -17,7 +17,7 @@ }; }; home-manager = { - url = "github:nix-community/home-manager/release-25.11"; + url = "github:nix-community/home-manager/release-25.05"; inputs.nixpkgs.follows = "nixpkgs"; }; nur = { @@ -30,6 +30,10 @@ }; # Linux-specific inputs + crowdsec = { + url = "git+https://codeberg.org/kampka/nix-flake-crowdsec.git"; + inputs.nixpkgs.follows = "nixpkgs"; + }; plasma-manager = { url = "github:nix-community/plasma-manager"; inputs = { @@ -41,28 +45,23 @@ # Darwin-specific inputs nix-darwin = { - url = "github:LnL7/nix-darwin/nix-darwin-25.11"; - inputs.nixpkgs.follows = "nixpkgs-darwin"; - }; - nix-rosetta-builder = { - url = "github:cpick/nix-rosetta-builder"; + url = "github:LnL7/nix-darwin/nix-darwin-25.05"; inputs.nixpkgs.follows = "nixpkgs-darwin"; }; }; outputs = { self, nix-darwin, nixpkgs, nixpkgs-darwin, nixpkgs-unstable - , home-manager, agenix, rycee-nurpkgs, nur, plasma-manager, quadlet-nix - , nix-rosetta-builder, ... }: + , home-manager, agenix, rycee-nurpkgs, nur, crowdsec, plasma-manager + , quadlet-nix, ... }: let mkHomeConfiguration = { hostname, arch ? "x86_64", os ? "linux" , desktop ? false, extraModules ? [ ] }: let system = "${arch}-${os}"; - syspkg = if os == "darwin" then nixpkgs-darwin else nixpkgs; - pkgs = import syspkg { + pkgs = import nixpkgs { inherit system; config.allowUnfree = true; - overlays = [ nur.overlays.default agenix.overlays.default ]; + overlays = [ nur.overlays.default ]; }; pkgs-unstable = import nixpkgs-unstable { inherit system; @@ -81,7 +80,7 @@ ] ++ (if desktop then [ ./homes/desktop.nix ] else [ ]) ++ (if (desktop && os == "linux") then [ ./homes/linux-desktop.nix - plasma-manager.homeModules.plasma-manager + plasma-manager.homeManagerModules.plasma-manager ] else [ ]) ++ extraModules; extraSpecialArgs = { @@ -102,12 +101,16 @@ "millironx@anderson" = mkHomeConfiguration { hostname = "anderson"; }; - "millironx@mcentire" = mkHomeConfiguration { hostname = "mcentire"; }; - "millironx@bosephus" = mkHomeConfiguration { hostname = "bosephus"; }; "tchristensen@beocat" = mkHomeConfiguration { hostname = "beocat"; }; + "millironx@harmony" = mkHomeConfiguration { + hostname = "harmony"; + arch = "aarch64"; + desktop = true; + }; + "millironx@odyssey" = mkHomeConfiguration { hostname = "odyssey"; desktop = true; @@ -123,11 +126,8 @@ }; agenix = agenix; }; - modules = [ - ./systems/darwin/corianne.nix - agenix.darwinModules.default - nix-rosetta-builder.darwinModules.default - ]; + modules = + [ ./systems/darwin/corianne.nix agenix.darwinModules.default ]; }; nixosConfigurations = { @@ -142,14 +142,13 @@ "mcentire" = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; - specialArgs = { - home-manager-quadlet-nix = quadlet-nix.homeManagerModules.quadlet; - }; modules = [ ./systems/linux/mcentire.nix agenix.nixosModules.default - home-manager.nixosModules.home-manager quadlet-nix.nixosModules.quadlet + crowdsec.nixosModules.crowdsec + crowdsec.nixosModules.crowdsec-firewall-bouncer + { nixpkgs.overlays = [ crowdsec.overlays.default ]; } ]; }; }; diff --git a/homes/common.nix b/homes/common.nix index 78d70a0..2b452dd 100644 --- a/homes/common.nix +++ b/homes/common.nix @@ -1,4 +1,13 @@ -{ config, lib, pkgs, pkgs-unstable, custom-pkgs, ... }: { +{ config, lib, pkgs, pkgs-unstable, ... }: +let + runic_version = "1.5.0"; + runic = pkgs.fetchFromGitHub { + owner = "fredrikekre"; + repo = "Runic.jl"; + rev = "v${runic_version}"; + hash = "sha256-y+kiBA94vUMHH0fEEBg7+c9PEgzjGqh6nCuSRnawhQI="; + }; +in { imports = [ ./../programs/shells.nix ./../programs/bat.nix @@ -11,8 +20,17 @@ ]; home = { stateVersion = "23.11"; + file = { + ".local/bin/runic" = { + source = runic + "/bin/runic"; + executable = true; + }; + ".local/bin/git-runic" = { + source = runic + "/bin/git-runic"; + executable = true; + }; + }; packages = with pkgs; [ - agenix btop cowsay figlet @@ -26,7 +44,7 @@ jq julia-bin lynx - mamba-cpp + micromamba most nextflow p7zip @@ -34,8 +52,6 @@ pipx python3 zulu17 - custom-pkgs.jlfmt - custom-pkgs.runic ]; sessionVariables = { PAGER = "most"; @@ -67,9 +83,24 @@ "tailscale set --exit-node=$(tailscale exit-node suggest | awk '{print $4}' | head -n1)"; # tsed - TailScale Exit node Disconnect tsed = "tailscale set --exit-node="; - micromamba = "mamba"; }; sessionPath = [ "$HOME/.local/bin" ]; + activation = { + recordHmGitHash = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + cd "$HOME/.config/home-manager" || exit 1 + if [ -z "$(${pkgs.git}/bin/git status --porcelain --untracked-files=no)" ]; then + run echo "$(${pkgs.git}/bin/git rev-parse HEAD)" | tee $HOME/.cache/hm-git-hash + else + run echo '*' | tee $HOME/.cache/hm-git-hash + fi + ''; + installRunic = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + run ${pkgs.julia-bin}/bin/julia --project=@runic --startup-file=no -e 'using Pkg; Pkg.add(name="Runic", version="${runic_version}")' + ''; + installJuliaFormatter = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + run ${pkgs.julia-bin}/bin/julia --project=@JuliaFormatter --startup-file=no -e 'using Pkg; Pkg.add(name="JuliaFormatter", version="2.1.6")' + ''; + }; }; programs = { home-manager.enable = true; diff --git a/homes/darwin.nix b/homes/darwin.nix index 9cabb63..d3c2982 100644 --- a/homes/darwin.nix +++ b/homes/darwin.nix @@ -7,7 +7,7 @@ ]; home = { packages = with pkgs; [ - macpm + asitop pinentry_mac (pkgs.writeShellScriptBin "uq" '' xattr -rdv com.apple.quarantine "/Applications/$1.app" @@ -34,6 +34,22 @@ launchd = { enable = true; agents = { + ollama = { + enable = true; + config = { + Label = "local.home-manager.ollama"; + ProgramArguments = [ "${pkgs.ollama}/bin/ollama" "serve" ]; + RunAtLoad = true; + KeepAlive = true; + StandardOutPath = + "${config.home.homeDirectory}/Library/Logs/ollama.log"; + StandardErrorPath = + "${config.home.homeDirectory}/Library/Logs/ollama-error.log"; + EnvironmentVariables = { + PATH = "${lib.makeBinPath [ pkgs.ollama ]}:$PATH"; + }; + }; + }; freetube-sync = { enable = true; diff --git a/homes/desktop.nix b/homes/desktop.nix index 255db78..2a0790c 100644 --- a/homes/desktop.nix +++ b/homes/desktop.nix @@ -2,6 +2,7 @@ imports = [ ./../programs/firefox.nix + ./../programs/ghostty.nix ./../programs/zed.nix ./../services/gpg-agent.nix ]; @@ -22,7 +23,7 @@ nil nixd nixfmt-classic - nixos-rebuild + ollama quarto roboto-slab shellcheck diff --git a/homes/harmony.nix b/homes/harmony.nix new file mode 100644 index 0000000..2e48431 --- /dev/null +++ b/homes/harmony.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, pkgs-unstable, ... }: { + # harmony is an Asahi Fedora box + # I don't use NixOS, so there are some programs that don't interact well with + # the base system (or won't even install) when installed from Nix. + # There is no uniform way to trigger dnf package installs from Nix, so I'm + # just going to list my packages here. I hope to create a custom script that + # mimics the ideas of a Brewfile someday + # TODO: Create a Brewfile equivalent for dnf + + # dnf repos: + # https://github.com/terrapkg/packages?tab=readme-ov-file + # https://pkgs.tailscale.com/stable/fedora/tailscale.repo + # https://packagecloud.io/filips/FirefoxPWA + + # copr repos: + # iucar/rstudio + + # dnf packages: + # apptainer + # chromium + # firefoxpwa - The nix version installs an "immutable" runtime, which simply launches extra browser windows on non-NixOS + # inkscape + # kate + # kdiff3 + # krita + # lutris + # musescore + # nextcloud-client + # nextcloud-client-dolphin + # obs-studio + # podman-compose + # podman-docker + # qownnotes + # qt + # rssguard + # rstudio-desktop + # steam + # supertuxkart + # tailscale + # thunderbird + # vlc + # vorta - The vorta package is aarch64 compatible, but you cannot see any icons, and it cannot access local ssh keys, so we have to use the dnf package instead + # yakuake + # zed + # zsh + # R + # https://downloads.sourceforge.net/project/mscorefonts2/rpms/msttcore-fonts-installer-2.6-1.noarch.rpm + home = { + username = "millironx"; + homeDirectory = "/home/millironx"; + # Signal desktop is not available in any other package repository for aarch64 linux + # Similarly, Bitwarden is non-functional in all other forms using a 16k page size + packages = with pkgs; [ + trayscale + veracrypt + pkgs-unstable.signal-desktop + pkgs.bitwarden-desktop + ]; + }; + programs = { + git = { + signing = { + key = "0x37A3041D1C8C4524!"; + signByDefault = true; + }; + }; + }; + services = { + gpg-agent = { sshKeys = [ "207D13371E19752A67AA2686C16354D9963821DB" ]; }; + }; + xdg = { + configFile = { + "nextflow.config".text = '' + params { + config_profile_description = 'harmony Asahi Linux local profile' + config_profile_contact = 'Thomas A. Christensen II <25492070+MillironX@users.noreply.github.com>' + config_profile_url = null + + max_memory = 12.GB + max_cpus = 12 + max_time = 7.d + } + + apptainer { + enabled = true + autoMounts = true + } + + process { + executor = 'local' + } + ''; + }; + }; +} diff --git a/homes/linux-desktop.nix b/homes/linux-desktop.nix index 2516d48..6d78716 100644 --- a/homes/linux-desktop.nix +++ b/homes/linux-desktop.nix @@ -113,12 +113,20 @@ in { configFile = { "plasma-workspace/env/ZED_WINDOW_DECORATIONS.sh".text = "export ZED_WINDOW_DECORATIONS=server"; + "dolphinrc".source = + mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/dolphinrc"; + "konsolerc".source = + mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/konsolerc"; "onedrive/config".text = '' force_session_upload = "true" delay_inotify_processing = "true" ''; + "yakuakerc".source = + mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/yakuakerc"; }; dataFile = { + "konsole/My Default.profile".source = + mkOutOfStoreSymlink "${home-manager-repo}/dotfiles/MyDefault.profile"; "kio/servicemenus/kate.desktop".source = ./../dotfiles/kate.desktop; "kio/servicemenus/vlc.desktop".source = ./../dotfiles/vlc.desktop; "kio/servicemenus/word-to-pdf.desktop".source = diff --git a/homes/mcentire.nix b/homes/mcentire.nix deleted file mode 100644 index 82adbbc..0000000 --- a/homes/mcentire.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: { - home = { - username = "millironx"; - homeDirectory = "/home/millironx"; - }; - programs = { }; - services = { }; -} diff --git a/inventory.yaml b/inventory.yaml index 63f1f3c..ba53698 100644 --- a/inventory.yaml +++ b/inventory.yaml @@ -3,13 +3,20 @@ ungrouped: hosts: localhost: ansible_connection: local + harmony: + ansible_connection: local odyssey: ansible_connection: local +asahi: + hosts: + harmony: + amd64: hosts: odyssey: fedora: hosts: + harmony: odyssey: diff --git a/modules/podman-secrets.nix b/modules/podman-secrets.nix deleted file mode 100644 index fb99285..0000000 --- a/modules/podman-secrets.nix +++ /dev/null @@ -1,167 +0,0 @@ -# Warning to my future self: This module was "vibe coded" by Claude Sonnet 4.5. -# I originally had a hand-written module in here that did the secrets -# translation as the root user. I knew that I would want to support multiple -# secrets files and multiple users, and thought I should be able to create an -# arbitrary number of them, similar to how you can have an arbitrary number -# of `programs.firefox.profiles`. Unfortunately, even after looking at lots of -# example modules, I could not figure out the syntax (Nix has a serious lack -# of minimum working examples), so I broke down and asked Claude to rewrite it -# for me. Based on everything that I read, this seems to be exactly what I asked -# for. -# -# Here is the prompt I used to get here: -# [@Per service isolation on NixOS with Traefik](zed:///agent/thread/94cb8a22-ff0c-4772-a1a1-018b0107f334?name=Per+service+isolation+on+NixOS+with+Traefik) -# -# [@podman-secrets.nix](file:///home/millironx/.config/home-manager/modules/podman-secrets.nix) -# -# I originally wrote this module assuming that I would use Podman as root for -# all containers. I would like to fix the module to have as many secrets files -# processed as needed with services setup for each secret that is run as the -# appropriate user. Ideally, the syntax for working with secrets to be -# translated would be -# -# ```nix -# { config, ... }: { -# age.secrets = { -# "caddy.toml" = { -# file = ./../secrets/caddy.toml.age; -# owner = "caddy"; -# group = "caddy"; -# }; -# -# "authentik.toml" = { -# file = ./../secrets/authentik.toml.age; -# owner = "authentik"; -# group = "authentik"; -# }; -# -# "freshrss.toml" = { -# file = ./../secrets/freshrss.toml.age; -# owner = "freshrss"; -# group = "freshrss"; -# }; -# }; -# -# millironx.podman-secrets = with config; { -# caddy = { -# user = "caddy"; -# secrets-files = [ -# ./../not-really-secret.toml -# age.secrets."caddy.toml".path -# ]; -# }; -# authentik = { -# user = "authentik"; -# secrets-files = [ -# age.secrets."authentik.toml".path -# ]; -# }; -# freshrss = { -# user = "freshrss"; -# secrets-files = [ -# age.secrets."freshrss.toml".path -# ]; -# }; -# }; -# } -# ``` -# -# Can you help me rewrite the module to accomplish this? -# -{ config, lib, pkgs, ... }: -with lib; -let - cfg = config.millironx.podman-secrets; - - secret-translator = pkgs.writeScriptBin "secret-translator" - (builtins.readFile ./../bin/secret-translator.jl); - - # Submodule type for each service's secrets configuration - serviceSecretsType = types.submodule ({ config, name, ... }: { - options = { - user = mkOption { - type = types.str; - description = "User account to run the secrets translation service as"; - example = "caddy"; - }; - - secrets-files = mkOption { - type = types.listOf (types.either types.path types.string); - description = - "List of TOML files containing secrets to translate to Podman secrets"; - example = literalExpression '' - [ - "/run/agenix/caddy.toml" - ./../not-really-secret.toml - ] - ''; - default = [ ]; - }; - - ref = mkOption { - type = types.str; - description = - "Reference to the systemd service name for declaring dependencies"; - readOnly = true; - default = "podman-secrets-${name}.service"; - example = "podman-secrets-caddy.service"; - }; - }; - }); - - # Generate a systemd user service for each configured service - mkSecretsService = name: serviceCfg: - nameValuePair "podman-secrets-${name}" { - description = "Podman secrets converter service for ${name}"; - wantedBy = [ "default.target" ]; - - unitConfig.ConditionUser = "${serviceCfg.user}"; - - serviceConfig = { - Type = "oneshot"; - ProtectProc = "invisible"; - ExecStart = "${secret-translator}/bin/secret-translator ${ - lib.concatStringsSep " " serviceCfg.secrets-files - }"; - Environment = "PATH=/run/wrappers/bin:${ - lib.makeBinPath (with pkgs; [ shadow podman julia-lts-bin ]) - }"; - }; - }; - - # Filter out services with no secrets-files - enabledServices = - lib.filterAttrs (name: serviceCfg: serviceCfg.secrets-files != [ ]) cfg; - -in { - options.millironx.podman-secrets = mkOption { - type = types.attrsOf serviceSecretsType; - description = '' - Per-service Podman secrets configuration. - Each attribute creates a separate systemd user service that translates TOML secrets - files into Podman secrets. - ''; - example = literalExpression '' - { - caddy = { - user = "caddy"; - secrets-files = [ - ./../not-really-secret.toml - config.age.secrets."caddy.toml".path - ]; - }; - authentik = { - user = "authentik"; - secrets-files = [ - config.age.secrets."authentik.toml".path - ]; - }; - } - ''; - default = { }; - }; - - config = mkIf (enabledServices != { }) { - systemd.user.services = lib.mapAttrs' mkSecretsService enabledServices; - }; -} diff --git a/pkgs/default.nix b/pkgs/default.nix index 8178242..2e0c11e 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,7 +1,6 @@ { pkgs, ... }: -with pkgs; { - ark = callPackage ./ark.nix { }; - jlfmt = callPackage ./jlfmt.nix { }; - runic = callPackage ./runic.nix { }; - sc4pac = callPackage ./sc4pac.nix { }; + +{ + ark = pkgs.callPackage ./ark.nix { }; + sc4pac = pkgs.callPackage ./sc4pac.nix { }; } diff --git a/pkgs/jlfmt.nix b/pkgs/jlfmt.nix deleted file mode 100644 index 21916a4..0000000 --- a/pkgs/jlfmt.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ pkgs, ... }: -with pkgs; -let - juliaWithPkgs = julia-bin.withPackages.override { setDefaultDepot = false; } - [ "JuliaFormatter" ]; - depotWithPkgs = runCommand "getDepot" { } '' - ${juliaWithPkgs}/bin/julia -e 'println(first(DEPOT_PATH))' | tee $out - ''; -in writeShellScriptBin "jlfmt" '' - export JULIA_DEPOT_PATH=$(< ${depotWithPkgs}) - exec ${juliaWithPkgs}/bin/julia --startup-file=no -e 'using JuliaFormatter; print(format_text(String(read(stdin))));' -- "$@" -'' diff --git a/pkgs/runic.nix b/pkgs/runic.nix deleted file mode 100644 index b91b550..0000000 --- a/pkgs/runic.nix +++ /dev/null @@ -1,12 +0,0 @@ -{ pkgs, ... }: -with pkgs; -let - juliaWithRunic = - julia-bin.withPackages.override { setDefaultDepot = false; } [ "Runic" ]; - depotWithRunic = runCommand "getRunicDepot" { } '' - ${juliaWithRunic}/bin/julia -e 'println(first(DEPOT_PATH))' | tee $out - ''; -in writeShellScriptBin "runic" '' - export JULIA_DEPOT_PATH=$(< ${depotWithRunic}) - exec ${juliaWithRunic}/bin/julia --startup-file=no -e 'using Runic; exit(Runic.main(ARGS))' -- "$@" -'' diff --git a/playbooks/config.yaml b/playbooks/config.yaml index 156dc63..4aa2dd4 100644 --- a/playbooks/config.yaml +++ b/playbooks/config.yaml @@ -11,7 +11,7 @@ mode: "755" - name: Create Firefox DNS policy ansible.builtin.template: - src: "policies.json" + src: "{{ playbook_dir }}/../templates/policies.json" dest: /etc/firefox/policies/policies.json mode: "644" diff --git a/playbooks/nix.yaml b/playbooks/nix.yaml index 50d9952..672725f 100644 --- a/playbooks/nix.yaml +++ b/playbooks/nix.yaml @@ -45,8 +45,7 @@ register: home_manager_exists - name: Init home-manager ansible.builtin.shell: | - /nix/var/nix/profiles/default/bin/nix run home-manager -- switch \ - --flake git+https://code.millironx.com/millironx/nix-dotfiles#{{ ansible_user_id }}@{{ ansible_hostname }} + /nix/var/nix/profiles/default/bin/nix run home-manager -- switch --flake git+https://code.millironx.com/millironx/nix-dotfiles#{{ ansible_user_id }}@{{ ansible_hostname }} when: not home_manager_exists.stat.exists register: home_manager_init changed_when: home_manager_init.rc == 0 diff --git a/playbooks/packages.yaml b/playbooks/packages.yaml index f13c01b..612acde 100644 --- a/playbooks/packages.yaml +++ b/playbooks/packages.yaml @@ -1,33 +1,78 @@ --- -- name: Configure dnf packages +# These are repos and packages that are useless or unavailable on Asahi Linux, +# or have completely separate install procedures. +- name: Configure amd64-specific dnf packages + hosts: amd64 + become: true + tasks: + - name: Install x86-specific dnf packages + ansible.builtin.dnf: + name: + - libdvdcss + - mkvtoolnix + - mpv + - protontricks + - x264 + - x264-libs + state: present + - name: Install VeraCrypt + ansible.builtin.dnf: + name: https://launchpad.net/veracrypt/trunk/1.26.20/+download/veracrypt-1.26.20-Fedora-40-x86_64.rpm + state: present + disable_gpg_check: true + +- name: Configure amd64-specific Flatpaks + hosts: amd64 + become: false + tasks: + - name: Install x86-specific Flatpaks + community.general.flatpak: + name: + - com.bitwarden.desktop + - com.slack.Slack + - dev.deedles.Trayscale + - org.signal.Signal + state: latest + method: user + remote: flathub + +- name: Configure Asahi Linux-specific dnf packages + hosts: asahi + become: true + tasks: + - name: Install aarch64-specific dnf packages + ansible.builtin.dnf: + name: + - veracrypt + +- name: Configure common (all arch) dnf packages hosts: fedora become: true tasks: - - name: Install dnf packages + - name: Install common (all arch) dnf packages ansible.builtin.dnf: name: - chromium + - firefoxpwa - fontconfig-devel - freetype-devel - fribidi-devel + - ghostty - inkscape - jq - kate - kdenlive - kdiff3 - krita - - libdvdcss - libjpeg-devel - libpng-devel - libtiff-devel - libwebp-devel - - mkvtoolnix - - mpv + - musescore - nextcloud-client - nextcloud-client-dolphin - obs-studio - onedrive - - protontricks - qownnotes - qt - rssguard @@ -37,8 +82,6 @@ - thunderbird - vlc - vorta - - x264 - - x264-libs - yakuake - zed - zsh @@ -49,11 +92,6 @@ name: https://downloads.sourceforge.net/project/mscorefonts2/rpms/msttcore-fonts-installer-2.6-1.noarch.rpm state: present disable_gpg_check: true - - name: Install VeraCrypt - ansible.builtin.dnf: - name: https://launchpad.net/veracrypt/trunk/1.26.20/+download/veracrypt-1.26.20-Fedora-40-x86_64.rpm - state: present - disable_gpg_check: true - name: Install rig (R installation manager) ansible.builtin.dnf: name: https://github.com/r-lib/rig/releases/download/latest/r-rig-latest-1.{{ ansible_architecture }}.rpm @@ -71,24 +109,21 @@ name: "*" state: latest # noqa: package-latest -- name: Configure Flatpaks +- name: Configure common (all arch) Flatpaks hosts: fedora become: false tasks: - - name: Install Flatpaks + - name: Install common (all arch) Flatpaks community.general.flatpak: name: - - com.bitwarden.desktop - com.github.tchx84.Flatseal - com.logseq.Logseq - - com.slack.Slack - - dev.deedles.Trayscale - io.freetubeapp.FreeTube - io.github.alainm23.planify - io.github.dweymouth.supersonic - io.openrct2.OpenRCT2 - - org.signal.Signal - org.zulip.Zulip + - net.ankiweb.Anki state: latest method: user remote: flathub diff --git a/playbooks/repos.yaml b/playbooks/repos.yaml index 476dfdb..b771518 100644 --- a/playbooks/repos.yaml +++ b/playbooks/repos.yaml @@ -1,6 +1,6 @@ --- -- name: Configure dnf package repositories - hosts: fedora +- name: Configure amd64-specific package repositories + hosts: amd64 become: true tasks: - name: Install RPM Fusion free repository @@ -20,6 +20,31 @@ - name: Install Zotero COPR repository community.general.copr: name: "mozes/zotero7" + +# Asahi Linux comes with its own strange version of RPMFusion installed, so +# RPMFusion is installed only on amd64 systems. In addition, VeraCrypt and +# Zotero *are* available via COPR, but from different repos than their amd64 +# counterparts. +# Also, Asahi has its own version string, so we have to manually specify the +# chroot for COPR repos added via Ansible. This is handled automatically when +# using `dnf copr enable ...`, but not via Ansible. +- name: Configure Asahi Linux-specific package repositories + hosts: asahi + become: true + tasks: + - name: Install Zotero COPR repository + community.general.copr: + name: "isaksamsten/Zotero" + chroot: "fedora-{{ ansible_distribution_major_version }}-aarch64" + - name: Install VeraCrypt COPR repository + community.general.copr: + name: "architektapx/veracrypt" + chroot: "fedora-{{ ansible_distribution_major_version }}-aarch64" + +- name: Configure common (all arch) package repositories + hosts: fedora + become: true + tasks: - name: Install Tailscale repo ansible.builtin.yum_repository: name: tailscale-stable @@ -28,6 +53,14 @@ enabled: true gpgcheck: true gpgkey: https://pkgs.tailscale.com/stable/fedora/repo.gpg + - name: Install FirefoxPWA repository + ansible.builtin.yum_repository: + name: firefoxpwa + description: FirefoxPWA repository + baseurl: https://packagecloud.io/filips/FirefoxPWA/fedora/$releasever/$basearch + gpgcheck: true + gpgkey: https://packagecloud.io/filips/FirefoxPWA/gpgkey + enabled: true # Note that I still have to specify the chroot for COPR repos b/c of Asahi - name: Install RStudio copr repository community.general.copr: @@ -77,7 +110,7 @@ register: terra_priority changed_when: terra_priority.rc != 0 -- name: Configure Flatpack remotes +- name: Configure Flathub remote hosts: fedora become: false tasks: diff --git a/programs/firefox.nix b/programs/firefox.nix index ed6705f..520a4ef 100644 --- a/programs/firefox.nix +++ b/programs/firefox.nix @@ -1,4 +1,4 @@ -{ pkgs, firefox-addons, buildFirefoxXpiAddon, lib, ... }: { +{ firefox-addons, buildFirefoxXpiAddon, lib, ... }: { programs.firefox = { enable = true; package = @@ -31,49 +31,49 @@ }; }; containersForce = true; - extensions.packages = with firefox-addons; - [ - bitwarden - multi-account-containers - libredirect - old-reddit-redirect - ublock-origin - user-agent-string-switcher - zotero-connector - (buildFirefoxXpiAddon rec { - pname = "always_in_container"; - version = "1.0.7"; - addonId = "{a1e9543e-5f73-4763-b376-04e53fd12cbd}"; - url = - "https://addons.mozilla.org/firefox/downloads/file/4032840/${pname}-${version}.xpi"; - sha256 = "sha256-bLxjL2P6Sd06q98MSHYRTNigtcjGwn/C2r4ANWCqKrw="; - meta = with lib; { - homepage = "https://github.com/tiansh/always-in-container"; - description = - "Chose a container every time you try to open a page out of a container"; - license = licenses.mpl20; - platforms = platforms.all; - }; - }) - (buildFirefoxXpiAddon rec { - pname = "open_with"; - version = "7.2.6"; - addonId = "openwith@darktrojan.net"; - url = - "https://addons.mozilla.org/firefox/downloads/file/3831723/${pname}-${version}.xpi"; - sha256 = "sha256-f9eGhLxg4UyVn4o5e4DRkraLWzj11SGto/GOwsJa9kg="; - meta = with lib; { - homepage = "https://darktrojan.github.io/openwith/"; - description = - "Quickly test out your web pages in Chrome, Edge, Safari, or Opera. Open With opens the current page in your other browsers with just two clicks."; - license = licenses.mpl20; - platforms = platforms.all; - }; - }) - ] ++ (if pkgs.stdenv.hostPlatform.isDarwin then - [ ] - else - [ plasma-integration ]); + extensions.packages = with firefox-addons; [ + bitwarden + multi-account-containers + floccus + libredirect + old-reddit-redirect + plasma-integration + pwas-for-firefox + ublock-origin + user-agent-string-switcher + web-archives + zotero-connector + (buildFirefoxXpiAddon rec { + pname = "always_in_container"; + version = "1.0.7"; + addonId = "{a1e9543e-5f73-4763-b376-04e53fd12cbd}"; + url = + "https://addons.mozilla.org/firefox/downloads/file/4032840/${pname}-${version}.xpi"; + sha256 = "sha256-bLxjL2P6Sd06q98MSHYRTNigtcjGwn/C2r4ANWCqKrw="; + meta = with lib; { + homepage = "https://github.com/tiansh/always-in-container"; + description = + "Chose a container every time you try to open a page out of a container"; + license = licenses.mpl20; + platforms = platforms.all; + }; + }) + (buildFirefoxXpiAddon rec { + pname = "open_with"; + version = "7.2.6"; + addonId = "openwith@darktrojan.net"; + url = + "https://addons.mozilla.org/firefox/downloads/file/3831723/${pname}-${version}.xpi"; + sha256 = "sha256-f9eGhLxg4UyVn4o5e4DRkraLWzj11SGto/GOwsJa9kg="; + meta = with lib; { + homepage = "https://darktrojan.github.io/openwith/"; + description = + "Quickly test out your web pages in Chrome, Edge, Safari, or Opera. Open With opens the current page in your other browsers with just two clicks."; + license = licenses.mpl20; + platforms = platforms.all; + }; + }) + ]; search = { default = "Kagi"; privateDefault = "Milliron X Search"; @@ -246,6 +246,7 @@ "floccus_handmadeideas_org-browser-action" "7esoorv3_alefvanoon_anonaddy_me-browser-action" "plasma-browser-integration_kde_org-browser-action" + "firefoxpwa_filips_si-browser-action" "_d07ccf11-c0cd-4938-a265-2a4d6ad01189_-browser-action" # Web Archives "openwith_darktrojan_net-browser-action" "zotero_chnm_gmu_edu-browser-action" @@ -281,6 +282,7 @@ "floccus_handmadeideas_org-browser-action" "7esoorv3_alefvanoon_anonaddy_me-browser-action" "plasma-browser-integration_kde_org-browser-action" + "firefoxpwa_filips_si-browser-action" "ublock0_raymondhill_net-browser-action" "_d07ccf11-c0cd-4938-a265-2a4d6ad01189_-browser-action" "zotero_chnm_gmu_edu-browser-action" diff --git a/programs/ghostty.nix b/programs/ghostty.nix new file mode 100644 index 0000000..bd91415 --- /dev/null +++ b/programs/ghostty.nix @@ -0,0 +1,19 @@ +{ pkgs, ... }: { + programs.ghostty = + let modifierKey = if pkgs.stdenv.isDarwin then "cmd" else "ctrl"; + in { + enable = true; + package = null; + enableBashIntegration = true; + enableZshIntegration = true; + settings = { + quick-terminal-position = "top"; + quick-terminal-screen = "main"; + quick-terminal-autohide = true; + quick-terminal-size = "50%,50%"; + keybind = "global:${modifierKey}+backquote=toggle_quick_terminal"; + macos-hidden = "always"; + linux-cgroup = "always"; + }; + }; +} diff --git a/programs/git.nix b/programs/git.nix index 244e916..b4d790d 100644 --- a/programs/git.nix +++ b/programs/git.nix @@ -1,11 +1,9 @@ { ... }: { programs.git = { enable = true; - settings = { - user = { - name = "Thomas A. Christensen II"; - email = "25492070+MillironX@users.noreply.github.com"; - }; + userName = "Thomas A. Christensen II"; + userEmail = "25492070+MillironX@users.noreply.github.com"; + extraConfig = { core = { editor = "nvim"; }; credential = { helper = "store"; }; color = { ui = "auto"; }; @@ -42,11 +40,6 @@ }; merge = { conflictstyle = "zdiff3"; }; pull = { rebase = true; }; - "url \"ssh://git@github.com/\"".insteadOf = "https://github.com/"; - "url \"ssh://git@gitlab.com/\"".insteadOf = "https://gitlab.com/"; - "url \"ssh://git@codeberg.com/\"".insteadOf = "https://codeberg.com/"; - "url \"ssh://git@code.millironx.com/\"".insteadOf = - "https://code.millironx.com/"; }; }; } diff --git a/programs/konsole.nix b/programs/konsole.nix deleted file mode 100644 index 66043de..0000000 --- a/programs/konsole.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ ... }: { - programs.konsole = { - enable = true; - defaultProfile = "millironx"; - profiles.millironx = { - colorScheme = "Breeze"; - font = { - name = "MesloLGS NF"; - size = 10; - }; - extraConfig = { - "Cursor Options".CursorShape = 1; - General.RemoteTabTitleFormat = "[SSH] %H"; - "Interaction Options" = { - CopyTextAsHTML = false; - MouseWheelZoomEnabled = false; - UnderlineFilesEnabled = true; - }; - "Terminal Features".BlinkingCursorEnabled = true; - }; - }; - }; -} diff --git a/programs/plasma.nix b/programs/plasma.nix index 2fdd769..ea0b6e7 100644 --- a/programs/plasma.nix +++ b/programs/plasma.nix @@ -1,177 +1,7 @@ { config, ... }: { - - imports = [ ./konsole.nix ./yakuake.nix ]; - programs.plasma = { enable = true; - overrideConfig = true; - shortcuts = { yakuake.toggle-window-state = "Ctrl+`"; }; - configFile = { - dolphinrc = { - DetailsMode.PreviewSize = 16; - General = { - BrowseThroughArchives = true; - EditableUrl = true; - GlobalViewProps = false; - ShowFullPath = true; - ShowStatusBar = "FullWidth"; - ShowZoomSlider = true; - }; - "KFileDialog Settings" = { - "Places Icons Auto-resize" = false; - "Places Icons Static Size" = 22; - }; - PreviewSettings.Plugins = - "audiothumbnail,avif,blenderthumbnail,comicbookthumbnail,cursorthumbnail,djvuthumbnail,ebookthumbnail,exrthumbnail,directorythumbnail,fontthumbnail,imagethumbnail,jpegthumbnail,jxl,kraorathumbnail,windowsexethumbnail,windowsimagethumbnail,mobithumbnail,opendocumentthumbnail,gsthumbnail,rawthumbnail,svgthumbnail,gdk-pixbuf-thumbnailer,ffmpegthumbs,gsf-office"; - }; - }; - input.mice = [{ - enable = true; - name = "Logitech M705"; - vendorId = "046d"; - productId = "406d"; - naturalScroll = true; - }]; - kwin = { - cornerBarrier = false; - titlebarButtons = { - left = [ "close" "minimize" "maximize" ]; - right = [ "help" ]; - }; - virtualDesktops = { - number = 2; - rows = 1; - }; - }; - panels = [ - ### Screen 0 panels ### - ##### Top: Fedora menu | App switcher | Menu bar | CPU monitor | Memory monitor | Network monitor | System tray | clock ##### - { - location = "top"; - floating = true; - height = 27; - lengthMode = "fill"; - opacity = "adaptive"; - hiding = "normalpanel"; - screen = 0; - widgets = [ - { kickoff = { icon = "fedora-logo-icon"; }; } - "org.kde.plasma.marginsseparator" - "org.kde.plasma.windowlist" - "org.kde.plasma.appmenu" - "org.kde.plasma.panelspacer" - { - name = "org.kde.plasma.systemmonitor.cpu"; - config = { - Appearance.chartFace = "org.kde.ksysguard.barchart"; - Sensors.highPrioritySensorIds = "[${ - builtins.concatStringsSep "," (builtins.genList - (i: ''"cpu/cpu${builtins.toString i}/usage"'') 12) - }]"; - }; - } - { - name = "org.kde.plasma.systemmonitor.memory"; - config.Appearance.chartFace = "org.kde.ksysguard.horizontalbars"; - } - { - name = "org.kde.plasma.systemmonitor.net"; - config = { - Appearance.chartFace = "org.kde.ksysguard.horizontalbars"; - Sensors.highPrioritySensorIds = - ''[ "network/all/download","network/all/upload" ]''; - # These are the values needed to make the network indicator - # actually useful, but it appears that plasma-manager doesn't - # support nesting this deep yet. Disable for now. - # "org.kde.ksysguard.horizontalbars".General = { - # rangeAuto = false; - # rangeFromMultiplier = 1048576; - # rangeFromUnit = 202; - # rangeToMultiplier = 1048576; - # rangeToUnit = 202; - # }; - }; - } - { systemTray = { }; } - { digitalClock = { }; } - ]; - } - ##### Bottom: Virtual desktop pager | Full-name taskbar w/ pins | Downloads folder | Trash folder - { - location = "bottom"; - floating = true; - height = 44; - lengthMode = "fill"; - opacity = "adaptive"; - hiding = "normalpanel"; - screen = 0; - widgets = [ - "org.kde.plasma.pager" - { - iconTasks = { - iconsOnly = false; - behavior.showTasks.onlyInCurrentScreen = true; - launchers = [ - "applications:systemsettings.desktop" - "applications:org.kde.discover.desktop" - "preferred://filemanager" - "preferred://browser" - "applications:net.thunderbird.Thunderbird.desktop" - "applications:io.github.alainm23.planify.desktop" - "applications:dev.zed.Zed.desktop" - "applications:com.logseq.Logseq.desktop" - "applications:net.lutris.Lutris.desktop" - ]; - }; - } - "org.kde.plasma.panelspacer" - "org.kde.plasma.marginsseparator" - { - name = "org.kde.plasma.folder"; - config = { - General.url = "file://${config.home.homeDirectory}/Downloads"; - }; - } - "org.kde.plasma.trash" - ]; - } - - ### Screen 1 panels ### - ##### Top: App switcher | Menu bar ##### - { - location = "top"; - floating = true; - height = 27; - lengthMode = "fill"; - opacity = "adaptive"; - hiding = "normalpanel"; - screen = 1; - widgets = [ "org.kde.plasma.windowlist" "org.kde.plasma.appmenu" ]; - } - ##### Bottom: Virtual desktop pager | Full-name taskbar w/o pins ##### - { - location = "bottom"; - floating = true; - height = 44; - lengthMode = "fill"; - opacity = "adaptive"; - hiding = "normalpanel"; - screen = 1; - widgets = [ - "org.kde.plasma.pager" - { - iconTasks = { - iconsOnly = false; - behavior.showTasks.onlyInCurrentScreen = true; - launchers = [ ]; - }; - } - ]; - } - ]; - powerdevil.AC.autoSuspend.action = "nothing"; workspace = { - lookAndFeel = "org.kde.breezedark.desktop"; wallpaperFillMode = "preserveAspectCrop"; wallpaperSlideShow = { interval = 86400; diff --git a/programs/shells.nix b/programs/shells.nix index edb0f18..93b2d9d 100644 --- a/programs/shells.nix +++ b/programs/shells.nix @@ -1,7 +1,7 @@ { pkgs, ... }: let conda_init = shell: '' - eval "$(${pkgs.mamba-cpp}/bin/mamba shell hook --shell ${shell})" + eval "$(${pkgs.micromamba}/bin/micromamba shell hook --shell ${shell})" ''; nd_bash_function = '' @@ -10,53 +10,11 @@ let } ''; - sourceCodeDirectory = - if pkgs.stdenv.hostPlatform.isDarwin then "~/Developer" else "~/src"; - clone_bash_function = '' - unalias gc - function gc() { - REPO_ID="$(echo "''${1}" | \ - awk '{ - sub(/^git@/, ""); - sub(/^https:\/\//, ""); - sub (/:/, "/"); - sub(/\.git$/, ""); - print - }')" - git clone "https://''${REPO_ID}.git" ${sourceCodeDirectory}/''${REPO_ID} - cd ${sourceCodeDirectory}/''${REPO_ID} - } - - ''; - repo_init_function = '' - function rinit() { - REPO_ID="$(echo "''${1}" | \ - awk '{ - sub(/^git@/, ""); - sub(/^https:\/\//, ""); - sub (/:/, "/"); - sub(/\.git$/, ""); - print - }')" - - mkdir -p ${sourceCodeDirectory}/''${REPO_ID} - cd ${sourceCodeDirectory}/''${REPO_ID} - - git init - - git remote add origin git@''${REPO_ID/\//:}.git - } - - ''; - - shell_functions = shell: - (conda_init shell) + nd_bash_function + clone_bash_function - + repo_init_function; in { programs = { bash = { enable = true; - initExtra = shell_functions "bash" + '' + initExtra = conda_init "bash" + nd_bash_function + '' export PS1="[\[\e[32m\]\u\[\e[m\]@\[\e[33m\]\h\[\e[m\] \[\e[34m\]\W\[\e[m\]] \\$ " ''; }; @@ -79,7 +37,7 @@ in { "zsh-users/zsh-completions" ]; }; - initContent = shell_functions "zsh"; + initContent = conda_init "zsh" + nd_bash_function; }; }; } diff --git a/programs/taskbar.nix b/programs/taskbar.nix index cff7787..757d42d 100644 --- a/programs/taskbar.nix +++ b/programs/taskbar.nix @@ -25,10 +25,6 @@ bundleIdentifier = "org.mozilla.thunderbird"; action = "launchOrActivateApp"; } - { - bundleIdentifier = "com.microsoft.Outlook"; - action = "launchOrActivateApp"; - } { bundleIdentifier = "dev.zed.Zed"; action = "launchOrActivateApp"; @@ -38,13 +34,11 @@ action = "launchOrActivateApp"; } { - # Instinct dashboard bundleIdentifier = "com.apple.Safari.WebApp.2F51A6D0-087A-438F-92D3-A73FE09CB4CC"; action = "launchOrActivateApp"; } { - # Carestream bundleIdentifier = "com.apple.Safari.WebApp.5EC6478E-03A6-4147-8A4D-6EF3DE3F06D3"; action = "launchOrActivateApp"; diff --git a/programs/yakuake.nix b/programs/yakuake.nix deleted file mode 100644 index f8b86a7..0000000 --- a/programs/yakuake.nix +++ /dev/null @@ -1,19 +0,0 @@ -# Note: this file uses the lower-level `programs.plasma.configFile` syntax -# since plasma-manager does not yet support a high-level module for Yakuake -{ ... }: { - programs.plasma.configFile.yakuakerc = { - "Desktop Entry".DefaultProfile = "millironx.profile"; - Shortcuts = { - next-session = "Shift+Right; Ctrl+Shift+Tab"; - previous-terminal = "none"; - }; - Window = { - DynamicTabTitles = true; - Height = 60; - Screen = 1; - ShowSystrayIcon = false; - Width = 60; - }; - Dialogs.FirstRun = false; - }; -} diff --git a/programs/zed.nix b/programs/zed.nix index 6985d69..19beb45 100644 --- a/programs/zed.nix +++ b/programs/zed.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: { +{ ... }: { programs.zed-editor = { enable = true; extensions = [ @@ -23,27 +23,27 @@ use_modifier_to_send = true; default_model = { provider = "zed.dev"; - model = "claude-sonnet-4-5"; + model = "claude-3-7-sonnet"; }; default_profile = "minimal"; }; buffer_font_family = "FiraCode Nerd Font"; buffer_font_size = 11; features = { edit_prediction_provider = "zed"; }; - git_hosting_providers = [ - { - provider = "forgejo"; - base_url = "https://code.millironx.com"; - name = "Milliron X Code"; - } - { - provider = "forgejo"; - base_url = "https://codeberg.org"; - name = "Codeberg"; - } - ]; languages = { - Julia = { formatter = { external = { command = "jlfmt"; }; }; }; + Julia = { + formatter = { + external = { + command = "julia"; + arguments = [ + "--project=@JuliaFormatter" + "--startup-file=no" + "-e" + "using JuliaFormatter; print(format_text(String(read(stdin))));" + ]; + }; + }; + }; LaTeX = { formatter = { external = { @@ -52,30 +52,13 @@ }; }; }; - Nix = { - formatter.external.command = "${pkgs.nixfmt-classic}/bin/nixfmt"; - }; }; lsp = { - nil = { settings.nix.flake.autoArchive = true; }; - texlab = { - settings = { - build = { - onSave = false; - forwardSearchAfter = true; - }; - forwardSearch = if pkgs.stdenv.hostPlatform.isDarwin then { - executable = - "/Applications/Skim.app/Contents/SharedSupport/displayline"; - args = [ "-r" "-g" "%l" "%p" "%f" ]; - } else { - executable = "/usr/bin/okular"; - args = [ "--unique" "file:%p#src:%l%f" ]; - }; - }; + nil = { + initialization_options.formatting.command = [ "nixfmt" ]; + settings.nix.flake.autoArchive = true; }; tinymist = { - initialization_options = { preview.background.enabled = true; }; settings = { exportPdf = "onSave"; outputPath = "$root/$name"; @@ -98,28 +81,5 @@ ui_font_size = 16; wrap_guides = [ 80 92 120 ]; }; - userTasks = [ - { - label = "latexmk (project)"; - command = "latexmk"; - args = [ "-synctex=1" "-pdf" "-recorder" ]; - cwd = "$ZED_DIRNAME"; - tags = [ "latex-build" ]; - } - { - label = "Open Typst preview"; - command = "${ - if pkgs.stdenv.hostPlatform.isDarwin then "open" else "xdg-open" - } http://127.0.0.1:23635/"; - use_new_terminal = true; - allow_concurrent_runs = false; - reveal = "never"; - reveal_target = "dock"; - hide = "always"; - shell = "system"; - show_summary = true; - show_command = true; - } - ]; }; } diff --git a/secrets.nix b/secrets.nix index ed1352e..3b3ede4 100644 --- a/secrets.nix +++ b/secrets.nix @@ -6,36 +6,25 @@ let "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxTfeg+GZsfmG8TuEV1xW1gXknAIKzZ3UjZ3guRY+EW root@nixos"; bosephus-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKaDPqRJHoqgY2pseh/mnhjaGWXprHk2s5I52LhHpHcF millironx@bosephus"; - corianne-host = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHKKkucebeb1GcerOZAAs5GQsgTS8kXw5W41b9Fy9+hp root@corianne.local"; + odyssey-millironx = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9Aj7BtQp1Roa0tgopDrUo7g2am5WJ43lO1d1fDUz45 millironx@odyssey"; corianne-millironx = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOgL2lO9RJBdQYANoxGyWXcNKi5/NZkRHHo/rNqaYMc/ millironx@corianne"; - mcentire-host = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINT51tQgsKzTIQc9WSQj01h/gPRvAD3k9jRhXppY7xmd root@nixos"; - mcentire-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOdC6eNx2nBi3PWK/n4GJMbVf+NlQJv13aUqxse/h1kL millironx@mcentire"; - odyssey-millironx = - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKM5Q2zl3b91j+foqcVeQT+wb5DFEp+MbgotTTaKqZZi millironx@odyssey"; + harmony-millironx = + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFBYxsCkw+ObDzIvU8z/rSlYcQx0JIt1bCVxKcDxeNNZ millironx@harmony"; + system-administrators = [ anderson-millironx bosephus-millironx - corianne-millironx - mcentire-millironx odyssey-millironx + corianne-millironx + harmony-millironx ]; in { - "secrets/ansible-vault-password.age".publicKeys = system-administrators; - "secrets/authentik.toml.age".publicKeys = system-administrators - ++ [ mcentire-host ]; - "secrets/borgmatic-passphrase.age".publicKeys = system-administrators - ++ [ mcentire-host ]; - "secrets/borgmatic-ssh-config.age".publicKeys = system-administrators - ++ [ mcentire-host ]; - "secrets/darwin-policies-json.age".publicKeys = system-administrators - ++ [ corianne-host ]; - "secrets/freshrss.toml.age".publicKeys = system-administrators - ++ [ mcentire-host ]; "secrets/network-information.age".publicKeys = system-administrators ++ [ bosephus-host ]; + "secrets/pihole.age".publicKeys = system-administrators ++ [ bosephus-host ]; + "secrets/ansible-vault-password.age".publicKeys = system-administrators; + "secrets/darwin-policies-json.age".publicKeys = system-administrators; } diff --git a/secrets/ansible-vault-password.age b/secrets/ansible-vault-password.age index 6c1379f..99a96bc 100644 --- a/secrets/ansible-vault-password.age +++ b/secrets/ansible-vault-password.age @@ -1,13 +1,13 @@ age-encryption.org/v1 --> ssh-ed25519 il3lzQ SoqTRahd/xUVe/pDmQI3jT5X0lTxOwhy8hct20fwil4 -UuYpQa5GpDALKQEMbSLnH2rp3kgPL+4zJZbJirkB5Q0 --> ssh-ed25519 1g/xww gYtrdwJlp1pxcZ7l+RvawRScFOh/ami3yJobbKPyLiM -oQ8dwIUIakV8WVvuknn87BYcmEBBT+UI3BxImd71/jE --> ssh-ed25519 dbKeHw KVdpRmBWRYd5NC3UK3e8Em3XefnVxxc9KfXzbksvTC0 -fwyK7ORnCadX8Czs0WKW3ZDa1jeu7Wjba7Vm9nKqCBs --> ssh-ed25519 3qPtug nEHt7lMjUrcehOGjtznFd+u60OdfG1dPJr/+aFP4OXY -DRtfbYQZJhMIfj1yHgpTdSU15z0Ld5/2wl0ATPN0W6w --> ssh-ed25519 FRQvIA a4zYtpYFVGSum3wD850lM/wEcokckt4mlDRsrb6QrHY -QF75fGiiKZc1oHSOdy+QvPnQ1hhaLRebaE7i0keZxHw ---- 8Y5Q9SlGWEzp9jeVcoHFrv3PR+eDyhOPFXIFRxZ1Koo -JDlv\lu$0 {riP7ϥP锓kr(PHW]r ّr \ No newline at end of file +-> ssh-ed25519 il3lzQ Ni2CHjeijXHfF62cUqVTm8MAOn6rRg8UrhqN6xvdkyk +DsT0Ysx88FlCLeRzoOGctX7KqatX9/UCr5WdtdLJAf4 +-> ssh-ed25519 1g/xww jRn91F29sISMyi41anAlzVCzt1t1DnUqxtryqkTQPlM +cysgZLQR0YhiJYXBl59DjKbm+N8FnjA46wkQtnAzBFA +-> ssh-ed25519 +kBihw t6wlSnDKGgSzGhNJnryXVbDR40DATaV3fHovtI/u7zo +zOyCZtzfLKeer9K6SMpfTxn6El4HB7gQFQqLOxIYB5U +-> ssh-ed25519 dbKeHw cn+8WTwis58bYm2pfEra6LeLvzEZ8GhZrOEeN+kkhCM +fnlUAj8JtG8+r7Cj8xYUgF+JM6Pwqawn4sGI1LOeN78 +-> ssh-ed25519 Svnssw zmDBR8TdRZ9NzNhwPYRN6c8naTxAkULyUZpKgk7Gshk +0XCwpegEIlGXhnzLLUtmciKQiYiZRgnSOSvCcYeXXk8 +--- D/lZ36n5sVste2NWfdOx8/klPh0CTmMjVQN74KIqDRY +]%C}NO"v#˱t_Q;^*!+<+dB/K` \ No newline at end of file diff --git a/secrets/authentik.toml.age b/secrets/authentik.toml.age deleted file mode 100644 index d3c91cc..0000000 Binary files a/secrets/authentik.toml.age and /dev/null differ diff --git a/secrets/borgmatic-passphrase.age b/secrets/borgmatic-passphrase.age deleted file mode 100644 index c3969d2..0000000 Binary files a/secrets/borgmatic-passphrase.age and /dev/null differ diff --git a/secrets/borgmatic-ssh-config.age b/secrets/borgmatic-ssh-config.age deleted file mode 100644 index 63dd59f..0000000 --- a/secrets/borgmatic-ssh-config.age +++ /dev/null @@ -1,16 +0,0 @@ -age-encryption.org/v1 --> ssh-ed25519 il3lzQ 6815+wa1JjdVUu8U8vaRah8kVsjR3Fsot99HKWl4SSA -hPYVZuN1yTKQYFIQvIRdmr400aijXleA22Bxh1nXKdc --> ssh-ed25519 1g/xww BPxSszlrjPTVJC+YOvo1N6ICUUdL7WKZX3DeambLjBY -JkJQFPGtxDtqeGj8Z1YtVq/pm6hgYKwzMW9MbtkvOwY --> ssh-ed25519 dbKeHw PU5cZrKCkAvUjI/opkboDQKSWJ8osAOQiI62f9lbfRY -ef1z6ZcBASkhC4fdcN+RRE7q28rB/DN8CVdoNVkC81I --> ssh-ed25519 3qPtug RWCMZiLQlS+bOOIBRGmoECOfqEI2uoaWCq/4ZuI86B4 -VOaLaH1VYnGoQzjb8seU6wVviB94W3qCdYW9Wf4PGIc --> ssh-ed25519 FRQvIA LCDwNMNVtTcI3GHPR2mcgtR16yAYYwLplI2nKUwNxDQ -vwXBIDlK7FBOsKt48Zv8mp0WFA/TKH2UJxtUxZoxzMI --> ssh-ed25519 +C0WRg a/R13LfNMjVjJxt2TtTHaqZOhsYJLY+HUGMHEDnkZWo -T2EfeE/a4W4bFvauynfh+4aJL1jhCpO8iBG2aTmKtyM ---- o7tyupfhbxh3dwSrBLsYX0V61va0USlqxheNsdBjVuQ -A q,:_aɪ)j12 #t,G* -XT(U5t6B皩80 *i׆^ߨ@aB@̃+oFwPci27YSXd g̲J \ No newline at end of file diff --git a/secrets/darwin-policies-json.age b/secrets/darwin-policies-json.age index 3f900dd..9fa2d2b 100644 Binary files a/secrets/darwin-policies-json.age and b/secrets/darwin-policies-json.age differ diff --git a/secrets/freshrss.toml.age b/secrets/freshrss.toml.age deleted file mode 100644 index 096f601..0000000 Binary files a/secrets/freshrss.toml.age and /dev/null differ diff --git a/secrets/network-information.age b/secrets/network-information.age index 2d42ae1..0de69b7 100644 Binary files a/secrets/network-information.age and b/secrets/network-information.age differ diff --git a/secrets/pihole.age b/secrets/pihole.age new file mode 100644 index 0000000..babead9 --- /dev/null +++ b/secrets/pihole.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 il3lzQ Q+/uqZhUWs5pb5T1ocD+/qTSo4DJbd/W1exruQ34zAE +8HFRvEblGVrkoVaqAl/Af6wrDn6A+3unZIMBipEkwgA +-> ssh-ed25519 1g/xww PqXxTvLaF6ZlcVov81VrVH130jFh2iGmHPRtBYV4ME4 +1VBknQzaNZyoz2wvgKX+IZGaOEnJ1xGvxPYxq10ar/U +-> ssh-ed25519 +kBihw QXNxY9OQeIM98OqmHoa/S2kMZqSX+ndgxGyCJpHJ+gg +b3DmfUswyPQ09sp57v3QMNEF/Ka3w9Qj2s1kGUSinmQ +-> ssh-ed25519 dbKeHw 5GzjKgjUX5e6Net7voWBykC17zRcdSFDFbDsSwp5FAU +GwTEg3YR9HdcQHPg+XjP2Lg1BpcWA4VunbZSBdxVaYU +-> ssh-ed25519 Svnssw imRjD5CJu/jOac3t/APHbYBnsyJVQdebR6K52A6GdwM +n+Q9kEEkYRBuEzWlSwbjJNsjF8uKloeUEWYxHa29B4U +-> ssh-ed25519 jb0ALQ 4qbGIofHcyhJVfL24peGqqzg0tFdxbWBHJFenwehIAI +Ta3ye4quyHvvE+2CGZwYvQMwWfdrLIdqADLvJYhllPY +--- 3hbht7PYqFafVmcQWQwv3q2gUXM8HXajtmAaMnrh59s + +X984R2,􈱨(#42#*, b禽H_z }߅x7A!))vʞ¨W-eX-G<@~Ek?kGlQK4c&*J9V_0 µz+ɰ¯C ўQGXkg* -jl31JMOE[=S \ No newline at end of file diff --git a/secrets_file.enc b/secrets_file.enc index 33fcb27..20df784 100644 --- a/secrets_file.enc +++ b/secrets_file.enc @@ -1,8 +1,10 @@ $ANSIBLE_VAULT;1.1;AES256 -33613635643765623937663135313833396162343134383466343966333964386364356134663264 -3137633339396462633431316634623834646437646162360a626564313831373761636161656232 -35316566336232666336646231356665366633303530623961666465366163306166623336656364 -3835353035333031620a633332376237336530343134623832363534383761616564616138363766 -30306361383462353361636161636335313461313835663362393839623735313738316465656537 -66396635323432376530346532353238346139376261366237343763373535623364633731323830 -333730373965613131336166626230333263 +65366137313461383534313965646333656565353061336361363661613033393264353661346337 +3838653162383134393463323631613439373663396363380a633339396236363962313333343465 +31623961393532666136616438633734366261353866383264323730383432326635626637343739 +3235313062623637380a386235316437396534353261383832643165316565386263396664363962 +62393364333335373631356161373263313930343565626433383539373030363662353630633933 +63336333613965653635313637336437653139616564313861336332323739653865383531356233 +31373530343766343131346663656566363038643230343462336332323135323337353539303763 +33366638393064323431323636346161343936643062323861313766613264336465326132333631 +33306666383561653965303539313366653030663330393363363565333439383133 diff --git a/secrets_harmony.enc b/secrets_harmony.enc new file mode 100644 index 0000000..e91177d --- /dev/null +++ b/secrets_harmony.enc @@ -0,0 +1,6 @@ +$ANSIBLE_VAULT;1.1;AES256 +38383539613238613864336630316433666436623334313334393762396536663530336264306661 +3338616565316138616666343862366638643134343931320a633366363539326461346636373738 +66393138653463663536313065623332383166386332303564323939336630333163623637386434 +6538393966633731660a616437356233643234363562366433663437383439326161353330356331 +63346432663036353332303266343361346266396437396131376531303265356233 diff --git a/secrets_odyssey.enc b/secrets_odyssey.enc index a7a96da..fba7129 100644 --- a/secrets_odyssey.enc +++ b/secrets_odyssey.enc @@ -1,9 +1,6 @@ $ANSIBLE_VAULT;1.1;AES256 -61363033383536303833366237323662663236313163663033306138383162383062643830616466 -6531636430613462646161343939343363663533373737340a613433363666353432383463356439 -33656266633131336565613433653062656563656637656464346232656238646339303961373265 -6639643637303433380a393163366331373964353261383662656664643031626432366231346332 -34303964346137616233343930333331306363326332383465653163386539306430303965316437 -30343333373565623431653436653832356366343937653136346535316166383262623730343831 -62376532346237323465653261316339353034323633623632313630666531373839633665333637 -34356162356565396564 +30343638643335363463653231623566623961613534323261393639623865633964653634333562 +3838613035393661656362383736313561366466396439390a383162366362643364636335613664 +39646137666437353762363764373562393736626530333336626261366232383063633732623238 +6531633638366335640a363461383535646663316533386137323966326237373836363561323462 +66646635383137333834363165666365366235333734646364616637383363666239 diff --git a/services/authentik.nix b/services/authentik.nix deleted file mode 100644 index f507dac..0000000 --- a/services/authentik.nix +++ /dev/null @@ -1,205 +0,0 @@ -{ config, pkgs, home-manager-quadlet-nix, ... }: -let - user = "authentik"; - state-directory = "/var/lib/authentik"; - port = "9000"; - -in { - # Secrets are translated in the system NixOS scope, but performed by the user, - # via a user systemd unit, so are available in the user's Podman secrets - age.secrets = { - "authentik.toml" = { - file = ./../secrets/authentik.toml.age; - owner = "${user}"; - }; - }; - - millironx.podman-secrets.authentik = { - user = "${user}"; - secrets-files = [ config.age.secrets."authentik.toml".path ]; - }; - - # Podman, unlike Docker apparently, does not automatically create mount points - # within folders, so every mounted folder needs to be specified here. - systemd.tmpfiles.rules = [ - "d ${state-directory} 1775 ${user} ${user} -" - "d ${state-directory}/database 1775 ${user} ${user} -" - "d ${state-directory}/media 1775 ${user} ${user} -" - "d ${state-directory}/certs 1775 ${user} ${user} -" - "d ${state-directory}/custom-templates 1775 ${user} ${user} -" - ]; - - services.caddy.virtualHosts."auth.millironx.com".extraConfig = '' - reverse_proxy http://127.0.0.1:${port} - ''; - - services.borgmatic.configurations."${config.networking.hostName}" = { - source_directories = [ - "${state-directory}/media" - "${state-directory}/certs" - "${state-directory}/custom-templates" - ]; - - postgresql_databases = [{ - name = "authentik"; - psql_command = - "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db psql --username=${user}"; - pg_dump_command = - "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db pg_dump --username=${user}"; - pg_restore_command = - "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec authentik-db pg_restore --username=${user}"; - }]; - }; - - # Create a dedicated user for this service - users.users."${user}" = { - # Group is technically not mandatory, but NixOS complains that an unset - # group is "unsafe." The group has to be declared below - group = "${user}"; - - # System users don't have a shell. For security purposes, that *would* be - # superior, but that means that, e.g. borgmatic can't `sudo` into the - # account to access Podman commands - isNormalUser = true; - - # A home directory is mandatory in order to allow systemd user units to be - # created and run - home = "${state-directory}"; - createHome = true; - - # Settings for running containers while a login shell is not active - linger = true; - autoSubUidGidRange = true; - }; - users.groups."${user}" = { }; - - home-manager.users."${user}" = { config, osConfig, ... }: { - imports = [ home-manager-quadlet-nix ]; - - home.stateVersion = "25.05"; - - virtualisation.quadlet = { - containers = { - authentik-db = { - autoStart = true; - containerConfig = { - image = "docker.io/library/postgres:16"; - environments = { - POSTGRES_DB = "${user}"; - POSTGRES_USER = "${user}"; - }; - secrets = [ - # POSTGRES_PASSWORD is used by the container to setup the - # database, PGPASSWORD is used by pg_dump to authenticate for - # backup purposes - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=POSTGRES_PASSWORD" - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env,target=PGPASSWORD" - ]; - - # Double dollarsigns are required for use of *container* environment - # variables, Nix escaping creates the weird $\${} syntax - healthCmd = "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"; - healthInterval = "30s"; - healthRetries = 5; - healthStartPeriod = "20s"; - - # Volumes have to be bound with the :U label to allow for username - # remapping in rootless containers. :Z/:z is not needed b/c NixOS - # does not support SELinux - volumes = - [ "${state-directory}/database:/var/lib/postgresql/data:U" ]; - - # A network is actually required for these containers to talk to one - # another. I suppose the more idiomatic way would be for these - # related containers to be in a "pod," but I'm still struggling - # learning the idiosyncrasies of quadlet/rootless/podman, so we'll - # stick with this for now - networks = - [ config.virtualisation.quadlet.networks.authentik-net.ref ]; - - }; - - # Allowing this container to start before the secrets are translated - # will lead to errors. Use osConfig b/c secrets are declared in the - # system NixOS scope, even though it is a user process. - unitConfig.Requires = - [ osConfig.millironx.podman-secrets.authentik.ref ]; - unitConfig.After = - [ osConfig.millironx.podman-secrets.authentik.ref ]; - }; - - authentik-worker = { - autoStart = true; - containerConfig = { - image = "ghcr.io/goauthentik/server:2025.10.2"; - environments = { - AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; - AUTHENTIK_POSTGRESQL__NAME = "${user}"; - AUTHENTIK_POSTGRESQL__USER = "${user}"; - }; - exec = "worker"; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" - "AUTHENTIK_SECRET_KEY,type=env" - ]; - volumes = [ - "${state-directory}/media:/media:U" - "${state-directory}/custom-templates:/templates:U" - "${state-directory}/certs:/certs:U" - ]; - networks = - [ config.virtualisation.quadlet.networks.authentik-net.ref ]; - }; - unitConfig.Requires = - [ config.virtualisation.quadlet.containers.authentik-db.ref ]; - unitConfig.After = - [ config.virtualisation.quadlet.containers.authentik-db.ref ]; - }; - - authentik = { - autoStart = true; - containerConfig = { - image = "ghcr.io/goauthentik/server:2025.10.2"; - environments = { - AUTHENTIK_POSTGRESQL__HOST = "authentik-db"; - AUTHENTIK_POSTGRESQL__NAME = "${user}"; - AUTHENTIK_POSTGRESQL__USER = "${user}"; - }; - exec = "server"; - secrets = [ - "AUTHENTIK_POSTGRESQL__PASSWORD,type=env" - "AUTHENTIK_SECRET_KEY,type=env" - "AUTHENTIK_EMAIL__HOST,type=env" - "AUTHENTIK_EMAIL__PORT,type=env" - "AUTHENTIK_EMAIL__USERNAME,type=env" - "AUTHENTIK_EMAIL__PASSWORD,type=env" - "AUTHENTIK_EMAIL__USE_SSL,type=env" - "AUTHENTIK_EMAIL__FROM,type=env" - ]; - - # Change from Traefik: publish ports to localhost only via 127.0.0.1 - # and then reverse proxy to that port. Authentik does not appear to - # have a way to configure the port, so we will use the default of - # 9000 for non-secured traffic. - publishPorts = [ "127.0.0.1:${port}:${port}" ]; - volumes = [ - "${state-directory}/media:/media:U" - "${state-directory}/custom-templates:/templates:U" - ]; - networks = - [ config.virtualisation.quadlet.networks.authentik-net.ref ]; - }; - unitConfig.Requires = - [ config.virtualisation.quadlet.containers.authentik-db.ref ]; - unitConfig.After = - [ config.virtualisation.quadlet.containers.authentik-db.ref ]; - }; - }; - - networks.authentik-net = { }; - - # One of the main advantages of using Quadlet - autoUpdate.enable = true; - }; - }; -} diff --git a/services/borgmatic.nix b/services/borgmatic.nix deleted file mode 100644 index c028df2..0000000 --- a/services/borgmatic.nix +++ /dev/null @@ -1,35 +0,0 @@ -{ pkgs, config, ... }: { - - # We don't want to expose the location where borg backups are going, so we - # will setup an encrypted ssh config that references the host/username - # combo as simply 'borgserver' - age.secrets = { - borgmatic-ssh-config = { file = ./../secrets/borgmatic-ssh-config.age; }; - borgmatic-passphrase = { file = ./../secrets/borgmatic-passphrase.age; }; - }; - - services.borgmatic = { - enable = true; - - # This is the bare-bones way to get Borgmatic up and running. Other services - # are expected to declare their stateful directories by adding to - # `services.borgmatic.configurations."${config.networking.hostName}".source_directories` - # and to add their databases to - # `services.borgmatic.configurations."${config.networking.hostName}".[mariadb|postgresql|etc]_databases` - - configurations."${config.networking.hostName}" = { - source_directories = [ "/home" "/root" ]; - repositories = [{ - label = "${config.networking.hostName}-default"; - path = "ssh://borgserver/./repo"; - }]; - ssh_command = - "${pkgs.openssh}/bin/ssh -F ${config.age.secrets.borgmatic-ssh-config.path}"; - encryption_passcommand = - "${pkgs.coreutils}/bin/cat ${config.age.secrets.borgmatic-passphrase.path}"; - keep_daily = 7; - keep_weekly = 4; - keep_monthly = 6; - }; - }; -} diff --git a/services/crowdsec.nix b/services/crowdsec.nix index 5c3e279..f7e2e5a 100644 --- a/services/crowdsec.nix +++ b/services/crowdsec.nix @@ -1,49 +1,90 @@ -{ pkgs, config, ... }: { +{ pkgs, config, ... }: +let + crowdsec-url = "127.0.0.1:2763"; + firewall-bouncer-name = "fw-bouncer"; + # Although this key can be reproduced by anyone who actually cares to, the + # Crowdsec API will not be exposed to the outside world, so keeping this key + # super secret really isn't that important to me. Still make it look random + # so that hungry botnets can't just slurp up the password in plaintext. + firewall-bouncer-key = builtins.hashString "sha256" + "${config.networking.hostName}-crowdsec-bouncer-salt"; + toMultiYAML = items: + pkgs.lib.concatMapStrings (item: + '' + + --- + '' + (pkgs.lib.generators.toYAML { } item) + "\n") items; +in { services = { crowdsec = { enable = true; - localConfig = { - acquisitions = [ - { - source = "journalctl"; - journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ]; - labels.type = "syslog"; - } - { - filenames = [ "/var/log/auth.log" ]; - labels.type = "syslog"; - } - { - filenames = [ "/var/log/syslog" "/var/log/kern.log" ]; - labels.type = "syslog"; - } - ]; - }; - hub = { - collections = [ - "crowdsecurity/base-http-scenarios" - "crowdsecurity/http-cve" - "crowdsecurity/http-dos" - "crowdsecurity/iptables" - "crowdsecurity/linux" - "crowdsecurity/sshd" - "crowdsecurity/whitelist-good-actors" - ]; - }; settings = { - general = { api.server.enable = true; }; - # See https://github.com/NixOS/nixpkgs/issues/445342 - lapi.credentialsFile = "/var/lib/crowdsec/lapi-credentials.yaml"; + api.server = { listen_uri = crowdsec-url; }; + allowLocalJournalAccess = true; + crowdsec_service.acquisition_path = pkgs.writeText "acquisitions.yaml" + (toMultiYAML [ + { + source = "journalctl"; + journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ]; + labels.type = "syslog"; + } + { + filenames = [ "/var/log/auth.log" ]; + labels.type = "syslog"; + } + { + filenames = [ "/var/log/syslog" "/var/log/kern.log" ]; + labels.type = "syslog"; + } + ]); }; - autoUpdateService = true; }; - crowdsec-firewall-bouncer = { enable = true; - registerBouncer.enable = true; + settings = { + api_url = firewall-bouncer-name; + api_key = firewall-bouncer-key; + }; }; }; - systemd.tmpfiles.rules = let cfg = config.services.crowdsec; - in [ "d /var/lib/crowdsec 0755 ${cfg.user} ${cfg.group}" ]; + systemd.services.crowdsec.serviceConfig = { + ExecStartPre = let + bouncer-script = pkgs.writeScriptBin "register-bouncer" '' + #!${pkgs.runtimeShell} + set -eu + set -o pipefail + + if ! cscli bouncers list | grep -q "${firewall-bouncer-name}"; then + cscli bouncers add "${firewall-bouncer-name}" --key "${firewall-bouncer-key}" + fi + ''; + collection-check = collection: '' + + if ! cscli collections list | grep -q "${collection}"; then + cscli collections install "${collection}" + fi + + ''; + collections = [ + "crowdsecurity/base-http-scenarios" + "crowdsecurity/http-cve" + "crowdsecurity/http-dos" + "crowdsecurity/iptables" + "crowdsecurity/linux" + "crowdsecurity/sshd" + "crowdsecurity/whitelist-good-actors" + ]; + collection-script = pkgs.writeScriptBin "install-collections" '' + #!${pkgs.runtimeShell} + set -eu + set -o pipefail + + ${pkgs.lib.concatMapStrings collection-check collections} + ''; + in [ + "${bouncer-script}/bin/register-bouncer" + "${collection-script}/bin/install-collections" + ]; + }; } diff --git a/services/freshrss.nix b/services/freshrss.nix deleted file mode 100644 index 2f142ff..0000000 --- a/services/freshrss.nix +++ /dev/null @@ -1,146 +0,0 @@ -{ config, pkgs, home-manager-quadlet-nix, ... }: - -let - user = "freshrss"; - port = "37374"; - stateDirectory = "/var/lib/freshrss"; - serviceContainer = "freshrss"; - stateSubDir = subDir: "${stateDirectory}/${subDir}"; - createTmpfilesRule = subDir: "d ${stateSubDir subDir} 1755 ${user} ${user}"; - - dbDirectories = [ "database" ]; - serviceDirectories = [ "data" "extensions" ]; -in { - age.secrets = { - "freshrss.toml" = { - file = ./../secrets/freshrss.toml.age; - owner = "${user}"; - }; - }; - - millironx.podman-secrets.freshrss = { - user = "${user}"; - secrets-files = [ config.age.secrets."freshrss.toml".path ]; - }; - - services.caddy.virtualHosts."feeds.millironx.com".extraConfig = '' - reverse_proxy http://127.0.0.1:${port} { - header_up X-Forwarded-Port 443 - } - ''; - - systemd.tmpfiles.rules = builtins.map createTmpfilesRule - ([ stateDirectory ] ++ dbDirectories ++ serviceDirectories); - - services.borgmatic.configurations."${config.networking.hostName}" = { - source_directories = builtins.map stateSubDir dbDirectories; - - postgresql_databases = [{ - name = serviceContainer; - psql_command = - "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${serviceContainer}-db psql --username=${user}"; - pg_dump_command = - "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${serviceContainer}-db pg_dump --username=${user}"; - pg_restore_command = - "/run/wrappers/bin/sudo -iu ${user} ${pkgs.podman}/bin/podman exec ${serviceContainer}-db pg_restore --username=${user}"; - }]; - }; - - users.users."${user}" = { - group = "${user}"; - isNormalUser = true; - home = "${stateDirectory}"; - createHome = true; - linger = true; - autoSubUidGidRange = true; - }; - users.groups."${user}" = { }; - - home-manager.users."${user}" = { config, osConfig, ... }: { - imports = [ home-manager-quadlet-nix ]; - - home.stateVersion = "25.05"; - - virtualisation.quadlet = let - inherit (config.virtualisation.quadlet) containers; - inherit (config.virtualisation.quadlet) networks; - secrets = osConfig.millironx.podman-secrets.freshrss; - - in { - containers = { - "${serviceContainer}-db" = { - autoStart = true; - containerConfig = { - image = "docker.io/library/postgres:16"; - environments = { - POSTGRES_DB = "${user}"; - POSTGRES_USER = "${user}"; - }; - secrets = [ - "POSTGRES_PASSWORD,type=env" - "POSTGRES_PASSWORD,type=env,target=PGPASSWORD" - ]; - healthCmd = "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"; - healthInterval = "30s"; - healthRetries = 5; - healthStartPeriod = "20s"; - volumes = - [ "${stateDirectory}/database:/var/lib/postgresql/data:U" ]; - networks = [ networks."${serviceContainer}".ref ]; - }; - unitConfig.Requires = [ secrets.ref ]; - unitConfig.After = [ secrets.ref ]; - }; - - "${serviceContainer}" = { - autoStart = true; - containerConfig = { - image = "docker.io/freshrss/freshrss:1"; - # Required to allow the container to talk to the host ports, in - # other words, to resolve Authentik correctly - addHosts = [ "auth.millironx.com:host-gateway" ]; - environments = { - TZ = osConfig.time.timeZone; - CRON_MIN = "2,32"; - LISTEN = "0.0.0.0:${port}"; - TRUSTED_PROXY = "172.16.0.1/12 192.168.0.1/16"; - OIDC_ENABLED = "1"; - OIDC_PROVIDER_METADATA_URL = - "https://auth.millironx.com/application/o/freshrss/.well-known/openid-configuration"; - OIDC_REMOTE_USER_CLAIM = "preferred_username"; - OIDC_SCOPES = "openid email profile"; - OIDC_X_FORWARDED_HEADERS = - "X-Forwarded-Host X-Forwarded-Port X-Forwarded-Proto"; - }; - secrets = [ - "OIDC_CLIENT_ID,type=env" - "OIDC_CLIENT_SECRET,type=env" - "OIDC_CLIENT_CRYPTO_KEY,type=env" - ]; - healthCmd = "cli/health.php"; - healthTimeout = "10s"; - healthStartPeriod = "60s"; - healthStartupInterval = "11s"; - healthInterval = "75s"; - healthRetries = 3; - networks = [ networks."${serviceContainer}".ref ]; - publishPorts = [ "127.0.0.1:${port}:${port}" ]; - volumes = [ - "${stateDirectory}/data:/var/www/FreshRSS/data:U" - "${stateDirectory}/extensions:/var/www/FreshRSS/extensions:U" - ]; - }; - unitConfig.Requires = - [ secrets.ref containers."${serviceContainer}-db".ref ]; - unitConfig.After = - [ secrets.ref containers."${serviceContainer}-db".ref ]; - }; - }; - - networks."${serviceContainer}" = { }; - - autoUpdate.enable = true; - autoEscape = true; - }; - }; -} diff --git a/services/nixos-update.nix b/services/nixos-update.nix new file mode 100644 index 0000000..f0678ec --- /dev/null +++ b/services/nixos-update.nix @@ -0,0 +1,50 @@ +# This file is designed to be used in the imports +{ pkgs, config, ... }: + +{ + environment.systemPackages = [ + (pkgs.writeScriptBin "update-nixos" '' + #!${pkgs.bash}/bin/bash + echo "Requesting system update..." + ${pkgs.systemd}/bin/systemctl start nixos-update.service + '') + ]; + + # Service to update NixOS configuration from git repo + systemd.services."nixos-update" = { + description = "Update NixOS configuration from git repository"; + path = with pkgs; [ coreutils ]; + script = '' + # Rebuild the system directly from the remote flake + ${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --flake git+https://code.millironx.com/millironx/nix-dotfiles.git#${config.networking.hostName} + ''; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + }; + + # Timer to run the update service daily at 3am + systemd.timers."nixos-update" = { + wantedBy = [ "timers.target" ]; + description = "Run NixOS update daily at 3am"; + timerConfig = { + OnCalendar = "3:00"; + Persistent = true; + Unit = "nixos-update.service"; + }; + }; + + # Polkit rule to allow non-root users to trigger the update + security.polkit.extraConfig = '' + polkit.addRule(function(action, subject) { + if (action.id == "org.freedesktop.systemd1.manage-units" && + action.lookup("unit") == "nixos-update.service" && + action.lookup("verb") == "start" && + subject.isInGroup("wheel")) { + return polkit.Result.YES; + } + }); + ''; + +} diff --git a/services/pihole.nix b/services/pihole.nix new file mode 100644 index 0000000..ed4cd19 --- /dev/null +++ b/services/pihole.nix @@ -0,0 +1,27 @@ +{ config, ... }: + +{ + age.secrets = { + pihole-credentials = { + file = ./../secrets/pihole.age; + owner = "root"; + group = "root"; + }; + }; + virtualisation = { + quadlet = { + containers = { + pihole = { + containerConfig = { + image = "docker.io/pihole/pihole:2025.06.2"; + publishPorts = + [ "53:53/tcp" "53:53/udp" "80:80/tcp" "443:443/tcp" ]; + environmentFiles = [ config.age.secrets.pihole-credentials.path ]; + networks = [ "bridge" ]; + dns = [ "127.0.0.1" "194.242.2.9" "9.9.9.9" ]; + }; + }; + }; + }; + }; +} diff --git a/services/samba.nix b/services/samba.nix index b248d33..e6fa607 100644 --- a/services/samba.nix +++ b/services/samba.nix @@ -2,6 +2,7 @@ services.samba = { enable = true; package = pkgs.sambaFull; + securityType = "user"; openFirewall = true; settings = { global = { diff --git a/systems/darwin/corianne.nix b/systems/darwin/corianne.nix index c83a9a1..db34258 100644 --- a/systems/darwin/corianne.nix +++ b/systems/darwin/corianne.nix @@ -15,8 +15,6 @@ in { rig-install ]; - age.secrets.firefox-policy.file = ./../../secrets/darwin-policies-json.age; - # Use a custom configuration.nix location. # $ darwin-rebuild switch -I darwin-config=$HOME/.config/nixpkgs/darwin/configuration.nix environment.darwinConfig = "$HOME/.config/home-manager/configuration.nix"; @@ -26,27 +24,9 @@ in { }; # Auto upgrade nix package and the daemon service. - nix = { - enable = true; - gc = { - automatic = true; - interval = { Weekday = 1; }; - options = '' - --delete-older-than 14d - ''; - }; - # Needed for rosetta-builder, see - # - # - linux-builder = { - enable = true; - ephemeral = true; - }; - extraOptions = '' - extra-platforms = x86_64-darwin - ''; - }; - nix-rosetta-builder.onDemand = true; + nix.enable = true; + #services.nix-daemon.tempDir = "/nix/tmp"; + nix.package = pkgs.nix; # Create /etc/zshrc that loads the nix-darwin environment. programs.zsh.enable = true; # default shell on catalina @@ -91,12 +71,11 @@ in { in [ (sysApp "Firefox") (sysApp "Thunderbird") - (sysApp "Microsoft Outlook") - (sysApp "Zed") (sysApp "Logseq") + (sysApp "Zed") (sysApp "Steam") - (localApp "Instinct Dashboard") - (localApp "Carestream") + (chromeApp "Instinct Dashboard") + (chromeApp "Carestream") ]; show-process-indicators = true; show-recents = false; @@ -151,11 +130,6 @@ in { --user=${config.system.primaryUser} \ --set-home \ _rig-install ${r-version} - - echo "Applying custom defaults..." - /usr/bin/defaults import \ - /Library/Preferences/org.mozilla.firefox \ - ${config.age.secrets.firefox-policy.path} ''; nix.settings.experimental-features = [ "nix-command" "flakes" ]; @@ -203,18 +177,23 @@ in { "docker" "docker-buildx" "docker-credential-helper" + "firefoxpwa" "mpv" ]; casks = [ "alt-tab" + "anki" "db-browser-for-sqlite" "dolphin" "firefox" "freetube" + "ghostty" "inkscape" "iterm2" + "logi-options+" "logseq" "macfuse" + "musescore" "nextcloud" "openrct2" "qownnotes" @@ -222,7 +201,6 @@ in { "rig" "rstudio" "signal" - "skim" "slack" "stats" "steam" @@ -232,7 +210,6 @@ in { "ungoogled-chromium" "veracrypt" "vlc" - "vienna" "vorta" "zed" "zotero" diff --git a/systems/linux/bosephus.nix b/systems/linux/bosephus.nix index 6c8d181..3a0a271 100644 --- a/systems/linux/bosephus.nix +++ b/systems/linux/bosephus.nix @@ -8,7 +8,9 @@ imports = [ ./hardware-configuration/bosephus.nix ./hardware-configuration/bosephus-external-drives.nix + ./../../services/nixos-update.nix ./../../services/samba.nix + ./../../services/pihole.nix ]; # Bootloader. @@ -16,8 +18,8 @@ boot.loader.efi.canTouchEfiVariables = true; # Ignore lid - so I can close without having the system go into sleep mode - services.logind.settings.Login.HandleLidSwitch = "ignore"; - services.logind.settings.Login.HandleLidSwitchDocked = "ignore"; + services.logind.lidSwitch = "ignore"; + services.logind.lidSwitchDocked = "ignore"; # Secrets age.secrets = { diff --git a/systems/linux/mcentire.nix b/systems/linux/mcentire.nix index fa0c08b..07135d1 100644 --- a/systems/linux/mcentire.nix +++ b/systems/linux/mcentire.nix @@ -3,11 +3,8 @@ { imports = [ # Include the results of the hardware scan. ./hardware-configuration/mcentire.nix - ./../../modules/podman-secrets.nix - ./../../services/borgmatic.nix + ./../../services/nixos-update.nix ./../../services/crowdsec.nix - ./../../services/authentik.nix - ./../../services/freshrss.nix ]; # Use the GRUB 2 boot loader. @@ -18,7 +15,6 @@ useDHCP = false; interfaces.eth0.useDHCP = true; hostName = "mcentire"; # Define your hostname. - firewall.allowedTCPPorts = [ 80 443 ]; }; # Set your time zone. @@ -44,7 +40,7 @@ millironx = { isNormalUser = true; description = "Thomas A. Christensen II"; - extraGroups = [ "adm" "wheel" ]; + extraGroups = [ "wheel" ]; }; }; @@ -58,15 +54,8 @@ services = { openssh.enable = true; tailscale.enable = true; - caddy.enable = true; - - # Do not "enable" database services, but include the package configuration - # so that borgmatic does not freak out about unset variables - postgresql.package = pkgs.postgresql_17; }; - virtualisation.quadlet.enable = true; - system.stateVersion = "25.05"; # Did you read the comment? nix = { extraOptions = "experimental-features = nix-command flakes"; }; } diff --git a/playbooks/templates/policies.json b/templates/policies.json similarity index 100% rename from playbooks/templates/policies.json rename to templates/policies.json