refactor(luna): massively overhaul luna to better handle opt-in state
Now uses BTRFS rollbacks instead of tmpfs
This commit is contained in:
parent
79ee36db2d
commit
7a64899cee
5
.envrc
Normal file
5
.envrc
Normal file
@ -0,0 +1,5 @@
|
||||
# vim: ft=bash
|
||||
if ! has nix_direnv_version || ! nix_direnv_version 2.5.1; then
|
||||
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.5.1/direnvrc" "sha256-puRzug17Ed4JFS2wbpqa3k764QV6xPP6O3A/ez/JpOM="
|
||||
fi
|
||||
use flake
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.direnv/
|
||||
*.ignore
|
105
flake.lock
105
flake.lock
@ -22,6 +22,29 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"blog": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"host": "gitlab.orion-technologies.io",
|
||||
"lastModified": 1701591195,
|
||||
"narHash": "sha256-cyU5Yv3vPaf9cfuqrScyObf8DA77KE+7HxF8WSmCEJA=",
|
||||
"owner": "blog",
|
||||
"repo": "blog",
|
||||
"rev": "cbaf7ebe37d5e305991150a6b3aa9468cfa0a713",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.orion-technologies.io",
|
||||
"owner": "blog",
|
||||
"repo": "blog",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@ -44,6 +67,26 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701905325,
|
||||
"narHash": "sha256-lda63LmEIlDMeCgWfjr3/wb487XPllBByfrGRieyEk4=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "1144887c6f4d2dcbb2316a24364ef53e25b0fcfe",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
@ -62,6 +105,24 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701680307,
|
||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
@ -114,35 +175,14 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"personal-blog": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"host": "gitlab.orion-technologies.io",
|
||||
"lastModified": 1701591195,
|
||||
"narHash": "sha256-cyU5Yv3vPaf9cfuqrScyObf8DA77KE+7HxF8WSmCEJA=",
|
||||
"owner": "blog",
|
||||
"repo": "blog",
|
||||
"rev": "cbaf7ebe37d5e305991150a6b3aa9468cfa0a713",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
"host": "gitlab.orion-technologies.io",
|
||||
"owner": "blog",
|
||||
"repo": "blog",
|
||||
"type": "gitlab"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"blog": "blog",
|
||||
"disko": "disko",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"impermanence": "impermanence",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"personal-blog": "personal-blog"
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
@ -159,6 +199,21 @@
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
127
flake.nix
127
flake.nix
@ -3,6 +3,7 @@
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
impermanence = {
|
||||
url = "github:nix-community/impermanence";
|
||||
};
|
||||
@ -10,69 +11,89 @@
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
personal-blog = {
|
||||
url = "gitlab:blog/blog?host=gitlab.orion-technologies.io";
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
blog = {
|
||||
type = "gitlab";
|
||||
owner = "blog";
|
||||
repo = "blog";
|
||||
host = "gitlab.orion-technologies.io";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
outputs = inputs @ { self, nixpkgs, impermanence, agenix, ... }:
|
||||
outputs = inputs @ { self, nixpkgs, impermanence, agenix, disko, flake-utils, blog, ... }:
|
||||
let
|
||||
specialArgs = {
|
||||
secrets = ./secrets;
|
||||
persist-dir = "/nix/persist";
|
||||
};
|
||||
lib = import ./lib // nixpkgs.lib;
|
||||
pkgs = nixpkgs.legacyPackages."x86_64-linux";
|
||||
defaults = {
|
||||
config = {
|
||||
environment.persistence = {
|
||||
"${specialArgs.persist-dir}" = {
|
||||
hideMounts = true;
|
||||
directories = [
|
||||
"/var/lib"
|
||||
"/var/log"
|
||||
"/etc/nixos"
|
||||
"/opt"
|
||||
"/persist"
|
||||
];
|
||||
files = [
|
||||
"/etc/machine-id"
|
||||
"/etc/ssh/ssh_host_ed25519_key"
|
||||
"/etc/ssh/ssh_host_ed25519_key.pub"
|
||||
"/etc/ssh/ssh_host_rsa_key"
|
||||
"/etc/ssh/ssh_host_rsa_key.pub"
|
||||
];
|
||||
};
|
||||
environment.etc.machine-id.source = "/nix/persist/ephemeral/etc/machine-id";
|
||||
environment.persistence.save = {
|
||||
hideMounts = true;
|
||||
persistentStoragePath = "/nix/persist/save";
|
||||
};
|
||||
environment.persistence.ephemeral = {
|
||||
persistentStoragePath = "/nix/persist/ephemeral";
|
||||
hideMounts = true;
|
||||
directories = [
|
||||
"/var/lib"
|
||||
"/var/log"
|
||||
"/etc/nixos"
|
||||
{ directory = "/persist"; user = "root"; group = "root"; mode = "0700"; }
|
||||
];
|
||||
};
|
||||
|
||||
age.identityPaths = [
|
||||
"/persist/nix.key"
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
nixosConfigurations.orion = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = specialArgs;
|
||||
modules = [
|
||||
{ _module.args = inputs; }
|
||||
defaults
|
||||
./hosts/orion
|
||||
impermanence.nixosModules.impermanence
|
||||
agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
nixosConfigurations.luna = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
specialArgs = specialArgs;
|
||||
modules = [
|
||||
{ _module.args = inputs; }
|
||||
defaults
|
||||
./hosts/luna
|
||||
impermanence.nixosModules.impermanence
|
||||
agenix.nixosModules.default
|
||||
];
|
||||
};
|
||||
};
|
||||
nixosConfigurations.luna =
|
||||
let
|
||||
hostname = "luna";
|
||||
in
|
||||
nixpkgs.lib.nixosSystem
|
||||
{
|
||||
system = "x86_64-linux";
|
||||
specialArgs = {
|
||||
inherit self;
|
||||
inherit flake-utils;
|
||||
inherit inputs;
|
||||
inherit hostname;
|
||||
inherit lib;
|
||||
inherit blog;
|
||||
secrets = "${self}/secrets/${hostname}";
|
||||
disk = "nvme0n1";
|
||||
fqdn = "orion-technologies.io";
|
||||
};
|
||||
modules = [
|
||||
{
|
||||
_module.args = { };
|
||||
}
|
||||
defaults
|
||||
impermanence.nixosModules.impermanence
|
||||
agenix.nixosModules.default
|
||||
disko.nixosModules.disko
|
||||
./hosts/${hostname}
|
||||
];
|
||||
};
|
||||
|
||||
} // flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ agenix.overlays.default ];
|
||||
};
|
||||
in
|
||||
{
|
||||
devShells.default =
|
||||
pkgs.mkShell
|
||||
{
|
||||
packages = with pkgs; [ age age-plugin-yubikey pkgs.agenix ];
|
||||
shellHook = ''
|
||||
export RULES="$PWD/secrets/secrets.nix"
|
||||
'';
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
{ config, lib, nixpkgs, ... }:
|
||||
{
|
||||
|
||||
imports = [
|
||||
./modules
|
||||
./os
|
||||
];
|
||||
system.stateVersion = "23.11";
|
||||
imports = (lib.recurseFilesInDirs [ ./os ./modules ] ".nix");
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
|
@ -2,15 +2,4 @@
|
||||
|
||||
{
|
||||
time.timeZone = "America/Chicago";
|
||||
|
||||
imports = [
|
||||
./services
|
||||
./docker
|
||||
./impermanence.nix
|
||||
./nix.nix
|
||||
./networking.nix
|
||||
./programs.nix
|
||||
./user.nix
|
||||
./system.nix
|
||||
];
|
||||
}
|
||||
|
@ -14,7 +14,4 @@
|
||||
package = pkgs.docker_24;
|
||||
};
|
||||
};
|
||||
imports = [
|
||||
./gitlab.nix
|
||||
];
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
{ lib, config, specialArgs, ... }:
|
||||
{ secrets, config, specialArgs, fqdn, ... }:
|
||||
let
|
||||
gitlab_home = "/opt/gitlab";
|
||||
hostname = "gitlab.orion-technologies.io";
|
||||
gitlab_home = "/var/lib/gitlab";
|
||||
gitlab_host = "gitlab.${fqdn}";
|
||||
in
|
||||
{
|
||||
environment.persistence.save.directories = [
|
||||
gitlab_home
|
||||
];
|
||||
virtualisation.oci-containers.containers.gitlab = {
|
||||
image = "gitlab/gitlab-ee:latest";
|
||||
autoStart = true;
|
||||
@ -18,7 +21,8 @@ in
|
||||
];
|
||||
extraOptions = [
|
||||
"--shm-size=256m"
|
||||
"--hostname=${hostname}"
|
||||
"--hostname=${gitlab_host}"
|
||||
"--pull=always"
|
||||
];
|
||||
};
|
||||
|
||||
@ -26,11 +30,11 @@ in
|
||||
2222
|
||||
];
|
||||
|
||||
age.secrets.gitlab-runner-reg-config.file = specialArgs.secrets + "/gitlab-runner-reg-config.age";
|
||||
age.secrets.gitlab-runner-reg-config.file = "${secrets}/gitlab-runner-reg-config.age";
|
||||
services.gitlab-runner = {
|
||||
enable = true;
|
||||
services = {
|
||||
default = with lib; {
|
||||
default = {
|
||||
registrationConfigFile = config.age.secrets.gitlab-runner-reg-config.path;
|
||||
dockerImage = "alpine";
|
||||
tagList = [
|
||||
@ -41,7 +45,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."${hostname}" = {
|
||||
services.nginx.virtualHosts."${gitlab_host}" = {
|
||||
locations."/".proxyPass = "http://127.0.0.1:8080";
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
|
@ -1,4 +0,0 @@
|
||||
{ ... }:
|
||||
{
|
||||
environment.persistence = { };
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
{ inputs, lib, pkgs, hostname, ... }:
|
||||
|
||||
let
|
||||
hostname = "luna";
|
||||
networks_dhcp_use_dns = "no";
|
||||
networks_dhcp = "ipv4";
|
||||
networks_multicast_dns = "no";
|
||||
|
@ -1,16 +1,13 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
{ pkgs, ... }: {
|
||||
nix = {
|
||||
settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
auto-optimise-store = true;
|
||||
trusted-users = ["@wheel"];
|
||||
trusted-users = [ "wheel" ];
|
||||
};
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 7d";
|
||||
dates = "daily";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
{ pkgs, ... }: {
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
programs = {
|
||||
zsh.enable = true;
|
||||
neovim = {
|
||||
enable = true;
|
||||
defaultEditor = true;
|
||||
@ -13,11 +10,12 @@
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim
|
||||
coreutils-full
|
||||
nano
|
||||
curl
|
||||
wget
|
||||
git
|
||||
jq
|
||||
rsync
|
||||
rustc
|
||||
cargo
|
||||
];
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
{ ... }:
|
||||
{
|
||||
imports = [
|
||||
./openssh.nix
|
||||
./fail2ban.nix
|
||||
./nginx.nix
|
||||
];
|
||||
}
|
@ -3,8 +3,5 @@
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
maxretry = 10;
|
||||
jails.DEFAULT.settings = {
|
||||
port = "2200";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
8
hosts/luna/modules/services/journald.nix
Normal file
8
hosts/luna/modules/services/journald.nix
Normal file
@ -0,0 +1,8 @@
|
||||
{ ... }:
|
||||
{
|
||||
services.journald = {
|
||||
extraConfig = ''
|
||||
SystemMaxUse=100G
|
||||
'';
|
||||
};
|
||||
}
|
@ -1,7 +1,4 @@
|
||||
{ config, pkgs, system, personal-blog, ... }:
|
||||
let
|
||||
blog-host = "blog.orion-technologies.io";
|
||||
in
|
||||
{ config, pkgs, blog, fqdn, ... }:
|
||||
{
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
@ -15,10 +12,10 @@ in
|
||||
defaults.email = "price@orion-technologies.io";
|
||||
};
|
||||
|
||||
services.nginx.virtualHosts."${blog-host}" = {
|
||||
services.nginx.virtualHosts."blog.${fqdn}" = {
|
||||
forceSSL = true;
|
||||
enableACME = true;
|
||||
root = personal-blog.packages.${pkgs.system}.default;
|
||||
root = blog.packages.${pkgs.system}.default;
|
||||
locations."/".index = "home.html";
|
||||
};
|
||||
|
||||
|
@ -1,20 +1,60 @@
|
||||
{ ... }:
|
||||
{ config, ... }:
|
||||
{
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
# We set the hostkeys manually so they persist through reboots
|
||||
hostKeys = [
|
||||
{
|
||||
path = (config.environment.persistence.ephemeral.persistentStoragePath + "/etc/ssh/ssh_host_ed25519_key");
|
||||
type = "ed25519";
|
||||
}
|
||||
];
|
||||
sftpFlags = [
|
||||
"-f AUTHPRIV"
|
||||
"-l INFO"
|
||||
];
|
||||
extraConfig = ''
|
||||
AllowUsers price
|
||||
'';
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
PermitRootLogin = "prohibit-password";
|
||||
PermitRootLogin = "no";
|
||||
LogLevel = "VERBOSE";
|
||||
KexAlgorithms = [
|
||||
"curve25519-sha256"
|
||||
"curve25519-sha256@libssh.org"
|
||||
"diffie-hellman-group16-sha512"
|
||||
"diffie-hellman-group18-sha512"
|
||||
"sntrup761x25519-sha512@openssh.com"
|
||||
"diffie-hellman-group-exchange-sha256"
|
||||
];
|
||||
Ciphers = [
|
||||
"chacha20-poly1305@openssh.com"
|
||||
"aes256-gcm@openssh.com"
|
||||
"aes128-gcm@openssh.com"
|
||||
"aes256-ctr"
|
||||
"aes192-ctr"
|
||||
"aes128-ctr"
|
||||
];
|
||||
Macs = [
|
||||
"hmac-sha2-512-etm@openssh.com"
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"umac-128-etm@openssh.com"
|
||||
];
|
||||
};
|
||||
ports = [
|
||||
2200
|
||||
];
|
||||
banner = ''
|
||||
┌────────────────────────────────────────────────────┐
|
||||
│ Orion Technologies - Security Notice │
|
||||
│ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄ │
|
||||
│ UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED │
|
||||
│ │
|
||||
│ You must have written, explicit, authorized │
|
||||
│ permission to access or configure this device. │
|
||||
│ Unauthorized attempts and actions to access or use │
|
||||
│ this system may result in civil and/or criminal │
|
||||
│ penalties. All activities performed on this device │
|
||||
│ are logged and monitored. │
|
||||
└────────────────────────────────────────────────────┘
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
{ pkgs, user, ... }:
|
||||
|
||||
{
|
||||
users.users = {
|
||||
root = {
|
||||
openssh.authorizedKeys.keys = [
|
||||
"no-touch-required sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJ9ODXLAIfGH/7VNobQsp5nwBvNoh+pQMEH7s2jkHpkqAAAACHNzaDpsdW5h"
|
||||
];
|
||||
initialPassword = "pass";
|
||||
};
|
||||
};
|
||||
}
|
19
hosts/luna/modules/users.nix
Executable file
19
hosts/luna/modules/users.nix
Executable file
@ -0,0 +1,19 @@
|
||||
{ pkgs, user, config, secrets, ... }:
|
||||
|
||||
{
|
||||
age.secrets.root-pw.file = "${secrets}/root-hash-pw.age";
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
users.users = {
|
||||
root = {
|
||||
passwordFile = config.age.secrets.root-pw.path;
|
||||
};
|
||||
price = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
shell = pkgs.bash;
|
||||
openssh.authorizedKeys.keys = [
|
||||
"no-touch-required sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJ9ODXLAIfGH/7VNobQsp5nwBvNoh+pQMEH7s2jkHpkqAAAACHNzaDpsdW5h"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
{ modulesPath, ... }:
|
||||
{ modulesPath, pkgs, ... }:
|
||||
{
|
||||
|
||||
imports =
|
||||
@ -10,6 +10,48 @@
|
||||
initrd = {
|
||||
availableKernelModules = [ "xhci_pci" "ahci" "nvme" "uas" "sd_mod" ];
|
||||
kernelModules = [ ];
|
||||
systemd = {
|
||||
enable = true;
|
||||
initrdBin = [ pkgs.libuuid pkgs.gawk ];
|
||||
services.rollback = {
|
||||
description = "Rollback btrfs root subvolume";
|
||||
wantedBy = [ "initrd.target" ];
|
||||
before = [ "sysroot.mount" ];
|
||||
after = [ "initrd-root-device.target" ];
|
||||
unitConfig.DefaultDependencies = "no";
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
mkdir -p /mnt
|
||||
DISK_LABEL="NixOS-Primary"
|
||||
ATTEMPTS=5
|
||||
printf "Attempting to find disk with label '%s'\n" "$DISK_LABEL"
|
||||
while ((ATTEMPTS > 0)); do
|
||||
if findfs LABEL="$DISK_LABEL"; then
|
||||
printf "Found disk!\n"
|
||||
break;
|
||||
fi
|
||||
((ATTEMPTS--))
|
||||
sleep 3
|
||||
printf "Remaining disk discovery attempts: %s\n" "$ATTEMPTS"
|
||||
done
|
||||
mount -t btrfs -o subvol=/ $(findfs LABEL="$DISK_LABEL") /mnt
|
||||
btrfs subvolume list -to /mnt/root \
|
||||
| awk 'NR>2 { printf $4"\n" }' \
|
||||
| while read subvol; do
|
||||
printf "Removing Subvolume: %s\n" "$subvol";
|
||||
btrfs subvolume delete "/mnt/$subvol"
|
||||
done
|
||||
|
||||
printf "Removing /root subvolume\n"
|
||||
btrfs subvolume delete /mnt/root
|
||||
|
||||
printf "Restoring base /root subvolume\n"
|
||||
btrfs subvolume snapshot /mnt/root-base /mnt/root
|
||||
|
||||
umount /mnt
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
loader = {
|
||||
systemd-boot.enable = true;
|
||||
|
@ -1,11 +1,6 @@
|
||||
{ modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./boot.nix
|
||||
./filesystem.nix
|
||||
./hardware.nix
|
||||
];
|
||||
system.stateVersion = "23.11";
|
||||
zramSwap.enable = true;
|
||||
}
|
||||
|
||||
|
57
hosts/luna/os/disk-config.nix
Normal file
57
hosts/luna/os/disk-config.nix
Normal file
@ -0,0 +1,57 @@
|
||||
{ disk ? "nvme0n1", ... }: {
|
||||
disko.devices = {
|
||||
disk.${disk} = {
|
||||
type = "disk";
|
||||
device = "/dev/${disk}";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
esp =
|
||||
let
|
||||
label = "NixOS-Boot";
|
||||
in
|
||||
{
|
||||
priority = 1;
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
content = {
|
||||
extraArgs = [ "-n ${label}" "-F 32" ];
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [
|
||||
"defaults"
|
||||
];
|
||||
};
|
||||
};
|
||||
root =
|
||||
let
|
||||
label = "NixOS-Primary";
|
||||
in
|
||||
{
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" "--label ${label}" ];
|
||||
postCreateHook = ''
|
||||
MOUNT="$(mktemp -d)"
|
||||
mount "/dev/disk/by-label/${label}" "$MOUNT" -o subvol=/
|
||||
trap 'umount $MOUNT; rm -rf $MOUNT' EXIT
|
||||
btrfs subvolume snapshot -r "$MOUNT/root" "$MOUNT/root-base"
|
||||
'';
|
||||
subvolumes = {
|
||||
"/root" = {
|
||||
mountpoint = "/";
|
||||
};
|
||||
"/nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [ "compress=zstd" "noatime" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
{
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "none";
|
||||
fsType = "tmpfs";
|
||||
options = [ "defaults" "noatime" "mode=755" ];
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-label/NixOS-Boot";
|
||||
fsType = "vfat";
|
||||
options = [ "defaults" "noatime" ];
|
||||
depends = [ "/" ];
|
||||
};
|
||||
|
||||
"/nix" = {
|
||||
device = "/dev/disk/by-label/NixOS-Primary";
|
||||
fsType = "btrfs";
|
||||
options = [ "subvol=@nix" "compress=zstd" "noatime" ];
|
||||
};
|
||||
};
|
||||
|
||||
zramSwap.enable = true;
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
{ lib, config, ... }:
|
||||
{
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
}
|
||||
|
1
hosts/luna/pubkey.nix
Normal file
1
hosts/luna/pubkey.nix
Normal file
@ -0,0 +1 @@
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF5AtCUEvm9pSi8iI4xH5wnJ6dR9tZZY7qPS4GLJbQAW luna"
|
257
install.bash
257
install.bash
@ -1,179 +1,106 @@
|
||||
#!/usr/env/bin bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
install() {
|
||||
set -euo pipefail
|
||||
local disk="${1}"
|
||||
local encrypt_disk="${2}"
|
||||
local host="${3}"
|
||||
set -Eeuo pipefail
|
||||
|
||||
local boot_partition=""
|
||||
local primary_partition=""
|
||||
if [[ "${disk}" == *"nvme"* ]]; then
|
||||
local boot_partition="${disk}p1"
|
||||
local primary_partition="${disk}p2"
|
||||
else
|
||||
local boot_partition="${disk}1"
|
||||
local primary_partition="${disk}2"
|
||||
SCRIPT_DIR="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
|
||||
gen-system-key() {
|
||||
local system="${1:?"No system provided to generate a key for!"}"
|
||||
local priv_key_path="${2:?"No private key path provided!"}"
|
||||
local key_file="out-key"
|
||||
local priv_key
|
||||
local pub_key
|
||||
|
||||
# Gen Key in a temp directory
|
||||
pushd "$(mktemp -d)" >/dev/null
|
||||
ssh-keygen -t ed25519 -f ./"${key_file}" -N '' -C "${system}" -q
|
||||
priv_key="$(cat "${key_file}")"
|
||||
pub_key="$(cat "${key_file}.pub")"
|
||||
rm -f "${key_file}" "${key_file}.pub" >/dev/null
|
||||
popd >/dev/null
|
||||
|
||||
# Update public key for system and rekey secrets
|
||||
printf "Rekeying for '%s' secrets with new system key!\n" "${system}" 1>&2
|
||||
local host_pubkey_path="${SCRIPT_DIR}/hosts/${system}/pubkey.nix"
|
||||
if [[ -r "${host_pubkey_path}" ]]; then
|
||||
local backup_pub_key_path
|
||||
backup_pub_key_path="${host_pubkey_path}.$(date +'%Y-%d-%m_%H:%M:%S')"
|
||||
printf "Backing up old public key file to '%s'!\n" "${backup_pub_key_path}" 1>&2
|
||||
mv "${host_pubkey_path}" "${backup_pub_key_path}"
|
||||
fi
|
||||
# The size is large because I'd like to be able to hibernate my laptop in its entirety. I have 64 GB of ram.
|
||||
printf '"%s"' > "${host_pubkey_path}" "${pub_key}"
|
||||
git add "${host_pubkey_path}" 1>&2
|
||||
|
||||
local label_crypt_luks="NixOS-Crypt"
|
||||
local label_primary="NixOS-Primary"
|
||||
local label_boot="NixOS-Boot"
|
||||
pushd secrets >/dev/null
|
||||
agenix -r -i "${priv_key_path}" 1>&2
|
||||
git add . 1>&2
|
||||
popd >/dev/null
|
||||
|
||||
swapoff -a >/dev/null 2>&1 || true
|
||||
umount /mnt/**/* >/dev/null 2>&1 || true
|
||||
umount /mnt/* >/dev/null 2>&1 || true
|
||||
umount /mnt >/dev/null 2>&1 || true
|
||||
cryptsetup close enc >/dev/null 2>&1 || true
|
||||
wipefs -a "${disk}" || true
|
||||
|
||||
### Partition The Disk
|
||||
parted "${disk}" -- mklabel gpt
|
||||
# Boot partition
|
||||
parted -a optimal "${disk}" -- mkpart ESP fat32 1MiB 1GiB
|
||||
parted "${disk}" -- set 1 boot on
|
||||
mkfs.vfat "${boot_partition}"
|
||||
fatlabel "${boot_partition}" "${label_boot}"
|
||||
# Primary Partition
|
||||
parted -a optimal "${disk}" -- mkpart "${label_primary}" 1Gib 100%
|
||||
|
||||
### Encrypt
|
||||
if [[ "${encrypt_disk}" == "yes" ]]; then
|
||||
cryptsetup --verify-passphrase -v luksFormat "${primary_partition}"
|
||||
cryptsetup config "${primary_partition}" --label "${label_crypt_luks}"
|
||||
# Have to decrypt it so we can actually get other things setup
|
||||
local crypt_open_name="enc"
|
||||
cryptsetup open "${primary_partition}" "${crypt_open_name}"
|
||||
primary_partition="/dev/mapper/${crypt_open_name}"
|
||||
fi
|
||||
|
||||
### BTRFS Setup
|
||||
# Go ahead and make the unencrypted BTRFS
|
||||
mkfs.btrfs -f -L "${label_primary}" "${primary_partition}"
|
||||
|
||||
# Mount it
|
||||
mount -t btrfs "${primary_partition}" /mnt
|
||||
|
||||
# Create our subvolumes
|
||||
btrfs subvolume create "/mnt/@nix"
|
||||
umount /mnt
|
||||
|
||||
### Final Mountings
|
||||
# Mount tmpfs to mnt
|
||||
mount -t tmpfs -o mode=755 none /mnt
|
||||
|
||||
# Create our directories
|
||||
mkdir /mnt/{"boot","nix"}
|
||||
# Mount our boot partition
|
||||
mount -t vfat -o defaults,noatime "${boot_partition}" /mnt/boot
|
||||
|
||||
# Mount our btrfs subvolumes individually with some btrfs options
|
||||
# NOTE: On high performance NVME SSDs with a beefy CPU it may be worth considering ZLO compression instead of ZSTD. In
|
||||
# many cases ZLO is more performant, especially when writing, than ZSTD while having a somewhat worse comrpession ratio.
|
||||
# WARN: ZLO *may* be a good solution, it can be VERY slow on incompressible data. Something to keep in mind.
|
||||
mount -t btrfs -o noatime,compress=zstd,subvol=@nix "${primary_partition}" /mnt/nix
|
||||
|
||||
# Persistence dir, dirs not to be wiped on reboot stored here
|
||||
mkdir -p /mnt/nix/persist
|
||||
# Actually install NixOS
|
||||
nixos-install --flake "git+file:.#${host}"
|
||||
# Finally, clone the flake into the persistent nixos config
|
||||
git clone . /mnt/nix/persist/etc/nixos/
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<-__EOF__
|
||||
Usage: $(basename "${0}") -d "/dev/DISK_HERE" -s 32 -e
|
||||
-h | -? | --help
|
||||
Shows this menu.
|
||||
Example:
|
||||
$(basename "${0}") -h
|
||||
|
||||
-d <string> | --disk <string> [REQUIRED]
|
||||
Path to a disk to install NixOS to.
|
||||
Default: none
|
||||
Example:
|
||||
$(basename "${0}") -d /dev/vda
|
||||
|
||||
-e | --encrypt [OPTIONAL]
|
||||
Enable disk encryption during install. Note, this will prompt you for the encryption password.
|
||||
Default: disabled
|
||||
Example:
|
||||
$(basename "${0}") -e
|
||||
__EOF__
|
||||
}
|
||||
|
||||
running_as_root() {
|
||||
((EUID == 0))
|
||||
printf "%s" "${priv_key}"
|
||||
}
|
||||
|
||||
main() {
|
||||
if ! running_as_root; then
|
||||
printf "This script MUST be ran as root, exiting!\n"
|
||||
local persist_dir="/mnt/nix/persist"
|
||||
local flake_install_path="${persist_dir}/ephemeral/etc/nixos"
|
||||
|
||||
local system="${1:?"Provide system to build!"}"
|
||||
local flake=".#${system}"
|
||||
local conn="${2:?"Provide ssh connection string! (E.g. root@myhost)"}"
|
||||
local priv_key_path="${3:?Provide path to private key}"
|
||||
shift 3
|
||||
if [[ ! -r "${priv_key_path}" ]]; then
|
||||
printf "Unable a private key file at '%s'\n!" "${priv_key_path}" 1>&2
|
||||
exit 1
|
||||
elif [[ ! -r "${SCRIPT_DIR}/hosts/${system}" ]]; then
|
||||
printf "Could not find a system named '%s' in '%s'!\n" "${system}" "${SCRIPT_DIR}/hosts" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
cat <<-__EOS__
|
||||
─────────────────────────────────
|
||||
Installing NixOS on Remote Host
|
||||
=================================
|
||||
Host: "${conn}"
|
||||
Flake: "${flake}"
|
||||
─────────────────────────────────
|
||||
__EOS__
|
||||
printf "Generating system keys\n"
|
||||
local new_sys_key
|
||||
new_sys_key="$(gen-system-key "${system}" "${priv_key_path}")"
|
||||
local nixos_anywhere_log
|
||||
nixos_anywhere_log="$(nix run github:nix-community/nixos-anywhere -- --flake "${flake}" "${conn}" --stop-after-disko 2>&1 | tee >(cat >&2))"
|
||||
local ssh_login_key="${nixos_anywhere_log##*$'\n'}"; ssh_login_key="${ssh_login_key#*\'}"; ssh_login_key="${ssh_login_key%\'*}"
|
||||
local ssh_opts="-i ${ssh_login_key} -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
|
||||
local ssh_cmd="ssh ${conn} ${ssh_opts}"
|
||||
local system_key_dest="${persist_dir}/ephemeral/etc/ssh/ssh_host_ed25519_key"
|
||||
printf "SSH Command: %s\n" "${ssh_cmd}"
|
||||
eval "${ssh_cmd}" <<- __EOS__
|
||||
mkdir -p "${persist_dir}/ephemeral/etc/ssh"
|
||||
mkdir -p "${persist_dir}/save"
|
||||
mkdir -p "${flake_install_path}"
|
||||
printf "Putting new system key into place\n"
|
||||
printf "%s\n" "${new_sys_key}" > "${system_key_dest}"
|
||||
chmod 0600 "${system_key_dest}"
|
||||
__EOS__
|
||||
printf "Copying flake to system\n";
|
||||
rsync -r "${SCRIPT_DIR}"/{*,.*} "${conn}:${flake_install_path}" -e "ssh ${ssh_opts}" --info=PROGRESS2
|
||||
printf "Doing final install\n"
|
||||
eval "${ssh_cmd}" <<- __EOS__
|
||||
set -euo pipefail
|
||||
cd "${flake_install_path}"
|
||||
nix-env -f '<nixpkgs>' -iA git
|
||||
sudo nixos-install --flake "git+file:${flake}" --no-root-password --no-channel-copy
|
||||
reboot
|
||||
__EOS__
|
||||
printf "%s\n" "${ssh_cmd}"
|
||||
|
||||
local disk=""
|
||||
local host=""
|
||||
local encrypt_disk="no"
|
||||
|
||||
while :; do
|
||||
case ${1} in
|
||||
-h | -\? | --help)
|
||||
usage # Display a usage synopsis.
|
||||
exit
|
||||
;;
|
||||
--) # End of all options.
|
||||
break
|
||||
;;
|
||||
-d | --disk)
|
||||
shift
|
||||
disk="${1}"
|
||||
if [[ ! -b "${disk}" ]]; then
|
||||
printf "Unable to read disk '%s', check that it exists, is a block device, and that you have write and read permissions for it!" "${disk}"
|
||||
exit 1
|
||||
fi
|
||||
printf "Setting installation disk to '%s'\n" "${disk}"
|
||||
;;
|
||||
-e | --encrypt)
|
||||
encrypt_disk="yes"
|
||||
printf "Enabled disk encryption\n"
|
||||
;;
|
||||
-H | --host)
|
||||
shift
|
||||
host="${1}"
|
||||
printf "Set host to '%s'\n" "${host}"
|
||||
;;
|
||||
-?*)
|
||||
printf 'Unknown option: %s\n' "$1" >&2
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*) # Default case: No more options, so break out of the loop.
|
||||
break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
set -euo pipefail
|
||||
if [[ -z "${disk}" ]]; then
|
||||
printf "Value for 'disk' (-d) was not provided! See '--help' for usage!\n"
|
||||
exit 1
|
||||
fi
|
||||
if [[ -z "${host}" ]]; then
|
||||
printf "Value to 'host' (-H) was not provided! See '--help' for usage!\n"
|
||||
exit 1
|
||||
fi
|
||||
read -r -s -n 1 -p "Press any key to begin NixOS installation to '${disk}' for host '${host}'!"
|
||||
printf "\n"
|
||||
printf "Installing in "
|
||||
for i in {3..1}; do
|
||||
printf "%s.." "${i}"
|
||||
sleep 1
|
||||
done
|
||||
printf "\n"
|
||||
install "${disk}" "${encrypt_disk}" "${host}"
|
||||
cat <<- __EOS__
|
||||
──────────────────────────────────────────
|
||||
Finished Installing NixOS on Remote Host
|
||||
==========================================
|
||||
Host: "${conn}"
|
||||
Flake: "${flake}"
|
||||
──────────────────────────────────────────
|
||||
__EOS__
|
||||
}
|
||||
|
||||
main "${@}"
|
||||
|
32
lib/default.nix
Normal file
32
lib/default.nix
Normal file
@ -0,0 +1,32 @@
|
||||
# Some of these functions were taken from https://github.com/NixOS/nixpkgs/blob/master/lib/
|
||||
rec {
|
||||
hasSuffix =
|
||||
suffix:
|
||||
string:
|
||||
let
|
||||
lenSuffix = builtins.stringLength suffix;
|
||||
lenString = builtins.stringLength string;
|
||||
in
|
||||
(
|
||||
lenString >= lenSuffix && (builtins.substring (lenString - lenSuffix) lenString string) == suffix
|
||||
);
|
||||
recurseDir = dir:
|
||||
let
|
||||
dirContents = builtins.readDir dir;
|
||||
in
|
||||
(builtins.concatMap
|
||||
(dirItem:
|
||||
let
|
||||
itemType = builtins.getAttr dirItem dirContents;
|
||||
itemPath = dir + "/${dirItem}";
|
||||
in
|
||||
if itemType == "directory" then
|
||||
(recurseDir itemPath)
|
||||
else
|
||||
[ itemPath ])
|
||||
(builtins.attrNames dirContents));
|
||||
recurseFilesInDir = dir: suffix:
|
||||
(builtins.filter (file: hasSuffix "${suffix}" file) (recurseDir dir));
|
||||
recurseFilesInDirs = dirs: suffix:
|
||||
(builtins.concatMap (dir: (recurseFilesInDir dir "${suffix}")) dirs);
|
||||
}
|
Binary file not shown.
10
secrets/luna/gitlab-runner-reg-config.age
Normal file
10
secrets/luna/gitlab-runner-reg-config.age
Normal file
@ -0,0 +1,10 @@
|
||||
age-encryption.org/v1
|
||||
-> ssh-ed25519 4sH96w zBi3BGIf/OJza0ADpk264QCudT5mKzxcxgfxoNI9HSw
|
||||
8Ys6frvd7UeXRXPpiClCJ+qoRHiE7K+TfQhbb1o34bk
|
||||
-> piv-p256 rJs1HA Aw/GcBY+XMD/9++r819joYKKyIrf8gbpjgIgugLhBtBq
|
||||
BTIRQ/6zl2HqJJrCGbeMwAwmp65EiU5jAs130/MoHOs
|
||||
-> OKjJEPyZ-grease l {KDS$m oX;O="m
|
||||
29gF4VbnR6zEbojhshhTvk2tYizn32MsCDsuutl+HCmVTNPvDIkWRSMPylfsZqLY
|
||||
AMl5wcis0Spit7SKkNKJVCtL/39fXu5zgJU
|
||||
--- VTqUeA4weWW1vN8qr5jsTgIgbU/3rvYQX8A0gPgYGus
|
||||
ÝúÑ<1A>†IVÒ¬Þïº*HøŒ[Õ°/IEz<45>Ôù#—ûMiÒ®Õp0ÒßMð(áë´TS—y§±î§—º‡¢ DÄn¾…@ƒ [/R‘亱?l7 (Ì7&–˜R›“ö<E2809C>8 D¥JE5°(˜±¦¨bÍÊpón5/›·w/çßâ°
|
BIN
secrets/luna/root-hash-pw.age
Normal file
BIN
secrets/luna/root-hash-pw.age
Normal file
Binary file not shown.
@ -1,15 +1,29 @@
|
||||
let
|
||||
keys = rec {
|
||||
master = "age1yubikey1qfnj0k4mkzrn8ef5llwh2sv6hd7ckr0qml3n9hzdpz9c59ypvryhyst87k0";
|
||||
orion-tech = {
|
||||
luna = [
|
||||
"age1jgwqs04tphuuklx4g3gjdg42mchagn2gu7sftknerh8y8l9n7v7s27wqgu"
|
||||
master
|
||||
root-dir = builtins.toString ./.;
|
||||
lib = import ../lib;
|
||||
master-keys = [
|
||||
"age1yubikey1qfnj0k4mkzrn8ef5llwh2sv6hd7ckr0qml3n9hzdpz9c59ypvryhyst87k0"
|
||||
];
|
||||
hosts = {
|
||||
luna =
|
||||
let
|
||||
secrets = "${root-dir}/luna";
|
||||
in
|
||||
[
|
||||
"${secrets}/gitlab-runner-reg-config.age"
|
||||
"${secrets}/root-hash-pw.age"
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
|
||||
{
|
||||
"gitlab-runner-reg-config.age".publicKeys = keys.orion-tech.luna;
|
||||
}
|
||||
(builtins.listToAttrs
|
||||
(builtins.concatMap
|
||||
(host:
|
||||
(builtins.map
|
||||
(secret: {
|
||||
name = builtins.toString secret;
|
||||
value = {
|
||||
publicKeys = [ (import ./../hosts/${host}/pubkey.nix) ] ++ master-keys;
|
||||
};
|
||||
})
|
||||
(builtins.getAttr host hosts)))
|
||||
(builtins.attrNames hosts)))
|
||||
|
Loading…
Reference in New Issue
Block a user