auth: add user for each administrator #261
|
@ -28,18 +28,18 @@ People with admin access to the infrastructure are added to [`logins/admins.nix`
|
|||
SSH is not reachable from the open internet. Instead, SSH Port 22 is protected by a wireguard VPN network. Thus, to get root access on the servers, at least two pieces of information have to be added to the admins config:
|
||||
|
||||
1. **SSH Public key**: self-explanatory. Add your public key to your user attrset under `sshPubKeys`.
|
||||
2. **Wireguard device**: each wireguard device has two parts: the public key and the IP addresses it should have in the wireguard network. The pub.solar wireguard network is spaced under `10.7.6.0/24` and `fd00:fae:fae:fae:fae::/80`. To add your device, it's best to choose a free number between 200 and 255 and use that in both the ipv4 and ipv6 ranges: `10.7.6.<ip-address>/32` `fd00:fae:fae:fae:fae:<ip-address>::/96`. For more information on how to generate keypairs, see [the NixOS Wireguard docs](https://nixos.wiki/wiki/WireGuard#Generate_keypair).
|
||||
2. **Wireguard device**: each wireguard device has two parts: the public key and the IP addresses it should have in the wireguard network. The pub.solar wireguard network uses the subnets `10.7.6.0/24` and `fd00:fae:fae:fae:fae::/80`. To add your device, it's best to choose a free number between 200 and 255 and use that in both the ipv4 and ipv6 ranges: `10.7.6.<ip-address>/32` `fd00:fae:fae:fae:fae:<ip-address>::/96`. For more information on how to generate keypairs, see [the NixOS Wireguard docs](https://nixos.wiki/wiki/WireGuard#Generate_keypair).
|
||||
|
||||
One can access our hosts using this domain scheme:
|
||||
|
||||
```
|
||||
ssh barkeeper@<hostname>.wg.pub.solar
|
||||
ssh <unix-username>@<hostname>.wg.pub.solar
|
||||
```
|
||||
|
||||
So, for example for `nachtigall`:
|
||||
|
||||
```
|
||||
ssh barkeeper@nachtigall.wg.pub.solar
|
||||
ssh teutat3s@nachtigall.wg.pub.solar
|
||||
```
|
||||
|
||||
Example NixOS snippet for WireGuard client config
|
||||
|
|
|
@ -7,16 +7,29 @@ be manually deployed.
|
|||
To deploy, make sure you have a [working development shell](./development-shell.md).
|
||||
Then, run `deploy-rs` with the hostname of the server you want to deploy:
|
||||
|
||||
### Dry-run
|
||||
|
||||
Use `--dry-activate` to show a diff of updated packages and all services that
|
||||
would be restarted by the update. This will also put all files in place without
|
||||
switching to the new generation, enabling a quick switch to the new config at a
|
||||
later moment.
|
||||
|
||||
For nachtigall.pub.solar:
|
||||
|
||||
```
|
||||
deploy --targets '.#nachtigall' --magic-rollback false --auto-rollback false --keep-result --result-path ./results
|
||||
deploy --targets '.#nachtigall' --ssh-user <unix-username> --magic-rollback false --auto-rollback false --keep-result --result-path ./results --dry-activate
|
||||
```
|
||||
|
||||
After reviewing the changes, apply the update with:
|
||||
|
||||
```
|
||||
deploy --targets '.#nachtigall' --ssh-user <unix-username> --magic-rollback false --auto-rollback false --keep-result --result-path ./results
|
||||
```
|
||||
|
||||
For metronom.pub.solar (aarch64-linux):
|
||||
|
||||
```
|
||||
deploy --targets '.#metronom' --magic-rollback false --auto-rollback false --keep-result --result-path ./results --remote-build
|
||||
deploy --targets '.#metronom' --ssh-user <unix-username> --magic-rollback false --auto-rollback false --keep-result --result-path ./results --remote-build
|
||||
```
|
||||
|
||||
Usually we skip all rollback functionality, but if you want to deploy a change
|
||||
|
@ -25,9 +38,6 @@ that might lock you out, e.g. to SSH, it might make sense to set these to `true`
|
|||
To skip flake checks, e.g. because you already ran them manually before
|
||||
deployment, add the flag `--skip-checks` at the end of the command.
|
||||
|
||||
`--dry-activate` can be used to only put all files in place without switching,
|
||||
to enable switching to the new config quickly at a later moment.
|
||||
|
||||
We use `--keep-result --result-path ./results` to keep the last `result`
|
||||
symlink of each `deploy` from being garbage collected. That way, we keep builds
|
||||
cached in the Nix store. This is optional and both flags can be removed if disk
|
||||
|
|
|
@ -8,7 +8,7 @@ Requirements:
|
|||
- [Setup WireGuard](./administrative-access.md#ssh-access) for hosts: `trinkgenossin`, optionally: `delite`, `blue-shell`
|
||||
|
||||
```
|
||||
ssh barkeeper@trinkgenossin.wg.pub.solar
|
||||
ssh <unix-username>@trinkgenossin.wg.pub.solar
|
||||
```
|
||||
|
||||
```
|
||||
|
@ -58,7 +58,7 @@ Further reading:
|
|||
### Notes on manual setup steps
|
||||
|
||||
```
|
||||
ssh barkeeper@trinkgenossin.wg.pub.solar
|
||||
ssh <unix-username>@trinkgenossin.wg.pub.solar
|
||||
|
||||
# Add a few spaces to avoid leaking the secret to the shell history
|
||||
export GARAGE_RPC_SECRET=<secret-in-keepass>
|
||||
|
|
|
@ -41,3 +41,7 @@ wrapped-ruby-mastodon-gems: 4.2.1 → 4.2.3
|
|||
zfs-kernel: 2.2.1-6.1.64 → 2.2.2-6.1.66
|
||||
zfs-user: 2.2.1 → 2.2.2
|
||||
```
|
||||
|
||||
### Deploying updates
|
||||
|
||||
See [deploying.md](./deploying.md).
|
||||
|
|
79
flake.nix
79
flake.nix
|
@ -120,56 +120,43 @@
|
|||
devShells.ci = pkgs.mkShell { buildInputs = with pkgs; [ nodejs ]; };
|
||||
};
|
||||
|
||||
flake =
|
||||
let
|
||||
username = "barkeeper";
|
||||
in
|
||||
{
|
||||
inherit username;
|
||||
flake = {
|
||||
nixosModules = builtins.listToAttrs (
|
||||
map (x: {
|
||||
name = x;
|
||||
value = import (./modules + "/${x}");
|
||||
}) (builtins.attrNames (builtins.readDir ./modules))
|
||||
);
|
||||
|
||||
nixosModules = builtins.listToAttrs (
|
||||
map (x: {
|
||||
name = x;
|
||||
value = import (./modules + "/${x}");
|
||||
}) (builtins.attrNames (builtins.readDir ./modules))
|
||||
);
|
||||
checks = builtins.mapAttrs (
|
||||
system: deployLib: deployLib.deployChecks self.deploy
|
||||
) inputs.deploy-rs.lib;
|
||||
|
||||
checks = builtins.mapAttrs (
|
||||
system: deployLib: deployLib.deployChecks self.deploy
|
||||
) inputs.deploy-rs.lib;
|
||||
formatter."x86_64-linux" = inputs.unstable.legacyPackages."x86_64-linux".nixfmt-rfc-style;
|
||||
|
||||
formatter."x86_64-linux" = inputs.unstable.legacyPackages."x86_64-linux".nixfmt-rfc-style;
|
||||
|
||||
deploy.nodes = self.lib.deploy.mkDeployNodes self.nixosConfigurations {
|
||||
nachtigall = {
|
||||
hostname = "nachtigall.wg.pub.solar";
|
||||
sshUser = username;
|
||||
};
|
||||
metronom = {
|
||||
hostname = "metronom.wg.pub.solar";
|
||||
sshUser = username;
|
||||
};
|
||||
tankstelle = {
|
||||
hostname = "tankstelle.wg.pub.solar";
|
||||
sshUser = username;
|
||||
};
|
||||
underground = {
|
||||
hostname = "80.244.242.3";
|
||||
sshUser = username;
|
||||
};
|
||||
trinkgenossin = {
|
||||
hostname = "trinkgenossin.wg.pub.solar";
|
||||
sshUser = username;
|
||||
};
|
||||
delite = {
|
||||
hostname = "delite.wg.pub.solar";
|
||||
sshUser = username;
|
||||
};
|
||||
blue-shell = {
|
||||
hostname = "blue-shell.wg.pub.solar";
|
||||
sshUser = username;
|
||||
};
|
||||
deploy.nodes = self.lib.deploy.mkDeployNodes self.nixosConfigurations {
|
||||
nachtigall = {
|
||||
hostname = "nachtigall.wg.pub.solar";
|
||||
};
|
||||
metronom = {
|
||||
hostname = "metronom.wg.pub.solar";
|
||||
};
|
||||
tankstelle = {
|
||||
hostname = "tankstelle.wg.pub.solar";
|
||||
};
|
||||
underground = {
|
||||
hostname = "80.244.242.3";
|
||||
};
|
||||
trinkgenossin = {
|
||||
hostname = "trinkgenossin.wg.pub.solar";
|
||||
};
|
||||
delite = {
|
||||
hostname = "delite.wg.pub.solar";
|
||||
};
|
||||
blue-shell = {
|
||||
hostname = "blue-shell.wg.pub.solar";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ in
|
|||
"${wireguardIPv6}/96"
|
||||
];
|
||||
privateKeyFile = config.age.secrets.wg-private-key.path;
|
||||
peers = flake.self.logins.admins.wireguardDevices ++ [
|
||||
peers = flake.self.logins.wireguardDevices ++ [
|
||||
{
|
||||
# trinkgenossin.pub.solar
|
||||
publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
|
||||
|
|
|
@ -22,7 +22,7 @@ in
|
|||
"${wireguardIPv6}/96"
|
||||
];
|
||||
privateKeyFile = config.age.secrets.wg-private-key.path;
|
||||
peers = flake.self.logins.admins.wireguardDevices ++ [
|
||||
peers = flake.self.logins.wireguardDevices ++ [
|
||||
{
|
||||
# trinkgenossin.pub.solar
|
||||
publicKey = "QWgHovHxtqiQhnHLouSWiT6GIoQDmuvnThYL5c/rvU4=";
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"fd00:fae:fae:fae:fae:3::/96"
|
||||
];
|
||||
privateKeyFile = config.age.secrets.wg-private-key.path;
|
||||
peers = flake.self.logins.admins.wireguardDevices ++ [
|
||||
peers = flake.self.logins.wireguardDevices ++ [
|
||||
{
|
||||
# nachtigall.pub.solar
|
||||
endpoint = "138.201.80.102:51820";
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"fd00:fae:fae:fae:fae:1::/96"
|
||||
];
|
||||
privateKeyFile = config.age.secrets.wg-private-key.path;
|
||||
peers = flake.self.logins.admins.wireguardDevices ++ [
|
||||
peers = flake.self.logins.wireguardDevices ++ [
|
||||
{
|
||||
# tankstelle.pub.solar
|
||||
endpoint = "80.244.242.5:51820";
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"fd00:fae:fae:fae:fae:4::/96"
|
||||
];
|
||||
privateKeyFile = config.age.secrets.wg-private-key.path;
|
||||
peers = flake.self.logins.admins.wireguardDevices ++ [
|
||||
peers = flake.self.logins.wireguardDevices ++ [
|
||||
{
|
||||
# nachtigall.pub.solar
|
||||
endpoint = "138.201.80.102:51820";
|
||||
|
|
|
@ -22,7 +22,7 @@ in
|
|||
"${wireguardIPv6}/96"
|
||||
];
|
||||
privateKeyFile = config.age.secrets.wg-private-key.path;
|
||||
peers = flake.self.logins.admins.wireguardDevices ++ [
|
||||
peers = flake.self.logins.wireguardDevices ++ [
|
||||
{
|
||||
# nachtigall.pub.solar
|
||||
endpoint = "138.201.80.102:51820";
|
||||
|
|
|
@ -6,19 +6,16 @@ in
|
|||
{
|
||||
flake = {
|
||||
logins = {
|
||||
admins =
|
||||
lib.lists.foldl
|
||||
(logins: adminConfig: {
|
||||
sshPubKeys = logins.sshPubKeys ++ (lib.attrsets.attrValues adminConfig.sshPubKeys);
|
||||
wireguardDevices =
|
||||
logins.wireguardDevices
|
||||
++ (if adminConfig ? "wireguardDevices" then adminConfig.wireguardDevices else [ ]);
|
||||
})
|
||||
{
|
||||
sshPubKeys = [ ];
|
||||
wireguardDevices = [ ];
|
||||
}
|
||||
(lib.attrsets.attrValues admins);
|
||||
admins = admins;
|
||||
wireguardDevices = lib.lists.foldl (
|
||||
wireguardDevices: adminConfig:
|
||||
wireguardDevices ++ (if adminConfig ? "wireguardDevices" then adminConfig.wireguardDevices else [ ])
|
||||
) [ ] (lib.attrsets.attrValues admins);
|
||||
sshPubKeys = lib.lists.foldl (
|
||||
sshPubKeys: adminConfig:
|
||||
sshPubKeys
|
||||
++ (if adminConfig ? "sshPubKeys" then lib.attrsets.attrValues adminConfig.sshPubKeys else [ ])
|
||||
) [ ] (lib.attrsets.attrValues admins);
|
||||
robots.sshPubKeys = lib.attrsets.attrValues robots;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -54,9 +54,5 @@
|
|||
};
|
||||
|
||||
time.timeZone = "Etc/UTC";
|
||||
|
||||
home-manager.users.${config.pub-solar-os.authentication.username} = {
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
{ flake, config, ... }:
|
||||
{ flake, lib, ... }:
|
||||
{
|
||||
home-manager.users.${config.pub-solar-os.authentication.username} = {
|
||||
programs.git.enable = true;
|
||||
programs.starship.enable = true;
|
||||
programs.bash.enable = true;
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
vimAlias = true;
|
||||
viAlias = true;
|
||||
defaultEditor = true;
|
||||
# configure = {
|
||||
# packages.myVimPackages = with pkgs.vimPlugins; {
|
||||
# start = [vim-nix vim-surrund rainbow];
|
||||
# };
|
||||
# };
|
||||
};
|
||||
};
|
||||
home-manager.users = (
|
||||
lib.attrsets.foldlAttrs (
|
||||
acc: name: value:
|
||||
acc
|
||||
// {
|
||||
${name} = {
|
||||
programs.git.enable = true;
|
||||
programs.starship.enable = true;
|
||||
programs.bash.enable = true;
|
||||
programs.neovim = {
|
||||
enable = true;
|
||||
vimAlias = true;
|
||||
viAlias = true;
|
||||
defaultEditor = true;
|
||||
# configure = {
|
||||
# packages.myVimPackages = with pkgs.vimPlugins; {
|
||||
# start = [vim-nix vim-surrund rainbow];
|
||||
# };
|
||||
# };
|
||||
};
|
||||
};
|
||||
}
|
||||
) { } flake.self.logins.admins
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,18 +11,6 @@
|
|||
inherit (lib) mkOption types;
|
||||
in
|
||||
{
|
||||
username = mkOption {
|
||||
description = "Username for the adminstrative user";
|
||||
type = types.str;
|
||||
default = flake.self.username;
|
||||
};
|
||||
|
||||
sshPubKeys = mkOption {
|
||||
description = "SSH Keys that should have administrative root access";
|
||||
type = types.listOf types.str;
|
||||
default = flake.self.logins.admins.sshPubKeys;
|
||||
};
|
||||
|
||||
root.initialHashedPassword = mkOption {
|
||||
description = "Hashed password of the root account";
|
||||
type = types.str;
|
||||
|
@ -43,36 +31,60 @@
|
|||
};
|
||||
|
||||
config = {
|
||||
users.users.${config.pub-solar-os.authentication.username} = {
|
||||
name = config.pub-solar-os.authentication.username;
|
||||
group = config.pub-solar-os.authentication.username;
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"docker"
|
||||
];
|
||||
isNormalUser = true;
|
||||
openssh.authorizedKeys.keys = config.pub-solar-os.authentication.sshPubKeys;
|
||||
};
|
||||
users.groups.${config.pub-solar-os.authentication.username} = { };
|
||||
users.users =
|
||||
(lib.attrsets.foldlAttrs (
|
||||
acc: name: value:
|
||||
acc
|
||||
// {
|
||||
${name} = {
|
||||
name = name;
|
||||
group = name;
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"docker"
|
||||
];
|
||||
isNormalUser = true;
|
||||
openssh.authorizedKeys.keys = lib.attrsets.attrValues value.sshPubKeys;
|
||||
};
|
||||
}
|
||||
) { } flake.self.logins.admins)
|
||||
// {
|
||||
# TODO: Remove when we stop locking ourselves out.
|
||||
root.openssh.authorizedKeys.keys = flake.self.logins.sshPubKeys;
|
||||
root.initialHashedPassword = config.pub-solar-os.authentication.root.initialHashedPassword;
|
||||
|
||||
# TODO: Remove when we stop locking ourselves out.
|
||||
users.users.root.openssh.authorizedKeys.keys = config.pub-solar-os.authentication.sshPubKeys;
|
||||
${config.pub-solar-os.authentication.robot.username} = {
|
||||
description = "CI and automation user";
|
||||
home = "/home/${config.pub-solar-os.authentication.robot.username}";
|
||||
createHome = true;
|
||||
useDefaultShell = true;
|
||||
uid = 998;
|
||||
group = "${config.pub-solar-os.authentication.robot.username}";
|
||||
isSystemUser = true;
|
||||
openssh.authorizedKeys.keys = config.pub-solar-os.authentication.robot.sshPubKeys;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.${config.pub-solar-os.authentication.robot.username} = {
|
||||
description = "CI and automation user";
|
||||
home = "/home/${config.pub-solar-os.authentication.robot.username}";
|
||||
createHome = true;
|
||||
useDefaultShell = true;
|
||||
uid = 998;
|
||||
group = "${config.pub-solar-os.authentication.robot.username}";
|
||||
isSystemUser = true;
|
||||
openssh.authorizedKeys.keys = config.pub-solar-os.authentication.robot.sshPubKeys;
|
||||
};
|
||||
home-manager.users = (
|
||||
lib.attrsets.foldlAttrs (
|
||||
acc: name: value:
|
||||
acc
|
||||
// {
|
||||
${name} = {
|
||||
home.stateVersion = "23.05";
|
||||
};
|
||||
}
|
||||
) { } flake.self.logins.admins
|
||||
);
|
||||
|
||||
users.groups.${config.pub-solar-os.authentication.robot.username} = { };
|
||||
|
||||
users.users.root.initialHashedPassword =
|
||||
config.pub-solar-os.authentication.root.initialHashedPassword;
|
||||
users.groups =
|
||||
(lib.attrsets.foldlAttrs (
|
||||
acc: name: value:
|
||||
acc // { "${name}" = { }; }
|
||||
) { } flake.self.logins.admins)
|
||||
// {
|
||||
${config.pub-solar-os.authentication.robot.username} = { };
|
||||
};
|
||||
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
# Please create this manually the first time.
|
||||
hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ];
|
||||
authorizedKeys = config.pub-solar-os.authentication.sshPubKeys;
|
||||
authorizedKeys = flake.self.logins.sshPubKeys;
|
||||
};
|
||||
postCommands = ''
|
||||
# Automatically ask for the password on SSH login
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
# Please create this manually the first time.
|
||||
hostKeys = [ "/etc/secrets/initrd/ssh_host_ed25519_key" ];
|
||||
authorizedKeys = config.pub-solar-os.authentication.sshPubKeys;
|
||||
authorizedKeys = flake.self.logins.sshPubKeys;
|
||||
};
|
||||
# this will automatically load the zfs password prompt on login
|
||||
# and kill the other prompt so boot can continue
|
||||
|
|
|
@ -66,7 +66,7 @@ in
|
|||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
user = nodes.client.users.users.${nodes.client.pub-solar-os.authentication.username};
|
||||
user = nodes.client.users.users.b12f;
|
||||
#uid = toString user.uid;
|
||||
bus = "DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u ${user.name})/bus";
|
||||
gdbus = "${bus} gdbus";
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
services.xserver.displayManager.gdm.enable = true;
|
||||
services.xserver.desktopManager.gnome.enable = true;
|
||||
services.xserver.displayManager.autoLogin.enable = true;
|
||||
services.xserver.displayManager.autoLogin.user = config.pub-solar-os.authentication.username;
|
||||
services.xserver.displayManager.autoLogin.user = "b12f";
|
||||
|
||||
systemd.user.services = {
|
||||
"org.gnome.Shell@wayland" = {
|
||||
|
|
Loading…
Reference in a new issue