diff --git a/devshells/java17-maven/flake.lock b/devshells/java17-maven/flake.lock index ae71305..b4da842 100644 --- a/devshells/java17-maven/flake.lock +++ b/devshells/java17-maven/flake.lock @@ -22,16 +22,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1736684107, - "narHash": "sha256-vH5mXxEvZeoGNkqKoCluhTGfoeXCZ1seYhC2pbMN0sg=", + "lastModified": 1766473571, + "narHash": "sha256-5G1NDO2PulBx1RoaA6U1YoUDX0qZslpPxv+n5GX6Qto=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "635e887b48521e912a516625eee7df6cf0eba9c1", + "rev": "76701a179d3a98b07653e2b0409847499b2a07d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixos-24.11", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } diff --git a/devshells/java17-maven/flake.nix b/devshells/java17-maven/flake.nix index 106308a..169ccb2 100644 --- a/devshells/java17-maven/flake.nix +++ b/devshells/java17-maven/flake.nix @@ -1,6 +1,6 @@ { description = "A basic flake with a shell"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; inputs.systems.url = "github:nix-systems/default"; inputs.flake-utils = { url = "github:numtide/flake-utils"; diff --git a/devshells/java21-maven/flake.lock b/devshells/java21-maven/flake.lock index 72a721c..b4da842 100644 --- a/devshells/java21-maven/flake.lock +++ b/devshells/java21-maven/flake.lock @@ -22,16 +22,16 @@ }, "nixpkgs": { "locked": { - "lastModified": 1734435836, - "narHash": "sha256-kMBQ5PRiFLagltK0sH+08aiNt3zGERC2297iB6vrvlU=", + "lastModified": 1766473571, + "narHash": "sha256-5G1NDO2PulBx1RoaA6U1YoUDX0qZslpPxv+n5GX6Qto=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4989a246d7a390a859852baddb1013f825435cee", + "rev": "76701a179d3a98b07653e2b0409847499b2a07d3", "type": "github" }, "original": { "owner": "NixOS", - "ref": "nixpkgs-unstable", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } diff --git a/devshells/java21-maven/flake.nix b/devshells/java21-maven/flake.nix index 79f8a2c..943795f 100644 --- a/devshells/java21-maven/flake.nix +++ b/devshells/java21-maven/flake.nix @@ -1,6 +1,6 @@ { description = "A basic flake with a shell"; - inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; inputs.systems.url = "github:nix-systems/default"; inputs.flake-utils = { url = "github:numtide/flake-utils"; diff --git a/flake.lock b/flake.lock index 000b4f1..d4e6d06 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,28 @@ { "nodes": { + "agenix": { + "inputs": { + "darwin": [], + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1762618334, + "narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=", + "owner": "ryantm", + "repo": "agenix", + "rev": "fcdea223397448d35d9b31f798479227e80183f6", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, "auto-cpufreq": { "inputs": { "nixpkgs": [ @@ -7,11 +30,11 @@ ] }, "locked": { - "lastModified": 1748372346, - "narHash": "sha256-7y7NZ6uW0GbT0h4gqfD2xvRuJj5IlPGw32oIc9Twga8=", + "lastModified": 1769608722, + "narHash": "sha256-yWUG0Emd9EuqIZ8jQ6fxqf7USw7Gtcqb4+sBhn+S+Wg=", "owner": "AdnanHodzic", "repo": "auto-cpufreq", - "rev": "becd5b89963fa54fef3566147f3fd2087f8a5842", + "rev": "a11a98c46bf6a77d0c2e0ea8d87acef78507cae5", "type": "github" }, "original": { @@ -20,6 +43,26 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769524058, + "narHash": "sha256-zygdD6X1PcVNR2PsyK4ptzrVEiAdbMqLos7utrMDEWE=", + "owner": "nix-community", + "repo": "disko", + "rev": "71a3fc97d80881e91710fe721f1158d3b96ae14d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -36,6 +79,21 @@ "type": "github" } }, + "flake-compat_2": { + "locked": { + "lastModified": 1747046372, + "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "gitignore": { "inputs": { "nixpkgs": [ @@ -61,20 +119,41 @@ "home-manager": { "inputs": { "nixpkgs": [ + "agenix", "nixpkgs" ] }, "locked": { - "lastModified": 1749154018, - "narHash": "sha256-gjN3j7joRvT3a8Zgcylnd4NFsnXeDBumqiu4HmY1RIg=", + "lastModified": 1745494811, + "narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=", "owner": "nix-community", "repo": "home-manager", - "rev": "7aae0ee71a17b19708b93b3ed448a1a0952bf111", + "rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be", "type": "github" }, "original": { "owner": "nix-community", - "ref": "release-25.05", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager_2": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1769580047, + "narHash": "sha256-tNqCP/+2+peAXXQ2V8RwsBkenlfWMERb+Uy6xmevyhM=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "366d78c2856de6ab3411c15c1cb4fb4c2bf5c826", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-25.11", "repo": "home-manager", "type": "github" } @@ -87,11 +166,11 @@ "pre-commit-hooks": "pre-commit-hooks" }, "locked": { - "lastModified": 1746906641, - "narHash": "sha256-b6few4tkqN2TWdrZTwWOjsWxA11rle7y9pcc0/ynuoE=", + "lastModified": 1764660538, + "narHash": "sha256-kEWb9Hc2OxdLhJ1pRdW7zRZ57Mul3/Jpy3vyhQ8Yq6o=", "owner": "~rycee", "repo": "lazy-apps", - "rev": "0b30a0bf524a661f9657c441d021aaa5724f12ff", + "rev": "4ddc92c77213f8ed3ddef1868f4a19002afa728a", "type": "sourcehut" }, "original": { @@ -102,11 +181,11 @@ }, "nixos-hardware": { "locked": { - "lastModified": 1749195551, - "narHash": "sha256-W5GKQHgunda/OP9sbKENBZhMBDNu2QahoIPwnsF6CeM=", + "lastModified": 1769302137, + "narHash": "sha256-QEDtctEkOsbx8nlFh4yqPEOtr4tif6KTqWwJ37IM2ds=", "owner": "NixOS", "repo": "nixos-hardware", - "rev": "4602f7e1d3f197b3cb540d5accf5669121629628", + "rev": "a351494b0e35fd7c0b7a1aae82f0afddf4907aa8", "type": "github" }, "original": { @@ -118,20 +197,36 @@ }, "nixpkgs": { "locked": { - "lastModified": 1749086602, - "narHash": "sha256-DJcgJMekoxVesl9kKjfLPix2Nbr42i7cpEHJiTnBUwU=", + "lastModified": 1769598131, + "narHash": "sha256-e7VO/kGLgRMbWtpBqdWl0uFg8Y2XWFMdz0uUJvlML8o=", "owner": "nixos", "repo": "nixpkgs", - "rev": "4792576cb003c994bd7cc1edada3129def20b27d", + "rev": "fa83fd837f3098e3e678e6cf017b2b36102c7211", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-25.05", + "ref": "nixos-25.11", "repo": "nixpkgs", "type": "github" } }, + "nixpkgs-libvncserver": { + "locked": { + "lastModified": 1750111231, + "narHash": "sha256-3a7Tha/RwYlzH/v3PJrG7+HjOj4c6YOv2K8sqdGsHVQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e6f23dc08d3624daab7094b701aa3954923c6bbb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e6f23dc08d3624daab7094b701aa3954923c6bbb", + "type": "github" + } + }, "nixpkgs-stable": { "locked": { "lastModified": 1730741070, @@ -148,6 +243,38 @@ "type": "github" } }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1769318308, + "narHash": "sha256-Mjx6p96Pkefks3+aA+72lu1xVehb6mv2yTUUqmSet6Q=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1cd347bf3355fce6c64ab37d3967b4a2cb4b878c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-25.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1769861584, + "narHash": "sha256-Tu85RXpHMAWmsltAEKsG1IB7JfNGbekeHh2CSR0/xG8=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "015e5f32a6258dc210b8e02fb47d86983959e243", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "pull/483348/merge", + "repo": "nixpkgs", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": "flake-compat", @@ -172,17 +299,89 @@ "type": "github" } }, + "proxmox-nixos": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs-libvncserver": "nixpkgs-libvncserver", + "nixpkgs-stable": "nixpkgs-stable_2", + "utils": "utils" + }, + "locked": { + "lastModified": 1769870714, + "narHash": "sha256-wjwCj70iiFXoAasQto+3jTaA4wCMOAs/rdX+nsmtBrQ=", + "owner": "SaumonNet", + "repo": "proxmox-nixos", + "rev": "c1f79f104930347a0b84abbca0d42884063a8c09", + "type": "github" + }, + "original": { + "owner": "SaumonNet", + "repo": "proxmox-nixos", + "type": "github" + } + }, "root": { "inputs": { + "agenix": "agenix", "auto-cpufreq": "auto-cpufreq", - "home-manager": "home-manager", + "disko": "disko", + "home-manager": "home-manager_2", "lazy-apps": "lazy-apps", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs", - "systems": "systems" + "nixpkgs-unstable": "nixpkgs-unstable", + "proxmox-nixos": "proxmox-nixos", + "secrets": "secrets", + "systems": "systems_3" + } + }, + "secrets": { + "flake": false, + "locked": { + "lastModified": 1769426267, + "narHash": "sha256-OBHSfMHZ+sWEtigOxTfIGnkZLPOz2P7VR8+KA2KY89g=", + "ref": "refs/heads/main", + "rev": "ebefef468e16eb692df0a3d54352c94a56110a97", + "revCount": 20, + "type": "git", + "url": "ssh://git@git.jfreudenberger.de/JuliusFreudenberger/nix-private.git" + }, + "original": { + "type": "git", + "url": "ssh://git@git.jfreudenberger.de/JuliusFreudenberger/nix-private.git" } }, "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": 1689347949, "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", @@ -196,6 +395,24 @@ "repo": "default-linux", "type": "github" } + }, + "utils": { + "inputs": { + "systems": "systems_2" + }, + "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" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 558ac71..1c26073 100644 --- a/flake.nix +++ b/flake.nix @@ -1,12 +1,21 @@ { description = "NixOS configuration of Julius Freudenberger"; + nixConfig = { + extra-substituters = [ + "https://cache.saumon.network/proxmox-nixos" + ]; + extra-trusted-public-keys = [ + "proxmox-nixos:D9RYSWpQQC/msZUWphOY2I5RLH5Dd6yQcaHIuug7dWM=" + ]; + }; + inputs = { - #nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; - nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11"; nixos-hardware.url = "github:NixOS/nixos-hardware/master"; home-manager = { - url = "github:nix-community/home-manager/release-25.05"; + url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; }; auto-cpufreq = { @@ -17,17 +26,35 @@ url = "sourcehut:~rycee/lazy-apps"; inputs.nixpkgs.follows = "nixpkgs"; }; - + proxmox-nixos.url = "github:SaumonNet/proxmox-nixos"; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + darwin.follows = ""; + }; + }; + secrets = { + url = "git+ssh://git@git.jfreudenberger.de/JuliusFreudenberger/nix-private.git"; + flake = false; + }; systems.url = "github:nix-systems/default-linux"; }; outputs = { self, nixpkgs, - #nixpkgs-unstable, + nixpkgs-unstable, nixos-hardware, home-manager, auto-cpufreq, + proxmox-nixos, + agenix, + disko, systems, ... } @ inputs: let @@ -54,10 +81,6 @@ system = "x86_64-linux"; specialArgs = { - #pkgs-unstable = import nixpkgs-unstable { - # inherit system; - # config.allowUnfree = true; - #}; inherit inputs outputs username; }; @@ -90,6 +113,44 @@ ./hosts/backup-raspberrypi ]; }; + + server = nixpkgs.lib.nixosSystem rec { + system = "x86_64-linux"; + + specialArgs = { + inherit inputs outputs; + }; + + modules = [ + ./hosts/nixos-server-test + proxmox-nixos.nixosModules.proxmox-ve + + ({...}: { + nixpkgs.overlays = [ + proxmox-nixos.overlays.${system} + ]; + }) + ]; + }; + + srv01-hf = nixpkgs.lib.nixosSystem rec { + system = "x86_64-linux"; + + specialArgs = { + inherit inputs outputs; + pkgs-unstable = import nixpkgs-unstable { + inherit system; + config.allowUnfree = true; + }; + }; + + modules = [ + disko.nixosModules.disko + agenix.nixosModules.default + ./hosts/srv01.hf + ]; + }; + }; }; } diff --git a/hosts/nixos-server-test/default.nix b/hosts/nixos-server-test/default.nix new file mode 100644 index 0000000..409e2fa --- /dev/null +++ b/hosts/nixos-server-test/default.nix @@ -0,0 +1,96 @@ +{ inputs, outputs, config, lib, pkgs, ... }: + +{ + imports = + [ + ../../modules/nix.nix + ../../modules/locale.nix + ../../modules/server-cli.nix + ../../modules/sshd.nix + # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + # Use the GRUB 2 boot loader. + boot = { + loader.grub = { + enable = true; + device = "/dev/vda"; + }; + tmp.useTmpfs = true; + }; + networking.hostName = "nixos-server"; # Define your hostname. + users = { + users = { + julius = { + isNormalUser = true; + uid = 1000; + extraGroups = [ "wheel" "julius" ]; + }; + }; + groups = { + julius = { + gid = 1000; + }; + }; + }; + + nix.settings = { + substituters = [ + "https://cache.saumon.network/proxmox-nixos" + ]; + trusted-public-keys = [ + "proxmox-nixos:D9RYSWpQQC/msZUWphOY2I5RLH5Dd6yQcaHIuug7dWM=" + ]; + }; + + services.proxmox-ve = { + enable = true; + ipAddress = "192.168.122.71"; + + # Make vmbr0 bridge visible in Proxmox web interface + bridges = [ "vmbr0" ]; + }; + + networking.useDHCP = false; + + systemd.network = { + enable = true; + + networks."10-lan" = { + matchConfig.Name = [ "enp1s0" ]; + networkConfig = { + Bridge = "vmbr0"; + }; + }; + + netdevs."vmbr0" = { + netdevConfig = { + Name = "vmbr0"; + Kind = "bridge"; + }; + }; + + networks."10-lan-bridge" = { + matchConfig.Name = "vmbr0"; + networkConfig = { + IPv6AcceptRA = true; + DHCP = "ipv4"; + }; + linkConfig.RequiredForOnline = "routable"; + }; + }; + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "25.05"; # Did you read the comment? +} diff --git a/hosts/nixos-server-test/hardware-configuration.nix b/hosts/nixos-server-test/hardware-configuration.nix new file mode 100644 index 0000000..6dfd7c4 --- /dev/null +++ b/hosts/nixos-server-test/hardware-configuration.nix @@ -0,0 +1,31 @@ +# 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 + "/profiles/qemu-guest.nix") + ]; + + boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/e46c412a-8b6d-41b8-b53c-65d7a8fc39ed"; + fsType = "ext4"; + }; + + 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.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/hosts/srv01.hf/default.nix b/hosts/srv01.hf/default.nix new file mode 100644 index 0000000..cbfa9e5 --- /dev/null +++ b/hosts/srv01.hf/default.nix @@ -0,0 +1,97 @@ +{ inputs, outputs, config, lib, pkgs, ... }: + +{ + imports = + [ + ../../modules/disko/efi-full-btrfs.nix + ./secrets.nix + + ../../users/julius/nixos-server.nix + ../../users/nixremote.nix + ../../modules/nix.nix + ../../modules/network-server.nix + ../../modules/locale.nix + ../../modules/server-cli.nix + ../../modules/sshd.nix + ../../modules/qemu-guest.nix + ../../modules/docker.nix + ../../modules/teleport.nix + ../../modules/portainer_agent.nix + ../../modules/pangolin.nix + ../../modules/newt.nix + ../../modules/dockhand.nix + ../../modules/auto-upgrade.nix + # Include the results of the hardware scan. + ./hardware-configuration.nix + ]; + + services.openssh.openFirewall = false; + services.teleport = { + enable = true; + settings.teleport = { + ca_pin = config.age.secrets."teleport-ca_pin".path; + auth_token = config.age.secrets."teleport-join_token".path; + }; + }; + + virtualisation.oci-containers.containers.portainer_agent.environmentFiles = [ config.age.secrets."portainer-join_token".path ]; + + services = { + pangolin = { + dnsProvider = "netcup"; + baseDomain = "juliusfr.eu"; + letsEncryptEmail = "contact@jfreudenberger.de"; + environmentFile = config.age.secrets."pangolin".path; + }; + traefik = { + environmentFiles = [ config.age.secrets."netcup-dns".path ]; + }; + }; + + services.newt-docker = { + enable = true; + pangolinEndpoint = "https://pangolin.juliusfr.eu"; + connectionSecret = config.age.secrets."newt"; + }; + + services.dockhand = { + enable = true; + appUrl = "dockhand.juliusfr.eu"; + }; + + systemd.network = { + enable = true; + networks."10-wan" = { + matchConfig.Name = "ens18"; + networkConfig.DHCP = "no"; + address = [ + "77.90.17.93/24" + "2a06:de00:100:63::2/64" + ]; + routes = [ + { Gateway = "77.90.17.1"; } + { Gateway = "2a06:de00:100::1"; GatewayOnLink = true; } + ]; + dns = [ "9.9.9.9" ]; + }; + }; + + # Disable classic networking configuration + networking.useDHCP = lib.mkForce false; + + networking.hostName = "srv01-hf"; # Define your hostname. + + # This option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "25.05"; # Did you read the comment? +} diff --git a/hosts/srv01.hf/hardware-configuration.nix b/hosts/srv01.hf/hardware-configuration.nix new file mode 100644 index 0000000..d152a40 --- /dev/null +++ b/hosts/srv01.hf/hardware-configuration.nix @@ -0,0 +1,24 @@ +# 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 + "/profiles/qemu-guest.nix") + ]; + + boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "sr_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + # 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.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/hosts/srv01.hf/secrets.nix b/hosts/srv01.hf/secrets.nix new file mode 100644 index 0000000..a328f24 --- /dev/null +++ b/hosts/srv01.hf/secrets.nix @@ -0,0 +1,11 @@ +{ inputs, ... }: +{ + age.secrets = { + teleport-ca_pin.file = "${inputs.secrets}/secrets/teleport/ca_pin"; + teleport-join_token.file = "${inputs.secrets}/secrets/srv01-hf/teleport_auth_token"; + portainer-join_token.file = "${inputs.secrets}/secrets/srv01-hf/portainer_join_token"; + netcup-dns.file = "${inputs.secrets}/secrets/dns-management/netcup"; + pangolin.file = "${inputs.secrets}/secrets/srv01-hf/pangolin"; + newt.file = "${inputs.secrets}/secrets/srv01-hf/newt"; + }; +} diff --git a/modules/arcane.nix b/modules/arcane.nix new file mode 100644 index 0000000..160088f --- /dev/null +++ b/modules/arcane.nix @@ -0,0 +1,64 @@ +{ + config, + lib, + ... +}: +let + cfg = config.services.arcane; +in { + options.services.arcane = { + enable = lib.mkEnableOption "arcane, a modern Docker management UI"; + appUrl = lib.mkOption { + description = "External URL arcane will be reachable from, without protocol"; + type = lib.types.str; + }; + secretFile = lib.mkOption { + description = '' + Agenix secret containing the following needed environment variables in dotenv notation: + - ENCRYPTION_KEY + - JWT_SECRET + - OIDC_CLIENT_ID + - OIDC_CLIENT_SECRET + - OIDC_ISSUER_URL + - OIDC_ADMIN_CLAIM + - OIDC_ADMIN_VALUE + ''; + }; + }; + + config = lib.mkIf cfg.enable { + virtualisation.oci-containers.containers = { + arcane = { + image = "ghcr.io/getarcaneapp/arcane:v1.11.2"; + volumes = [ + "/var/run/docker.sock:/var/run/docker.sock" + ]; + environment = { + APP_URL = "https://${cfg.appUrl}"; + PUID = "1000"; + PGID = "1000"; + LOG_LEVEL = "info"; + LOG_JSON = "false"; + OIDC_ENABLED = "true"; + OIDC_SCOPES = "openid email profile groups"; + DATABASE_URL = "file:data/arcane.db?_pragma=journal_mode(WAL)&_pragma=busy_timeout(2500)&_txlock=immediate"; + }; + environmentFiles = [ + cfg.secretFile.path + ]; + networks = [ + "traefik" + ]; + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.arcane.middlewares" = "arcane-oidc-auth@file"; + "traefik.http.routers.arcane.rule" = "Host(`${cfg.appUrl}`)"; + "traefik.http.services.arcane.loadbalancer.server.port" = "3552"; + }; + extraOptions = [ + ''--mount=type=volume,source=arcane-data,target=/app/data,volume-driver=local'' + ]; + }; + }; + }; +} diff --git a/modules/auto-upgrade.nix b/modules/auto-upgrade.nix new file mode 100644 index 0000000..3dc9849 --- /dev/null +++ b/modules/auto-upgrade.nix @@ -0,0 +1,37 @@ +{ + inputs, + pkgs, + ... +}: { + system.autoUpgrade = { + enable = true; + flags = [ + "--recreate-lock-file" # Deprecated, but will hopefully be reintroduced + "-L" + ]; + flake = inputs.self.outPath; + dates = "02:00"; + randomizedDelaySec = "45min"; + allowReboot = true; + rebootWindow = { + lower = "01:00"; + upper = "05:00"; + }; + }; + + # Also needs access to the nix-private repo which contains the encrypted secrets + programs.ssh = { + extraConfig = " + Host git.jfreudenberger.de + Port 222 + User git + IdentityFile /etc/ssh/ssh_host_ed25519_key + "; + knownHostsFiles = [ + (pkgs.writeText "forgejo.keys" ''[git.jfreudenberger.de]:222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK+uqIeb9+AoqwD0Z6xLKI2dsRoS9Qh/VwboYfGpBJd+ +[git.jfreudenberger.de]:222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8GDSt4LsCzOoIZkqZRLgXyTLyHoJu62cFFP88i8GpSadyV6mJPkK5p2mgBzN/BM9I/G2VWfvqdM8Fy/7p3S8kDhmmkOk1AK7C/+qaQKsKcQauJuzNXlwMHG1Ivath80TO9PIQc9jYakP9xl8SACd5bwkvfEm3rS5awZ8T2hWgnsgO8pFHFOFmFnVbujXZk58FVTCxpgyPqjFv76JSYxpHk1VtiQ52jScsreOImEOWWg88f9IM9etWcshuxte4zudaqc2KjjAB6pYMuVj7O6cwMXKjCUxTzyomWjr2JoEruIslifbZ6bJGgswg5ENJSKURuMPgTuGM6Nrjp75V/yFD +[git.jfreudenberger.de]:222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOS447cAWRZgHPs6MOoRS6/J66oY753QPiM7BI63/qNDd5qrCan153dJd5lBGwDR0vMWiV/0cmzuACfP5QS1Lv8= + '') + ]; + }; +} diff --git a/modules/disko/efi-full-btrfs.nix b/modules/disko/efi-full-btrfs.nix new file mode 100644 index 0000000..59e8b26 --- /dev/null +++ b/modules/disko/efi-full-btrfs.nix @@ -0,0 +1,61 @@ +{ + disko.devices = { + disk = { + sda = { + type = "disk"; + device = "/dev/sda"; + content = { + type = "gpt"; + partitions = { + MBR = { + type = "EF02"; # for grub MBR + size = "1M"; + priority = 1; # Needs to be first partition + }; + ESP = { + priority = 1; + name = "ESP"; + size = "500M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" ]; + }; + }; + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; # Override existing partition + # Subvolumes must set a mountpoint in order to be mounted, + # unless their parent is mounted + subvolumes = { + # Subvolume name is different from mountpoint + "/rootfs" = { + mountpoint = "/"; + }; + # Subvolume name is the same as the mountpoint + "/home" = { + mountOptions = [ "compress=zstd" ]; + mountpoint = "/home"; + }; + # Sub(sub)volume doesn't need a mountpoint as its parent is mounted + "/home/julius" = { }; + # Parent is not mounted so the mountpoint must be set + "/nix" = { + mountOptions = [ "compress=zstd" "noatime" ]; + mountpoint = "/nix"; + }; + }; + + mountpoint = "/partition-root"; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/docker.nix b/modules/docker.nix index b9f7aa1..2c88d1a 100644 --- a/modules/docker.nix +++ b/modules/docker.nix @@ -4,8 +4,15 @@ ... }: { - virtualisation.docker = { - enable = true; + virtualisation = { + docker = { + enable = true; + daemon.settings = { + ipv6 = true; + ip6tables = true; + }; + }; + oci-containers.backend = "docker"; }; } diff --git a/modules/dockhand.nix b/modules/dockhand.nix new file mode 100644 index 0000000..7eeaf8e --- /dev/null +++ b/modules/dockhand.nix @@ -0,0 +1,46 @@ +{ + config, + lib, + ... +}: +let + cfg = config.services.dockhand; +in { + options.services.dockhand = { + enable = lib.mkEnableOption "dockhand, a powerful, intuitive Docker platform"; + appUrl = lib.mkOption { + description = "External URL dockhand will be reachable from, without protocol"; + type = lib.types.str; + }; + }; + + config = lib.mkIf cfg.enable { + virtualisation.oci-containers.containers = { + dockhand = { + image = "fnsys/dockhand:v1.0.12"; + volumes = [ + "/var/run/docker.sock:/var/run/docker.sock" + ]; + environment = { + PUID = "1000"; + PGID = "1000"; + }; + networks = [ + "pangolin" + ]; + labels = { + "pangolin.public-resources.dockhand.name" = "dockhand"; + "pangolin.public-resources.dockhand.full-domain" = cfg.appUrl; + "pangolin.public-resources.dockhand.protocol" = "http"; + "pangolin.public-resources.dockhand.auth.sso-enabled" = "true"; + "pangolin.public-resources.dockhand.auth.auto-login-idp" = "1"; + "pangolin.public-resources.dockhand.targets[0].method" = "http"; + }; + extraOptions = [ + ''--mount=type=volume,source=dockhand-data,target=/app/data,volume-driver=local'' + ''--group-add=131'' # docker group + ]; + }; + }; + }; +} diff --git a/modules/gui-coding.nix b/modules/gui-coding.nix index 33056ef..223f2b6 100644 --- a/modules/gui-coding.nix +++ b/modules/gui-coding.nix @@ -4,9 +4,8 @@ ... }: { environment.systemPackages = with pkgs; [ - jetbrains.idea-ultimate - jetbrains.pycharm-professional - jetbrains.phpstorm + jetbrains.idea + jetbrains.pycharm vscodium-fhs zed-editor.fhs diff --git a/modules/i3.nix b/modules/i3.nix index dcefbd7..80fcb57 100644 --- a/modules/i3.nix +++ b/modules/i3.nix @@ -18,7 +18,7 @@ lightlocker xautolock # lock screen after some time i3status # provide information to i3bar - i3-gaps # i3 with gaps + i3 # i3 with gaps nitrogen # set wallpaper acpi # battery information arandr # screen layout manager diff --git a/modules/k3s.nix b/modules/k3s.nix new file mode 100644 index 0000000..2dab28a --- /dev/null +++ b/modules/k3s.nix @@ -0,0 +1,28 @@ +{ + pkgs, + lib, + ... +}: { + + services.k3s = { + enable = true; + role = "server"; + token = "verysecrettoken"; + extraFlags = toString ([ + "--write-kubeconfig-mode \"0644\"" + "--disable servicelb" + "--disable traefik" + "--disable local-storage" + ]); + }; + + networking.firewall.allowedTCPPorts = [ + 6443 + 2379 + 2380 + ]; + networking.firewall.allowedUDPPorts = [ + 8472 + ]; + +} diff --git a/modules/laptop.nix b/modules/laptop.nix index 73f9fa6..49e7492 100644 --- a/modules/laptop.nix +++ b/modules/laptop.nix @@ -6,10 +6,10 @@ boot.kernelPackages = pkgs.linuxKernel.packages.linux_zen; - services.logind = { - lidSwitch = "suspend-then-hibernate"; - lidSwitchDocked = "suspend-then-hibernate"; - powerKey = "ignore"; + services.logind.settings.Login = { + HandleLidSwitch= "suspend-then-hibernate"; + HandleLidSwitchDocked = "suspend-then-hibernate"; + HandlePowerKey = "ignore"; }; programs.auto-cpufreq.enable = true; diff --git a/modules/network-server.nix b/modules/network-server.nix index 99645e8..017b1b0 100644 --- a/modules/network-server.nix +++ b/modules/network-server.nix @@ -5,5 +5,6 @@ }: { networking = { useDHCP = true; + firewall.allowPing = false; }; } diff --git a/modules/newt.nix b/modules/newt.nix new file mode 100644 index 0000000..1f8dafd --- /dev/null +++ b/modules/newt.nix @@ -0,0 +1,72 @@ +{ + pkgs, + config, + lib, + ... +}: +let + + cfg = config.services.newt-docker; + +in { + + options.services.newt-docker = { + enable = lib.mkEnableOption "Newt, user space tunnel client for Pangolin"; + pangolinEndpoint = lib.mkOption { + description = "External URL of the Pangolin instance"; + type = lib.types.str; + }; + connectionSecret = lib.mkOption { + description = "Secrets for Pangolin authentication."; + type = lib.types.anything; + }; + }; + + config = lib.mkIf cfg.enable { + virtualisation.oci-containers.containers = { + newt = { + image = "fosrl/newt:1.9.0"; + autoStart = true; + networks = [ + "pangolin" + ]; + environment = { + PANGOLIN_ENDPOINT = cfg.pangolinEndpoint; + DOCKER_SOCKET = "/var/run/docker.sock"; + }; + environmentFiles = [ cfg.connectionSecret.path ]; + volumes = [ + "/var/run/docker.sock:/var/run/docker.sock:ro" + ]; + extraOptions = [ + "--add-host=host.docker.internal:host-gateway" + ]; + }; + }; + + systemd.services."docker-pangolin" = { + after = [ + "docker-network-pangolin.service" + ]; + requires = [ + "docker-network-pangolin.service" + ]; + }; + + systemd.services."docker-network-pangolin" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + }; + script = '' + docker network inspect pangolin || docker network create pangolin --ipv4 --ipv6 --subnet=172.18.0.0/16 --gateway=172.18.0.1 + ''; + }; + + networking.firewall.extraCommands = '' + iptables -A INPUT -p icmp --source 100.89.128.0/24 -j ACCEPT + iptables -A INPUT -p tcp --source 172.18.0.0/12 --dport 22 -j ACCEPT + ''; + + }; +} diff --git a/modules/pangolin.nix b/modules/pangolin.nix new file mode 100644 index 0000000..3da3c9e --- /dev/null +++ b/modules/pangolin.nix @@ -0,0 +1,43 @@ +{ + pkgs-unstable, + ... +}: { + + services = { + pangolin = { + enable = true; + package = pkgs-unstable.fosrl-pangolin; + openFirewall = true; + settings = { + app = { + save_logs = true; + log_failed_attempts = true; + }; + domains = { + domain1 = { + prefer_wildcard_cert = true; + }; + }; + flags = { + disable_signup_without_invite = true; + disable_user_create_org = true; + }; + }; + }; + }; + +} + +# Settings needed on the host +# +# services = { +# pangolin = { +# dnsProvider = ""; +# baseDomain = ""; +# letsEncryptEmail = ""; +# environmentFile = config.age.secrets."".path; +# }; +# traefik = { +# environmentFiles = [ config.age.secrets."".path ]; +# }; +# }; diff --git a/modules/portainer_agent.nix b/modules/portainer_agent.nix new file mode 100644 index 0000000..408834b --- /dev/null +++ b/modules/portainer_agent.nix @@ -0,0 +1,21 @@ +{ + ... +}: { + virtualisation.oci-containers.containers = { + portainer_agent = { + image = "portainer/agent:2.33.2"; + volumes = [ + "/var/run/docker.sock:/var/run/docker.sock" + "/var/lib/docker/volumes:/var/lib/docker/volumes" + "/:/host" + ]; + environment = { + EDGE = "1"; + CAP_HOST_MANAGEMENT = "1"; + }; + extraOptions = [ + ''--mount=type=volume,source=portainer_agent,target=/data,volume-driver=local'' + ]; + }; + }; +} diff --git a/modules/qemu-guest.nix b/modules/qemu-guest.nix new file mode 100644 index 0000000..97e2081 --- /dev/null +++ b/modules/qemu-guest.nix @@ -0,0 +1,7 @@ +{ + ... +}: { + + services.qemuGuest.enable = true; + +} diff --git a/modules/sshd.nix b/modules/sshd.nix new file mode 100644 index 0000000..49af4a5 --- /dev/null +++ b/modules/sshd.nix @@ -0,0 +1,13 @@ +{ + pkgs, + lib, + ... +}: { + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + PermitRootLogin = "no"; + }; + }; +} diff --git a/modules/systemd-boot.nix b/modules/systemd-boot.nix new file mode 100644 index 0000000..02f515d --- /dev/null +++ b/modules/systemd-boot.nix @@ -0,0 +1,15 @@ +{ + ... +}: { + + boot = { + loader = { + systemd-boot = { + enable = true; + }; + efi.canTouchEfiVariables = true; + }; + tmp.useTmpfs = true; + }; + +} diff --git a/modules/traefik.nix b/modules/traefik.nix new file mode 100644 index 0000000..92b1204 --- /dev/null +++ b/modules/traefik.nix @@ -0,0 +1,221 @@ +{ + pkgs, + config, + lib, + ... +}: +let + + cfg = config.services.traefik-docker; + + mapOidcClientNameToEnv = stringToReplace: lib.replaceString "-" "_" (lib.toUpper stringToReplace); + + traefik-mtls-config = (pkgs.formats.yaml { }).generate "traefik-mtls-config" { + tls.options.default.clientAuth = { + caFiles = "caFiles/root_ca.crt"; + clientAuthType = "VerifyClientCertIfGiven"; + }; + }; + +in { + + options.services.traefik-docker = { + enable = lib.mkEnableOption "traefik web server hosted as OCI container"; + dashboardUrl = lib.mkOption { + description = "External URL the traefik dashboard will be reachable from, without protocol"; + type = lib.types.str; + }; + dnsSecrets = lib.mkOption { + description = "Secrets for DNS providers."; + type = lib.types.listOf lib.types.anything; + }; + mTLSCaCertSecret = lib.mkOption { + description = "Agenix secret containing the CA file to verify client certificates against."; + }; + oidcAuthProviderUrl = lib.mkOption { + description = "Provider URL of OIDC auth provider."; + type = lib.types.str; + }; + oidcClients = lib.mkOption { + example = '' + immich = { + scopes = [ + "openid" + "email" + "profile" + ]; + enableBypassUsingClientCertificate = true; + usePkce = true; + }; + ''; + description = "Attribute set of OIDC clients with their configurations."; + type = lib.types.attrsOf ( + lib.types.submodule { + options = { + secret = lib.mkOption { + description = ''Agenix secret containing the following needed environment variables in dotenv notation: + - _OIDC_AUTH_SECRET + - _OIDC_AUTH_PROVIDER_CLIENT_ID + - _OIDC_CLIENT_SECRET + ''; + }; + scopes = lib.mkOption { + default = [ "openid" ]; + example = [ "openid" "email" "profile" "groups" ]; + description = "OIDC scopes to request from auth provider."; + type = lib.types.listOf lib.types.str; + }; + usePkce = lib.mkOption { + default = true; + description = "Whether to enable PKCE for this provider."; + type = lib.types.bool; + }; + enableBypassUsingClientCertificate = lib.mkOption { + default = false; + description = "Whether to allow bypassing OIDC protection when a verified client certificate is presented."; + type = lib.types.bool; + }; + useClaimsFromUserInfo = lib.mkOption { + default = false; + description = "When enabled, an additional request to the provider's userinfo_endpoint is made to validate the token and to retrieve additional claims. The userinfo claims are merged directly into the token claims, with userinfo values overriding token values for non-security-critical claims."; + type = lib.types.bool; + }; + headers = lib.mkOption { + default = []; + description = "Headers to be added to the upstream request. Templating is possible. Documentation can be found here: https://traefik-oidc-auth.sevensolutions.cc/docs/getting-started/middleware-configuration"; + type = lib.types.listOf (lib.types.submodule { + options = { + Name = lib.mkOption { + description = "The name of the header which should be added to the upstream request."; + type = lib.types.str; + }; + Value = lib.mkOption { + description = "The value of the header, which can use Go-Templates."; + type = lib.types.str; + }; + }; + }); + }; + }; + } + ); + }; + }; + + config = lib.mkIf cfg.enable { + virtualisation.oci-containers.containers = { + traefik = { + image = "traefik:v3.6.6"; + cmd = [ + "--providers.docker=true" + "--providers.docker.exposedByDefault=false" + "--providers.docker.network=traefik" + "--providers.file.directory=/dynamic-config" + "--log.level=INFO" + "--api=true" + "--ping=true" + "--entrypoints.web.address=:80" + "--entrypoints.websecure.address=:443" + "--entrypoints.websecure.transport.respondingTimeouts.readTimeout=600s" + "--entrypoints.websecure.transport.respondingTimeouts.idleTimeout=600s" + "--entrypoints.websecure.transport.respondingTimeouts.writeTimeout=600s" + "--entrypoints.web.http.redirections.entrypoint.to=websecure" + "--entrypoints.websecure.asDefault=true" + "--entrypoints.websecure.http.middlewares=strip-mtls-headers@docker,pass-tls-client-cert@docker" + "--entrypoints.websecure.http.tls.certresolver=letsencrypt" + "--certificatesresolvers.letsencrypt.acme.storage=/certs/acme.json" + "--certificatesresolvers.letsencrypt.acme.dnschallenge=true" + "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=netcup" + "--experimental.plugins.traefik-oidc-auth.modulename=github.com/sevensolutions/traefik-oidc-auth" + "--experimental.plugins.traefik-oidc-auth.version=v0.17.0" + ]; + autoStart = true; + ports = [ + "80:80" + "443:443" + ]; + networks = [ + "traefik" + ]; + environment = { + OIDC_AUTH_PROVIDER_URL = cfg.oidcAuthProviderUrl; + }; + environmentFiles = lib.forEach cfg.dnsSecrets (secret: secret.path) ++ (lib.mapAttrsToList (oidcClientName: oidcClientConfig: oidcClientConfig.secret.path) cfg.oidcClients); + labels = { + "traefik.enable" = "true"; + "traefik.http.routers.dashboard.rule" = "Host(`${cfg.dashboardUrl}`)"; + "traefik.http.routers.dashboard.service" = "dashboard@internal"; + "traefik.http.routers.dashboard.middlewares" = "traefik-dashboard-oidc-auth@file"; + "traefik.http.routers.api.rule" = "Host(`${cfg.dashboardUrl}`) && (PathPrefix(`/api`) || PathPrefix(`/oidc/callback`))"; + "traefik.http.routers.api.service" = "api@internal"; + "traefik.http.routers.api.middlewares" = "traefik-dashboard-oidc-auth@file"; + "traefik.http.middlewares.strip-mtls-headers.headers.customrequestheaders.X-Forwarded-Tls-Client-Cert" = ""; + "traefik.http.middlewares.pass-tls-client-cert.passtlsclientcert.pem" = "true"; + }; + volumes = let + oidc-config = lib.mapAttrs' ( + oidcClientName: oidcClientConfig: + lib.nameValuePair "${oidcClientName}-oidc-auth" { + plugin.traefik-oidc-auth = { + LogLevel = "INFO"; + Secret = ''{{ env "${mapOidcClientNameToEnv oidcClientName}_OIDC_AUTH_SECRET" }}''; + Provider = { + Url = ''{{ env "OIDC_AUTH_PROVIDER_URL" }}''; + ClientId = ''{{ env "${mapOidcClientNameToEnv oidcClientName}_OIDC_AUTH_PROVIDER_CLIENT_ID" }}''; + ClientSecret = ''{{ env "${mapOidcClientNameToEnv oidcClientName}_OIDC_AUTH_PROVIDER_CLIENT_SECRET" }}''; + UsePkce = oidcClientConfig.usePkce; + UseClaimsFromUserInfo = oidcClientConfig.useClaimsFromUserInfo; + }; + Scopes = oidcClientConfig.scopes; + LoginUrl = ''{{ env "OIDC_AUTH_PROVIDER_URL" }}''; + } // (lib.attrsets.optionalAttrs oidcClientConfig.enableBypassUsingClientCertificate { + BypassAuthenticationRule = "HeaderRegexp(`X-Forwarded-Tls-Client-Cert`, `.+`)"; + }) // (lib.attrsets.optionalAttrs ((lib.length oidcClientConfig.headers) > 0) { + Headers = oidcClientConfig.headers; + }); + } + ) cfg.oidcClients; + traefik-oidc-authentication-config = (pkgs.formats.yaml {}).generate "traefik-oidc-auth" { + http.middlewares = oidc-config; + }; + in [ + "/var/run/docker.sock:/var/run/docker.sock" + "${traefik-oidc-authentication-config}:/dynamic-config/traefik-oidc-auth.yaml:ro" + "${traefik-mtls-config}:/dynamic-config/traefik-mtls.yaml:ro" + "${cfg.mTLSCaCertSecret.path}:/caFiles/root_ca.crt:ro" + ]; + extraOptions = [ + ''--mount=type=volume,source=certs,target=/certs,volume-driver=local'' + "--add-host=host.docker.internal:host-gateway" + "--health-cmd=wget --spider --quiet http://localhost:8080/ping" + "--health-interval=10s" + "--health-timeout=5s" + "--health-retries=3" + "--health-start-period=5s" + ]; + }; + }; + + systemd.services."docker-traefik" = { + after = [ + "docker-network-traefik.service" + ]; + requires = [ + "docker-network-traefik.service" + ]; + }; + + systemd.services."docker-network-traefik" = { + path = [ pkgs.docker ]; + serviceConfig = { + Type = "oneshot"; + }; + script = '' + docker network inspect traefik || docker network create traefik --ipv4 --ipv6 --subnet=172.18.0.0/16 --gateway=172.18.0.1 + ''; + }; + + networking.firewall.extraCommands = "iptables -t nat -I PREROUTING -s 172.18.0.0/16 -d 172.18.0.0/16 -j MASQUERADE"; + + }; +} diff --git a/modules/typesetting.nix b/modules/typesetting.nix index 56ba34e..b4e321f 100644 --- a/modules/typesetting.nix +++ b/modules/typesetting.nix @@ -5,7 +5,7 @@ }: { environment.systemPackages = with pkgs; [ typst - typstfmt + typstyle texliveFull diff --git a/modules/virtualization.nix b/modules/virtualization.nix index b1cde0f..4eb21ce 100644 --- a/modules/virtualization.nix +++ b/modules/virtualization.nix @@ -3,12 +3,16 @@ lib, ... }: { - environment.systemPackages = with pkgs; [ - virt-manager - ]; - virtualisation = { - libvirtd.enable = true; + libvirtd = { + enable = true; + qemu = { + swtpm.enable = true; + vhostUserPackages = [ pkgs.virtiofsd ]; + }; + }; spiceUSBRedirection.enable = true; }; + + programs.virt-manager.enable = true; } diff --git a/users/julius/nixos-server.nix b/users/julius/nixos-server.nix new file mode 100644 index 0000000..5802f86 --- /dev/null +++ b/users/julius/nixos-server.nix @@ -0,0 +1,23 @@ +{ + ... +}: { + + users = { + users = { + julius = { + initialPassword = "password"; + isNormalUser = true; + uid = 1000; + group = "julius"; + extraGroups = [ "wheel" ]; + }; + }; + groups = { + julius = { + gid = 1000; + }; + }; + }; + + nix.settings.trusted-users = [ "julius" ]; +} diff --git a/users/julius/nixos.nix b/users/julius/nixos.nix index a424826..81c9e60 100644 --- a/users/julius/nixos.nix +++ b/users/julius/nixos.nix @@ -6,7 +6,7 @@ }: { users.users.julius = { isNormalUser = true; - extraGroups = [ "wheel" "networkmanager" "docker" "libvirtd" ]; + extraGroups = [ "wheel" "networkmanager" "docker" "libvirtd" "kvm" ]; shell = pkgs.zsh; }; diff --git a/users/nixremote.nix b/users/nixremote.nix new file mode 100644 index 0000000..b0075cb --- /dev/null +++ b/users/nixremote.nix @@ -0,0 +1,13 @@ +{ + ... +}: { + users.users = { + nixremote = { + isNormalUser = true; + uid = 1100; + group = "users"; + }; + }; + + nix.settings.trusted-users = [ "nixremote" ]; +}