Compare commits

...

40 Commits

Author SHA1 Message Date
Sam 3e5ebafed6 sops to create ssh keys for users 2024-05-23 09:48:00 +00:00
Sam 1c0725912d minimal bootstrap install 2024-05-23 00:10:58 +01:00
Sam 8679f14566 minimal bootstrap install 2024-05-22 23:38:48 +01:00
Sam 0b58cf8c4d auto: bootstrapping bootstrap 2024-05-22 21:21:20 +01:00
Sam 9271ecc22b auto: bootstrapping bootstrap-nixos 2024-05-22 21:17:27 +01:00
Sam d0b5a08056 auto: bootstrapping bootstrap-nixos 2024-05-22 21:15:58 +01:00
Sam 84bc747593 auto: bootstrapping bootstrap-nixos 2024-05-22 21:15:22 +01:00
Sam 5fea003213 auto: bootstrapping bootstrap-nixos 2024-05-22 21:14:47 +01:00
Sam 104bcd2615 auto: bootstrapping bootstrap-nixos 2024-05-22 21:14:20 +01:00
Sam 806c8364d7 auto: bootstrapping bootstrap-nixos 2024-05-22 21:10:41 +01:00
Sam 871d4f7256 auto: bootstrapping sparky 2024-05-22 20:34:18 +01:00
Sam b482071005 auto: bootstrapping sparky 2024-05-22 17:44:08 +01:00
Sam 623c979342 auto: bootstrapping sparky 2024-05-22 17:39:12 +01:00
Sam 9ded1a9371 auto: bootstrapping sparky 2024-05-22 17:32:02 +01:00
Sam 02b9de7372 auto: bootstrapping sparky 2024-05-22 17:31:06 +01:00
Sam b3b8e178e1 removed some persisted files 2024-05-22 17:27:24 +01:00
Sam e9823f76b2 more changes 2024-05-22 17:23:17 +01:00
Sam 0178448748 added passwds to config & updated bootstrap script 2024-05-21 19:11:23 +01:00
Sam 2d3398b217 remove sops paths 2024-05-20 00:33:06 +01:00
Sam 3b653ecb20 modify justfile 2024-05-19 23:34:15 +01:00
Sam c914883610 revert bootstrap 2024-05-19 23:33:42 +01:00
Sam 82f5d9ebfe change bootstap to get age key from target host 2024-05-19 21:55:25 +01:00
Sam 521bafe3f8 xdg dirs 2024-05-18 14:53:10 +01:00
Sam b83147b16b xdg dirs 2024-05-18 14:51:03 +01:00
Sam 54caab4d8c changed ssh keys 2024-05-18 14:46:08 +01:00
Sam 578ddc7921 removed passphrase from deploy key 2024-05-18 11:54:14 +01:00
Sam 9df3bf2ff8 changed media to sparky 2024-05-17 20:17:53 +01:00
Sam 878fffd900 fixed sam home zsh issue 2024-05-17 10:54:53 +01:00
Sam 58d5e6b58f persistance working 2024-05-17 09:38:40 +01:00
Sam 234fb16de9 move persist to nixos system 2024-05-17 09:17:03 +01:00
Sam 4fa3b400d7 move persist to nixos system 2024-05-17 09:16:33 +01:00
Sam 12229e57b6 move persist to nixos system 2024-05-17 09:15:46 +01:00
samual.shop@proton.me 07f064e4fd impermanence module and home-manager 2024-05-17 00:07:42 +00:00
Sam f90f7cf8a4 working btrfs impermanence & added lvm to disko 2024-05-17 00:37:19 +01:00
Sam b4feb6e77a btrfs-impermanence.nix 2024-05-16 23:27:06 +01:00
Sam 57c4e06080 resolved conflict 2024-05-16 20:20:05 +01:00
Sam ebc79952ff added media 2024-05-16 20:19:01 +01:00
samual.shop@proton.me 014cc98716 added hardware-config.nix 2024-05-16 19:18:24 +00:00
Sam 178b0f3931 add devices var to disko and modified bootstrap.sh 2024-05-16 19:14:21 +01:00
Sam f6b48d0b25 update just file, revisions to bootstrap.sh 2024-05-16 16:54:21 +01:00
35 changed files with 751 additions and 308 deletions

View File

@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1715756862,
"narHash": "sha256-cNGZK/RNvb29giR2KtnbwU5lx2Kw+wWqAaeWqfYlPts=",
"lastModified": 1716431128,
"narHash": "sha256-t3T8HlX3udO6f4ilLcN+j5eC3m2gqsouzSGiriKK6vk=",
"owner": "nix-community",
"repo": "disko",
"rev": "cb1d6fba694ab3887600d606106f5a044ba1712c",
"rev": "7ffc4354dfeb37c8c725ae1465f04a9b45ec8606",
"type": "github"
},
"original": {
@ -27,11 +27,11 @@
]
},
"locked": {
"lastModified": 1715486357,
"narHash": "sha256-4pRuzsHZOW5W4CsXI9uhKtiJeQSUoe1d2M9mWU98HC4=",
"lastModified": 1716448020,
"narHash": "sha256-u1ddoBOILtLVX4NYzqSZ9Qaqusql1M4reLd1fs554hY=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "44677a1c96810a8e8c4ffaeaad10c842402647c1",
"rev": "25dedb0d52c20448f6a63cc346df1adbd6ef417e",
"type": "github"
},
"original": {
@ -40,14 +40,29 @@
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1708968331,
"narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"nix-secrets": {
"flake": false,
"locked": {
"lastModified": 1715783829,
"narHash": "sha256-aNuuTd4nXt9SxYLgJSgBxuvIBmAyh5+2IT2iLepZKds=",
"lastModified": 1716456952,
"narHash": "sha256-fd57j4M++Fte1hrRZkDIqGbYbimqPNmERlFr/Fbh1Ek=",
"ref": "refs/heads/master",
"rev": "450e494f36a74c0786d1cb01db46731b01b713dc",
"revCount": 5,
"rev": "f5abdf254dbee888be5f65c96a4a571f2a91da91",
"revCount": 28,
"type": "git",
"url": "ssh://git@git.bitlab21.com/sam/nix-secrets.git"
},
@ -70,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": {
@ -86,11 +101,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1715534503,
"narHash": "sha256-5ZSVkFadZbFP1THataCaSf0JH2cAH3S29hU9rrxTEqk=",
"lastModified": 1716330097,
"narHash": "sha256-8BO3B7e3BiyIDsaKA0tY8O88rClYRTjvAp66y+VBUeU=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "2057814051972fa1453ddfb0d98badbea9b83c06",
"rev": "5710852ba686cc1fd0d3b8e22b3117d43ba374c2",
"type": "github"
},
"original": {
@ -104,6 +119,7 @@
"inputs": {
"disko": "disko",
"home-manager": "home-manager",
"impermanence": "impermanence",
"nix-secrets": "nix-secrets",
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable",
@ -118,11 +134,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1715482972,
"narHash": "sha256-y1uMzXNlrVOWYj1YNcsGYLm4TOC2aJrwoUY1NjQs9fM=",
"lastModified": 1716400300,
"narHash": "sha256-0lMkIk9h3AzOHs1dCL9RXvvN4PM8VBKb+cyGsqOKa4c=",
"owner": "mic92",
"repo": "sops-nix",
"rev": "b6cb5de2ce57acb10ecdaaf9bbd62a5ff24fa02e",
"rev": "b549832718b8946e875c016a4785d204fcfc2e53",
"type": "github"
},
"original": {

View File

@ -17,6 +17,10 @@
inputs.nixpkgs.follows = "nixpkgs";
};
impermanence = {
url = "github:nix-community/impermanence";
};
# Secrets management
sops-nix = {
url = "github:mic92/sops-nix";
@ -34,6 +38,7 @@
nixpkgs,
home-manager,
disko,
#impermanence,
...
} @ inputs:
let
@ -73,11 +78,18 @@
bootstrap = nixpkgs.lib.nixosSystem {
inherit specialArgs;
modules = [
disko.nixosModules.disko
./hosts/common/disks/gpt-bios-compact.nix
./hosts/bootstrap
];
};
sparky = nixpkgs.lib.nixosSystem {
inherit specialArgs;
modules = [
./hosts/sparky
home-manager.nixosModules.home-manager{
home-manager.extraSpecialArgs = specialArgs;
}
];
};
};
# # Standalone home-manager configuration entrypoint

View File

@ -1,5 +1,6 @@
{ pkgs, ... }:
{ config, lib, pkgs, outputs, ... }:
{
imports = [
./zsh.nix
] ;
}

23
home/common/core/zsh.nix Normal file
View File

@ -0,0 +1,23 @@
{ pkgs, config, ... }: {
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
shellAliases = {
ll = "ls -l";
};
history.size = 10000;
history.path = "${config.xdg.dataHome}/zsh/history";
initExtra = ''
bindkey -v
bindkey "^H" backward-delete-char
bindkey "^?" backward-delete-char
set -o vi
export TERM=xterm
'';
};
}

View File

@ -1,8 +1,10 @@
{ inputs, config, ... }:
{ inputs, config, osConfig, ... }:
let
secretsDirectory = builtins.toString inputs.nix-secrets;
secretsFile = "${secretsDirectory}/secrets.yaml";
homeDirectory = config.home.homeDirectory;
username = config.home.username;
hostname = osConfig.networking.hostName;
in
{
imports = [
@ -10,18 +12,10 @@ in
];
sops = {
age.keyFile = "${homeDirectory}/.config/sops/age/keys.txt";
age.sshKeyPaths = ["${homeDirectory}/.ssh/id_ed25519"];
defaultSopsFile = "${secretsFile}";
validateSopsFiles = false;
secrets = {
"ssh_keys/sam/gitea" = {
path = "${homeDirectory}/.ssh/gitea";
};
"ssh_keys/sam/gitea.pub" = {
path = "${homeDirectory}/.ssh/gitea.pub";
};
};
};
}

View File

@ -5,12 +5,13 @@
...
}: {
imports = [
# Import users
./users/admin
./common/core
./common/optional/sops.nix
# Import optional
./common/optional/git.nix
# Import users
./users/admin
];

View File

@ -5,6 +5,9 @@
...
}: {
imports = [
# Import users
./users/sam
./common/core
./common/optional/desktop/hyprland
./common/optional/desktop/waybar.nix
@ -12,9 +15,6 @@
# Import optional
./common/optional/git.nix
# Import users
./users/sam
];
# ------

18
home/sparky.nix Normal file
View File

@ -0,0 +1,18 @@
{
pkgs,
config,
lib,
...
}: {
imports = [
# Import users
./users/media
./common/core
./common/optional/sops.nix
# Import optional
./common/optional/git.nix
];
}

View File

@ -11,28 +11,6 @@
home.packages = [
];
programs.zsh = {
enable = true;
enableCompletion = true;
autosuggestion.enable = true;
syntaxHighlighting.enable = true;
shellAliases = {
ll = "ls -l";
};
history.size = 10000;
history.path = "${config.xdg.dataHome}/zsh/history";
initExtra = ''
bindkey -v
bindkey "^H" backward-delete-char
bindkey "^?" backward-delete-char
set -o vi
export TERM=xterm
'';
};
home.file = {
};

View File

@ -0,0 +1,39 @@
{ config, pkgs, lib, outputs, inputs, ... }:
{
home.username = "media";
home.homeDirectory = "/home/media";
home.stateVersion = "23.11";
imports = [
inputs.impermanence.nixosModules.home-manager.impermanence
] ++ (builtins.attrValues outputs.homeManagerModules); # import all homeManagerModules?
xdg.userDirs = {
enable = true;
createDirectories = false;
desktop = "/home/media/Desktop";
documents = null;
download = null;
music = null;
pictures = null;
publicShare = null;
templates = null;
videos = null;
};
home.packages = [
];
home.file = {
};
home.sessionPath = [
];
home.sessionVariables = {
};
programs.home-manager.enable = true;
}

View File

@ -16,29 +16,7 @@
pkgs.xfce.thunar
#pkgs.age
];
programs.zsh = {
enable = true;
enableCompletion = true;
programs.zsh.autosuggestion.enable = true;
syntaxHighlighting.enable = true;
shellAliases = {
ll = "ls -l";
};
history.size = 10000;
history.path = "${config.xdg.dataHome}/zsh/history";
initExtra = ''
bindkey -v
bindkey "^H" backward-delete-char
bindkey "^?" backward-delete-char
set -o vi
export TERM=xterm
'';
};
home.file = {
".icons/bibata".source = "${pkgs.bibata-cursors}/share/icons/Bibata-Modern-Classic";
};
@ -71,6 +49,5 @@
IMAGE_EDITOR="";
};
programs.home-manager.enable = true;
}

View File

@ -1,89 +1,103 @@
{ lib, pkgs, configLib, configVars, ... }:
{ inputs, config, lib, pkgs, outputs,... }:
let
pubKeys = lib.filesystem.listFilesRecursive (../common/users/keys);
in
{
imports = [
imports =
[
# Disk configuration
inputs.disko.nixosModules.disko
(import ../common/disks/std-disk-config.nix { device = "/dev/vda"; })
../common/optional/btrfs-impermanence.nix
inputs.impermanence.nixosModules.impermanence
# Import core options
./hardware-configuration.nix
../common/core
];
# Import optional options
# ../common/optional/openssh
nixpkgs = {
overlays = [
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
];
config = {
allowUnfree = true;
};
};
# Create users for this host
../common/users/admin
];
fileSystems."/persist".neededForBoot = true;
environment.persistence."/persist" = {
hideMounts = true;
directories = [
"/etc/nixos"
];
files = [
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
"/etc/ssh/deploy_key-ssh-ed25519"
];
};
#virtualisation.virtualbox.guest.enable = true;
virtualisation.libvirtd = {
qemu = {
package = pkgs.qemu_kvm; # only emulates host arch, smaller download
swtpm.enable = true; # allows for creating emulated TPM
ovmf.packages = [(pkgs.OVMF.override {
secureBoot = true;
tpmSupport = true;
}).fd]; # or use pkgs.OVMFFull.fd, which enables more stuff
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
timeout = 3;
};
};
#fileSystems."/boot".options = ["umask=0077"]; # Removes permissions and security warnings.
#boot.loader.efi.canTouchEfiVariables = true;
#boot.loader.grub.device = "/dev/vda";
boot.loader.grub.enable = true;
# boot.loader.systemd-boot = {
# enable = true;
# # we use Git for version control, so we don't need to keep too many generations.
# # FIXME lower this even more after testing complete
# configurationLimit = lib.mkDefault 10;
# # pick the highest resolution for systemd-boot's console.
# consoleMode = lib.mkDefault "max";
# };
boot.initrd.systemd.enable = true;
i18n.defaultLocale = "en_GB.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "uk";
useXkbConfig = false;
users = {
mutableUsers = true;
extraUsers = {
root = {
initialPassword = "1234";
openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
};
};
};
networking = {
hostName = "bootstrap";
networkmanager.enable = true;
enableIPv6 = false;
};
services = {
qemuGuest.enable = true;
openssh = {
enable = true;
ports = [22]; # FIXME: Make this use configVars.networking
settings.PermitRootLogin = "yes";
# Fix LPE vulnerability with sudo use SSH_AUTH_SOCK: https://github.com/NixOS/nixpkgs/issues/31611
# this mitigates the security issue caused by enabling u2fAuth in pam
authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"];
services.openssh = {
enable = true;
ports = [22];
authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"];
hostKeys = [{
path = "/persist/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}];
settings = {
PasswordAuthentication = false;
PermitRootLogin = "yes";
PubKeyAuthentication = "yes";
StreamLocalBindUnlink = "yes";
UsePAM = true;
};
};
programs.ssh.extraConfig = ''
Host git.bitlab21.com
IdentitiesOnly yes
StrictHostKeyChecking no
IdentityFile /etc/ssh/deploy_key-ssh-ed25519
'';
security.pam = {
sshAgentAuth.enable = true;
#FIXME the above is deprecated in 24.05 but we will wait until release
#sshAgentAuth.enable = true;
services = {
sudo.u2fAuth = true;
};
};
networking.firewall.allowedTCPPorts = [ 22 ];
# ssh-agent is used to pull my private secrets repo from gitlab when deploying nix-config.
# programs.ssh.startAgent = true;
environment.systemPackages = builtins.attrValues {
inherit(pkgs)
wget
curl
git
rsync;
services = {
qemuGuest.enable = true;
};
nix.settings.experimental-features = [ "nix-command" "flakes" ];
system.stateVersion = "23.11";
}

View File

@ -10,17 +10,9 @@
boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" "kvm-intel" ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" =
{
};
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

View File

@ -1,6 +1,8 @@
{pkgs, ...}: {
{ pkgs, lib, inputs, config, ...}:
{
imports = [
./sops.nix
./locale.nix
];
environment.systemPackages = [
@ -8,6 +10,7 @@
pkgs.curl
pkgs.just
pkgs.git
pkgs.neovim
];
}

View File

@ -0,0 +1,8 @@
{
i18n.defaultLocale = "en_GB.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "uk";
useXkbConfig = false;
};
}

View File

@ -1,8 +1,8 @@
{ pkgs, inputs, config, configVars, ... }:
{ pkgs, inputs, config, username, ... }:
let
secretsDirectory = builtins.toString inputs.nix-secrets;
secretsFile = "${secretsDirectory}/secrets.yaml";
homeDirectory = "/home/${configVars.username}";
in
{
imports = [
@ -15,8 +15,12 @@ in
age = {
sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
keyFile = "/var/lib/sops-nix/key.txt";
generateKey = true;
};
secrets = {
"passwords/root".neededForUsers = true;
"ssh_keys/deploy_key/id_ed25519" = {
path = "/etc/ssh/deploy_key-ssh-ed25519";
};
};
};
}

View File

@ -0,0 +1,63 @@
{
disko.devices = {
disk = {
vdb = {
type = "disk";
device = "/dev/vdb";
content = {
type = "gpt";
partitions = {
ESP = {
size = "512M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [
"defaults"
];
};
};
luks = {
size = "100%";
content = {
type = "luks";
name = "crypted";
# disable settings.keyFile if you want to use interactive password entry
#passwordFile = "/tmp/secret.key"; # Interactive
settings = {
allowDiscards = true;
keyFile = "/tmp/secret.key";
};
additionalKeyFiles = [ "/tmp/additionalSecret.key" ];
content = {
type = "btrfs";
extraArgs = [ "-f" ];
subvolumes = {
"/root" = {
mountpoint = "/";
mountOptions = [ "compress=zstd" "noatime" ];
};
"/home" = {
mountpoint = "/home";
mountOptions = [ "compress=zstd" "noatime" ];
};
"/nix" = {
mountpoint = "/nix";
mountOptions = [ "compress=zstd" "noatime" ];
};
"/swap" = {
mountpoint = "/.swapvol";
swap.swapfile.size = "20M";
};
};
};
};
};
};
};
};
};
};
}

View File

@ -1,11 +1,9 @@
{device ? throw "Must define a device, e.g. /dev/sda"}:
{
disko.devices = {
disk = {
#FIXME change to proper device or make dynamic like figdetingbits
sda = {
disk.main = {
inherit device;
type = "disk";
# FIXME change to proper device or make dynamic like figdetingbits
device = "/dev/sda";
content = {
type = "gpt";
partitions = {
@ -21,25 +19,38 @@
mountpoint = "/boot";
};
};
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
root = {
name = "root";
size = "100%";
content = {
type = "lvm_pv";
vg = "root_vg";
};
};
};
};
};
lvm_vg = {
root_vg = {
type = "lvm_vg";
lvs = {
root = {
size = "100%FREE";
content = {
type = "btrfs";
extraArgs = ["-f"];
subvolumes = {
"/root" = {
mountpoint = "/";
};
"/persist" = {
mountOptions = [ "compress=zstd" ];
mountOptions = [ "subvol=persist" ];
mountpoint = "/persist";
};
"/nix" = {
mountOptions = [ "compress=zstd" "noatime" ];
mountOptions = [ "subvol=nix" "noatime" ];
mountpoint = "/nix";
};
@ -51,7 +62,6 @@
};
};
};
};
};
};
};

View File

@ -0,0 +1,29 @@
{lib, ...}:
{
boot.initrd.postDeviceCommands = lib.mkAfter ''
mkdir /btrfs_tmp
mount /dev/root_vg/root /btrfs_tmp
if [[ -e /btrfs_tmp/root ]]; then
mkdir -p /btrfs_tmp/old_roots
timestamp=$(date --date="@$(stat -c %Y /btrfs_tmp/root)" "+%Y-%m-%-d_%H:%M:%S")
mv /btrfs_tmp/root "/btrfs_tmp/old_roots/$timestamp"
fi
delete_subvolume_recursively() {
IFS=$'\n'
for i in $(btrfs subvolume list -o "$1" | cut -f 9- -d ' '); do
delete_subvolume_recursively "/btrfs_tmp/$i"
done
btrfs subvolume delete "$1"
}
for i in $(find /btrfs_tmp/old_roots/ -maxdepth 1 -mtime +30); do
delete_subvolume_recursively "$i"
done
btrfs subvolume create /btrfs_tmp/root
umount /btrfs_tmp
'';
}

View File

@ -0,0 +1,33 @@
{ lib, config, ... }:
let
sshPort = 22;
in
{
services.openssh = {
enable = true;
ports = [ sshPort ];
authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"];
hostKeys = [{
path = "/persist/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}];
settings = {
PasswordAuthentication = false;
PermitRootLogin = "no";
PubKeyAuthentication = "yes";
StreamLocalBindUnlink = "yes";
UsePAM = true;
};
};
security.pam = {
sshAgentAuth.enable = true;
};
programs.ssh.extraConfig = ''
Host git.bitlab21.com
IdentitiesOnly yes
StrictHostKeyChecking no
IdentityFile /etc/ssh/deploy_key-ssh-ed25519
'';
networking.firewall.allowedTCPPorts = [ sshPort ];
}

View File

@ -1,22 +0,0 @@
{ lib, config, ... }:
let
sshPort = 22;
in
{
services.openssh = {
enable = true;
ports = [ sshPort ];
settings = {
# Harden
PasswordAuthentication = true;
PermitRootLogin = "no";
# Automatically remove stale sockets
StreamLocalBindUnlink = "yes";
};
};
networking.firewall.allowedTCPPorts = [ sshPort ];
}

View File

@ -1 +0,0 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILywv6g5k5cOVplxgbbStrGf3qYVukgCcd80TJSBM8e8 sam@nixos

View File

@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFc+y7KKEbutJe9u9UPP3rWqchjS7/yrpyoQRd178c7u sam

View File

@ -0,0 +1,49 @@
{ pkgs, inputs, config, lib, ... }:
let
pubKeys = lib.filesystem.listFilesRecursive (../keys);
hostname = config.networking.hostName;
sopsHashedPasswordFile = lib.optionalString (lib.hasAttr "sops-nix" inputs) config.sops.secrets."passwords/media".path;
secretsDirectory = builtins.toString inputs.nix-secrets;
secretsFile = "${secretsDirectory}/secrets.yaml";
in
{
users.users.media = {
isNormalUser = true;
shell = pkgs.zsh; # default shell
#hashedPasswordFile = sopsHashedPasswordFile;
password = "nixos";
openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
extraGroups =
[ "qemu-libvirtd" "libvirtd"
"wheel" "video" "audio" "disk" "networkmanager"
];
};
sops.secrets."passwords/media" = {
sopsFile = "${secretsFile}";
neededForUsers = true;
};
sops.secrets."ssh_keys/media/id_ed25519" = {
path = "/home/media/.ssh/id_ed25519";
};
sops.secrets."ssh_keys/media/id_ed25519.pub" = {
path = "/home/media/.ssh/id_ed25519.pub";
};
programs.zsh.enable = true;
programs.fuse.userAllowOther = true;
home-manager = {
extraSpecialArgs = { inherit inputs; };
users = {
media = import ../../../../home/${hostname}.nix;
};
};
environment.systemPackages = [
];
}

View File

@ -1,14 +1,18 @@
{ 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;
secretsDirectory = builtins.toString inputs.nix-secrets;
secretsFile = "${secretsDirectory}/secrets.yaml";
in
{
users.users.sam = {
mutableUsers = true;
isNormalUser = true;
#password = "nixos"; # Overridden if sops is working
shell = pkgs.zsh; # default shell
initialPassword = "nixos";
hashedPasswordFile = sopsHashedPasswordFile;
openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
extraGroups = [
@ -20,9 +24,13 @@ in
};
sops.secrets."passwords/sam" = {
sopsFile = "${secretsFile}";
neededForUsers = true;
};
programs.zsh.enable = true;
#home-manager.users.sam =
home-manager = {
extraSpecialArgs = { inherit inputs; };
users = {

View File

@ -41,13 +41,6 @@
time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "uk";
useXkbConfig = false;
};
programs.gnupg.agent = {
enable = true;
enableSSHSupport = true;

View File

@ -1,32 +0,0 @@
{ inputs, config, lib, pkgs, outputs,... }:
{
imports =
[
# Import core options
./hardware-configuration.nix
../common/core
# Import optional options
../common/optional/pipewire.nix
../common/optional/hyprland.nix
../common/optional/displayManager/sddm.nix
../common/optional/openssh
# Create users for this host
../common/users/sam
];
nixpkgs = {
overlays = [
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
];
config = {
allowUnfree = true;
};
};
nix.settings.experimental-features = [ "nix-command" "flakes" ];

View File

@ -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
@ -42,13 +42,6 @@
time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "uk";
useXkbConfig = false;
};
services.printing.enable = true;
services.libinput.enable = true;

107
hosts/sparky/default.nix Normal file
View File

@ -0,0 +1,107 @@
{ inputs, config, lib, pkgs, outputs,... }:
let
sopsHashedPasswordFile = lib.optionalString (lib.hasAttr "sops-nix" inputs) config.sops.secrets."passwords/root".path;
secretsDirectory = builtins.toString inputs.nix-secrets;
secretsFile = "${secretsDirectory}/secrets.yaml";
in
{
imports =
[
# Disk configuration
inputs.disko.nixosModules.disko
(import ../common/disks/std-disk-config.nix { device = "/dev/vda"; })
../common/optional/btrfs-impermanence.nix
inputs.impermanence.nixosModules.impermanence
# Create users for this host
../common/users/media
# Import core options
./hardware-configuration.nix
../common/core
# Import optional options
../common/optional/openssh.nix
];
nixpkgs = {
overlays = [
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
];
config = {
allowUnfree = true;
};
};
fileSystems."/persist".neededForBoot = true;
environment.persistence."/persist" = {
hideMounts = true;
directories = [
"/etc/nixos"
"/var/log"
"/var/lib/nixos"
"/var/lib/systemd/coredump"
"/etc/NetworkManager/system-connections"
];
files = [
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
];
users.media= {
directories = [
"sync"
"keep"
".ssh"
".config/dconf"
".config/cinnamon"
".config/nemo"
];
files = [
];
};
};
users = {
mutableUsers = true;
extraUsers = {
root = {
hashedPasswordFile = sopsHashedPasswordFile;
};
};
};
boot = {
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
timeout = 3;
};
};
networking = {
hostName = "sparky";
networkmanager.enable = true;
enableIPv6 = false;
};
services = {
qemuGuest.enable = true;
};
#services.libinput.enable = true;
#services.displayManager.defaultSession = "cinnamon";
# services.xserver = {
# enable = true;
# displayManager.lightdm.enable = true;
# desktopManager = {
# cinnamon.enable = true;
# };
# };
#
nix.settings.experimental-features = [ "nix-command" "flakes" ];
system.stateVersion = "23.11";
}

View File

@ -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 = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
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.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp1s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

View File

@ -4,15 +4,15 @@ SOPS_FILE := "../nix-secrets/secrets.yaml"
default:
@just --list
# ensure the latest revisions of nix-secrets are used next time a rebuild occurs
update-nix-secrets:
# fetches from remote and updates flake.lock with latest revisions of nix-secrets for next time a rebuild occurs
update-flake-secrets:
(cd ../nix-secrets && git fetch && git rebase) || true
nix flake lock --update-input nix-secrets
# full system rebuild from flake (stages changes and automatically detects host)
rebuild-system:
git add *.nix
sudo nixos-rebuild switch --flake $HOME/nixos#$(hostname)
sudo nixos-rebuild switch --flake .#$(hostname)
# updates all flake inputs for system
update-flake:
@ -23,9 +23,10 @@ edit-sops:
echo "Editing {{SOPS_FILE}}"
nix-shell -p sops --run "SOPS_AGE_KEY_FILE=~/.config/sops/age/keys.txt sops {{SOPS_FILE}}"
# update
update-secrets:
# update keys in secrets.yaml and push to remote
update-sops-secrets:
cd $HOME/nix-secrets && (\
nix-shell -p sops --run "sops updatekeys -y secrets.yaml" && \
git add -u && (git commit -m "updated secrets" || true) && git push \
)

View File

@ -12,87 +12,100 @@ for the root user.
read -p "Confirm host had been setup using the above steps...(yes|no): " confirm
[ "$confirm" != "yes" ] && echo "Exiting" && exit 0
cd ~
read -p "Enter hostname: " hostname
read -p "Enter username: " username
read -p "Enter ip address: " ip
# Target host details
#cd ~
#read -p "Enter hostname: " hostname
#read -p "Enter username: " username
#read -p "Enter ip address: " ip
#read -p "Enter nixosSystem to build, e.g. 'bootstrap': " config
hostname="bootstrap"
ip="192.168.122.192"
config="bootstrap"
KEY_DIR="$HOME/keys/$hostname/"
mkdir -p $KEY_DIR
ssh-copy-id -i "$(readlink -n "$HOME/.ssh/gitea.pub" )" "root@$ip"
# Generate key name and dir
HOST_KEY_DIR="$HOME/keys/hosts/$hostname"
mkdir -p "$HOST_KEY_DIR"
echo "Creating ssh keys for new host. Will create in current directory: "$KEY_DIR
KEY_NAME="ssh_ed25519_key_$hostname"
# 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"
KNOWN_HOSTS=$(grep "$ip" ~/.ssh/known_hosts)
confirm_delete=""
# Delete key in known hosts if exists
sed -i "/$ip/d" ~/.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
# Authorise source public key
echo "Copying pubkey to target host"
ssh-copy-id -i "$(readlink -f "$HOME/.ssh/id_ed25519.pub")" "root@$ip"
overwrite=""
[ -f "$KEY_DIR/$KEY_NAME" ] && read -p "Key exists, would you like to overwrite it? (yes|no) " overwrite
# 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"
HOST_AGE_KEY=$(cat "$HOST_KEY_DIR/age_host_key")
echo -e "Host age key:\n$HOST_AGE_KEY\n"
echo "These keys needs to be inserted into .sops.yaml file. This will be prompted again later."
[ "$overwrite" == "yes" ] && ssh-keygen -t ed25519 -f "$KEY_DIR/$KEY_NAME" -C "$hostname@$ip" -N ""
# Create temp directory for ssh keys to be copied to host:
temp=$(mktemp -d)
echo "Copying ssh key to target host:"
# Rsync currently not available in Nixos. Use scp instead.
#rsync -av "ssh_ed25519_key_$hostname"* "root@$ip:/etc/ssh/"
scp -i "$KEY_DIR/ssh_ed25519_key_$hostname"* "root@$ip:/etc/ssh/"
[ $? != 0 ] && echo "Error copying keys to target host" && exit 1
# Function to cleanup temporary directory on exit
cleanup() {
rm -rf "$temp"
}
trap cleanup EXIT
echo "Generating age key from 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
# Create the directory where sshd expects to find the host keys
install -d -m755 "$temp/persist/etc/ssh"
AGE_KEY=$(cat "$KEY_DIR/age_key_$hostname")
cat "$HOST_KEY_DIR/ssh_host_ed25519_key" > "$temp/persist/etc/ssh/ssh_host_ed25519_key"
cat "$HOST_KEY_DIR/ssh_host_ed25519_key.pub" > "$temp/persist/etc/ssh/ssh_host_ed25519_key.pub"
echo -e "Age key:\n$AGE_KEY\n"
echo "This needs to be inserted into .sops.yaml file."
chmod 600 "$temp/persist/etc/ssh/ssh_host_ed25519_key"
chmod 644 "$temp/persist/etc/ssh/ssh_host_ed25519_key.pub"
# Install Nixos bootstrap
# Install Nixos to target
cd "$HOME/nixos"
SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --flake .#bootstrap root@"$ip" -i "$KEY_DIR/ssh_ed25519_key_$hostname"
git add . && git commit -m "auto: bootstrapping $hostname" && git push
[ $? != 0 ] && echo "Error commiting current changes" && exit 1
SHELL=/bin/sh nix run github:nix-community/nixos-anywhere -- --extra-files "$temp" --flake .#"$config" root@"$ip" -i "$HOME/.ssh/id_ed25519"
[ $? != 0 ] && echo "Error installing Nixos" && exit 1
## Delete keys from local known_hosts
echo "Deleting host from known_hosts"
sed -i "/$ip/d" ~/.ssh/known_hosts
# Check host OS has booted (and not booted back into live cd)
while true;
do
read -p "Confirm live CD has been removed... (yes|no)" confirm
read -p "Confirm live CD has been removed... (yes|no): " confirm
[ "$confirm" = "yes" ] && break
done
echo "Waiting for $ip to come back online and port 22 to be open..."
while ! ping -c 1 $ip &> /dev/null || ! nc -zvw3 $ip 22 &> /dev/null
do
echo "$ip is still offline or port 22 is not open. Checking again in 5 seconds..."
sleep 5
done
echo "$ip is now online and port 22 is open!"
echo "Configuring ssh keys on target host to enable connection to gitea:"
ssh-copy-id -i "$HOME/.ssh/gitea.pub" "$username@$ip"
read -r -d '' config << EOM
Host git.bitlab21.com
IdentitiesOnly yes
StrictHostKeyChecking no
IdentityFile ~/.ssh/gitea
EOM
# Authorise source public key
echo "Copying pubkey to target host"
ssh-copy-id -i "$(readlink -f "$HOME/.ssh/id_ed25519.pub")" "root@$ip"
# Append the string to file on target machine
echo "$config" | ssh "$username@$ip" 'mkdir -p ~/.ssh/ && cat > ~/.ssh/config'
# Copy deploy_key to target for personal repo authorisation
scp -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "$(readlink -f "$HOME/.ssh/deploy_key-ssh-ed25519")" "root@$ip:/persist/etc/ssh/deploy_key-ssh-ed25519"
echo -e "
Complete!
Now add the age key to .sops.yaml, like this:
Now add the new target host age key to .sops.yaml. This is needed to enable the
new host to decrypt the secrets.yaml file from the ssh key we generated
previously.
Enter the details as following:
keys:
- &hosts:
- &$hostname $AGE_KEY
- &$hostname $HOST_AGE_KEY
creation_rules:
- path_regex: secrets.yaml$
@ -100,13 +113,16 @@ creation_rules:
- age:
- *$hostname
Then to update the keys for the secrets.yaml file, run:
'sops --config .sops.yaml updatekeys secrets.yaml'
or with nix-shell:
'nix-shell -p sops --run 'sops --config .sops.yaml updatekeys secrets.yaml''
then run 'nix flake lock --update-input nix-secrets $HOME/nixos'
Finally, commit and push these changes to remote so they can be accessed on
the new host.
Then update (i.e. re-encrypt) the secrets.yaml file with the new keys, run:
'sops --config .sops.yaml updatekeys secrets.yaml'
or with just:
'just update-sops-secrets'
Then commit and push these changes to remote so they can be accessed on the new
host.
"
while true;
@ -115,12 +131,8 @@ do
[ "$confirm" = "yes" ] && break
done
echo "Copying gitea private ssh key to host"
echo "New password is 'nixos'"
ssh -i "$(readlink -f "$HOME/.ssh/id_ed25519")" "root@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nixos.git /persist/etc/nixos/'"
rsync -av "$(readlink -n "$HOME/.ssh/gitea" )" "$username@$ip":~/.ssh/gitea
ssh "$username@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nixos.git'"
ssh "$username@$ip" "nix-shell -p git --run 'git clone git@git.bitlab21.com:sam/nix-secrets.git'"
echo -e "###\nSuccessfully installed Nixos on the target host!\n###"
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/'"
exit 0

35
scripts/generate_age_keys.sh Executable file
View File

@ -0,0 +1,35 @@
#!/usr/bin/env bash
echo "Generating an age key based on the new ssh_host_ed25519_key."
target_key=$(ssh-keyscan -p $ssh_port -t ssh-ed25519 "$target_destination" 2>&1 | grep ssh-ed25519 | cut -f2- -d" ")
age_key=$(nix shell nixpkgs#ssh-to-age.out -c sh -c "echo $target_key | ssh-to-age")
if grep -qv '^age1' <<<"$age_key"; then
echo "The result from generated age key does not match the expected format."
echo "Result: $age_key"
echo "Expected format: age10000000000000000000000000000000000000000000000000000000000"
exit 1
else
echo "$age_key"
fi
echo "Updating nix-secrets/.sops.yaml"
cd ../nix-secrets
SOPS_FILE=".sops.yaml"
sed -i "{
# Remove any * and & entries for this host
/[*&]$target_hostname/ d;
# Inject a new age: entry
# n matches the first line following age: and p prints it, then we transform it while reusing the spacing
/age:/{n; p; s/\(.*- \*\).*/\1$target_hostname/};
# Inject a new hosts: entry
/&hosts:/{n; p; s/\(.*- &\).*/\1$target_hostname $age_key/}
}" $SOPS_FILE
echo "Updating nix-secrets/.sops.yaml"
cd -
just rekey
echo "Updating flake lock on source machine with new .sops.yaml info"
nix flake lock --update-input nix-secrets

60
scripts/generate_ssh_keys.sh Executable file
View File

@ -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 ""