agenix
This commit is contained in:
parent
d16c7baa4a
commit
9241fe5e5c
30
README.md
30
README.md
|
@ -21,7 +21,7 @@ the unofficial NixOS wiki [Full Disk Encryption](https://nixos.wiki/wiki/Full_Di
|
|||
gist](https://gist.github.com/martijnvermaat/76f2e24d0239470dd71050358b4d5134).
|
||||
|
||||
We create a 1GiB EFI boot partition (`/dev/sda1`) and the rest will be our LUKS-encrypted volume:
|
||||
```bash
|
||||
```fish
|
||||
# Create partition table
|
||||
parted /dev/sda -- mklabel gpt
|
||||
|
||||
|
@ -58,19 +58,35 @@ sda
|
|||
└─vg-root ext4 1.0 nix
|
||||
```
|
||||
|
||||
### Installation
|
||||
Whereas the [NixOS manual](https://nixos.org/manual/nixos/stable/index.html#sec-installation-manual-installing) mounts
|
||||
the newly-created `nixos` partition to `/mnt`, we will follow the _tmpfs as root_ blogpost and mount `/mnt` as `tmpfs`:
|
||||
```bash
|
||||
```fish
|
||||
mount -t tmpfs none /mnt
|
||||
mount --mkdir /dev/disk/by-label/BOOT /mnt/boot
|
||||
mount --mkdir /dev/disk/by-label/nix /mnt/nix
|
||||
mkdir -p /mnt/nix/persist/
|
||||
```
|
||||
|
||||
### Secrets
|
||||
All files in the Nix store are world-readable, so it is not a suitable place for including cleartext secrets,
|
||||
even if we had a scheme to securely transfer them to each system. [Agenix](https://github.com/ryantm/agenix)
|
||||
solves this issue by encrypting the secrets using [age](https://github.com/FiloSottile/age), and then decrypting
|
||||
and symlinking them using the system's SSH host key during system activation.
|
||||
|
||||
To bootstrap a new system, we must first generate a host key manually using `ssh-keygen -A -f /mnt/nix/persist`
|
||||
during installation. Then, on an existing system, add the new host's public key to `secrets.nix` and rekey all
|
||||
secrets using `agenix --rekey`. Commit and push the changes and proceed below.
|
||||
|
||||
When managing secrets, the Keepass recovery key is used like so:
|
||||
```fish
|
||||
set AGE_KEY_FILE (mktemp); read -s > $AGE_KEY_FILE
|
||||
agenix -i $AGE_KEY_FILE -e foo.age
|
||||
```
|
||||
|
||||
### Installation
|
||||
The remaining installation can be done (more or less) according to the [NixOS
|
||||
manual](https://nixos.org/manual/nixos/stable/index.html#sec-installation-manual-installing).
|
||||
```bash
|
||||
```fish
|
||||
cd /mnt/nix
|
||||
git clone https://git.caspervk.net/caspervk/nixos.git tmp
|
||||
cd tmp/
|
||||
|
@ -78,10 +94,6 @@ nixos-generate-config --root /mnt --show-hardware-config
|
|||
vim hosts/omega/hardware.nix
|
||||
git add . # nix sometimes ignores files outside version control
|
||||
nixos-install --no-root-passwd --flake .#omega
|
||||
|
||||
# Make sure to set a password
|
||||
mkpasswd > /mnt/nix/persist/passwordfile
|
||||
chmod 400 /mnt/nix/persist/passwordfile
|
||||
```
|
||||
|
||||
### Hardware Configuration
|
||||
|
@ -94,7 +106,7 @@ enough](https://sourcegraph.com/search?q=context%3Aglobal+repo%3A%5Egithub%5C.co
|
|||
|
||||
|
||||
## Useful Commands
|
||||
```bash
|
||||
```fish
|
||||
# upgrade system
|
||||
sudo nixos-rebuild switch --flake .
|
||||
|
||||
|
|
65
flake.lock
65
flake.lock
|
@ -1,5 +1,30 @@
|
|||
{
|
||||
"nodes": {
|
||||
"agenix": {
|
||||
"inputs": {
|
||||
"darwin": [],
|
||||
"home-manager": [
|
||||
"home-manager"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1707830867,
|
||||
"narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -28,11 +53,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708451036,
|
||||
"narHash": "sha256-tgZ38NummEdnXvxj4D0StHBzXgceAw8CptytHljH790=",
|
||||
"lastModified": 1708591310,
|
||||
"narHash": "sha256-8mQGVs8JccWTnORgoLOTh9zvf6Np+x2JzhIc+LDcJ9s=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "517601b37c6d495274454f63c5a483c8e3ca6be1",
|
||||
"rev": "0e0e9669547e45ea6cca2de4044c1a384fd0fe55",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -79,11 +104,11 @@
|
|||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1708091350,
|
||||
"narHash": "sha256-o28BJYi68qqvHipT7V2jkWxDiMS1LF9nxUsou+eFUPQ=",
|
||||
"lastModified": 1708594753,
|
||||
"narHash": "sha256-c/gH7iXS/IYH9NrFOT+aJqTq+iEBkvAkpWuUHGU3+f0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "106d3fec43bcea19cb2e061ca02531d54b542ce3",
|
||||
"rev": "3f7d0bca003eac1a1a7f4659bbab9c8f8c2a0958",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -95,11 +120,11 @@
|
|||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1708294118,
|
||||
"narHash": "sha256-evZzmLW7qoHXf76VCepvun1esZDxHfVRFUJtumD7L2M=",
|
||||
"lastModified": 1708566995,
|
||||
"narHash": "sha256-e/THimsoxxMAHSbwMKov5f5Yg+utTj6XVGEo24Lhx+0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "e0da498ad77ac8909a980f07eff060862417ccf7",
|
||||
"rev": "3cb4ae6689d2aa3f363516234572613b31212b78",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -111,11 +136,11 @@
|
|||
},
|
||||
"nixpkgs-unstable": {
|
||||
"locked": {
|
||||
"lastModified": 1708296515,
|
||||
"narHash": "sha256-FyF489fYNAUy7b6dkYV6rGPyzp+4tThhr80KNAaF/yY=",
|
||||
"lastModified": 1708655239,
|
||||
"narHash": "sha256-ZrP/yACUvDB+zbqYJsln4iwotbH6CTZiTkANJ0AgDv4=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b98a4e1746acceb92c509bc496ef3d0e5ad8d4aa",
|
||||
"rev": "cbc4211f0afffe6dfd2478a62615dd5175a13f9a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -127,6 +152,7 @@
|
|||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"home-manager": "home-manager",
|
||||
"home-manager-unstable": "home-manager-unstable",
|
||||
"impermanence": "impermanence",
|
||||
|
@ -135,6 +161,21 @@
|
|||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-unstable": "nixpkgs-unstable"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"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",
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
impermanence = {
|
||||
url = "github:nix-community/impermanence";
|
||||
};
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs"; # use the same nixpkgs as the system
|
||||
inputs.home-manager.follows = "home-manager"; # use the same home-manager as the system
|
||||
inputs.darwin.follows = ""; # don't download dawrin dependencies
|
||||
};
|
||||
nix-index-database = {
|
||||
url = "github:nix-community/nix-index-database";
|
||||
inputs.nixpkgs.follows = "nixpkgs"; # use the same nixpkgs as the system
|
||||
|
|
21
modules/base/agenix.nix
Normal file
21
modules/base/agenix.nix
Normal file
|
@ -0,0 +1,21 @@
|
|||
{ agenix, pkgs, ... }: {
|
||||
# Agenix manages the deployment of secrets by public-key encrypting them to
|
||||
# each system's ssh host key. See the README for more information.
|
||||
# https://github.com/ryantm/agenix
|
||||
# https://nixos.wiki/wiki/Comparison_of_secret_managing_schemes
|
||||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
];
|
||||
|
||||
# Agenix attempts to decrypt secrets before impermanence symlinks the ssh
|
||||
# host key. Refer directly to the key on the persistent partition, which is
|
||||
# mounted in stage 1 of the boot process, before agenix runs.
|
||||
# https://github.com/ryantm/agenix/issues/45#issuecomment-901383985
|
||||
age.identityPaths = [ "/nix/persist/etc/ssh/ssh_host_ed25519_key" ];
|
||||
|
||||
# `agenix` cli tool
|
||||
environment.systemPackages = [
|
||||
agenix.packages.${pkgs.system}.default
|
||||
];
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
{ ... }: {
|
||||
imports = [
|
||||
./agenix.nix
|
||||
./docker.nix
|
||||
./fish.nix
|
||||
./git.nix
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
{ pkgs, ... }: {
|
||||
{ config, pkgs, ... }: {
|
||||
users = {
|
||||
# Don't allow imperative modifications to users (incompatible with impermanence)
|
||||
mutableUsers = false;
|
||||
|
||||
users = {
|
||||
root = {
|
||||
# TODO: The passwordfile is manually generated during the initial setup
|
||||
# to avoid (hashed) secrets in the public git repo. It should replaced
|
||||
# with a proper secret management scheme, such as agenix.
|
||||
hashedPasswordFile = "/nix/persist/passwordfile";
|
||||
hashedPasswordFile = config.age.secrets.users-hashed-password-file.path;
|
||||
};
|
||||
caspervk = {
|
||||
isNormalUser = true;
|
||||
description = "Casper V. Kristensen";
|
||||
# TODO: The hashedPasswordFile is manually generated during the initial
|
||||
# setup to avoid (hashed) secrets in the public git repo. It should
|
||||
# replaced with a proper secret management scheme, such as agenix.
|
||||
hashedPasswordFile = "/nix/persist/passwordfile";
|
||||
hashedPasswordFile = config.age.secrets.users-hashed-password-file.path;
|
||||
extraGroups = [
|
||||
"wheel" # allows sudo
|
||||
"video" # allows controlling brightness
|
||||
|
@ -27,4 +21,11 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets.users-hashed-password-file = {
|
||||
file = ../../secrets/users-hashed-password-file.age;
|
||||
mode = "400";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
}
|
||||
|
|
23
secrets/secrets.nix
Normal file
23
secrets/secrets.nix
Normal file
|
@ -0,0 +1,23 @@
|
|||
# This file is NOT imported into the NixOS configuration. It is only used for
|
||||
# the agenix CLI tool to know which public keys to use for encryption. See the
|
||||
# README for more information.
|
||||
# https://github.com/ryantm/agenix
|
||||
|
||||
let
|
||||
# Get a system's public key using:
|
||||
# > cat /etc/ssh/ssh_host_ed25519_key.pub
|
||||
# If you change or add a key, all secrets need to be `agenix --rekey`'ed.
|
||||
mu = "todo";
|
||||
omega = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvFN4vnqPX31+4/ZJxOJ7/bSUEu2xB6ovezPQjLm13H root@omega";
|
||||
tor = "todo";
|
||||
zeta = "todo";
|
||||
# Recovery and management key from Keepass. Used like so:
|
||||
# > set AGE_KEY_FILE (mktemp); read -s > $AGE_KEY_FILE
|
||||
# > agenix -i $AGE_KEY_FILE -e foo.age
|
||||
recovery = "age1rd6hhd724s3r9xe4gfuy38rl0xfu8c7pkuefsrdwqfcknujzecyqz7ldyj";
|
||||
|
||||
all = [ omega recovery ];
|
||||
in
|
||||
{
|
||||
"users-hashed-password-file.age".publicKeys = all;
|
||||
}
|
7
secrets/users-hashed-password-file.age
Normal file
7
secrets/users-hashed-password-file.age
Normal file
|
@ -0,0 +1,7 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-ed25519 fY+XUg ThWnidSUv20sqdMebPW0aV512ascEV4WyDia72vhTnI
|
||||
fbFAnyqqqpp9fEct2EiLG1wWw//U8kWcpf0QnbSh33Y
|
||||
-> X25519 ZbC+v0St7P+W/AHq1Afst7ylmZUFA7OIhiElfexTHgg
|
||||
2DbCqyjULhmDji3E1HrPuO8WW74dIia1GFOSCaeGliU
|
||||
--- 6W7LaM4dc6tJONcmtVAwhI/NcOE8EUYPrg75K6Qpynw
|
||||
%?ó4k=/ýä_ƒ<5F>½a#]Éào>Ÿ¬¨tVÆ°EªW“õµŽåRþ÷~¾8Ñ;më¬"˜€&˹ÏGŠ]ïsAN¦pÀŸõW²ƒŽÅNKø„Ɖ˜™p¿ƒªóP$8e
|
Loading…
Reference in a new issue