Compare commits

..

No commits in common. "3e5ebafed6435f47ed2e8dae3b87e45ae086d56b" and "0359491756e19f18f30096ead9c18abd5c2049e9" have entirely different histories.

35 changed files with 308 additions and 751 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,6 +11,28 @@
home.packages = [ 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 = { home.file = {
}; };

View File

@ -1,39 +0,0 @@
{ 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,7 +16,29 @@
pkgs.xfce.thunar pkgs.xfce.thunar
#pkgs.age #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 = { home.file = {
".icons/bibata".source = "${pkgs.bibata-cursors}/share/icons/Bibata-Modern-Classic"; ".icons/bibata".source = "${pkgs.bibata-cursors}/share/icons/Bibata-Modern-Classic";
}; };
@ -49,5 +71,6 @@
IMAGE_EDITOR=""; IMAGE_EDITOR="";
}; };
programs.home-manager.enable = true;
} }

View File

@ -1,103 +1,89 @@
{ inputs, config, lib, pkgs, outputs,... }: { lib, pkgs, configLib, configVars, ... }:
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 # Import core options
./hardware-configuration.nix ./hardware-configuration.nix
../common/core ../common/core
];
nixpkgs = { # Import optional options
overlays = [ # ../common/optional/openssh
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.unstable-packages
];
config = {
allowUnfree = true;
};
};
fileSystems."/persist".neededForBoot = true; # Create users for this host
environment.persistence."/persist" = { ../common/users/admin
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"
];
};
boot = { #virtualisation.virtualbox.guest.enable = true;
loader = { virtualisation.libvirtd = {
systemd-boot.enable = true; qemu = {
efi.canTouchEfiVariables = true; package = pkgs.qemu_kvm; # only emulates host arch, smaller download
timeout = 3; 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
}; };
}; };
#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;
users = { i18n.defaultLocale = "en_GB.UTF-8";
mutableUsers = true; console = {
extraUsers = { font = "Lat2-Terminus16";
root = { keyMap = "uk";
initialPassword = "1234"; useXkbConfig = false;
openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key);
};
};
}; };
networking = { networking = {
hostName = "bootstrap"; hostName = "bootstrap";
networkmanager.enable = true; networkmanager.enable = true;
enableIPv6 = false; enableIPv6 = false;
}; };
services.openssh = { services = {
enable = true; qemuGuest.enable = true;
ports = [22]; openssh = {
authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"]; enable = true;
hostKeys = [{ ports = [22]; # FIXME: Make this use configVars.networking
path = "/persist/etc/ssh/ssh_host_ed25519_key"; settings.PermitRootLogin = "yes";
type = "ed25519"; # 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
settings = { authorizedKeysFiles = lib.mkForce ["/etc/ssh/authorized_keys.d/%u"];
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 = { security.pam = {
sshAgentAuth.enable = true; 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 ];
services = { # ssh-agent is used to pull my private secrets repo from gitlab when deploying nix-config.
qemuGuest.enable = true; # programs.ssh.startAgent = true;
environment.systemPackages = builtins.attrValues {
inherit(pkgs)
wget
curl
git
rsync;
}; };
nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.settings.experimental-features = [ "nix-command" "flakes" ];
system.stateVersion = "23.11"; system.stateVersion = "23.11";
} }

View File

@ -10,9 +10,17 @@
boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ]; boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
boot.initrd.kernelModules = [ ]; boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ]; boot.kernelModules = [ "kvm-amd" "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" =
{
};
swapDevices =
[
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking # 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 # (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 # still possible to use this option, but it's recommended to use it in conjunction

View File

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

View File

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

View File

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

View File

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

View File

@ -1,29 +0,0 @@
{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

@ -1,33 +0,0 @@
{ 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

@ -0,0 +1,22 @@
{ 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

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

View File

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

View File

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

View File

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

32
hosts/media/default.nix Normal file
View File

@ -0,0 +1,32 @@
{ 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/pipewire.nix
../common/optional/hyprland.nix ../common/optional/hyprland.nix
../common/optional/displayManager/sddm.nix ../common/optional/displayManager/sddm.nix
../common/optional/openssh.nix ../common/optional/openssh
# Create users for this host # Create users for this host
../common/users/sam ../common/users/sam
@ -42,6 +42,13 @@
time.timeZone = "Europe/London"; time.timeZone = "Europe/London";
i18n.defaultLocale = "en_GB.UTF-8";
console = {
font = "Lat2-Terminus16";
keyMap = "uk";
useXkbConfig = false;
};
services.printing.enable = true; services.printing.enable = true;
services.libinput.enable = true; services.libinput.enable = true;

View File

@ -1,107 +0,0 @@
{ 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

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

View File

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

View File

@ -1,35 +0,0 @@
#!/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

View File

@ -1,60 +0,0 @@
#!/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 ""