Compare commits
8 Commits
3bcd4c3c13
...
124d326c0e
| Author | SHA1 | Date | |
|---|---|---|---|
| 124d326c0e | |||
| 90528bd243 | |||
| 7e6ae8f0dd | |||
| 11a89aa772 | |||
| cd52edbc4d | |||
| 66ba64801f | |||
| 62788417f0 | |||
| 0a222a5474 |
@@ -1,4 +1,3 @@
|
||||
include ./taskrc.d/$HOSTNAME
|
||||
include ./taskrc.d/aliases
|
||||
include ./taskrc.d/urgency
|
||||
include ./taskrc.d/reports
|
||||
@@ -12,4 +11,3 @@ rc.json.array=on
|
||||
rc.verbose=nothing
|
||||
news.version=3.1.0
|
||||
|
||||
recurrence=off
|
||||
|
||||
36
flake.lock
generated
36
flake.lock
generated
@@ -121,11 +121,11 @@
|
||||
},
|
||||
"locked": {
|
||||
"dir": "pkgs/firefox-addons",
|
||||
"lastModified": 1778040175,
|
||||
"narHash": "sha256-SSXJp3BMjO2LrW/VLjNdGGcjd3RFEyV4FemYA6OGrYw=",
|
||||
"lastModified": 1778904158,
|
||||
"narHash": "sha256-xZ/zdpu9X8OI1jGqd4z6W1hKa+DQh8A9k3TH6w9tNbo=",
|
||||
"owner": "rycee",
|
||||
"repo": "nur-expressions",
|
||||
"rev": "3bd76b0f41e65661866bddcac57ebe83aeadb581",
|
||||
"rev": "c31bafebd7e30517ead27149ad790802b998e98f",
|
||||
"type": "gitlab"
|
||||
},
|
||||
"original": {
|
||||
@@ -284,11 +284,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1776796298,
|
||||
"narHash": "sha256-PcRvlWayisPSjd0UcRQbhG8Oqw78AcPE6x872cPRHN8=",
|
||||
"lastModified": 1778507602,
|
||||
"narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "3cfd774b0a530725a077e17354fbdb87ea1c4aad",
|
||||
"rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -342,11 +342,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1778009629,
|
||||
"narHash": "sha256-nUoQtf4Zq7DRYJrfv904hjrxjAlWVP6a1pNNFKx3FCg=",
|
||||
"lastModified": 1778921576,
|
||||
"narHash": "sha256-jgIbBcGgKTtkp+lBas29hNFUU1t5O/2+GFvUjbiG0vM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "00ed86e58bb6979a7921859fd1615d19382eac5c",
|
||||
"rev": "32b42d71b4b22c4465963285bb6e462d7c93d45e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -451,11 +451,11 @@
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1777917524,
|
||||
"narHash": "sha256-k+LVe9YaO2BEPB9AaCtTtOMCeGi4dxDo6gt4Un3qoPY=",
|
||||
"lastModified": 1778924461,
|
||||
"narHash": "sha256-pDGhSCz+QxjHzP9gqYpK59k4Z1ZpVyYjzBgoXLFXh9s=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "df7783100babf59001340a7a874ba3824e441ecb",
|
||||
"rev": "65a5c8f9c19d5f9d1b06d8942b04d790414ccfdd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -467,11 +467,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1777954456,
|
||||
"narHash": "sha256-hGdgeU2Nk87RAuZyYjyDjFL6LK7dAZN5RE9+hrDTkDU=",
|
||||
"lastModified": 1778443072,
|
||||
"narHash": "sha256-zi7/fsqM/kFdNuED//4WOCUtezGtKKqRNORjMvfwjnA=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "549bd84d6279f9852cae6225e372cc67fb91a4c1",
|
||||
"rev": "da5ad661ba4e5ef59ba743f0d112cbc30e474f32",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -714,11 +714,11 @@
|
||||
"tinted-zed": "tinted-zed"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1777835090,
|
||||
"narHash": "sha256-VLH8zPweblCOvpnQXp4fVs7f6Q79YhXF5XFKlOrvIFk=",
|
||||
"lastModified": 1778776709,
|
||||
"narHash": "sha256-YhnEcpiY6+l3RFA+cPmdTaeODGvNRuqE8B7VBjPVIxo=",
|
||||
"owner": "danth",
|
||||
"repo": "stylix",
|
||||
"rev": "7989a1054b01153212dede6005abfd1576b8328c",
|
||||
"rev": "e8ea85b4f7dddda9603e0f1ac86cd92cee3b2819",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -30,8 +30,9 @@
|
||||
../../modules/ssh
|
||||
../../modules/taskwarrior
|
||||
../../modules/terminal
|
||||
../../modules/zk
|
||||
../../modules/torrenting
|
||||
../../modules/yubikey
|
||||
../../modules/zk
|
||||
];
|
||||
|
||||
home = {
|
||||
@@ -58,6 +59,7 @@
|
||||
shell.bash.aliases.lang-js = true;
|
||||
shell.bash.addBinToPath = true;
|
||||
torrenting.enable = true;
|
||||
my.yubikey.enable = true;
|
||||
zk.enable = true;
|
||||
|
||||
programs = {
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
../../modules/ssh
|
||||
../../modules/taskwarrior
|
||||
../../modules/terminal
|
||||
../../modules/yubikey
|
||||
];
|
||||
|
||||
home = {
|
||||
@@ -53,6 +54,7 @@
|
||||
git.github.enable = true;
|
||||
shell.bash.aliases.lang-js = true;
|
||||
shell.bash.addBinToPath = true;
|
||||
my.yubikey.enable = true;
|
||||
|
||||
programs = {
|
||||
home-manager.enable = true;
|
||||
|
||||
61
home/modules/ssh/README.md
Normal file
61
home/modules/ssh/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# SSH keys
|
||||
|
||||
* primary keys (host-specific, non-resident)
|
||||
* backup key (shared, resident)
|
||||
|
||||
## generate keys
|
||||
|
||||
### YubiKey 01 - `host_01`
|
||||
|
||||
```sh
|
||||
ssh-keygen -t ed25519-sk \
|
||||
-O verify-required \
|
||||
-f ~/.ssh/id_ed25519_sk \
|
||||
-C "h@host_01"
|
||||
```
|
||||
|
||||
### YubiKey 01 — `host_02`
|
||||
|
||||
```sh
|
||||
ssh-keygen -t ed25519-sk \
|
||||
-O verify-required \
|
||||
-f ~/.ssh/id_ed25519_sk \
|
||||
-C "h@host_02"
|
||||
```
|
||||
|
||||
### YubiKey 02 - `host_*`
|
||||
|
||||
```sh
|
||||
ssh-keygen -t ed25519-sk \
|
||||
-O resident \
|
||||
-O verify-required \
|
||||
-f ~/.ssh/id_ed25519_sk_bak \
|
||||
-C "backup"
|
||||
```
|
||||
|
||||
## register keys
|
||||
|
||||
when you the primary key (`id_ed25519_sk.pub`), make sure to also register the
|
||||
backup key (`id_ed25519_sk_bak.pub`) if needed.
|
||||
|
||||
## recovery scenarios
|
||||
|
||||
| scenario | recovery |
|
||||
|---|---|
|
||||
| primary key file lost | generate new primary key on that device, re-register (use backup key) |
|
||||
| primary YubiKey lost | generate new primary keys on all devices using new YubiKey (use backup key) |
|
||||
| backup key file lost | regenerate from backup YubiKey resident key (use `ssh-keygen -K`) |
|
||||
| backup YubiKey lost | generate resident backup key, distribute across hosts, re-register (use primary key) |
|
||||
|
||||
## notes / to do
|
||||
|
||||
TODO: automate distributing `id_ed25519_sk_bak`, `id_ed25519_sk_bak.pub` to all devices
|
||||
TODO: declare setup scripts (use e.g. `$HOSTNAME`)
|
||||
TODO: register backup key with hosts (add to authorized hosts for each host)
|
||||
TODO: register backup key with services (e.g. Gitea)
|
||||
TODO: make sure to fall back to backup key when host-specific primary key is not present
|
||||
TODO: see if / how `-O application=ssh:<name>` could be used
|
||||
|
||||
## references
|
||||
|
||||
* <https://developers.yubico.com/SSH/Securing_SSH_with_FIDO2.html>
|
||||
@@ -35,6 +35,7 @@ in
|
||||
// {
|
||||
"*" = {
|
||||
addKeysToAgent = "yes";
|
||||
forwardAgent = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
19
home/modules/yubikey/default.nix
Normal file
19
home/modules/yubikey/default.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
options.my.yubikey = {
|
||||
enable = lib.mkEnableOption "yubikey";
|
||||
};
|
||||
|
||||
config = lib.mkIf config.my.yubikey.enable {
|
||||
home.packages = with pkgs; [
|
||||
yubikey-manager
|
||||
yubikey-personalization
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -91,21 +91,8 @@ in
|
||||
];
|
||||
|
||||
my.yubikey = {
|
||||
enable = false;
|
||||
keys = [
|
||||
{
|
||||
handle = "<KeyHandle1>";
|
||||
userKey = "<UserKey1>";
|
||||
coseType = "<CoseType1>";
|
||||
options = "<Options1>";
|
||||
}
|
||||
{
|
||||
handle = "<KeyHandle2>";
|
||||
userKey = "<UserKey2>";
|
||||
coseType = "<CoseType2>";
|
||||
options = "<Options2>";
|
||||
}
|
||||
];
|
||||
enable = true;
|
||||
pam.enable = false;
|
||||
};
|
||||
|
||||
services.locate = {
|
||||
|
||||
@@ -1 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOOXPEhdKOVnb6mkeLLUcFGt+mnUR5pMie17JtjrxwgO h@andromache
|
||||
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIj+isTFg+W3v68HL28a9p9nX7ldAxu+ht9uUfKLvqcwAAAABHNzaDo= h@andromache
|
||||
|
||||
@@ -99,21 +99,7 @@ in
|
||||
|
||||
my.yubikey = {
|
||||
enable = true;
|
||||
# inherit (config.host) username;
|
||||
# keys = [
|
||||
# {
|
||||
# handle = "<KeyHandle1>";
|
||||
# userKey = "<UserKey1>";
|
||||
# coseType = "<CoseType1>";
|
||||
# options = "<Options1>";
|
||||
# }
|
||||
# {
|
||||
# handle = "<KeyHandle2>";
|
||||
# userKey = "<UserKey2>";
|
||||
# coseType = "<CoseType2>";
|
||||
# options = "<Options2>";
|
||||
# }
|
||||
# ];
|
||||
pam.enable = false;
|
||||
};
|
||||
|
||||
services = {
|
||||
|
||||
@@ -26,6 +26,13 @@ in
|
||||
useNautilus = false;
|
||||
};
|
||||
|
||||
programs.xwayland.enable = true;
|
||||
|
||||
environment = {
|
||||
systemPackages = [ pkgs.xwayland-satellite ];
|
||||
sessionVariables.NIXOS_OZONE_WL = "1";
|
||||
};
|
||||
|
||||
xdg.portal = {
|
||||
enable = true;
|
||||
extraPortals = [
|
||||
|
||||
@@ -17,7 +17,8 @@ in
|
||||
};
|
||||
|
||||
# auto generate authorized_keys from `authorizedHosts`
|
||||
config.users.users.${username}.openssh.authorizedKeys.keys = lib.flatten (
|
||||
config.users.users.${username}.openssh.authorizedKeys.keys =
|
||||
lib.flatten (
|
||||
map (
|
||||
hostname:
|
||||
let
|
||||
@@ -25,5 +26,6 @@ in
|
||||
in
|
||||
lib.optionals (builtins.pathExists keyFile) (lib.splitString "\n" (builtins.readFile keyFile))
|
||||
) ((builtins.filter (h: h != config.host.name) adminHosts) ++ config.ssh.authorizedHosts)
|
||||
);
|
||||
)
|
||||
++ lib.splitString "\n" (builtins.readFile ./ssh_bak.pub);
|
||||
}
|
||||
|
||||
@@ -14,8 +14,16 @@ in
|
||||
chmod 644 "$HOST_DIR/ssh_host.pub"
|
||||
fi
|
||||
|
||||
USER_KEY="/home/${username}/.ssh/id_ed25519.pub"
|
||||
if [ -f "$USER_KEY" ] && [ -d "$HOST_DIR" ]; then
|
||||
USER_KEY=""
|
||||
for candidate in \
|
||||
"/home/${username}/.ssh/id_ed25519_sk.pub" \
|
||||
"/home/${username}/.ssh/id_ed25519.pub"; do
|
||||
if [ -f "$candidate" ]; then
|
||||
USER_KEY="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -n "$USER_KEY" ] && [ -d "$HOST_DIR" ]; then
|
||||
cp "$USER_KEY" "$HOST_DIR/ssh_user.pub"
|
||||
chown ${username}:users "$HOST_DIR/ssh_user.pub"
|
||||
chmod 644 "$HOST_DIR/ssh_user.pub"
|
||||
|
||||
1
modules/ssh/ssh_bak.pub
Normal file
1
modules/ssh/ssh_bak.pub
Normal file
@@ -0,0 +1 @@
|
||||
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAINg9dwrE10NQ7WMhL/hFJHRNFlDedvloCm9E4XEfnpStAAAABHNzaDo= backup
|
||||
@@ -15,13 +15,13 @@ let
|
||||
in
|
||||
{
|
||||
options.my.yubikey = {
|
||||
enable = mkEnableOption "yubiKey U2F authentication";
|
||||
|
||||
enable = mkEnableOption "YubiKey";
|
||||
pam = {
|
||||
enable = mkEnableOption "YubiKey PAM U2F";
|
||||
origin = mkOption {
|
||||
type = types.str;
|
||||
default = "pam://yubi";
|
||||
};
|
||||
|
||||
keys = mkOption {
|
||||
type = types.listOf (
|
||||
types.submodule {
|
||||
@@ -48,16 +48,24 @@ in
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
services.udev.packages = with pkgs; [
|
||||
yubikey-manager
|
||||
yubikey-personalization
|
||||
];
|
||||
})
|
||||
(mkIf (cfg.enable && cfg.pam.enable) {
|
||||
security.pam = {
|
||||
u2f = {
|
||||
enable = true;
|
||||
settings = {
|
||||
interactive = true;
|
||||
cue = true;
|
||||
inherit (cfg) origin;
|
||||
authfile = pkgs.writeText "u2f-mappings" (authfileContent username cfg.keys);
|
||||
origin = cfg.pam.origin;
|
||||
authfile = pkgs.writeText "u2f-mappings" (authfileContent username cfg.pam.keys);
|
||||
};
|
||||
};
|
||||
services = {
|
||||
@@ -65,7 +73,6 @@ in
|
||||
sudo.u2fAuth = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.udev.packages = with pkgs; [ yubikey-personalization ];
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user