Migrate sshd to clanServices

- migrate service
- add deprecation notice to old module
- add check
- update docs
This commit is contained in:
pinpox
2025-06-09 17:21:25 +02:00
parent 3b33d42ef3
commit c5341837b4
26 changed files with 404 additions and 1 deletions

View File

@@ -53,6 +53,7 @@ in
dummy-inventory-test = import ./dummy-inventory-test nixosTestArgs; dummy-inventory-test = import ./dummy-inventory-test nixosTestArgs;
borgbackup = import ./borgbackup nixosTestArgs; borgbackup = import ./borgbackup nixosTestArgs;
data-mesher = import ./data-mesher nixosTestArgs; data-mesher = import ./data-mesher nixosTestArgs;
syncthing = import ./syncthing nixosTestArgs;
} }
// lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "aarch64-linux") { // lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "aarch64-linux") {
# for some reason this hangs in an odd place in CI, but it works on my machine ... # for some reason this hangs in an odd place in CI, but it works on my machine ...

View File

@@ -1,7 +1,7 @@
--- ---
description = "Enables secure remote access to the machine over ssh." description = "Enables secure remote access to the machine over ssh."
categories = ["System", "Network"] categories = ["System", "Network"]
features = [ "inventory" ] features = [ "inventory", "deprecated" ]
--- ---
This module will setup the opensshd service. This module will setup the opensshd service.

View File

@@ -0,0 +1,209 @@
{ ... }:
{
_class = "clan.service";
manifest.name = "clan-core/sshd";
manifest.description = "Enables secure remote access to the machine over ssh.";
manifest.categories = [
"System"
"Network"
];
roles.client = {
interface =
{ lib, ... }:
{
options.certificate = {
searchDomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "mydomain.com" ];
description = ''
List of domains to include in the certificate.
This option will prepend the machine name in front of each domain
before adding it to the certificate.
'';
};
};
};
perInstance =
{ settings, ... }:
{
nixosModule =
{
config,
lib,
pkgs,
...
}:
{
clan.core.vars.generators.openssh-ca = lib.mkIf (settings.certificate.searchDomains != [ ]) {
share = true;
files.id_ed25519.deploy = false;
files."id_ed25519.pub" = {
deploy = false;
secret = false;
};
runtimeInputs = [
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519
'';
};
programs.ssh.knownHosts.ssh-ca = lib.mkIf (settings.certificate.searchDomains != [ ]) {
certAuthority = true;
extraHostNames = builtins.map (domain: "*.${domain}") settings.certificate.searchDomains;
publicKey = config.clan.core.vars.generators.openssh-ca.files."id_ed25519.pub".value;
};
};
};
};
roles.server = {
interface =
{ lib, ... }:
{
options = {
hostKeys.rsa.enable = lib.mkEnableOption "Generate RSA host key";
certificate = {
searchDomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "mydomain.com" ];
description = ''
List of domains to include in the certificate. This option will
prepend the machine name in front of each domain before adding
it to the certificate.
'';
};
};
};
};
perInstance =
{ settings, ... }:
{
nixosModule =
{
config,
lib,
pkgs,
...
}:
{
clan.core.vars.generators = {
openssh-ca = lib.mkIf (settings.certificate.searchDomains != [ ]) {
share = true;
files.id_ed25519.deploy = false;
files."id_ed25519.pub" = {
deploy = false;
secret = false;
};
runtimeInputs = [
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519
'';
};
openssh-cert = lib.mkIf (settings.certificate.searchDomains != [ ]) {
files."ssh.id_ed25519-cert.pub".secret = false;
dependencies = [
"openssh"
"openssh-ca"
];
validation = {
name = config.clan.core.settings.machine.name;
domains = lib.genAttrs settings.certificate.searchDomains lib.id;
};
runtimeInputs = [
pkgs.openssh
pkgs.jq
];
script =
let
stringSet = list: builtins.attrNames (builtins.groupBy lib.id list);
domains = stringSet settings.certificate.searchDomains;
in
''
ssh-keygen \
-s $in/openssh-ca/id_ed25519 \
-I ${config.clan.core.settings.machine.name} \
-h \
-n ${lib.concatMapStringsSep "," (d: "${config.clan.core.settings.machine.name}.${d}") domains} \
$in/openssh/ssh.id_ed25519.pub
mv $in/openssh/ssh.id_ed25519-cert.pub "$out"/ssh.id_ed25519-cert.pub
'';
};
openssh-rsa = lib.mkIf settings.hostKeys.rsa.enable {
files."ssh.id_rsa" = { };
files."ssh.id_rsa.pub".secret = false;
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
];
script = ''
ssh-keygen -t rsa -b 4096 -N "" -f "$out"/ssh.id_rsa
'';
};
openssh = {
files."ssh.id_ed25519" = { };
files."ssh.id_ed25519.pub".secret = false;
migrateFact = "openssh";
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/ssh.id_ed25519
'';
};
};
programs.ssh.knownHosts.ssh-ca = lib.mkIf (settings.certificate.searchDomains != [ ]) {
certAuthority = true;
extraHostNames = builtins.map (domain: "*.${domain}") settings.certificate.searchDomains;
publicKey = config.clan.core.vars.generators.openssh-ca.files."id_ed25519.pub".value;
};
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
settings.HostCertificate = lib.mkIf (
settings.certificate.searchDomains != [ ]
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
hostKeys =
[
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional settings.hostKeys.rsa.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
};
programs.ssh.knownHosts.clan-sshd-self-ed25519 = {
hostNames = [
"localhost"
config.networking.hostName
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
};
};
};
};
}

View File

@@ -0,0 +1,19 @@
{ lib, self, ... }:
{
clan.modules = {
sshd = lib.modules.importApply ./default.nix { };
};
perSystem =
{ pkgs, ... }:
{
checks = lib.optionalAttrs (pkgs.stdenv.isLinux) {
sshd = import ./tests/vm/default.nix {
inherit pkgs;
clan-core = self;
nixosLib = import (self.inputs.nixpkgs + "/nixos/lib") { };
};
};
};
}

View File

@@ -0,0 +1,62 @@
{
pkgs,
nixosLib,
clan-core,
...
}:
nixosLib.runTest (
{ ... }:
{
imports = [
clan-core.modules.nixosVmTest.clanTest
];
hostPkgs = pkgs;
name = "sshd";
clan = {
directory = ./.;
modules."@clan/sshd" = ../../default.nix;
inventory = {
machines.server = { };
machines.client = { };
instances = {
sshd-test = {
module.name = "@clan/sshd";
roles.server.machines."server".settings = {
certificate.searchDomains = [ "example.com" ];
hostKeys.rsa.enable = true;
};
roles.client.machines."client".settings = {
certificate.searchDomains = [ "example.com" ];
};
};
};
};
};
nodes = {
server = { };
client = { };
};
testScript = ''
start_all()
# Check that sshd port is open on the server
server.succeed("${pkgs.netcat}/bin/nc -z -v 127.0.0.1 22")
# Check that /etc/ssh/ssh_known_hosts contains the required CA string on the server
server.succeed("grep '^@cert-authority ssh-ca,\*.example.com ssh-ed25519 ' /etc/ssh/ssh_known_hosts")
# Check that server contains a line starting with 'localhost,server ssh-ed25519'
server.succeed("grep '^localhost,server ssh-ed25519 ' /etc/ssh/ssh_known_hosts")
# Check that /etc/ssh/ssh_known_hosts contains the required CA string on the client
client.succeed("grep '^.cert-authority ssh-ca.*example.com ssh-ed25519 ' /etc/ssh/ssh_known_hosts")
'';
}
)

View File

@@ -0,0 +1,6 @@
[
{
"publickey": "age124l8cfswl97ck0e0qw8l47usf375srn69e4mhxr3gr40erxw7pesftxshx",
"type": "age"
}
]

View File

@@ -0,0 +1,6 @@
[
{
"publickey": "age1f39qxz84yv272wk636el0kdyagzudcs99ucpkjarsj2rey6yvccse9lwet",
"type": "age"
}
]

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:anP0O+JjJDg3vcm9BzNSZ7pun/wkgDQtBFlAZiVdNTzLQJuRmQLnzh3M6HVZpaIm4vtKKXwvoW+6OxagZtAujuO0vfCVal/xNH4=,iv:D5jY2mXxPhXeX7cHuFKqhm5gAnErW/NZSGqgXGRgyLY=,tag:Xgt2/IcXxbx8uo1ne765Gg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKQmsyTWloZWRCN216elBD\nS1NMVDlrcHpBT05YOUJ3SmpTN3MzMWlrSXo0CmVjNGdETVpuaGhWWE1KVmYyS04x\nQ2hLdWxmNmNFQzdNckRtQXVSajRZK1EKLS0tIG9OYmR5RUhYRmM1R3V6QTZDa2Yz\nSCtpTkZNaGRVRTNJK2N0QUR6aXdGMjgKXWGMFKeqY12wAhLheA44ZZmXdHWhYFF0\nzYAASccNOxf+AjnbYd8l4wOMGRhE0nqIW60kudQM/pPVprYR9p0eHQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-06-09T19:51:26Z",
"mac": "ENC[AES256_GCM,data:IwXjc6aOs+hsAEnUN44SzIr8otAq1g18IleZtmSxYJvs/XGiEBeOy9BPiKutlf2uTgiUJgz2f/799ifvBCjgmUZzbsdMw6OFOKB+BDuZHO4FCPg4nUC8AJ4DkA+tYVqZEPbMsOhWmwqPnLg3tvyIvGBgBtEu1zqe6UnYcs/UVAk=,iv:Ks4L5+aBHrDRaspdqRJTWg3a0zufqwTIvUEx6JFvhhc=,tag:2MU7JlamUQy8FFHLbvqVhQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../users/admin

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:I/owfPMFtZtI23/2G8h67cZ+j3ZvU2CJ0PiR6gY4mH6IelDoKN/oFF9VmxDDcSNQPGY+aI8squqnOAbGZxjnxx+uU75j0IfcPvk=,iv:l++juCs2uVExfoAlg/Ho9sXDJeWspWwWfE5zWGr7iNw=,tag:4UkvlSq1WONy03NBDAP/4g==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlZ2ZHcHhzSUFlYU5vbjEy\nVVlhQ2hDL0lmK2FHeEFXQzBndnJoQ3VoeTFBCk9Jc2h4S1Yzb0Exam40RWpiSkhW\neVFibkw2RHB5VXdRQlBnc2VxOHdtU1kKLS0tIHV4RGRsdzE1amQyRFdwY1FCdnZ6\nM0pOdlBtYUtOUVNuV01lbTFoSFVlUEUKDuT0iyCQaUcfa+9mC1yGtC8XUm2ihfOu\neNM5lQ5vGOdFjumhUgWwBVHSMvqWd/Y2dNfIsJOQ95nvm48LSCOWVQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-06-09T19:51:28Z",
"mac": "ENC[AES256_GCM,data:Qw3p5S9xTdfCIH4sGdDp/5uFe17+8St6HAWTAmtsrkN1IApWiFgO65Io/5kjjzvsPlb5tYa73irfzvHjKZeacDkUzrCGr+U92nECiAtoawD7VZMp4f3d81erFQ8Vh92+Y8oByPFwLXIUC1FCe7LrtdhYWsgYRBdeDtcNMW+Yums=,iv:DQ/2E71p+SJceQYZ/1zsrI9CYO0PHktCn59lli6ZLQk=,tag:BGfLj9Detkri/ivaK2R/PQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../users/admin

View File

@@ -0,0 +1,4 @@
{
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"type": "age"
}

View File

@@ -0,0 +1 @@
6e0863a6ca671e08b2f8ecbf9bb410953f5c6625cf61e04744393acb18db1c91

View File

@@ -0,0 +1 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIIVAZzuQVwfTqUCbcj3xlsW+/4to2v/r7cU7+FvU5F0MAAAAIOrepoK2S7VKrauHjf9SmMedDj1MxCMpJkehTrZC/XUTAAAAAAAAAAAAAAACAAAABnNlcnZlcgAAABYAAAASc2VydmVyLmV4YW1wbGUuY29tAAAAAAAAAAD//////////wAAAAAAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAge/ie7wQVq53Qpx/igaCsBiQrGLAnqV/Mmj7uS2A4q70AAABTAAAAC3NzaC1lZDI1NTE5AAAAQIW5ykVePfn24zFYoVnVwO4c+pqpkwxN00E+Vj8vKCcbUU5dAH3AH7X2Sl1WPFSBaIMX6tx8doC0tPohoLXZOA4= nixbld@kiwi

View File

@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCrCdAtYO93aa1m2kTyXz67IE6nO0w5qHwZbPPiMQH7EmAvdF3ROvvCooC2lKtuAtjJT71T9MalljRpv1yFVzALW+uOrqUjIZMNYJSoRF2KbGVbofF/2pi8ZVTFCvXfSLhy7Qhh5DppAET8Sp/vHk5tK+NMIxT5aiYHz9G3yxkjnvlUAiBpQjiWjxSQRXItgB/VqmUPv8dkTwobhQXjs7Q71nMCvPUB6CL5GHFZcN10wZovTFilOA1cge2II3QZ6Fw07hDga02sdTyUphBreZNtivyGgKcS2g0RFjpsV4udk3s6oBHNe463ngrPs/iqBe/r7AAVB4PC8VbKM5du+DKGybUf2JRi85Y7evicElLo0/Cu/0fSg/KAGOW2+GwcmD+A/zGpX/5dTHq1cYS4Zg24+1mpO/Hk9xqGQditnSUc6FTk1E/XaxWQOAv4m+a4811puvWUyllyvu1ETq0PujoayalIjQCYR2z7BBUghn2hcigv2jaIN9Q5LvWc2h4BRbgWf/ovWPG/wUN8B3nC/cmLBRTFjVxnJUVcgWPIV89jjARUZmyG2HEHxlxKKEQ+TSlTXfMpAwXssCMJ+bYs0+cXewnW8T+KsckABLyjBrqsFmEbA+auRVE31XLsA4jm1yybNtkraIHprTiT1RLCrn0wDfBXwd8DEqGFfMuoQ4J3gw== nixbld@kiwi

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/server

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data: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,iv:HyFkKHy8Jk/NcsCsUhwZI24X/9ZhOwMmyNmvYrgMBSw=,tag:Vu7UvIwr4pd1i9wdK7CRGQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1f39qxz84yv272wk636el0kdyagzudcs99ucpkjarsj2rey6yvccse9lwet",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArSkZEUzljMW04NERjMlZ6\nUkdQVy9RT1ZNbnZWN0hLdzhQT2VjWDlBZG5nCkJZbGZmNFp0aXZ5d3BrVWw2dVd0\nQ1c5SjRhL3dXQzFqcjBLZDhkOHVFdGMKLS0tIDZVSVpQUlJITzd4M3VWZUtnNjlJ\nNEtXNzVFS1FDN1dJTUZxeHg1Mm9uNEEKNHkM7rAPY97nH77w6sWEWGayPwNVkS+d\nMcQJKMknkGuhD5jS0XZF4m+J1yv8VisVECNDD6jo9bIKw2f62l2cYA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0M252OE0rV2dGT1c1b2FG\nMjBHYXpHWGFRRitXTEVLcVc2K0FMUkpjbUhVCldMelhUZmhza1VaMzBLekZTamlK\nU1FKMmt1dUdRN1oyWmtNZnlScHJsRTQKLS0tIGxtZGxvelZwS0VYNWZ6Y1RtU0Ev\naTVHZVhpZ0luWVBpTGdDYk1FRkpQdFEKL7Rw1hwIs8qLHi899xS9CTiysGnrSvmS\nDBvD8cFyxKbOzKxE6s1KkBjp/9jI2t4fcHfAAJwH18h6O+OiT+6GyA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-06-09T19:51:32Z",
"mac": "ENC[AES256_GCM,data:TaeTF0M5zqmiI0ANLIABskA6YHfSB41PMkL1j3WHoff8tO73YVM/l+yg4fs0HgsFZ/eDMG1gyHEzM8nGHeZ+oexla+ByAT9kgCZ1LaHCqANhMOlYCM9CLWqJg4OUUhi88f8147Gz6D9viMbOtRXvcOF+PdifCD70Ji02BGKApUU=,iv:pm+pYCWHRyKHavc3ZBgkiV+86RqcL3zJ0Li85SVw+6Q=,tag:D/hRrQaTxEr1cG3r7KloPg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOrepoK2S7VKrauHjf9SmMedDj1MxCMpJkehTrZC/XUT nixbld@kiwi

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/server

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:2eY77OJxJceog1MK0tLlu6FWyQLAz12w9GkwIq251ajbns1tiotUfPi5VecrTSU00aejA3GRg2Mp37kVHPCGLlwTVrqWJqJ2SG3FpqvdAhAwVNV4i3VlqIt8kT6P3WqhkOGCwIgcKEPwJ7EmYtBwihZosUw1xL3NflYAdzvH4wtqB9WrenHXsnK5zn4+F+CFOD8YtjY4QUrkPleeZE202fAlu6ItTwITZA0I9MqVRFUZC7XLoPltKkF9nNucfP3zz4oMko2wwyNeaj9ZQJYzzCuFQrTvq5AbN/Fq5weFO57QbysKsYEX1FcOI9njVTrffF70MEr7peJOB/kk0FKrG5ihy+stZ8WSYH9cE76ezA25FyB8eSv2Em0KjUxgc3v/9CWA8qvUeTRNSnv7hbe7J/ozGSRWkNCzFe9tQLdxJmfT+8RB9WKE50shSLvm9O2YoCWN6CDH5n+ifuyuF4eGJxVOEWXfBUebRjXrvczqE6+XHtMg0ZIfN+xIF6Ge0cFep+AtOHUgcY/CZf4yGshu,iv:/I4X6ljLySVXlmMHtHBTt/s3jdwYEOoQIb2yv6Tg/QA=,tag:XOn9ichWhpI7By9Hwe3g7Q==,type:str]",
"sops": {
"age": [
{
"recipient": "age1f39qxz84yv272wk636el0kdyagzudcs99ucpkjarsj2rey6yvccse9lwet",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlcDZCUmQ0UXVJMTczVVhJ\nT1c1V1U5QUdCdW94Q0c4VFp1empUWWhWcmo0CllUdlZhWnhZK1dta0NDNStjZDJD\nRTBOUmFaT1owY1J3TWZxMm9Pd2FNZWcKLS0tIGxCTWRKa3RKdlhsNmZveTV2TDF5\nMktOazU0SWZoYWNhSmxvTTZ3Wnd6eXcK6dIuJ3vR4f7qSRC2i8gQPx1wVDNnRcZu\nbz5f3aw0HhvnDRtgGfra9DVAyrJt7FVlEqMTMV6Cb5yr59fZAdvReQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIOWFjejdVaUdLUEY2T3pn\nR2RieWVTNTRHa2R6UWZZQ0FPcjNaQ0c0WlNVCnp2bkJvUXVPS2NXSGRGT3MrUzlz\nYnlyY2pjYXlGaVY0L3M2eURPWlFWZjQKLS0tIDFXaVNnRHREVUFHMDVQY05MZUFm\neVN5Vlc4S0FWRm5QQW9PQUNnZ1FjY1UKVmrCJ1x5B3uoA1YlFCTVaggVUZMtXoQN\nFA+hclCt/3Rt6EOajxjgF+nv8QNLnusj+IQgsgDh5H+YldLbu5XfUg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-06-09T19:51:30Z",
"mac": "ENC[AES256_GCM,data:PG7jsFaXYmqFc7+z8/HgeMjGa5UwJi2XigYDQJ6zYNuMt4xsrK2G/Zss4uUAK5oSNN/TG3QJzR21OVGTsuZee+oCwho9P/px9as52sr1tzSJOwhboHb1S+CftWcqN3METYPwdowVvgrCJFAhWdKKTNy4DNzli7HJ+SDR6xE2da8=,iv:5/tzaObkRhSPdd6V/VLNlPzlKIReZMWTObqZZIbn5b8=,tag:Wje1JKGOQj7elnCWKN+IrA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHv4nu8EFaud0Kcf4oGgrAYkKxiwJ6lfzJo+7ktgOKu9 nixbld@kiwi

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:Qje3bXRHcAiFCslFfAeUTcOn2woc06e1sLAoH16x1sZ7N0i07rHqwsBjn7nKvMee6tktIjLMGTPOQL9TLgYI+wDgU5MHqlZlVBnYLk+VXYEKhymDlS3RAg5pbrmJzkucl/Vw5VBlDK+n8qnrgFG2pgpiC6Lzb5f4I7pxUl4zcz9jCf0Stj10lVQgkbvnr8UMUvcb1vUF/EAhF6WhhhgrhpbYrK+PkNW6EXmxIXdUdXvSqVWvJby2NgBaGOM1lwnWv4LOOiJ1BNXnOnLE0a8+8SjqahzqroeFvUCtoFxJ45/LqFTtgS9cQ44FaqrMRSWlOgsNR2BkeT449fKUCwYfEW1g/R47I9hAm/bcKrOBpHdAji/hpcDy73Qb9ZKrY6/0kRXl/ECI3YVX8nrHIjEJpoZ7a/dxJu7z8OOdb7gP2mVPTiWcbpD/KwpefDWLKnYhBrXUNaqSajf95Ahln2Vn6sALbbjcUzs/x5OqchYe1/kYy7MaGbEFNPeINnGid73c7xfUoyI90Ho4azLW8Q/n,iv:9heXX8g1P8/4gGT3+RYYmz6rJ5EnIDr5w1OAbGybL+I=,tag:p6mHZ8+EaJ+Nyn59n2TQ4g==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkNlpCNGR0SHVtVzJ2K0hM\ncng1ZWlTSGQzWndXVWhlbEZMN25TUklXV1I4Cm9PZkJ3Zi81YXoxdzVPTFI3dE1a\nUnJnUmJPbi9CYmdFL2ltaTRSQ1MreFUKLS0tIDE4Y05IamJjL0huY2l2YU4zbDJs\ndTl1b0wzaTM4MndlcFZYVThqbWtVeFUKuSZLJpUrccuusJPU2xWHw19wTN8mKZW3\n1GJJjlb79rZp/RbSMxFxkyVHgu+F9kbpRgViICJSWkeR495786oArA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-06-09T19:51:28Z",
"mac": "ENC[AES256_GCM,data:fgs9ftvz3wFsCsTJ94vnriYaG6JxZ4xbZan1J6TL/P3WoLR3KgacKuOxUfOCq5fRmz5wezyjoyRaYpm9AnDKLWDS0Tlu8Ja763FBYtPJHRsPc4giHr3QyQrIr8gG9DhmKNpBO7dzI02mkQmNU6ar3rGytGI9l5jYTHpnRqQCtQQ=,iv:GHV71/RE5R6TWwWvjjsEweruUQPvVLljmCK8qgTQga4=,tag:eJfy+ohGeBiZQaT5jRuWfQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../sops/users/admin

View File

@@ -92,6 +92,7 @@ nav:
- reference/clanServices/importer.md - reference/clanServices/importer.md
- reference/clanServices/localsend.md - reference/clanServices/localsend.md
- reference/clanServices/mycelium.md - reference/clanServices/mycelium.md
- reference/clanServices/sshd.md
- reference/clanServices/hello-world.md - reference/clanServices/hello-world.md
- reference/clanServices/wifi.md - reference/clanServices/wifi.md
- reference/clanServices/zerotier.md - reference/clanServices/zerotier.md