From 017844874802806fb8ea7aa898fe50e7c9b907b9 Mon Sep 17 00:00:00 2001 From: Sam Date: Tue, 21 May 2024 19:11:23 +0100 Subject: [PATCH] added passwds to config & updated bootstrap script --- flake.lock | 38 ++++----- home/common/optional/sops.nix | 10 +-- hosts/common/core/default.nix | 15 +++- hosts/common/core/sops.nix | 10 ++- .../{openssh/default.nix => openssh.nix} | 5 +- hosts/common/users/sam/default.nix | 8 +- hosts/nixdev/default.nix | 2 +- hosts/sparky/default.nix | 11 +-- scripts/bootstrap.sh | 80 +++++++++++-------- scripts/generate_ssh_keys.sh | 60 ++++++++++++++ 10 files changed, 161 insertions(+), 78 deletions(-) rename hosts/common/optional/{openssh/default.nix => openssh.nix} (82%) create mode 100755 scripts/generate_ssh_keys.sh diff --git a/flake.lock b/flake.lock index 042d3cd..858ff35 100644 --- a/flake.lock +++ b/flake.lock @@ -7,11 +7,11 @@ ] }, "locked": { - "lastModified": 1715872464, - "narHash": "sha256-mkZ3hrPG7d+qL7B6pQcrNfPh2mnQEJR3FHK93qCp6Uk=", + "lastModified": 1716168343, + "narHash": "sha256-82oT27w9smpItZ+PyN2C0PjIwZYbIocwXSM4u1igXuc=", "owner": "nix-community", "repo": "disko", - "rev": "5f6dbcce99d60dd77f96dfc66d06bbea149a40e1", + "rev": "6f01b9710bc4d3bf006eb8df928b4b15e0430901", "type": "github" }, "original": { @@ -27,11 +27,11 @@ ] }, "locked": { - "lastModified": 1715486357, - "narHash": "sha256-4pRuzsHZOW5W4CsXI9uhKtiJeQSUoe1d2M9mWU98HC4=", + "lastModified": 1715930644, + "narHash": "sha256-W9pyM3/vePxrffHtzlJI6lDS3seANQ+Nqp+i58O46LI=", "owner": "nix-community", "repo": "home-manager", - "rev": "44677a1c96810a8e8c4ffaeaad10c842402647c1", + "rev": "e3ad5108f54177e6520535768ddbf1e6af54b59d", "type": "github" }, "original": { @@ -58,11 +58,11 @@ "nix-secrets": { "flake": false, "locked": { - "lastModified": 1716153530, - "narHash": "sha256-riMwDwr4q5XbaE/Vd7FrYOrf9huJznTIPwemUqBPljw=", + "lastModified": 1716313798, + "narHash": "sha256-XQnaNbpCxUo97c64IBbrbSKAA5FJb6FTyylPFRp/ZyY=", "ref": "refs/heads/master", - "rev": "80e1cc126aeaaf1244b713407f12d69aa255b57d", - "revCount": 17, + "rev": "6f2eb80d6a641515e205fd7df615453567ad9ffe", + "revCount": 20, "type": "git", "url": "ssh://git@git.bitlab21.com/sam/nix-secrets.git" }, @@ -85,11 +85,11 @@ }, "nixpkgs-stable": { "locked": { - "lastModified": 1715458492, - "narHash": "sha256-q0OFeZqKQaik2U8wwGDsELEkgoZMK7gvfF6tTXkpsqE=", + "lastModified": 1716061101, + "narHash": "sha256-H0eCta7ahEgloGIwE/ihkyGstOGu+kQwAiHvwVoXaA0=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8e47858badee5594292921c2668c11004c3b0142", + "rev": "e7cc61784ddf51c81487637b3031a6dd2d6673a2", "type": "github" }, "original": { @@ -101,11 +101,11 @@ }, "nixpkgs-unstable": { "locked": { - "lastModified": 1715787315, - "narHash": "sha256-cYApT0NXJfqBkKcci7D9Kr4CBYZKOQKDYA23q8XNuWg=", + "lastModified": 1716137900, + "narHash": "sha256-sowPU+tLQv8GlqtVtsXioTKeaQvlMz/pefcdwg8MvfM=", "owner": "nixos", "repo": "nixpkgs", - "rev": "33d1e753c82ffc557b4a585c77de43d4c922ebb5", + "rev": "6c0b7a92c30122196a761b440ac0d46d3d9954f1", "type": "github" }, "original": { @@ -134,11 +134,11 @@ "nixpkgs-stable": "nixpkgs-stable" }, "locked": { - "lastModified": 1715482972, - "narHash": "sha256-y1uMzXNlrVOWYj1YNcsGYLm4TOC2aJrwoUY1NjQs9fM=", + "lastModified": 1716244104, + "narHash": "sha256-XXbqfkyWe0d0O+zqRQWi2oXi6wYDmTzXedFkBRwx1VI=", "owner": "mic92", "repo": "sops-nix", - "rev": "b6cb5de2ce57acb10ecdaaf9bbd62a5ff24fa02e", + "rev": "fddd52460e3332eedd8a0043af5675338a5b3e0b", "type": "github" }, "original": { diff --git a/home/common/optional/sops.nix b/home/common/optional/sops.nix index 505d6d6..b08cc52 100644 --- a/home/common/optional/sops.nix +++ b/home/common/optional/sops.nix @@ -12,18 +12,10 @@ in ]; sops = { - age.sshKeyPaths = ["${homeDirectory}/.ssh/ssh_host_ed25519_key"]; + age.sshKeyPaths = ["${homeDirectory}/.ssh/id_ed25519"]; defaultSopsFile = "${secretsFile}"; validateSopsFiles = false; - secrets = { - "ssh_keys/${username}@${hostname}/${username}@${hostname}-ssh-ed25519" = { - path = "${homeDirectory}/.ssh/ssh_host_ed25519_key"; - }; - "ssh_keys/${username}@${hostname}/${username}@${hostname}-ssh-ed25519.pub" = { - path = "${homeDirectory}/.ssh/ssh_host_ed25519_key.pub"; - }; - }; }; } diff --git a/hosts/common/core/default.nix b/hosts/common/core/default.nix index 667587b..e8b1624 100644 --- a/hosts/common/core/default.nix +++ b/hosts/common/core/default.nix @@ -1,4 +1,8 @@ -{pkgs, ...}: { +{pkgs, lib, inputs, config, ...}: +let + sopsHashedPasswordFile = lib.optionalString (lib.hasAttr "sops-nix" inputs) config.sops.secrets."passwords/root".path; +in +{ imports = [ ./sops.nix ./locale.nix @@ -12,4 +16,13 @@ pkgs.neovim ]; + users = { + mutableUsers = true; + extraUsers = { + root = { + hashedPasswordFile = sopsHashedPasswordFile; + }; + }; + }; + } diff --git a/hosts/common/core/sops.nix b/hosts/common/core/sops.nix index ac5bda1..5c71b95 100644 --- a/hosts/common/core/sops.nix +++ b/hosts/common/core/sops.nix @@ -1,8 +1,8 @@ -{ pkgs, inputs, config, configVars, ... }: +{ pkgs, inputs, config, ... }: let secretsDirectory = builtins.toString inputs.nix-secrets; secretsFile = "${secretsDirectory}/secrets.yaml"; - homeDirectory = "/home/${configVars.username}"; + hostname = config.networking.hostName; in { imports = [ @@ -15,8 +15,10 @@ in age = { sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; - keyFile = "/var/lib/sops-nix/key.txt"; - generateKey = true; + }; + secrets = { + "passwords/root".neededForUsers = true; + "passwords/sam".neededForUsers = true; }; }; } diff --git a/hosts/common/optional/openssh/default.nix b/hosts/common/optional/openssh.nix similarity index 82% rename from hosts/common/optional/openssh/default.nix rename to hosts/common/optional/openssh.nix index 85c5aab..23a0fc3 100644 --- a/hosts/common/optional/openssh/default.nix +++ b/hosts/common/optional/openssh.nix @@ -7,7 +7,7 @@ in services.openssh = { enable = true; ports = [ sshPort ]; - + authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/default"]; settings = { # Harden PasswordAuthentication = true; @@ -15,7 +15,8 @@ in # Automatically remove stale sockets StreamLocalBindUnlink = "yes"; }; - }; + + networking.firewall.allowedTCPPorts = [ sshPort ]; } diff --git a/hosts/common/users/sam/default.nix b/hosts/common/users/sam/default.nix index 9782693..e1da96b 100644 --- a/hosts/common/users/sam/default.nix +++ b/hosts/common/users/sam/default.nix @@ -1,14 +1,16 @@ { pkgs, inputs, config, lib, ... }: let - pubKeys = lib.filesystem.listFilesRecursive (../keys); hostname = config.networking.hostName; + pubKeys = lib.filesystem.listFilesRecursive (../keys); + sopsHashedPasswordFile = lib.optionalString (lib.hasAttr "sops-nix" inputs) config.sops.secrets."passwords/sam".path; + in { users.users.sam = { + #mutableUsers = false; isNormalUser = true; - #password = "nixos"; # Overridden if sops is working shell = pkgs.zsh; # default shell - + hashedPasswordFile = sopsHashedPasswordFile; openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key); extraGroups = [ diff --git a/hosts/nixdev/default.nix b/hosts/nixdev/default.nix index f45fd70..77b5f7d 100644 --- a/hosts/nixdev/default.nix +++ b/hosts/nixdev/default.nix @@ -11,7 +11,7 @@ ../common/optional/pipewire.nix ../common/optional/hyprland.nix ../common/optional/displayManager/sddm.nix - ../common/optional/openssh + ../common/optional/openssh.nix # Create users for this host ../common/users/sam diff --git a/hosts/sparky/default.nix b/hosts/sparky/default.nix index c1dd7a6..b7ff47e 100644 --- a/hosts/sparky/default.nix +++ b/hosts/sparky/default.nix @@ -1,5 +1,4 @@ { inputs, config, lib, pkgs, outputs,... }: - { imports = [ @@ -13,6 +12,9 @@ ./hardware-configuration.nix ../common/core + # Import optional options + ../common/optional/openssh.nix + # Create users for this host ../common/users/media @@ -34,6 +36,7 @@ hideMounts = true; directories = [ "/etc/nixos" + "/etc/ssh" "/var/log" "/var/lib/nixos" "/var/lib/systemd/coredump" @@ -70,12 +73,6 @@ services = { qemuGuest.enable = true; - openssh = { - enable = true; - ports = [22]; # FIXME: Make this use configVars.networking - settings.PermitRootLogin = "yes"; - authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"]; - }; }; services.libinput.enable = true; services.displayManager.defaultSession = "cinnamon"; diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index bcddd33..eb74392 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -19,38 +19,47 @@ read -p "Enter username: " username read -p "Enter ip address: " ip read -p "Enter nixosSystem to build, e.g. 'bootstrap': " config +echo " +Details entered: +Hostname: $hostname +Username: $username +IP address: $ip +System to build: $config +" +read -p "Is this correct? (yes|no): " check_details +[ "$check_details" != "yes" ] && echo "Try again. Exiting" && exit 0 + # Generate key name and dir -KEY_DIR="$HOME/keys/$hostname/" -mkdir -p $KEY_DIR -KEY_NAME="$username@$hostname-ssh-ed25519" +HOST_KEY_DIR="$HOME/keys/hosts/$hostname" +USER_KEY_DIR="$HOME/keys/users/$username" +mkdir -p "$HOST_KEY_DIR" "$USER_KEY_DIR" + +# Create ssh keys if not exists +echo "Creating '$hostname' ssh keys" +bash "/$HOME/nixos/scripts/generate_ssh_keys.sh" --type "host" --username "root" --hostname "$hostname" +echo "Creating '$username' ssh keys" +bash "/$HOME/nixos/scripts/generate_ssh_keys.sh" --type "user" --username "$username" --hostname "$hostname" # Delete key in known hosts if exists -confirm_delete="" -KNOWN_HOSTS=$(grep "$ip" ~/.ssh/known_hosts) -[ "$KNOWN_HOSTS" != "" ] && echo -e "Host found in: ~/.ssh/known_hosts\n\n$KNOWN_HOSTS\n" && read -p "Delete existing hosts from ~/.ssh/known_hosts? (yes|no) " confirm_delete -[ "$confirm_delete" = "yes" ] && sed -i "/$ip/d" ~/.ssh/known_hosts - -# Generate new keys for target host if not exists -echo "Creating ssh keys for new host." -overwrite="" -[ -f "$KEY_DIR/$KEY_NAME" ] && read -p "Target host key '$KEY_NAME' already exists, would you like to overwrite it? (yes|no) " overwrite -[ -z "$overwrite" ] || [ "$overwrite" == "yes" ] && ssh-keygen -t ed25519 -f "$KEY_DIR/$KEY_NAME" -C "$username@$hostname" -N "" +sed -i "/$ip/d" ~/.ssh/known_hosts # Authorise source public key echo "Copying pubkey to target host" -ssh-copy-id -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key.pub")" "root@$ip" +ssh-copy-id -i "$(readlink -f "$HOME/.ssh/id_ed25519.pub")" "root@$ip" -# Generate age key from target host public ssh key -echo "Generating age key from target host ssh key" -nix-shell -p ssh-to-age --run "cat $KEY_DIR/$KEY_NAME.pub | ssh-to-age > $KEY_DIR/age_key_$hostname" -[ $? != 0 ] && echo "Error generating age key" && exit 1 -AGE_KEY=$(cat "$KEY_DIR/age_key_$hostname") -echo -e "Age key:\n$AGE_KEY\n" -echo "This key needs to be inserted into .sops.yaml file. This will be prompted again later." +# Generate age key from target host and user public ssh key +echo "Generating age key from target host and user ssh key" +nix-shell -p ssh-to-age --run "cat $HOST_KEY_DIR/ssh_host_ed25519_key.pub | ssh-to-age > $HOST_KEY_DIR/age_host_key" +nix-shell -p ssh-to-age --run "cat $USER_KEY_DIR/id_ed25519.pub | ssh-to-age > $USER_KEY_DIR/age_user_key" +HOST_AGE_KEY=$(cat "$HOST_KEY_DIR/age_host_key") +USER_AGE_KEY=$(cat "$USER_KEY_DIR/age_user_key") +echo -e "Host age key:\n$HOST_AGE_KEY\n" +echo -e "User age key:\n$USER_AGE_KEY\n" +echo "These keys needs to be inserted into .sops.yaml file. This will be prompted again later." # Install Nixos to target cd "$HOME/nixos" -SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --flake .#"$config" root@"$ip" -i "$HOME/.ssh/ssh_host_ed25519_key" +SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --flake .#"$config" root@"$ip" -i "$HOME/.ssh/id_ed25519" [ $? != 0 ] && echo "Error installing Nixos" && exit 1 ## Delete keys from local known_hosts @@ -73,15 +82,19 @@ echo "$ip is now online and port 22 is open!" # Authorise source public key echo "Copying pubkey to target host" -ssh-copy-id -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key.pub")" "$username@$ip" +ssh-copy-id -i "$(readlink -f "$HOME/.ssh/id_ed25519.pub")" "$username@$ip" + +# Copy host ssh keys to target & delete key in known hosts (because of key change) +scp -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$HOST_KEY_DIR/ssh_host_ed25519_key" "root@$ip:/etc/ssh/ssh_host_ed25519_key" && sed -i "/$ip/d" ~/.ssh/known_hosts +scp -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$HOST_KEY_DIR/ssh_host_ed25519_key.pub" "root@$ip:/etc/ssh/ssh_host_ed25519_key.pub" + +# Copy user ssh keys to target +scp -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$USER_KEY_DIR/id_ed25519_key" "$username@$ip:~/.ssh/id_ed25519" +scp -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$USER_KEY_DIR/id_ed25519_key.pub" "$username@$ip~/.ssh/id_ed25519.pub" # Copy deploy_key to target for personal repo authorisation -scp -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key")" "$(readlink -f "$HOME/.ssh/deploy_key-ssh-ed25519")" "media@$ip:~/.ssh/deploy_key-ssh-ed25519" -scp -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key")" "$(readlink -f "$HOME/.ssh/deploy_key-ssh-ed25519.pub")" "media@$ip:~/.ssh/deploy_key-ssh-ed25519.pub" - -# Copy previously generated ssh keys -scp -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key")" "$KEY_DIR/$KEY_NAME" "media@$ip:~/.ssh/ssh_host_ed25519_key" -scp -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key")" "$KEY_DIR/$KEY_NAME.pub" "media@$ip:~/.ssh/ssh_host_ed25519_key.pub" +scp -i "$(readlink -f "$HOME/.ssh/id_ed25519.pub")" "$(readlink -f "$HOME/.ssh/deploy_key-ssh-ed25519")" "$username@$ip:~/.ssh/deploy_key-ssh-ed25519" +scp -i "$(readlink -f "$HOME/.ssh/id_ed25519.pub")" "$(readlink -f "$HOME/.ssh/deploy_key-ssh-ed25519.pub")" "$username@$ip:~/.ssh/deploy_key-ssh-ed25519.pub" echo "Configuring target host ssh connection to enable connection to gitea repos:" read -r -d '' config << EOM @@ -101,13 +114,16 @@ previously. Enter the details as following: keys: +- &users: + - &$username $USER_AGE_KEY - &hosts: - - &$hostname $AGE_KEY + - &$hostname $HOST_AGE_KEY creation_rules: - path_regex: secrets.yaml$ key_groups: - age: + - *$username - *$hostname Then update (i.e. re-encrypt) the secrets.yaml file with the new keys, run: @@ -128,8 +144,8 @@ do [ "$confirm" = "yes" ] && break done -ssh -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key")" "$username@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nixos.git'" -ssh -i "$(readlink -f "$HOME/.ssh/ssh_host_ed25519_key")" "$username@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nix-secrets.git'" +ssh -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$username@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nixos.git'" +ssh -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$username@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nix-secrets.git'" echo "Successfully installed Nixos on the target host!" echo "Please remote into the new host and run 'sudo nixos-generate-config && cp /etc/nixos/hardware-configuration.nix /home/$username/nixos/hosts/$hostname/'" diff --git a/scripts/generate_ssh_keys.sh b/scripts/generate_ssh_keys.sh new file mode 100755 index 0000000..cb16f80 --- /dev/null +++ b/scripts/generate_ssh_keys.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# +# usage: ./generate_ssh_keys.sh --type "host" --username "root" --hostname "hostname" +# + +while [[ $# -gt 0 ]] +do + key="$1" + + case $key in + --type) + type="$2" + shift # past argument + shift # past value + ;; + --username) + username="$2" + shift # past argument + shift # past value + ;; + --hostname) + hostname="$2" + shift # past argument + shift # past value + ;; + *) # unknown option + echo "Unknown option $1" + exit 1 + ;; + esac +done + +if [[ -z "$type" || -z "$username" || -z "$hostname" ]]; then + echo "All arguments are not specified." + exit 1 +fi + +if [[ $type != "user" && $type != "host" ]]; then + echo "Invalid type. It should be either 'user' or 'host'" + exit 1 +fi + +HOST_KEY_DIR="$HOME/keys/hosts/$hostname" +USER_KEY_DIR="$HOME/keys/users/$username" +mkdir -p "$HOST_KEY_DIR" "$USER_KEY_DIR" + +if [[ $type == "user" ]]; then + keyfile="id_ed25519" + name="$username" +else + keyfile="ssh_host_ed25519_key" + name="root@$hostname" +fi + +keydir=$([[ $type == "user" ]] && echo "$USER_KEY_DIR" || echo "$HOST_KEY_DIR") +fullpath="$keydir/$keyfile" +overwrite="" +[ -f "$fullpath" ] && read -p "Target key '$fullpath' already exists, would you like to overwrite it? (yes|no) " overwrite +[ "$overwrite" = "yes" ] || [ -z "$overwrite" ] && ssh-keygen -t ed25519 -f "$fullpath" -C "$name" -N "" +