feat: Nebula mesh network overlay #12

Merged
greg merged 9 commits from klaatu/nixos:feat/nebula-mesh into main 2026-04-04 03:03:53 +00:00
29 changed files with 623 additions and 10 deletions
+3
View File
@@ -30,6 +30,9 @@
greg = {
home = true;
gnome.enable = true;
nebula = {
enable = true;
};
greg marked this conversation as resolved
Review

Move this to be a default value in the module.

Move this to be a default value in the module.
podman.enable = true;
print.enable = true;
tailscale = {
+9
View File
@@ -35,6 +35,15 @@ in
greg = {
home = true;
gnome.enable = false;
nebula = {
enable = true;
# genesis IS the routing node for the home LAN — it does not route through itself.
# Override the module default (which points at genesis) to avoid a routing loop.
unsafeRoutes = [ ];
greg marked this conversation as resolved Outdated
Outdated
Review

Override the default value of unsafeRoutes here, because this node is the routing node.

Override the default value of unsafeRoutes here, because this node is the routing node.
# genesis routes the home LAN (10.42.0.0/16) into the Nebula overlay.
# Sign genesis's cert with -subnets '10.42.0.0/16' (see secrets/nebula/README.md).
routesSubnet = "10.42.0.0/16";
};
proxies = {
};
};
+1
View File
@@ -49,6 +49,7 @@ in
greg = {
home = true;
nebula.enable = true;
proxies = {
"jellyfin.home".target = "http://localhost:8096/";
"jellyfin.thehellings.lan".target = "http://localhost:8096/";
+1
View File
@@ -42,6 +42,7 @@
vip = metadata.hosts.${config.networking.hostName}.ip;
priority = 255;
};
nebula.enable = true;
podman.enable = true;
tailscale = {
enable = true;
+1
View File
@@ -85,6 +85,7 @@ in
vip = ip;
priority = 254;
};
nebula.enable = true;
tailscale = {
enable = true;
tags = [ "home" ];
+4
View File
@@ -26,6 +26,10 @@
greg = {
home = false;
linode.enable = true;
nebula = {
enable = true;
isLighthouse = true;
};
proxies."immich.thehellings.com" = {
genAliases = false;
target = "http://localhost:${builtins.toString config.services.immich-public-proxy.port}";
+1
View File
@@ -26,6 +26,7 @@
vipInterface = "enp12s0";
priority = 253;
};
nebula.enable = true;
remote-builder.enable = true;
runner = {
enable = true;
+1
View File
@@ -22,6 +22,7 @@
./router.nix
./rpi4.nix
./syncthing.nix
./nebula.nix
./tailscale.nix
./vmdev.nix
];
+229
View File
@@ -0,0 +1,229 @@
{
config,
lib,
metadata,
...
}:
# Nebula overlay mesh network module (greg namespace)
#
# This module configures a Nebula node for the nebula.thehellings.com overlay.
# CIDR: 10.157.0.0/16
# Lighthouse: linode (public internet, acts as relay too)
#
# Each host requires:
# secrets/nebula/<hostname>.key.age - encrypted private key
# secrets/nebula/<hostname>.crt - certificate (public, unencrypted in repo)
# secrets/nebula/ca.crt - CA certificate (public, unencrypted in repo)
#
# The nebula IP for each host must be set in network.json under
# hosts.<name>.nebulaIp (e.g. "10.157.0.1")
#
# Lighthouse address is the public IP/DNS of linode. Update the
# `lighthouseAddrs` option below or override per-host if it changes.
let
cfg = config.greg.nebula;
nebulaDomain = "nebula.thehellings.com";
# Linode's public address — used by all non-lighthouse hosts to reach it.
# Override with greg.nebula.lighthouseAddr if the public IP ever changes.
defaultLighthouseAddr = "linode.${nebulaDomain}";
in
{
options.greg.nebula = {
enable = lib.mkEnableOption "Nebula overlay mesh network";
isLighthouse = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Whether this host is a Nebula lighthouse/relay node";
};
isRelay = lib.mkOption {
type = lib.types.bool;
default = cfg.isLighthouse;
description = "Whether this host acts as a relay (am_relay). Defaults to true when isLighthouse is true.";
};
nebulaIp = lib.mkOption {
type = lib.types.str;
description = "This host's Nebula overlay IP (e.g. 10.157.0.1)";
default =
let
hostData = metadata.hosts.${config.networking.hostName} or { };
in
hostData.nebulaIp
or (throw "greg.nebula.nebulaIp must be set for host ${config.networking.hostName}");
};
lighthouseAddr = lib.mkOption {
type = lib.types.str;
default = defaultLighthouseAddr;
description = "Public address (host:port) used to reach the lighthouse from non-lighthouse hosts";
};
lighthouseNebulaIp = lib.mkOption {
type = lib.types.str;
default =
let
linodeData = metadata.hosts.linode or { };
in
linodeData.nebulaIp or "10.157.0.1";
description = "Nebula overlay IP of the lighthouse host";
};
port = lib.mkOption {
type = lib.types.port;
default = 4242;
description = "UDP port Nebula listens on";
};
# unsafe_routes: allow non-Nebula subnets to be routed through this host.
# Used on genesis to expose 10.42.0.0/16 (the home LAN) to the overlay.
unsafeRoutes = lib.mkOption {
type = lib.types.listOf (
lib.types.submodule {
options = {
route = lib.mkOption {
type = lib.types.str;
description = "CIDR to route through this host (e.g. 10.42.0.0/16)";
};
via = lib.mkOption {
type = lib.types.str;
description = "Nebula overlay IP of the host that provides the route";
};
};
}
);
# Default: route the home LAN through genesis (the home router node).
# Hosts that ARE genesis (or any other routing node) should override this to [].
default = [ ];
description = ''
List of unsafe_routes to configure on this host (for reaching non-Nebula subnets).
Defaults to routing the home LAN (10.42.0.0/16) through genesis (10.157.0.2).
Override to [] on hosts that are themselves a routing node (e.g. genesis).
'';
};
# Whether this host IS the router for an unsafe subnet
# (enables IP forwarding + nftables masquerade for the home LAN)
routesSubnet = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
When set, this host will route traffic from the Nebula overlay
to this subnet. Enables IP forwarding and nftables masquerade.
Example: "10.42.0.0/16"
'';
};
};
config = lib.mkIf cfg.enable {
# agenix: decrypt this host's Nebula private key at boot
age.secrets."nebula-${config.networking.hostName}-key" = {
file = ../../secrets/nebula/${config.networking.hostName}.key.age;
owner = config.systemd.services."nebula@${nebulaDomain}".serviceConfig.User;
mode = "0400";
};
services.nebula.networks.${nebulaDomain} = {
enable = true;
# CA certificate (public — lives unencrypted in the repo)
ca = ../../secrets/nebula/ca.crt;
# Host certificate (public — lives unencrypted in the repo)
cert = ../../secrets/nebula/${config.networking.hostName}.crt;
# Private key (agenix-decrypted at runtime)
key = config.age.secrets."nebula-${config.networking.hostName}-key".path;
# Static host map: tell every node where the lighthouse lives
staticHostMap = {
"${cfg.lighthouseNebulaIp}" = [ "${cfg.lighthouseAddr}:${toString cfg.port}" ];
};
isLighthouse = cfg.isLighthouse;
isRelay = cfg.isRelay;
listen = {
host = "0.0.0.0";
# Lighthouses and relays need a fixed port; regular nodes use 0 (OS-assigned)
port = if (cfg.isLighthouse || cfg.isRelay) then cfg.port else null;
};
lighthouses = lib.optionals (!cfg.isLighthouse) [ cfg.lighthouseNebulaIp ];
relays = lib.optionals (!cfg.isLighthouse && !cfg.isRelay) [ cfg.lighthouseNebulaIp ];
tun = {
# Interface name
device = "nebula0";
};
settings.tun.unsafe_routes = cfg.unsafeRoutes;
# Firewall: permissive defaults — tighten per-host as desired
firewall = {
outbound = [
{
port = "any";
proto = "any";
host = "any";
}
];
inbound = [
# Allow ICMP (ping) from any Nebula peer
{
port = "any";
proto = "icmp";
host = "any";
}
# Allow all traffic from within the Nebula overlay
{
port = "any";
proto = "any";
host = "any";
}
]
# When routing an unsafe subnet, allow inbound traffic destined
# for that subnet from any Nebula peer (local_cidr scopes it)
++ lib.optionals (cfg.routesSubnet != null) [
{
port = "any";
proto = "any";
host = "any";
local_cidr = cfg.routesSubnet;
}
];
};
};
# Open the Nebula UDP port in the firewall
networking.firewall.allowedUDPPorts = [ cfg.port ];
# When this host routes traffic to a non-Nebula subnet, enable IP
# forwarding and add nftables masquerade rules (see unsafe_routes guide).
boot.kernel.sysctl = lib.mkIf (cfg.routesSubnet != null) {
"net.ipv4.ip_forward" = lib.mkDefault "1";
};
networking.nftables.tables = lib.mkIf (cfg.routesSubnet != null) {
nebula_routing = {
family = "ip";
content = ''
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 10.157.0.0/16 ip daddr ${cfg.routesSubnet} counter masquerade
}
chain forward {
type filter hook forward priority filter; policy accept;
ct state related,established counter accept
iifname "nebula0" ip saddr 10.157.0.0/16 ip daddr ${cfg.routesSubnet} counter accept
}
'';
};
};
};
}
+46 -10
View File
@@ -16,21 +16,29 @@
"ip": null,
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFxmnCj2E9DxcnefPW+n4yCuLShxqr0p024riogdeXA3",
"ts": "100.70.99.91",
"system": "x86_64-linux"
"system": "x86_64-linux",
"nebulaIp": "10.157.0.7"
},
"genesis": {
"ip": "10.42.1.5",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO/CGE2rqlL2Qr0TJkwQMsHFSDkhGWlrUlvfcvcylO1n",
"ts": "100.96.198.104",
"system": "x86_64-linux",
"tags": ["router", "server"]
"tags": [
"router",
"server"
],
"nebulaIp": "10.157.0.2"
},
"hosea": {
"ip": "10.42.1.7",
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKLIwkTTXA56sUlUjEulXXZRvZy5H4a5ZwgKWLlpkQDz",
"ts": "100.68.203.1",
"system": "x86_64-linux",
"tags": ["server"]
"tags": [
"server"
],
"nebulaIp": "10.157.0.3"
},
"icdm-root": {
"external": true,
@@ -42,8 +50,16 @@
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHleYKtfV4W1Z63Ysu9w5Rbglqlz4F92YcZoMkucoTNf",
"ts": "100.84.183.79",
"system": "x86_64-linux",
"systems": ["x86_64-linux", "aarch64-linux"],
"tags": ["builder", "kube", "server"]
"systems": [
"x86_64-linux",
"aarch64-linux"
],
"tags": [
"builder",
"kube",
"server"
],
"nebulaIp": "10.157.0.4"
},
"iso": {
"external": true,
@@ -59,8 +75,16 @@
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOjQjXq9WYU2Ki27BR9WwJ4ZruS/lJXbjC1b0Q42Adi0",
"ts": "100.102.186.39",
"system": "x86_64-linux",
"systems": ["x86_64-linux", "aarch64-linux"],
"tags": ["builder", "kube", "server"]
"systems": [
"x86_64-linux",
"aarch64-linux"
],
"tags": [
"builder",
"kube",
"server"
],
"nebulaIp": "10.157.0.5"
},
"joel": {
"external": true,
@@ -72,7 +96,11 @@
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMv9Zud3kZOl86gtmkn+uj3D4kiXWDPtyUL02VVLNR4Q",
"ts": "100.109.86.8",
"system": "x86_64-linux",
"tags": ["public", "server"]
"tags": [
"public",
"server"
],
"nebulaIp": "10.157.0.1"
},
"MacBook-Pro.local": {
"external": true,
@@ -108,8 +136,16 @@
"pubkey": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOos0zQePsa+T6Z2dsKbPOvEdrBQ8a6mx3s7pN6ysCI0",
"ts": "100.90.74.19",
"system": "x86_64-linux",
"systems": ["x86_64-linux", "aarch64-linux"],
"tags": ["builder", "kube", "server"]
"systems": [
"x86_64-linux",
"aarch64-linux"
],
"tags": [
"builder",
"kube",
"server"
],
"nebulaIp": "10.157.0.6"
}
}
}
+2
View File
@@ -0,0 +1,2 @@
# Ensure that this doesn't accidentally get committed
*.key
+8
View File
@@ -0,0 +1,8 @@
# Files that belong here (committed to repo):
# ca.crt — Nebula CA certificate (public)
# *.crt — per-host certificates (public)
# *.key.age — agenix-encrypted private keys (safe to commit)
#
# Files that must NEVER be committed:
# ca.key — CA private key (keep offline!)
# *.key — plaintext host private keys (encrypt with agenix first)
+109
View File
@@ -0,0 +1,109 @@
# Nebula PKI Bootstrap Guide
This directory holds the Nebula CA certificate, host certificates, and
agenix-encrypted private keys for the `nebula.thehellings.com` overlay network.
## CIDR
`10.157.0.0/16`
## Host IP Assignments
| Host | Nebula IP | Role |
|-----------|-------------|----------------------|
| linode | 10.157.0.1 | Lighthouse + relay |
| genesis | 10.157.0.2 | LAN router (unsafe) |
| hosea | 10.157.0.3 | Regular node |
| isaiah | 10.157.0.4 | Regular node |
| jeremiah | 10.157.0.5 | Regular node |
| zeke | 10.157.0.6 | Regular node |
| exodus | 10.157.0.7 | Regular node (laptop) |
---
## Step 1 — Install nebula-cert
```bash
nix shell nixpkgs#nebula
```
## Step 2 — Create the CA
Run once; keep `ca.key` offline/safe (do NOT commit it):
```bash
nebula-cert ca -name "thehellings.com" -out-crt ca.crt -out-key ca.key
```
Commit `ca.crt` (public) to the repo at `secrets/nebula/ca.crt`.
Store `ca.key` securely (password manager / offline).
## Step 3 — Sign host certificates
For most hosts (no subnet routing):
```bash
nebula-cert sign -ca-crt ca.crt -ca-key ca.key \
-name <hostname> \
-ip <nebulaIp>/16 \
-out-crt secrets/nebula/<hostname>.crt \
-out-key secrets/nebula/<hostname>.key
```
For **genesis** (routes the home LAN `10.42.0.0/16`), add `-subnets`:
```bash
nebula-cert sign -ca-crt ca.crt -ca-key ca.key \
-name genesis \
-ip 10.157.0.2/16 \
-subnets '10.42.0.0/16' \
-out-crt secrets/nebula/genesis.crt \
-out-key secrets/nebula/genesis.key
```
Commit `*.crt` files (public) to the repo.
Do NOT commit raw `*.key` files — encrypt them first (Step 4).
## Step 4 — Encrypt private keys with agenix
From the repo root:
```bash
cd nixos
for host in linode genesis hosea isaiah jeremiah zeke exodus; do
agenix -e secrets/nebula/${host}.key.age < secrets/nebula/${host}.key
rm secrets/nebula/${host}.key # remove plaintext key
done
```
The `secrets/secrets.nix` file already declares the `.key.age` recipients.
## Step 5 — Configure linode's public DNS / firewall
- Add a DNS A record: `linode.nebula.thehellings.com` → linode's public IP
- Open UDP port `4242` in linode's firewall / Linode Cloud Firewall rules
## Step 6 — Deploy
```bash
colmena apply --on linode # lighthouse first
colmena apply # rest of the fleet
```
## Verifying
```bash
# From any host, ping another by Nebula IP
ping 10.157.0.2 # genesis
# From any host, reach home LAN via unsafe_routes
ping 10.42.1.1 # UDM Pro (via genesis)
```
## Notes
- `ca.crt` is public and lives in the repo unencrypted.
- `*.crt` (host certs) are public and live in the repo unencrypted.
- `*.key.age` are agenix-encrypted private keys (in `secrets/nebula/`).
- The NixOS module (`modules/nixos/nebula.nix`) references these paths directly.
- The lighthouse (`linode`) has `isLighthouse = true` and `isRelay = true`.
- `genesis` has `routesSubnet = "10.42.0.0/16"` which enables IP forwarding
and nftables masquerade so Nebula peers can reach the home LAN.
- All other hosts have `unsafeRoutes` pointing to genesis (10.157.0.2) for
the 10.42.0.0/16 subnet.
+5
View File
@@ -0,0 +1,5 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGGoCCAD3RoZWhlbGxpbmdzLmNvbYQB/4UEac2JJoYEa668poIgUABA1IfasOIr
5hw9rQQIMzYwszJHtYp9ugmJcLLunqaDQHcumg7wvHWfQtm9ONu136FMxdSeXPvx
3QO+IOTHxm/8nuCyYUuegR6edKdxVxUPWGFkVq8M5ExxgxqsD2u2AgQ=
-----END NEBULA CERTIFICATE V2-----
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGloD+ABmV4b2R1c6EHBAUKnQAHEIUEac2MaYYEa668pYcgg4lMYGB2VakRFO6b
K9vHSLzjZpuqhBVQ7MReOwUHQKyCIJs1EbYsPKmY0efr23jfpyncEByAqEuDvKMz
2+fUUzoRg0DsosJ26LJhHe1MBvQbKx//ZwJ1iTEWmkGJnAfdglLpcf6RWtSOQaEL
UXpSV2MK3IbgSpP26zRI8mpp9OW9ApQM
-----END NEBULA CERTIFICATE V2-----
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGvoEmAB2dlbmVzaXOhBwQFCp0AAhCiBwQFCioAABCFBGnNjNCGBGuuvKWHIIOJ
TGBgdlWpERTumyvbx0i842abqoQVUOzEXjsFB0CsgiAgHipBP9jhM6AtUoB6/NLR
6Ijhq9VYjlJqJcu02sDseYNAxzppNhLFQ8Q8aZiYDe8Tt8U9HbBZERXS80hmia8a
6nUcpsL6tgc7n1hq/a4CxsSWoz8desGBF/BZKq4qEzwwBQ==
-----END NEBULA CERTIFICATE V2-----
+38
View File
@@ -0,0 +1,38 @@
age-encryption.org/v1
-> ssh-ed25519 87huqg WXMqashYNOR9yEbdbSUDmDzoMoqgcoMsT2MH2S0GKmg
2HtruRcG98iQuf4qmfrqSAm87HkejgmQdVJHJyOOwOI
-> ssh-ed25519 8UnW5Q v29MY1lo+DDut1YuTfRWN3zQADxQHJXbIIUPuUJ3sAM
qtZyn+8TGe9+bJwwvjyR76k6K9ZqGyKhQGTQKLnylZk
-> ssh-ed25519 UFfTmg 9q7zsYWj8q5DpPoRxJgUeRMgxDPTE8q6pfHW3Qgh9hA
dDfyqKQmFS17v7j2u7VoGUteG9hvAxEmopgIaIK/Y+k
-> ssh-ed25519 xNtnoA fT16NQwHegZ8NID1mdIJMu3UrSD2+9t7lq8+np+HGi4
Wv5wIZK3ET0QHeHD2QcNYAe6uPB0lwFw7gy96EwV98s
-> ssh-ed25519 aY2AXA h93ygtkSRcDpVHy1ZhFWxLbOU0rdH1zGeZNP9Y1lbH4
z0HjGZenKe9cQTBUAgufIUgElSqrKQAcdcPAXE6MtFI
-> ssh-ed25519 AQhf1g C+o3QKZbh85eO25aYtcjPOSp3PINPkOCsc+4GHkq+Qs
q2A7PK6zxcGiMwv3pdpd37xkQ4VWbZvUM49WaULuYzw
-> ssh-ed25519 mOmPfg if1IROrr9joSCWV/DdtF5mydOKabZkXmsdAwiCErWls
vykl/npqwKDP3a+n57Ala6QaPX/+izTputvkLsdOdWs
-> ssh-ed25519 YJiRbw te0RkrNjbL1J76T59XWnZuDTUuGsXIaqgAcrPV9CUgo
TpAV/oTT6MI1LgWhhgFZr0El92HQpowHhg5nGRjzs10
-> ssh-ed25519 0/WsKg IlmjW0LvTTimuyX7pZsFjlACBJe0niM9kM/7kdJH8Tk
NYERifDZzpmvhzn2Rf0YPviJHfGwlXGaut8Iz1JewUE
-> ssh-ed25519 Nl/5yA kP9Lys5bCdpDDPFmeWvpzUqQe5WQBvSvYuWB+mhdVWM
YHoc8vhAW/t+USrTNKbUR5IWdMqr2Ks4dA0Bamp52S4
-> ssh-ed25519 GdLgCQ D4/qiTTvYk8jxewNQCVfoBQYXu+oV7q3tT3a89kG2gk
YkzdAgpG2WsQDVpmou7fZDx6BP/SWvQPHrqXVsYMMAY
-> ssh-ed25519 tOH/HQ vgvAN0DO1T8crhQ+hcKUx7ddHXGi2rH05Bpz1rjBU2A
2qGje0ciWf25ZCKQ4R2mcox2nCLr10YQjU8wEyYyOSg
-> ssh-ed25519 FpzvfQ Z7u0rxi2n3iDSiosLHR8JMahjVITwHi45I/e2kG7xz8
7boIDstWnjmhs4JIZcC9Oe9TVerRwCpMw6KO9pd+mJg
-> ssh-ed25519 kdPvzQ Ts1NyubR5GHNQMouf2g+CB66tP30eBgMRPY+JI4hdUI
oVYtbwVaPAI58OLFp2ZiPq25jlPPzmhnhtFeJIaLaAg
-> ssh-ed25519 onmXpg yIecAxAGjIc3MM9Jj2isTAeRdnw3yu2Z0V9h+9LN6AU
7O1kkpjssbiMzl4urn2abrV7m7+zUFs8NRbpmh/2TbE
-> ssh-ed25519 CnhD0g BUYpZVebroM2eA7jGqczpC7vlsDcdRkU2hrSUZTZ2gE
Jbumonfp1U8URoTNkNP+d3Kyvor1jm9L1PDVUwtZgUg
-> ssh-ed25519 4ep2UA SnRm7O7Lu9ljkA9FrJn+S90TGrE+aXK+WbKAQqJRzVw
VpqLszwhrXDGdJuv//jrkTXfnqzMbliEEYm3HDCQ+8o
--- yBFC+vpdV8kCw3toDhSLnWbBdZGWB3E/Ja2N0LwQ7Ws
î"nõ4°ÎcsÉN·žÕÍ€u¬yˆµƒ}xr␍ìãËõdñîÓ^JÄE³cC°5␍Ïï'ƒz–Ì’¡…‹Å‘¯Ñ»n@ûå&uñÿ´¯
Æ ‡{(p…ˆk«Ø‘— nL[ ÄÿAîÚcô^ìÅsž ¤Ãä§È¤‘¢vLA ýÑr²ï4-‚D çû}vÊyÙ aQ
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGkoD6ABWhvc2VhoQcEBQqdAAMQhQRpzYxphgRrrrylhyCDiUxgYHZVqREU7psr
28dIvONmm6qEFVDsxF47BQdArIIgsu+XmvDcRq7CtqiLC2sSK1eCcZ8XtMSpb1Vh
64R7NgWDQJYr4aQrWlhuDLZR0ZkRoFYXzj34OpeXDUCFOaTAVoRRHvIvge2umpMa
YwgjY9reccBqdFRAoAkaJBt6wixrGgs=
-----END NEBULA CERTIFICATE V2-----
+37
View File
@@ -0,0 +1,37 @@
age-encryption.org/v1
-> ssh-ed25519 87huqg btSjOfzdV07UqZLYHUneGnFJowu4FHz9RrJ7+7ddJXs
58MQvGqjYEnyIh1IVhOv3KmGXXdtJfeehcDYEaLgDso
-> ssh-ed25519 8UnW5Q zH+7egFzPKq4936zmLu30rDmcKhobhNeDii9KyVBrhQ
EAktJPVzwbtZW+13QgnTieT5byTAjR9LUHjlJS6qfRg
-> ssh-ed25519 UFfTmg fdJBTqLeTyz7Xq4zLoGFzkCFpvQ3LwcqfEOMbYrXfGA
6RMYkDlEKbK7R2/gi/aBv92qZQti4LQxLE5Rkp8QXmQ
-> ssh-ed25519 xNtnoA qIHYXNrH6/1uW4VhSXc3S3KN0pZnpC5VOlbk8Jcb7F0
8h/o26hN98uf9kPbupzSX8V+3y163MlZQEi4vZbwDGg
-> ssh-ed25519 aY2AXA +s/czaDMCl/6RTQSdaOwn4fka9dTTuPppqA3+WDTzD8
Z6iKe15fqSNMOCku684M9dn1aKKIUzKfLzq/NiF+L7A
-> ssh-ed25519 AQhf1g 5M4AsA5NVhbBtpeCEk2txeFKq6YvX1R3qiv0Fu5U5XY
3jrHOW5pKckBvO9IMnNeq1xVWxpdcsZhyzruJZA6m4w
-> ssh-ed25519 mOmPfg /Ho4F8SLEnZS7XE7L0y0ife5DOLf0QfJCi+alwMDCy8
vef+X+2AfGZTFY7ktmUhqmRV/RF/XoAfWNIQMUP9KUc
-> ssh-ed25519 YJiRbw Hmx9RE09dq57CE6av0FA3iDDzFMpQLKLEUpkVymXnTw
gqniOzWFXAglRhe3oLp2SmtYujUZXwAOa9SsvFTBFEM
-> ssh-ed25519 0/WsKg EianWFyBA57VdsfY3fTvMCZ7DIvm3t+BhwBtx/qXOzs
qFxbQsfWbZJQ2vVnVxSdX1hw/MBS0JL44tVKDax4v/8
-> ssh-ed25519 Nl/5yA OxFWVZhphi0JMr+nco6rEIsOvM4wE0N1tq33V1PODRc
hb5JOjYomRkz+ERyYeBOmX/ZMW3q8usNvB8yZE8AIpk
-> ssh-ed25519 GdLgCQ aO0zk3ruD2oBnEJ6fMUv1JmIYWpoo2DgEqC0NpA2fmc
6PctZY6vS3FnLVW/HbQXLEVKQHN2YGlunexHYTX0Tl0
-> ssh-ed25519 tOH/HQ Vw8Uv0unsRMzgPE6NZhB1OcnU8C65uer5fJejQH9KzQ
MpaE+W/Hpm59LYwvGESKn6Bz+236x1pbMup8uZ4z6nc
-> ssh-ed25519 FpzvfQ 8Q7j/490GgZJf7mc8lsydYOKpyjLSKEXQHqqz+31T0c
iNlRFeNjVSmsTLEwnuQhKypCOiZ3SCWJXTtz34tPgsg
-> ssh-ed25519 kdPvzQ AOhJrxYuhkqDVbkhlpGhA925tInO5YfnTCh337LPcms
kv/RBK7BD/g6mnsGY8jHeXwAM6Pj3PMQ9lx2MOIn1Pg
-> ssh-ed25519 onmXpg dWB5HHlKL9MqP1a0gnpSSDAOOwLdkdqS92X69ZoYry0
7W6QYnIGu8iUqGMzUKWOr3AzVjSNegt7BL17ZkP6Z44
-> ssh-ed25519 CnhD0g 1xYVgHZJImVsk30tT4hC+Wfla0xssBcYS70mAG91h0g
pSCVA/tSP17FSBqmSx+mQjwwv9SrHgIZiI5g5E9Rkao
-> ssh-ed25519 4ep2UA 8P+sxx5e/JhdlGQ26EzavfRst+i79kAvAV0iZBRfsCQ
O2OqHFbZmj1A8Wvj7p66YhpIuPHxFsnnyUt3xLJ6HRQ
--- Tex+YxBloLbsHGMdMhvYly7XwY8wmSZ2sP3R3J5a0Jw
ˆìm+ nçy­j¶§.m'î•1Î;]&}2LňºZÏlùÉ®|æ„ùjO=¡dE­ºôm>܉×)䩸®½Tu`–©rb:¯ØÃ!ŽZh6 Ù׃Ö?íOyGùà õ_‹Îó„¯Ü­lQÐf°ËÙ”½nâ½"ßnêÎs£Žm‡rDUœôr})ExjhçÜ  eŒêi“ªt
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGloD+ABmlzYWlhaKEHBAUKnQAEEIUEac2MaYYEa668pYcgg4lMYGB2VakRFO6b
K9vHSLzjZpuqhBVQ7MReOwUHQKyCIBv+1Lr/E3Q6d99laLGdXRTss2SIL4OGBp8z
qqfEsAMpg0CyDSEYuL8GaHQq708GbCxhxFifCZaRTB+ReGBScmhT9XhIwSLHRRZJ
1TmoY4QvrdPOS3NAWvlawk/JUqN7SWQL
-----END NEBULA CERTIFICATE V2-----
Binary file not shown.
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGnoEGACGplcmVtaWFooQcEBQqdAAUQhQRpzYxphgRrrrylhyCDiUxgYHZVqREU
7psr28dIvONmm6qEFVDsxF47BQdArIIgHXr6BLGmqfF92GXiN6MBj3ac0p/EtNYf
xR3/EdI5GnGDQIFxfV5fVwi26+IRk9QIFxyyFBtmsZyPbdxL8ca1WUPm3lCNA4BT
Knd9Y3Zlp6L35L4/dzSqAVoXu2nlHF6SOAA=
-----END NEBULA CERTIFICATE V2-----
+38
View File
@@ -0,0 +1,38 @@
age-encryption.org/v1
-> ssh-ed25519 87huqg oq74sKlsXTuQiPF3vIpfFbXh4fLRWoEprZ1h5MFiyWQ
58TOYaLR4Afm2ZSpWOHbr5ZWhzT08VSP+v9U0/lAXfs
-> ssh-ed25519 8UnW5Q TBEe5WrfKcXulpJo6yKUdQJHwuSyJiXQRfcwL43V0mo
dTYL5omLZDCmbExfcTwfENbh0/U3h651V8f6pHkSyw8
-> ssh-ed25519 UFfTmg wmSLwX0Wi3z2pT1Ag5QzalAFmFnPTBH1kXBsfg+98m4
V3unDcMC3pPlFJpG5yFi+wdCUzJEcXcxEUPOtug8v10
-> ssh-ed25519 xNtnoA P/DzjGiesuoFbsUHf2hrtm1hYn7QDlHEM4Pn+HPp51I
EwByGfMGGByPJeP+fC1fXtXwjtH81NSjcmBkR1Yspzo
-> ssh-ed25519 aY2AXA Ffs4EXgQ+3UknIyTWZNfsDJY/uwM2JGMKYgoZq4SQ3Q
ZwVfFdBdEtswaNMNcmX1sCJrEOHt10M17AFH08kKNpQ
-> ssh-ed25519 AQhf1g FBnnAMCfUus06OPeLIhoV4yeSXdY8DGz3w9PCOuHYEY
OmqAuVpc6UnvShK8wMbHboAlDq/TlNQkEnUX36duOWk
-> ssh-ed25519 mOmPfg /HHd/eEJjAlj83IwGtE+Hsk5dVjWYYoChFrm+Tb2g3E
f+S6iK6fNcKoCMDnH7HLC3LrZk/jwpfxCi6DFgFuW5Q
-> ssh-ed25519 YJiRbw 3iblt4OCf+OOgriTYMWDDI9FhFCQQwR19pWpgyfh+Gk
RaIjKHzOoiEdpedS3GBeBrq9M3OZs8CHPuMdzph9Gj8
-> ssh-ed25519 0/WsKg hLS/sxN+t8LdaTLp5qIRodex6Qc2DhE3ljL65cHbUDA
X6S4fFz6v70UC8BpXCnFvvHpsKpGett2s5wthsCjBJ4
-> ssh-ed25519 Nl/5yA rJF2bbel2dZhH7CuC99TnG281c+9cUPF7+u0QmJ5oBU
Pqr5fWB94NJHM4Py8sqleDgE6A26PGCTmjVv2e+t2EM
-> ssh-ed25519 GdLgCQ wqdRmufRVW/GKqAl0UqPBUQXVUHRD1wC8dJVlcKS4kA
MdsqIGyyMiEcF1lwnlv2JACQaoT0ryepkGYb80odJBI
-> ssh-ed25519 tOH/HQ zFxCw9h85aJj81i07vWMsOR1VQdwebrNutvpftfobl4
kJHWriqUGEYtWIAye6S5hLiuMnYybMmM/eI2X88WAbI
-> ssh-ed25519 FpzvfQ +iEyOgAINtNgxctHfMt+Fj/4eGZVjsTB4godZj2UMlE
sMrf5bW23oTEo9kQVuCmJGsMrzAFB/C3S+tEMf2sDSw
-> ssh-ed25519 kdPvzQ 8aLywX0Y8/UbEwrH90/Y5/6bwKpkY3sEP9xcn7YAuk0
jkXdLMmD5Xm+0Sl7nCrxcrHTG7/QD1Su0ODvna5mHN0
-> ssh-ed25519 onmXpg qAUGZKgUjAAdlaqcOrl8TSZVUlPaECW5DDrkdWZjAUo
+PfGPASqJ84Czlco8ZUuE/wyE+rl9ww2iep9zs/9LwU
-> ssh-ed25519 CnhD0g oVxR+8Xe9qQY8y6sCFWbqHxGPj1ECqISXMU7KAw6nUQ
tU4/lvxoK/KV7R+3L9IiJTidodtAySAzkIXTc33vyaA
-> ssh-ed25519 4ep2UA m+GmFvXANTiMr6U02p3GWDLr4Alk78Ae6+ePkk2qCVY
gzufOMJbBdhqb8/VIHyLVwDfShMkYZm3Y2wbPlC4GA8
--- 4papXHguyw6dkzGpQOp1G0uK/ztnh8vxaYzJGaDlVmE
4ú7 ~Mãû…¬’òÙ8&Á'Xbãe ¯_·èèÿ¬­íÇ ís8xg|qMžZ>éÕåÕ´ c^㛯·1ëƒê–,E£nÔH»Ë]LÅŒ{öIEøÉ«jY—Я‡¿úõ q 2IF³ÕÄY|%²Õ
ImÚx•¦Øh@xzÁ .jö»÷KS V.¯-ü%Ô;~É–1
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGloD+ABmxpbm9kZaEHBAUKnQABEIUEac2aEoYEa668pYcgg4lMYGB2VakRFO6b
K9vHSLzjZpuqhBVQ7MReOwUHQKyCIEFgo5SZK7RybOKbcnXELxD4/L6k6y/YWOoJ
gGfhTdE0g0BeK8VBDuyxp+5rBUWhJaYMBfWJ2qidGwpeGQ+KgVew5auaf+wv4vek
LopzejwCv7rKAIKoB7fNO1HDbYw2WXYG
-----END NEBULA CERTIFICATE V2-----
+38
View File
@@ -0,0 +1,38 @@
age-encryption.org/v1
-> ssh-ed25519 87huqg DhN/+7v38sO9JrmbpYWtu324Giuair8QxWiDQCSt5gk
Waw20Mw9N+8HVLfpmAb6bxtwNTOJKIQNF9RAt2CizaM
-> ssh-ed25519 8UnW5Q 7xjuMFRQnDI0EVMIG3r+lBQ/iQp+5cuP/e8Hd1Z6yl8
7YKREAZx2VSXr1SdiVuSbi8zzsbgWo7oXhwQmTCxC00
-> ssh-ed25519 UFfTmg ZYevBcuVZGZM/00QmV5exil67o6Dvu51PS8d5LDSmWE
ddT6lI7aWXeefOuUoU3YdNBY/ZTqwVmAAtJY2FPUYRY
-> ssh-ed25519 xNtnoA TE1vwgCi+E3yTyIdLlC6Yj9ZsNDKqwN/bqwtB2SZXnI
tle+S8sDQQcADhsiwmHCZpgu3WxfVujDeZeaie3wIi0
-> ssh-ed25519 aY2AXA Mgq42aCTJTM5wTrsBB/WiX8oA9cQZkeTNg2e/jkqSX4
Ken49j/VMBWMr9jmwEi1RjiDThmUR9rUhVqyiMTrhNc
-> ssh-ed25519 AQhf1g /6VEx46A9pI/UZnu25SOnSND+weefGyjbX63WclcgBo
MI7RqhtaEd4FWjIrZNYRiGU9ukiRMfFYW73NC9Pn0n4
-> ssh-ed25519 mOmPfg rQC30TaeT1LvDO1AsjfLrGRLpolDPoCAjtjvk5jpM3A
Mtvq40Vkdy8GlYYRADERH7R7TrOrMmgc4L53a2S53X0
-> ssh-ed25519 YJiRbw pjzxg4h4RsReraBckNC4lrou7mrcLrFMKBQFelVZIS8
nSp+SiiR28F2qEyQOmtkyjLI8me5soL99ZfX2CyCtOQ
-> ssh-ed25519 0/WsKg gJDZIO6jB2X7JcxvBQoKUjs+CmC3dM7/o86ayxuzDAM
J1GJ8QCsdm+MV5vLKy0lDEZphcqtncdHA3Uhswtbjfk
-> ssh-ed25519 Nl/5yA k+mNdOtNlcUtvijYanWqE6Jqx3BtssT9WlgrII53JFY
qMFDbWsK7oqkn3+n29pupruUH1aL1GJTPdnHcd/saaU
-> ssh-ed25519 GdLgCQ s1oCQaEMJamaGiUNwRJYGDmcnmjMs/pSUDp8MW0biy4
ckhFXcx1t18WjY/W1urrNmZ9qab3dIlEqs5e1AaJrjE
-> ssh-ed25519 tOH/HQ EDPn55ZqtWAphmJJw+zW7RowoLyZ5Vo5Rn6LcmtHGxA
+HSdz8oRjjr+2oXPcce5u72z7iN5LmFRULxVhCsFenY
-> ssh-ed25519 FpzvfQ tJYYwIiFw+kdI6LHBd1QSh3eRprF9pTubyLfUN+JsXQ
zSR6ptxNZNLuktnRdw6wzf2TwRh5sBncJgZfqSBGMc8
-> ssh-ed25519 kdPvzQ WiR1O62lBJQCzQF021arLQuEKJOQm3mqa5dy927IFlE
asbdcEecJRVTaasDhtAb2mB6p8gELA53nHG0bhp9j4w
-> ssh-ed25519 onmXpg IlP7xoTg6qbCbeg4c7jGtUTueI2q5OWT8ot/tBZW0HY
kHNPz3hUsQZuwsJRol6BwvExp8keJzcl0K4G9VELcBk
-> ssh-ed25519 CnhD0g wVmnrThi15hQJ1JIiazwo9Tk8Hns9ALkG1Aps8gcYz4
sSy1EVAvdZAWyDI6WJfs+UQ3E8SCGq+qVQzVhrd/GXw
-> ssh-ed25519 4ep2UA nUckpcS8Sa5+RF7/Z5nexV7S5h9hFoj+UAfFzq7lQwk
hrZPftJLld4FvSDnsQC7zb/yLJujY7Jm4wki1qHunoY
--- o/cAY7EryjxlJn9BxuyQQE1s1Bwj8AIupTBMEAz+CLo
®_PLÒ‹"oĨ0ÊN›ô’†%käóf®Ï.«»ÕZUt¬þI,¼f驱òý‰ù
ÚÏ™ÕzögQÑ]¶LèY¹rŒ BÒqãõ-R„Ñ—¥Àsñôy¥L…™ÔfÎYÚ*IÈú‡àifV©') újV’8÷Ž–␍h0ë}f Öãòœ[Ó£RÄ!í{Õ‡TÚMthÏ
+6
View File
@@ -0,0 +1,6 @@
-----BEGIN NEBULA CERTIFICATE V2-----
MIGjoD2ABHpla2WhBwQFCp0ABhCFBGnNjGmGBGuuvKWHIIOJTGBgdlWpERTumyvb
x0i842abqoQVUOzEXjsFB0CsgiCirKKbej7yAALn41C+MYmertD9LOv09gZ61ODF
wEcnB4NAfix/r3q+XLYe3egKUoqJUW2i11x0ST0hxqhJUd8LjHKirRyHsvUraMbG
c8x+CXsCPLgheGt548PpmrObQWtrBA==
-----END NEBULA CERTIFICATE V2-----
Binary file not shown.
+10
View File
@@ -137,4 +137,14 @@ in
"compose/attic.env.age".publicKeys = everyone;
"grafana-api-token.age".publicKeys = everyone;
# Nebula mesh network — one private key per host, encrypted to that host's
# system key + all user keys so Greg can (re)encrypt them from any machine.
"nebula/genesis.key.age".publicKeys = everyone;
"nebula/hosea.key.age".publicKeys = everyone;
"nebula/isaiah.key.age".publicKeys = everyone;
"nebula/jeremiah.key.age".publicKeys = everyone;
"nebula/linode.key.age".publicKeys = everyone;
"nebula/zeke.key.age".publicKeys = everyone;
"nebula/exodus.key.age".publicKeys = everyone;
}