From 383f4ef56fe5f0dbb954f85c3ba241cb1730a5b4 Mon Sep 17 00:00:00 2001
From: m3tm3re
Date: Fri, 24 Apr 2026 21:38:57 +0200
Subject: [PATCH] feat: tuwunel matrix server + hermes update
---
coding-rules.json | 1 +
docs/AGENIX-GUIDE.md | 191 ++++++++++++++++++
flake.lock | 56 +++--
flake.nix | 2 +-
hosts/common/ports.nix | 2 +-
hosts/common/users/m3tam3re.nix | 1 +
hosts/m3-atlas/secrets.nix | 5 +-
hosts/m3-atlas/services/default.nix | 2 +-
.../services/{conduit.nix => tuwunel.nix} | 30 +--
secrets.nix | 2 +-
secrets/conduit-env.age | Bin 1409 -> 0 bytes
secrets/tuwunel-registration-token.age | 25 +++
12 files changed, 281 insertions(+), 36 deletions(-)
create mode 100644 coding-rules.json
create mode 100644 docs/AGENIX-GUIDE.md
rename hosts/m3-atlas/services/{conduit.nix => tuwunel.nix} (55%)
delete mode 100644 secrets/conduit-env.age
create mode 100644 secrets/tuwunel-registration-token.age
diff --git a/coding-rules.json b/coding-rules.json
new file mode 100644
index 0000000..361a457
--- /dev/null
+++ b/coding-rules.json
@@ -0,0 +1 @@
+{"$schema":"https://opencode.ai/config.json","instructions":[".opencode-rules/concerns/coding-style.md",".opencode-rules/concerns/naming.md",".opencode-rules/concerns/documentation.md",".opencode-rules/concerns/testing.md",".opencode-rules/concerns/git-workflow.md",".opencode-rules/concerns/project-structure.md",".opencode-rules/languages/nix.md"]}
diff --git a/docs/AGENIX-GUIDE.md b/docs/AGENIX-GUIDE.md
new file mode 100644
index 0000000..0d888db
--- /dev/null
+++ b/docs/AGENIX-GUIDE.md
@@ -0,0 +1,191 @@
+# Agenix Secret Management Guide
+
+A guide for creating and managing encrypted secrets using agenix in the nixos-config project.
+
+## Prerequisites
+
+- SSH key pair (ed25519 or rsa) in `~/.ssh/`
+- Access to the nixos-config repository
+- Secret added to `secrets.nix` with appropriate public keys
+
+---
+
+## Creating a New Secret
+
+### Step 1: Add Secret to secrets.nix
+
+Edit `secrets.nix` and add a new entry:
+
+```nix
+"secrets/.age".publicKeys = systems ++ users;
+```
+
+Where:
+- `` is the desired filename (without `.age`)
+- `systems` = hosts that can decrypt this secret
+- `users` = users that can decrypt this secret
+
+Example:
+```nix
+"secrets/my-service-api-key.age".publicKeys = systems ++ users;
+```
+
+### Step 2: Create the Encrypted Secret
+
+Navigate to the nixos-config directory:
+
+```bash
+cd ~/p/NIX/nixos-config
+```
+
+Generate a secure random token (if needed):
+
+```bash
+head -c 32 /dev/urandom | base64 | tr -d '\n'
+```
+
+Or use a specific value:
+
+```bash
+echo -n "your-secret-value-here" > /tmp/token.txt
+```
+
+Encrypt and create the secret file:
+
+```bash
+cat /tmp/token.txt | RULES=./secrets.nix nix develop . --command sh -c 'agenix -e secrets/.age'
+```
+
+The `-e` flag encrypts stdin content into the age file. If no stdin is provided, agenix opens your editor.
+
+### Step 3: Verify the Secret
+
+Decrypt to verify:
+
+```bash
+RULES=./secrets.nix nix develop . --command agenix -d secrets/.age
+```
+
+You should see your secret value printed to stdout.
+
+### Step 4: Use in NixOS Configuration
+
+Reference the secret in your service config:
+
+```nix
+{ config, ... }:
+
+{
+ # For environment files
+ environmentFiles = [ config.age.secrets."my-secret-name".path ];
+
+ # For file-based secrets
+ environmentFile = config.age.secrets."my-secret-name".path;
+}
+```
+
+The secret will be available at `/run/agenix/` when the system builds.
+
+---
+
+## Common Patterns
+
+### Token-Based Registration (e.g., Tuwunel)
+
+```nix
+# secrets.nix
+"secrets/tuwunel-registration-token.age".publicKeys = systems ++ users;
+```
+
+```nix
+# services/tuwunel.nix
+settings.global = {
+ allow_registration = true;
+ registration_token_file = config.age.secrets."tuwunel-registration-token".path;
+};
+```
+
+### API Keys via Environment Files
+
+```nix
+# secrets.nix
+"secrets/my-service-env.age".publicKeys = systems ++ users;
+```
+
+Create `my-service-env.age` containing:
+```
+MY_SERVICE_API_KEY=your-key-here
+DATABASE_URL=postgres://...
+```
+
+Reference in config:
+```nix
+environmentFiles = [ config.age.secrets."my-service-env".path ];
+```
+
+### File-Based Secrets
+
+For binary files or specific file paths:
+
+```nix
+settings = {
+ tls.cert = config.age.secrets."tls-cert".path;
+ tls.key = config.age.secrets."tls-key".path;
+};
+```
+
+---
+
+## Agenix Command Reference
+
+| Command | Description |
+|---------|-------------|
+| `agenix -e ` | Edit/create encrypted secret (opens editor or uses stdin) |
+| `agenix -d ` | Decrypt and print to stdout |
+| `agenix -r` | Re-encrypt all secrets (after changing public keys) |
+| `agenix --validate-config` | Validate secrets.nix syntax |
+
+### Environment Variables
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `RULES` | `./secrets.nix` | Path to secrets.nix file |
+| `EDITOR` | `$EDITOR` | Editor for interactive editing |
+
+---
+
+## Troubleshooting
+
+### "No identity found to decrypt"
+
+**Cause**: No SSH private key available.
+
+**Solution**: Ensure your private key is in `~/.ssh/`:
+- `~/.ssh/id_rsa`
+- `~/.ssh/id_ed25519`
+- Or specify with `-i /path/to/private/key`
+
+### "Failed to find config root"
+
+**Cause**: Agenix can't find `secrets.nix`.
+
+**Solution**: Use `RULES=./secrets.nix` or run from the nixos-config directory.
+
+### Rekeying Secrets
+
+After adding new public keys to `secrets.nix`, re-encrypt all secrets:
+
+```bash
+cd ~/p/NIX/nixos-config
+RULES=./secrets.nix nix develop . --command agenix -r
+```
+
+---
+
+## Security Notes
+
+- Never commit plaintext secrets to git
+- Always use `secrets.nix` for encryption keys
+- Include only necessary hosts/users in public keys
+- Rotate secrets periodically
+- Use `agenix -r` after modifying public keys
diff --git a/flake.lock b/flake.lock
index b3d5470..4f16f4b 100644
--- a/flake.lock
+++ b/flake.lock
@@ -26,11 +26,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
- "lastModified": 1776092721,
- "narHash": "sha256-avV4Snqp0K57I9s8D61+GHlg9DYZFSIvjaS4d4RYpG8=",
+ "lastModified": 1777053633,
+ "narHash": "sha256-AtoguTQc8x4ysH5KSlRaFMx1elTOnTdk1u4YtqlttVU=",
"ref": "refs/heads/master",
- "rev": "0ad41acb03eee0e22cba611b2171a3d3ee30cb10",
- "revCount": 72,
+ "rev": "6e0e847299b81665ba594668fff208278bb3de3b",
+ "revCount": 73,
"type": "git",
"url": "https://code.m3ta.dev/m3tam3re/AGENTS"
},
@@ -139,16 +139,16 @@
]
},
"locked": {
- "lastModified": 1776182890,
- "narHash": "sha256-+/VOe8XGq5klpU+I19D+3TcaR7o+Cwbq67KNF7mcFak=",
- "owner": "Mic92",
+ "lastModified": 1776192490,
+ "narHash": "sha256-5gYQNEs0/vDkHhg63aHS5g0IwG/8HNvU1Vr00cElofk=",
+ "owner": "nix-community",
"repo": "bun2nix",
- "rev": "648d293c51e981aec9cb07ba4268bc19e7a8c575",
+ "rev": "6ef9f144616eedea90b364bb408ef2e1de7b310a",
"type": "github"
},
"original": {
- "owner": "Mic92",
- "ref": "catalog-support",
+ "owner": "nix-community",
+ "ref": "staging-2.1.0",
"repo": "bun2nix",
"type": "github"
}
@@ -280,21 +280,22 @@
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs_3",
+ "npm-lockfile-fix": "npm-lockfile-fix",
"pyproject-build-systems": "pyproject-build-systems",
"pyproject-nix": "pyproject-nix_2",
"uv2nix": "uv2nix_2"
},
"locked": {
- "lastModified": 1776369186,
- "narHash": "sha256-+Kltn1Ar0Ye4iBc6UVwvNPGI0uIgnCktl4Obh964/60=",
+ "lastModified": 1776983519,
+ "narHash": "sha256-cJEYjf8xV4vDw9xRBh9SHMhamj5wNjEhmMO5O3s5lag=",
"owner": "NousResearch",
"repo": "hermes-agent",
- "rev": "1dd6b5d5fb94cac59e93388f9aeee6bc365b8f42",
+ "rev": "bf196a3fc0fd1f79353369e8732051db275c6276",
"type": "github"
},
"original": {
"owner": "NousResearch",
- "ref": "v2026.4.16",
+ "ref": "v2026.4.23",
"repo": "hermes-agent",
"type": "github"
}
@@ -428,11 +429,11 @@
"treefmt-nix": "treefmt-nix"
},
"locked": {
- "lastModified": 1776870400,
- "narHash": "sha256-PleMddBk0Vp2iVsNVgqmL00u1xX1cFx8FVYOEOur/1Q=",
+ "lastModified": 1777055188,
+ "narHash": "sha256-Cdo4+L4KTEBXCyJyZdXOjyXmnwl1m5VzHJ5uIwQTENE=",
"owner": "numtide",
"repo": "llm-agents.nix",
- "rev": "bd0e8933483e6e1b33bd83c5e844926b33db0f75",
+ "rev": "bee1f681fda054c310cd25fbc944e02a7648a0ee",
"type": "github"
},
"original": {
@@ -772,6 +773,27 @@
"type": "github"
}
},
+ "npm-lockfile-fix": {
+ "inputs": {
+ "nixpkgs": [
+ "hermes-agent",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1775903712,
+ "narHash": "sha256-2GV79U6iVH4gKAPWYrxUReB0S41ty/Y3dBLquU8AlaA=",
+ "owner": "jeslie0",
+ "repo": "npm-lockfile-fix",
+ "rev": "c6093acb0c0548e0f9b8b3d82918823721930fe8",
+ "type": "github"
+ },
+ "original": {
+ "owner": "jeslie0",
+ "repo": "npm-lockfile-fix",
+ "type": "github"
+ }
+ },
"nur": {
"inputs": {
"flake-parts": "flake-parts_3",
diff --git a/flake.nix b/flake.nix
index 1f483e4..d7d5231 100644
--- a/flake.nix
+++ b/flake.nix
@@ -65,7 +65,7 @@
url = "github:vercel-labs/skills";
flake = false;
};
- hermes-agent.url = "github:NousResearch/hermes-agent/v2026.4.16";
+ hermes-agent.url = "github:NousResearch/hermes-agent/v2026.4.23";
};
outputs = {
diff --git a/hosts/common/ports.nix b/hosts/common/ports.nix
index 85ef345..f33fb13 100644
--- a/hosts/common/ports.nix
+++ b/hosts/common/ports.nix
@@ -38,7 +38,7 @@
kestra = 3018;
outline = 3019;
authentik = 3023;
- conduit = 3024;
+ tuwunel = 3024;
# Home automation
homarr = 7575;
diff --git a/hosts/common/users/m3tam3re.nix b/hosts/common/users/m3tam3re.nix
index ae367e9..fb7607b 100644
--- a/hosts/common/users/m3tam3re.nix
+++ b/hosts/common/users/m3tam3re.nix
@@ -25,6 +25,7 @@
openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC3YEmpYbM+cpmyD10tzNRHEn526Z3LJOzYpWEKdJg8DaYyPbDn9iyVX30Nja2SrW4Wadws0Y8DW+Urs25/wVB6mKl7jgPJVkMi5hfobu3XAz8gwSdjDzRSWJrhjynuaXiTtRYED2INbvjLuxx3X8coNwMw58OuUuw5kNJp5aS2qFmHEYQErQsGT4MNqESe3jvTP27Z5pSneBj45LmGK+RcaSnJe7hG+KRtjuhjI7RdzMeDCX73SfUsal+rHeuEw/mmjYmiIItXhFTDn8ZvVwpBKv7xsJG90DkaX2vaTk0wgJdMnpVIuIRBa4EkmMWOQ3bMLGkLQeK/4FUkNcvQ/4+zcZsg4cY9Q7Fj55DD41hAUdF6SYODtn5qMPsTCnJz44glHt/oseKXMSd556NIw2HOvihbJW7Rwl4OEjGaO/dF4nUw4c9tHWmMn9dLslAVpUuZOb7ykgP0jk79ldT3Dv+2Hj0CdAWT2cJAdFX58KQ9jUPT3tBnObSF1lGMI7t77VU= m3tam3re@m3-nix"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBZcjCKl0DRuOUOMXbM0GKY5JjvmyFpVZ/tRlTKWu/zp razr"
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEZbg/Z9mnflXuLahGY8WOSBMqbgeqVIkIwRkquys1Ml sascha.koenig@azintec.com"
];
packages = [inputs.home-manager.packages.${pkgs.stdenv.hostPlatform.system}.default];
};
diff --git a/hosts/m3-atlas/secrets.nix b/hosts/m3-atlas/secrets.nix
index a4716bd..1a8e166 100644
--- a/hosts/m3-atlas/secrets.nix
+++ b/hosts/m3-atlas/secrets.nix
@@ -33,6 +33,10 @@
restreamer-env = {file = ../../secrets/restreamer-env.age;};
searx = {file = ../../secrets/searx.age;};
tailscale-key = {file = ../../secrets/tailscale-key.age;};
+ tuwunel-registration-token = {
+ file = ../../secrets/tuwunel-registration-token.age;
+ owner = "tuwunel";
+ };
traefik = {
file = ../../secrets/traefik.age;
owner = "traefik";
@@ -65,7 +69,6 @@
owner = "m3tam3re";
};
authentik-env = {file = ../../secrets/authentik-env.age;};
- conduit-env = {file = ../../secrets/conduit-env.age;};
};
};
}
diff --git a/hosts/m3-atlas/services/default.nix b/hosts/m3-atlas/services/default.nix
index 0e18ffb..806e523 100644
--- a/hosts/m3-atlas/services/default.nix
+++ b/hosts/m3-atlas/services/default.nix
@@ -1,6 +1,6 @@
{
imports = [
- ./conduit.nix
+ ./tuwunel.nix
./containers
./gitea.nix
./gitea-actions-runner.nix
diff --git a/hosts/m3-atlas/services/conduit.nix b/hosts/m3-atlas/services/tuwunel.nix
similarity index 55%
rename from hosts/m3-atlas/services/conduit.nix
rename to hosts/m3-atlas/services/tuwunel.nix
index 024531f..48facd2 100644
--- a/hosts/m3-atlas/services/conduit.nix
+++ b/hosts/m3-atlas/services/tuwunel.nix
@@ -1,44 +1,46 @@
-{config, ...}: {
- services.matrix-conduit = {
+{config, ...}: let
+ # Tuwunel uses a list for ports
+ tuwunel-port = config.m3ta.ports.get "tuwunel";
+in {
+ services.matrix-tuwunel = {
enable = true;
settings.global = {
server_name = "m3ta.dev";
- address = "127.0.0.1";
- port = config.m3ta.ports.get "conduit";
+ address = ["127.0.0.1"];
+ port = [tuwunel-port];
max_request_size = 20000000;
- allow_registration = false;
+ allow_registration = true;
+ registration_token_file = config.age.secrets."tuwunel-registration-token".path;
allow_encryption = true;
allow_federation = true;
trusted_servers = ["matrix.org"];
- database_backend = "rocksdb";
};
- secretFile = config.age.secrets.conduit-env.path;
};
- # Traefik configuration for Conduit
+ # Traefik configuration for Tuwunel
services.traefik.dynamicConfigOptions.http = {
- services.conduit.loadBalancer.servers = [
+ services.tuwunel.loadBalancer.servers = [
{
- url = "http://localhost:${toString (config.m3ta.ports.get "conduit")}/";
+ url = "http://localhost:${toString tuwunel-port}/";
}
];
- routers.conduit = {
+ routers.tuwunel = {
rule = "Host(`matrix.m3ta.dev`)";
tls = {
certResolver = "godaddy";
};
- service = "conduit";
+ service = "tuwunel";
entrypoints = "websecure";
};
# Federation endpoint on base domain
- routers.conduit-federation = {
+ routers.tuwunel-federation = {
rule = "Host(`m3ta.dev`) && PathPrefix(`/_matrix`)";
tls = {
certResolver = "godaddy";
};
- service = "conduit";
+ service = "tuwunel";
entrypoints = "websecure";
};
};
diff --git a/secrets.nix b/secrets.nix
index 831e8f9..ee1fa9f 100644
--- a/secrets.nix
+++ b/secrets.nix
@@ -16,7 +16,6 @@ in {
"secrets/anytype-key.age".publicKeys = systems ++ users;
"secrets/anytype-key-ares.age".publicKeys = systems ++ users;
"secrets/authentik-env.age".publicKeys = systems ++ users;
- "secrets/conduit-env.age".publicKeys = systems ++ users;
"secrets/baserow-env.age".publicKeys = systems ++ users;
"secrets/ghost-env.age".publicKeys = systems ++ users;
"secrets/littlelink-m3tam3re.age".publicKeys = systems ++ users;
@@ -51,4 +50,5 @@ in {
"secrets/honcho-key.age".publicKeys = systems ++ users;
"secrets/hermes-env.age".publicKeys = systems ++ users;
"secrets/hermes-cloud-env.age".publicKeys = systems ++ users;
+ "secrets/tuwunel-registration-token.age".publicKeys = systems ++ users;
}
diff --git a/secrets/conduit-env.age b/secrets/conduit-env.age
deleted file mode 100644
index dded15150d6654da5cdf6067c1e3d0f4d08974ed..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1409
zcmYdHPt{G$OD?J`D9Oyv)5|YP*Do{V(zR14F3!+RO))YxHMCSP@$>O6Dp$z$G;lX_
z&v3HT&Nt4f%q&R^G>)?Lw6qLMH}*~S&kOS_%StwPDXxleFXl3>s?756@W=_t@C!C7
ztjsG8bkPnnEU_?7bI%UY_pR_sEDnxxiOMl7aYeVyG`l>x*ij+0u-rAZJiy7v+@~~K
z-#6W;)IBhy(yuthEXXxGD>ch3t=PjX(kRr+Ba|zVwd0)XA`cJg0if1_ngY|)S^63*OF2{50^yev_Kz|lng_E
z6T`eb(^1^eS1AP$9IHZtUEM4z%Zt<8Lb6Q^lYFyXLh=&*+{68f%1pxo
zjSJHPwad|MOE&Qf%yCqx3`)yR&P~e>@sD(IDKv8o4h<^scQ*3%&2%YtHp>lh&-Tp^
z3ikK4h)Cv2&I>MZsx(UW3eO0OEHo{RFm)_5GY<|fP4rK7kIc@>HmpjuG&eEGNsWZr
zR#cp*;1ZbQYF^G2o?e-k9GP7jQ0y0M>RFWUnrrS>7GxQuof($z|z#G>KYZ4k?EQ1Y?xQ&uWgoPY3^&{k?vJh%vEF(;8N_BXp$FRSs7ZG
zl$lu?=;0e_?o{fMA6iuGQ
z9Byck8sTmbnCxufA6{IQ{gN+nG$Mb9OUk69#!g?V`fp9S$JF8D0=(QC`9oUhWZUo}O#z<7r+PX6ff1=^W}5WKfx!6zHDsYF_G^9br-K?-k}1
zkz$ll84?-f6=+tXA7vg{UX&DRQQ&FB<>Hp_Uf^o(m{yQgRp8;|ni^STlx%1o5ojJz
z=wD`Op6yYPZW&-$WNI905|k0)U*Q~K;U8XL>RV{$qHXMF$`w#mlIrSS=^CK#9~i8i
zl3kH%l;UArn3!c$tZ!avl4la0<7SX-WDy=wU{qk9ooL~zpC3`>oD||65Mq&C9>`Uq
zos{X5SCr%*;qU66m~9?mksVQNQ047Z;A>D&W|SD<>|`3@;q9Ft8W0fX8|)sc?dx3V
z=28@uVwi7OkzB-+$5;j$2c`R
zCp*k3+t@KX%`q@N$}o`2(>T{WyfnC^#}S
zEhIhM%-EAlS65d-Kd2}*+b=9XIHxqjpvpKfxysPpw>ZGHAgA2WBP=DLBCFgeBe^n7
zJ2IK8VTWklK`rK;OHDqPM!mBRC{>%rbF*lZ^wD$daG_ZcOx=gwTbVb-Szy7s595k;XE4=CM
z%u^fztK@H6Y4SdjuHFB}Pe9h7;BGxb+00LeUflC{cNTKDHsn2CE&kTHWR6HD0O?rZ
A)Bpeg
diff --git a/secrets/tuwunel-registration-token.age b/secrets/tuwunel-registration-token.age
new file mode 100644
index 0000000..ec0e266
--- /dev/null
+++ b/secrets/tuwunel-registration-token.age
@@ -0,0 +1,25 @@
+age-encryption.org/v1
+-> ssh-ed25519 4NLKrw u9nwBPCI+zx7fYqOzv/63Y4mBK/n5GWhWGaPuWeFhEg
+3yCRXT+yzXNj+1VKxVu5N2+Ny0Q+AMS6t/zpZxSgONk
+-> ssh-ed25519 5kwcsA v7wY7U6E/We+1jWZEfLDkktdYf+ghngJWv96R4TPtxw
+kGoyKE32eqonVlE1Ur47t3kpwUtcQcdmSxBh8YFM2Ms
+-> ssh-ed25519 9d4YIQ 0PH2mtTx4EmwrRh9+QxEmYgVpGzQ2vlsh1SzaBwHGGE
+Um0pazZRjpfJFG11kib7fLV494OOyVXxrMAzoZ9JDD0
+-> ssh-ed25519 3Bcr1w /ikZTn/m+w7LlUx5iLbmLvH4gVAzLwR1qj97aJ5/CCc
+bVQT83BVrousaRnAaOgw0w9cCOulCslT6WpLpAGWz1c
+-> ssh-ed25519 c4NQlA slStbXPWuslSQftcqBE7qdQ+wF+rADcbyqUe7sC8ZxM
+rJw7+fA8kncbBdbYWAhS+TlGVJK4l7dOaxLuUigRHuM
+-> ssh-rsa DQlE7w
+nk4lSYyM1mom5GJva11LGS8FnZX7OVk0tpC+H2mYqKgfmJm3yyFrZNUOKZHT/EtN
+WpH5oHKWMhveBCPBB20JNNMg4hfJv4E3MfivXp2dABH/Y1vitG9pZKlp8KKsC6nC
+K/OR6y50L57KcC3M0WJ1fVTfaITdzugBGr3UYEUERG+6lw9EJmnlef+6OLafPyJM
+HslKUP54oSuMeI1Gdqne94nGjj8K/MFzOOxgIYVAGUayIK1RMiajKTfDo6E+irFn
+FJnZn4sVpsvD5FXZbmXWOORKz3APA9NbwvmjEgT9TZz+aZKHgS2qyyE8VrPr8vHO
+wBdlmKuV9U2DLSdFAIjwVXg1olarh4ZuC1+i/x6l7je6MYCwAMJwaUBnTNlBcXCg
+4REScinoz9Cx+Rjuk9OjYFrrpjCXJEfKwaHXNHW04VxnMb7mQ2I3/EQ5/NnJ2PaC
+vf8JdGaenSnRmTCj7977SmuN9dFIDnwvNkLxE3wAa8ziWbJeC4jeaIhE4uUp36gF
+
+-> ssh-ed25519 CSMyhg KpY+UDROmpjQSXrerSVADQlj/9rWWc4iD90vRM5aX3k
+TBhiMdnx4WpH6t6TgVXfTQayyIrOCFabii96hFK0FY8
+--- gAkvzBVNmd7e5uSyyg4vS5cnObeZ2t2xgOiWrP55KK8
+?Žë0žÎ¦›òxp¸a¡{ă9¦'Å¿e<ÕK„—“´¥¼¸SôÕøÅJ²?ö°~§0?:öðct$òØåJRËåì
\ No newline at end of file