Merge pull request 'modules/user: Improve user module' (#4305) from user into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4305
This commit is contained in:
hsjobeki
2025-07-12 11:57:44 +00:00
6 changed files with 90 additions and 81 deletions

View File

@@ -37,6 +37,22 @@
- `clan vars get <machine-name> <name-of-password-variable>` - `clan vars get <machine-name> <name-of-password-variable>`
''; '';
}; };
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 { groups = lib.mkOption {
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
@@ -73,8 +89,8 @@
... ...
}: }:
{ {
users.mutableUsers = false;
users.users.${settings.user} = { users.users.${settings.user} = {
isNormalUser = settings.regularUser;
extraGroups = settings.groups; extraGroups = settings.groups;
hashedPasswordFile = hashedPasswordFile =
@@ -122,4 +138,11 @@
}; };
}; };
}; };
perMachine = {
nixosModule = {
# Immutable users to ensure that this module has exclusive control over the users.
users.mutableUsers = false;
};
};
} }

View File

@@ -13,6 +13,8 @@
roles.default.machines."server".settings = { roles.default.machines."server".settings = {
user = "root"; user = "root";
prompt = false; prompt = false;
# Important: 'root' must not be a regular user. See: https://github.com/NixOS/nixpkgs/issues/424404
regularUser = false;
}; };
}; };
user-password-test = { user-password-test = {
@@ -31,7 +33,6 @@
server = { server = {
users.users.testuser.group = "testuser"; users.users.testuser.group = "testuser";
users.groups.testuser = { }; users.groups.testuser = { };
users.users.testuser.isNormalUser = true;
}; };
}; };

View File

@@ -23,6 +23,5 @@
"video" "video"
"input" "input"
]; ];
uid = 1000;
}; };
} }

View File

@@ -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 = { machines = {
# "jon" will be the hostname of the machine # jon = { config, ... }: {
jon = # environment.systemPackages = [ pkgs.asciinema ];
{ 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@<new-hostname>
# 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 <IP> with the IP of the installer printed on the screen or by running the `ip addr` command.
# ssh root@<IP> 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 = [ "<YOUR SSH_KEY>" ]
'';
# 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@<new-hostname>
# 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 <IP> with the IP of the installer printed on the screen or by running the `ip addr` command.
# ssh root@<IP> 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 = [ "<YOUR SSH_KEY>" ]
'';
/*
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;
};
}; };
} }

View File

@@ -6,7 +6,6 @@
outputs = outputs =
inputs@{ inputs@{
self,
flake-parts, flake-parts,
... ...
}: }:
@@ -22,7 +21,9 @@
]; ];
# https://docs.clan.lol/guides/getting-started/flake-parts/ # https://docs.clan.lol/guides/getting-started/flake-parts/
clan = import ./clan.nix { inherit self; }; clan = {
imports = [ ./clan.nix ];
};
perSystem = perSystem =
{ pkgs, inputs', ... }: { pkgs, inputs', ... }:

View File

@@ -5,6 +5,27 @@
}; };
flake = { 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 = checks.x86_64-linux.template-minimal =
let let
path = self.clan.templates.clan.minimal.path; path = self.clan.templates.clan.minimal.path;