diff --git a/clanServices/users/default.nix b/clanServices/users/default.nix index f92ac0003..bd15cc178 100644 --- a/clanServices/users/default.nix +++ b/clanServices/users/default.nix @@ -37,6 +37,22 @@ - `clan vars get ` ''; }; + regularUser = lib.mkOption { + type = lib.types.bool; + default = true; + example = false; + description = '' + Whether the user should be a regular user or a system user. + + Regular users are normal users that can log in and have a home directory. + + System users are used for system services and do not have a home directory. + + !!! Warning + `root` cannot be a regular user. + You must set this to `false` for `root` + ''; + }; groups = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; @@ -73,8 +89,8 @@ ... }: { - users.mutableUsers = false; users.users.${settings.user} = { + isNormalUser = settings.regularUser; extraGroups = settings.groups; hashedPasswordFile = @@ -122,4 +138,11 @@ }; }; }; + + perMachine = { + nixosModule = { + # Immutable users to ensure that this module has exclusive control over the users. + users.mutableUsers = false; + }; + }; } diff --git a/clanServices/users/tests/vm/default.nix b/clanServices/users/tests/vm/default.nix index c879ea136..147fecc8a 100644 --- a/clanServices/users/tests/vm/default.nix +++ b/clanServices/users/tests/vm/default.nix @@ -13,6 +13,8 @@ roles.default.machines."server".settings = { user = "root"; prompt = false; + # Important: 'root' must not be a regular user. See: https://github.com/NixOS/nixpkgs/issues/424404 + regularUser = false; }; }; user-password-test = { @@ -31,7 +33,6 @@ server = { users.users.testuser.group = "testuser"; users.groups.testuser = { }; - users.users.testuser.isNormalUser = true; }; }; diff --git a/templates/clan/default/modules/shared.nix b/templates/clan/default/modules/shared.nix index 4f25bb63b..672e4e23b 100644 --- a/templates/clan/default/modules/shared.nix +++ b/templates/clan/default/modules/shared.nix @@ -23,6 +23,5 @@ "video" "input" ]; - uid = 1000; }; } diff --git a/templates/clan/flake-parts/clan.nix b/templates/clan/flake-parts/clan.nix index a29e89894..f18dd7a8a 100644 --- a/templates/clan/flake-parts/clan.nix +++ b/templates/clan/flake-parts/clan.nix @@ -1,81 +1,45 @@ -{ self }: { - meta.name = "__CHANGE_ME__"; # Ensure this is unique among all clans you want to use. + # Ensure this is unique among all clans you want to use. + meta.name = "__CHANGE_ME__"; - inherit self; + # Docs: See https://docs.clan.lol/reference/clanServices + inventory.instances = { + + # Docs: https://docs.clan.lol/reference/clanServices/admin/ + # Admin service for managing machines + # This service adds a root password and SSH access. + admin = { + roles.default.tags.all = { }; + roles.default.settings.allowedKeys = { + # Insert the public key that you want to use for SSH access. + # All keys will have ssh access to all machines ("tags.all" means 'all machines'). + # Alternatively set 'users.users.root.openssh.authorizedKeys.keys' in each machine + "admin-machine-1" = "__YOUR_PUBLIC_KEY__"; + }; + }; + + # Docs: https://docs.clan.lol/reference/clanServices/zerotier/ + # The lines below will define a zerotier network and add all machines as 'peer' to it. + # !!! Manual steps required: + # - Define a controller machine for the zerotier network. + # - Deploy the controller machine first to initilize the network. + zerotier = { + # Replace with the name (string) of your machine that you will use as zerotier-controller + # See: https://docs.zerotier.com/controller/ + # Deploy this machine first to create the network secrets + roles.controller.machines."__YOUR_CONTROLLER__" = { }; + # Peers of the network + # tags.all means 'all machines' will joined + roles.peer.tags.all = { }; + }; + }; + + # Additional NixOS configuration can be added here. + # machines/jon/configuration.nix will be automatically imported. + # See: https://docs.clan.lol/guides/more-machines/#automatic-registration machines = { - # "jon" will be the hostname of the machine - jon = - { pkgs, ... }: - { - imports = [ - ./modules/shared.nix - ./modules/disko.nix - ./machines/jon/configuration.nix - ]; - - nixpkgs.hostPlatform = "x86_64-linux"; - - # Set this for clan commands use ssh i.e. `clan machines update` - # If you change the hostname, you need to update this line to root@ - # This only works however if you have avahi running on your admin machine else use IP - clan.core.networking.targetHost = pkgs.lib.mkDefault "root@jon"; - - # You can get your disk id by running the following command on the installer: - # Replace with the IP of the installer printed on the screen or by running the `ip addr` command. - # ssh root@ lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT - disko.devices.disk.main = { - device = "/dev/disk/by-id/__CHANGE_ME__"; - }; - - # IMPORTANT! Add your SSH key here - # e.g. > cat ~/.ssh/id_ed25519.pub - users.users.root.openssh.authorizedKeys.keys = throw '' - Don't forget to add your SSH key here! - users.users.root.openssh.authorizedKeys.keys = [ "" ] - ''; - - # Zerotier needs one controller to accept new nodes. Once accepted - # the controller can be offline and routing still works. - clan.core.networking.zerotier.controller.enable = true; - }; - # "sara" will be the hostname of the machine - sara = - { pkgs, ... }: - { - imports = [ - ./modules/shared.nix - ./modules/disko.nix - ./machines/sara/configuration.nix - ]; - - nixpkgs.hostPlatform = "x86_64-linux"; - - # Set this for clan commands use ssh i.e. `clan machines update` - # If you change the hostname, you need to update this line to root@ - # This only works however if you have avahi running on your admin machine else use IP - clan.core.networking.targetHost = pkgs.lib.mkDefault "root@sara"; - - # You can get your disk id by running the following command on the installer: - # Replace with the IP of the installer printed on the screen or by running the `ip addr` command. - # ssh root@ lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT - disko.devices.disk.main = { - device = "/dev/disk/by-id/__CHANGE_ME__"; - }; - - # IMPORTANT! Add your SSH key here - # e.g. > cat ~/.ssh/id_ed25519.pub - users.users.root.openssh.authorizedKeys.keys = throw '' - Don't forget to add your SSH key here! - users.users.root.openssh.authorizedKeys.keys = [ "" ] - ''; - - /* - After jon is deployed, uncomment the following line - This will allow sara to share the VPN overlay network with jon - The networkId is generated by the first deployment of jon - */ - # clan.core.networking.zerotier.networkId = builtins.readFile ../../vars/per-machine/jon/zerotier/zerotier-network-id/value; - }; + # jon = { config, ... }: { + # environment.systemPackages = [ pkgs.asciinema ]; + # }; }; } diff --git a/templates/clan/flake-parts/flake.nix b/templates/clan/flake-parts/flake.nix index 340c9b2a2..722e5dc3c 100644 --- a/templates/clan/flake-parts/flake.nix +++ b/templates/clan/flake-parts/flake.nix @@ -6,7 +6,6 @@ outputs = inputs@{ - self, flake-parts, ... }: @@ -22,7 +21,9 @@ ]; # https://docs.clan.lol/guides/getting-started/flake-parts/ - clan = import ./clan.nix { inherit self; }; + clan = { + imports = [ ./clan.nix ]; + }; perSystem = { pkgs, inputs', ... }: diff --git a/templates/flake-module.nix b/templates/flake-module.nix index 366fd7ef7..806bb6426 100644 --- a/templates/flake-module.nix +++ b/templates/flake-module.nix @@ -5,6 +5,27 @@ }; flake = { + checks.x86_64-linux.equal-templates = + inputs.nixpkgs.legacyPackages.x86_64-linux.runCommand "minimal-clan-flake" { } + '' + file1=${./clan/default/clan.nix} + file2=${./clan/flake-parts/clan.nix} + + echo "Comparing $file1 and $file2" + if cmp -s "$file1" "$file2"; then + echo "clan.nix files are identical" + else + echo "clan.nix files are out of sync" + echo "Please make sure to keep templates clan.nix files in sync." + echo "files: templates/clan/default/clan.nix templates/clan/flake-parts/clan.nix" + echo "--------------------------------\n" + diff "$file1" "$file2" + echo "--------------------------------\n\n" + exit 1 + fi + + touch $out + ''; checks.x86_64-linux.template-minimal = let path = self.clan.templates.clan.minimal.path;