ssh + fmt + doc + agenix
This commit is contained in:
parent
36a0ab9b94
commit
962d900c01
14 changed files with 419 additions and 46 deletions
42
README.md
42
README.md
|
@ -1,23 +1,35 @@
|
|||
# NixOS
|
||||
|
||||
Ce repo contient la configuration NixOS des différentes machines présentes dans
|
||||
l'infrastructure de Aurore et ce décompose en plusieurs partie :
|
||||
l'infrastructure de Aurore et se décompose en plusieurs parties :
|
||||
|
||||
- [disks](./disks) : contient la configuration [disko](https://github.com/nix-community/disko)
|
||||
des machines.
|
||||
- [devshells](./devshells) : contient des shells nix pour faciliter l'édition
|
||||
des configurations nixos.
|
||||
- [hosts](./hosts) : contient la configuration spécifique à chaque machine,
|
||||
typiquement la configuration réseau,
|
||||
- [profiles](./profiles) : contient la configuration des différents modules
|
||||
utilisé,
|
||||
- [disks](./disks) : contient la configuration [disko](https://github.com/nix-community/disko)
|
||||
des machines.
|
||||
- [secrets](./secrets) : contient l'ensemble des secrets chiffrés avec
|
||||
[agenix](https://github.com/ryantm/agenix).
|
||||
|
||||
## Gestion des secrets
|
||||
|
||||
Dans NixOS, l'ensemble des fichiers est écrit dans `/nix/store` et qui est
|
||||
visible par tous les programmes (et tout les utilisateur⋅ices). De plus,
|
||||
l'ensemble des fichiers de configurations se trouvent sur un repo git publique.
|
||||
Pour ces deux raisons, il est préférable de chiffrer les secrets à l'aide de
|
||||
[agenix](https://github.com/ryantm/agenix). Pour plus de détaille dans
|
||||
[secrets](./secrets)
|
||||
|
||||
## Installation d'une machine
|
||||
|
||||
Si la configuration est déjà écrite, il faut alors suivre les étapes
|
||||
suivantes :
|
||||
Si la configuration est déjà écrite, il faut alors suivre les étapes suivantes :
|
||||
|
||||
1. S'assurer que la machine a accès à internet et possède un serveur DNS,
|
||||
1. Importer les fichiers de configurations,
|
||||
1. Si nécéssaire, il faut de générer le fichier `hardware-configuration.nix`
|
||||
1. Si nécessaire, il faut de générer le fichier `hardware-configuration.nix`
|
||||
à l'aide de la commande `nixos-generate-config --no-filesystems --root .`
|
||||
puis de l'ajouter dans la configuration,
|
||||
1. Vérifier que la configuration `disko` utilisée est compatible, la
|
||||
|
@ -40,3 +52,21 @@ Remarque :
|
|||
> nix-store en utilisant la RAM à l'aide de la commande :
|
||||
> `mount -o remount,size=3G,noatime /nix/.rw-store`
|
||||
> Cependant, cela peut être risquer s'il n'y a pas suffisamment de RAM.
|
||||
|
||||
Remarque :
|
||||
|
||||
> Si l'installation nécéssite le déchiffrement de secrets, l'installation
|
||||
> pourrait échouée. Veuillez alors suivre la procédure décrite dans
|
||||
> [secrets](./secrets).
|
||||
|
||||
## Formattage
|
||||
|
||||
La flake contient un formatter ([treefmt](https://github.com/numtide/treefmt-nix))
|
||||
qui s'exécute automatiquement lors d'un `nix flake check`. Si le repo n'est pas
|
||||
formatter, une erreur sera alors retournée en suggérant des modifications. Pour
|
||||
appliquer les modifications suggérées, il est alors possible d"exécuter la
|
||||
commande :
|
||||
|
||||
```bash
|
||||
$ nix fmt
|
||||
```
|
||||
|
|
10
devshells/README.md
Normal file
10
devshells/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Devshells
|
||||
|
||||
Un `devshells` permet de créer un environnement contenant des outils pour
|
||||
faciliter le développement de projet.
|
||||
|
||||
Pour activer un `devshells` il suffit d'exécuter la commande :
|
||||
|
||||
```bash
|
||||
$ nix develop
|
||||
```
|
9
devshells/default.nix
Normal file
9
devshells/default.nix
Normal file
|
@ -0,0 +1,9 @@
|
|||
{ pkgs, agenix }:
|
||||
|
||||
pkgs.mkShell {
|
||||
name = "nix";
|
||||
|
||||
packages = [
|
||||
agenix.packages.x86_64-linux.default
|
||||
];
|
||||
}
|
88
flake.lock
88
flake.lock
|
@ -1,5 +1,50 @@
|
|||
{
|
||||
"nodes": {
|
||||
"agenix": {
|
||||
"inputs": {
|
||||
"darwin": "darwin",
|
||||
"home-manager": "home-manager",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754433428,
|
||||
"narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"darwin": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1744478979,
|
||||
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "lnl7",
|
||||
"ref": "master",
|
||||
"repo": "nix-darwin",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -38,6 +83,27 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"agenix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1745494811,
|
||||
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1758070117,
|
||||
|
@ -71,12 +137,28 @@
|
|||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"agenix": "agenix",
|
||||
"disko": "disko",
|
||||
"flake-parts": "flake-parts",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -84,11 +166,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1758206697,
|
||||
"narHash": "sha256-/DbPkh6PZOgfueCbs3uzlk4ASU2nPPsiVWhpMCNkAd0=",
|
||||
"lastModified": 1758728421,
|
||||
"narHash": "sha256-ySNJ008muQAds2JemiyrWYbwbG+V7S5wg3ZVKGHSFu8=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "128222dc911b8e2e18939537bed1762b7f3a04aa",
|
||||
"rev": "5eda4ee8121f97b218f7cc73f5172098d458f1d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
83
flake.nix
83
flake.nix
|
@ -5,24 +5,32 @@
|
|||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
|
||||
treefmt-nix = {
|
||||
url = "github:numtide/treefmt-nix";
|
||||
# Secret management
|
||||
agenix = {
|
||||
url = "github:ryantm/agenix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# Disks management
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# Formatter
|
||||
treefmt-nix = {
|
||||
url = "github:numtide/treefmt-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
inputs@{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-parts,
|
||||
disko,
|
||||
...
|
||||
inputs@{ self
|
||||
, agenix
|
||||
, disko
|
||||
, flake-parts
|
||||
, nixpkgs
|
||||
, ...
|
||||
}:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
imports = [ inputs.treefmt-nix.flakeModule ];
|
||||
|
@ -30,25 +38,48 @@
|
|||
systems = [ "x86_64-linux" ];
|
||||
|
||||
flake = with nixpkgs.lib; {
|
||||
nixosConfigurations =
|
||||
let
|
||||
defaultConfig = [
|
||||
./profiles/common
|
||||
nixosConfigurations =
|
||||
let
|
||||
defaultConfig = [
|
||||
./profiles/common
|
||||
|
||||
disko.nixosModules.disko
|
||||
];
|
||||
defaultVM = [
|
||||
./profiles/vm
|
||||
./disks/layout_vm.nix
|
||||
] ++ defaultConfig;
|
||||
in {
|
||||
jitsi = nixosSystem {
|
||||
specialArgs = inputs;
|
||||
modules = [
|
||||
./hosts/vm/jitsi
|
||||
] ++ defaultVM;
|
||||
};
|
||||
};
|
||||
agenix.nixosModules.default
|
||||
disko.nixosModules.disko
|
||||
];
|
||||
defaultVM = [
|
||||
./profiles/vm
|
||||
./disks/layout_vm.nix
|
||||
]
|
||||
++ defaultConfig;
|
||||
in
|
||||
{
|
||||
jitsi = nixosSystem {
|
||||
specialArgs = inputs;
|
||||
modules = [
|
||||
./hosts/vm/jitsi
|
||||
]
|
||||
++ defaultVM;
|
||||
};
|
||||
};
|
||||
};
|
||||
perSystem = { config, pkgs, system, ... }:
|
||||
{
|
||||
devShells = {
|
||||
default = pkgs.callPackage ./devshells/default.nix { inherit (inputs) agenix; };
|
||||
};
|
||||
|
||||
# Formatter
|
||||
treefmt.config = {
|
||||
package = pkgs.treefmt;
|
||||
|
||||
programs = {
|
||||
# *.nix
|
||||
nixpkgs-fmt.enable = true;
|
||||
|
||||
# *.md (and more)
|
||||
prettier.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
4
profiles/common/README.md
Normal file
4
profiles/common/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Common
|
||||
|
||||
Ce répertoire contient l'ensemble des fichiers de configurations qui sont
|
||||
communs à toutes les machines (physiques et virtuelles).
|
|
@ -6,6 +6,7 @@
|
|||
./networking.nix
|
||||
./nix.nix
|
||||
./ntp.nix
|
||||
./programs.nix
|
||||
./ssh.nix
|
||||
./tmp.nix
|
||||
];
|
||||
|
|
|
@ -4,16 +4,11 @@
|
|||
programs = {
|
||||
git.enable = true;
|
||||
htop.enable = true;
|
||||
neovim.enable = true;
|
||||
screen.enable = true;
|
||||
tmux.enable = true;
|
||||
vim.enable = true;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
bat
|
||||
fd
|
||||
helix
|
||||
inetutils
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,9 +1,78 @@
|
|||
{ ... }:
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
age.secrets = {
|
||||
ssh_users_ca = {
|
||||
file = ../../secrets/common/ssh/users_ca.age;
|
||||
path = "/etc/ssh/users_ca.pub";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
mode = "400";
|
||||
};
|
||||
};
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
|
||||
settings.PermitRootLogin = "no";
|
||||
extraConfig = ''
|
||||
AcceptEnv LANG LC_*
|
||||
AllowAgentForwarding no
|
||||
AllowTcpForwarding yes
|
||||
AuthenticationMethods publickey
|
||||
MaxStartups 10:30:100
|
||||
PermitTTY yes
|
||||
PermitTunnel no
|
||||
PermitUserRC no
|
||||
PermitUserEnvironment no
|
||||
PrintLastLog yes
|
||||
SyslogFacility AUTH
|
||||
UsePAM no
|
||||
TCPKeepAlive yes
|
||||
TrustedUserCAKeys ${config.age.secrets.ssh_users_ca.path}
|
||||
VersionAddendum none
|
||||
'';
|
||||
|
||||
settings = {
|
||||
AllowUsers = [ "root" ];
|
||||
PasswordAuthentication = false;
|
||||
KbdInteractiveAuthentication = false;
|
||||
|
||||
LogLevel = "VERBOSE";
|
||||
PermitRootLogin = "yes";
|
||||
|
||||
Ciphers = [
|
||||
"chacha20-poly1305@openssh.com"
|
||||
"aes256-gcm@openssh.com"
|
||||
"aes128-gcm@openssh.com"
|
||||
"aes256-ctr"
|
||||
"aes192-ctr"
|
||||
"aes128-ctr"
|
||||
];
|
||||
|
||||
KexAlgorithms = [
|
||||
"curve25519-sha256@libssh.org"
|
||||
"ecdh-sha2-nistp521"
|
||||
"ecdh-sha2-nistp384"
|
||||
"ecdh-sha2-nistp256"
|
||||
"diffie-hellman-group-exchange-sha256"
|
||||
];
|
||||
|
||||
Macs = [
|
||||
"hmac-sha2-512-etm@openssh.com"
|
||||
"hmac-sha2-256-etm@openssh.com"
|
||||
"umac-128-etm@openssh.com"
|
||||
"hmac-sha2-512"
|
||||
"hmac-sha2-256"
|
||||
"umac-128@openssh.com"
|
||||
];
|
||||
};
|
||||
|
||||
sftpFlags = [
|
||||
"-f AUTHPRIV"
|
||||
"-l INFO"
|
||||
];
|
||||
};
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"cert-authority,no-touch-required,principals=\"any,newcomer,${config.networking.fqdn}\" ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBIpT7d7WeR88bs53KkNkZNOzkPJ7CQ5Ui6Wl9LXzAjjIdH+hKJieBMHrKew7+kzxGYaTqXWF1fQWsACG6aniy7VZpsdgTaNw7qr9frGfmo950V7IlU6w1HRc5c+3oVBWpg=="
|
||||
];
|
||||
|
||||
}
|
||||
|
|
4
profiles/vm/README.md
Normal file
4
profiles/vm/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
# VM
|
||||
|
||||
Ce répertoire contient l'ensemble des fichiers de configurations qui sont
|
||||
communs aux à toutes les VM.
|
|
@ -1,11 +1,18 @@
|
|||
{ lib, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
imports = [
|
||||
(modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.availableKernelModules = [
|
||||
"ata_piix"
|
||||
"uhci_hcd"
|
||||
"virtio_pci"
|
||||
"virtio_scsi"
|
||||
"sd_mod"
|
||||
"sr_mod"
|
||||
];
|
||||
boot.initrd.kernelModules = [ "dm-snapshot" ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
|
17
secrets.nix
Normal file
17
secrets.nix
Normal file
|
@ -0,0 +1,17 @@
|
|||
let
|
||||
# responsable technique
|
||||
korenstin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBu/fWY86IU7s5JIcxu8rsDwHd0JalvK1tUSzAAy3S3e korenstin@nixos";
|
||||
lafeychine = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHHt8Bk4HAmuLYif/K6JAXteZFyihX6KKL5gM7gCA2Cl lafeychine@P14s";
|
||||
respo_technique = [
|
||||
korenstin
|
||||
lafeychine
|
||||
];
|
||||
|
||||
# vm
|
||||
jitsi = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFBwpK5qfEsuapx+8tOCmEY0hpy3V6M0OSqwoByriCX5 root@jitsi";
|
||||
vm = [ jitsi ];
|
||||
in
|
||||
{
|
||||
"secrets/common/ssh/users_ca.age".publicKeys = respo_technique ++ vm;
|
||||
}
|
||||
|
114
secrets/README.md
Normal file
114
secrets/README.md
Normal file
|
@ -0,0 +1,114 @@
|
|||
# Agenix
|
||||
|
||||
Agenix est un outil permettant d'inclure des secrets dans une configuration
|
||||
NixOS et notamment de ne pas les copier les secrets dans `/nix/store` qui est
|
||||
visible par tout le monde (dit "world readable"), c'est-à-dire par tout les
|
||||
processus et tout les utilisateur⋅ices.
|
||||
|
||||
Pour plus d'information sur agenix, veuillez vous réferer à la [documentation
|
||||
officielle](https://github.com/ryantm/agenix)
|
||||
|
||||
## Pré-requis
|
||||
|
||||
La présente documentation présuppose que l'ordinateur exécutant les commandes
|
||||
possède NixOS ou le gestionnaire de paquet [nix](nixos.org/download/).
|
||||
|
||||
## Fonctionnement
|
||||
|
||||
### Génération des clés de (dé)chiffrement
|
||||
|
||||
Tout d'abord, agenix utilise des clés de chiffrement asymétrique pour chiffrer
|
||||
et déchiffrer les secrets. Pour cela, il faut en premier lieu en générer et les
|
||||
indiquer à agenix.
|
||||
|
||||
#### Utilisateur⋅ice
|
||||
|
||||
Pour un⋅e utilisateur⋅ice, il convient de générer une clé ssh (ed25519) avec
|
||||
la commande :
|
||||
|
||||
```bash
|
||||
$ ssh-keygen -t ed25519
|
||||
```
|
||||
|
||||
La commande vous indiquera où la clé sera enregistrée (et de changer
|
||||
l'emplacement le cas échéant). Rappelez-vous bien de la localisation car elle
|
||||
sera nécessaire par la suite.
|
||||
|
||||
Remarque :
|
||||
|
||||
> Pour des raisons de préférence personnelle, il peut être préféré de ne pas
|
||||
> mettre le nom par défaut (`<username>@<host>`). Il convient alors d'utiliser
|
||||
> la commande suivante :
|
||||
|
||||
```bash
|
||||
$ ssh-keygen -t ed25519 -C <quelque>@<chose>
|
||||
```
|
||||
|
||||
#### Machines
|
||||
|
||||
Pour une machine, les clés ssh sont automatiquement générées lors de
|
||||
l'installation, et la clé publique se trouvent (généralement) dans
|
||||
`/etc/ssh/ssh_host_ed25519_key.pub`.
|
||||
|
||||
### Ajout des clés et rechiffrement
|
||||
|
||||
Une fois les clés générés, il faut alors les ajouter dans le fichier `secrets`
|
||||
qui se trouve à la racine du projet.
|
||||
|
||||
:warning: ATTENTION :warning:
|
||||
|
||||
> Seule la clé publique doit être ajouté et elle est identifiable au fait que
|
||||
> le fichier se termine par `.pub`.
|
||||
|
||||
Une fois ajouter, il faut alors que quelqu'un ayant les secrets chiffrés pour
|
||||
sa clé ssh rechiffre les secrets pour votre clé. Cela se fait avec les
|
||||
commandes :
|
||||
|
||||
```bash
|
||||
$ nix develop
|
||||
$ agenir -r # -r ou --rekey
|
||||
```
|
||||
|
||||
Remarque :
|
||||
|
||||
> Ces commandes fonctionnent également lors du retrait de clé ou lors de
|
||||
> changement.
|
||||
|
||||
### Créer et éditer un fichier
|
||||
|
||||
Pour éditer un fichier, il suffit d'utiliser les commandes :
|
||||
|
||||
```bash
|
||||
$ nix develop
|
||||
$ agenix -e <chemin/du/fichier>.age -i <chemin/de/la/clé>
|
||||
```
|
||||
|
||||
Pour créer un nouveau fichier, il faut préalablement l'ajouter dans
|
||||
`secrets.nix`. Il est alors important d'ajouter les clés pour lesquelles le
|
||||
fichier doit être chiffré. Il est préférable de respecter _leitmotiv_ le
|
||||
suivant : seul les machines et personnes ayant besoin du secret doivent avoir
|
||||
accès audit secret.
|
||||
|
||||
Une fois cela effectué, la commande pour créer le fichier est la même que celle
|
||||
pour les éditer (excepté le `-i` puisque qu'il n'y a pas besoin de déchiffrer
|
||||
le secrets).
|
||||
|
||||
### Utiliser agenix dans une configuration
|
||||
|
||||
Pour utiliser agenix dans une configuration, il faut commencer par écrire le
|
||||
fichier :
|
||||
|
||||
```nix
|
||||
age.secrets = {
|
||||
<name> = {
|
||||
file = ../../secrets/<chemin>.age;
|
||||
path = "/chemin";
|
||||
owner = "<owner>";
|
||||
group = "<root>";
|
||||
mode = "420";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Puis, il est possible de spécifier le chemin avec `config.age.secrets.<name>.path`
|
||||
à l'endroit qui convient.
|
BIN
secrets/common/ssh/users_ca.age
Normal file
BIN
secrets/common/ssh/users_ca.age
Normal file
Binary file not shown.
Loading…
Reference in a new issue