1
0
Fork 0
This commit is contained in:
Lukas Wurzinger 2025-05-18 01:08:10 +02:00
parent b8af0e9761
commit 8164e92af6
No known key found for this signature in database
84 changed files with 674 additions and 567 deletions

View file

@ -2,25 +2,51 @@
This is my cobbled together NixOS configuration. There are many like it, but this one is mine. Copy at your own risk.
## Structure
* common: Sane defaults that make sense to use for every host.
* modules: Regular NixOS modules.
* profiles: Higher-level NixOS modules that conform to different roles that a host may have.
* packages: Packages that I couldn't fit anywhere else.
* secrets: Agenix secrets.
* hosts: Hosts exposed in `nixosConfigurations`.
* pubkeys.nix: Nix expression with all my SSH public keys, used for OpenSSH, Agenix and Restic.
* lib.nix: Nixpkgs' lib with some extra functionality.
## Ports
* 80X0: Public HTTP services that are proxied through nginx
* 40X0: Syncthing instances (4000 being the system instance, subsequent ones are for individual users)
## Installation
```bash
nix run git+https://codeberg.org/helvetica/puter.git#disk /path/to/disk
# TODO: Configure additional disks
mkdir -p /mnt/etc/ssh
cat > /mnt/etc/ssh/ssh_host_ed25519_key
chmod 600 /mnt/etc/ssh/ssh_host_ed25519_key
ssh-keygen -f /mnt/etc/ssh/ssh_host_ed25519_key -y > /mnt/etc/ssh/ssh_host_ed25519_key.pub
nixos-install --no-root-password --flake git+https://codeberg.org/helvetica/puter.git#hostname
```
## systemd-cryptenroll
```bash
systemd-cryptenroll /dev/sdX --tpm2-device=auto
```
## Create tar for sbctl
```bash
sudo sbctl create-keys
sudo tar --create --directory /var/lib/sbctl . | agenix -e secure-boot/hostname.tar.age
```
## TODO
- [ ] lanzaboote
- [ ] monitoring (prometheus)
- [ ] logging (loki)
- [ ] kiosk
- [ ] tailscale and headscale
- [ ] game rom sync insomniac
- [ ] Lanzaboote
- [ ] Monitoring
- [ ] Rom sync
- [ ] insomniac backups
- [ ] nginx websites
## port allocation
* 80X0: public HTTP services that are proxied through nginx
* 40X0: syncthing instances (4000 being the system instance, subsequent ones are for individual users)
* 60X0: private HTTP services that are accessible via tailscale
* 20XX: Administrative stuff, like prometheus etc.
* 8000: vaultwarden
* 8010: headscale
* 4000: syncthing

View file

@ -1,5 +0,0 @@
{
programs.bash.interactiveShellInit = ''
shopt -s autocd globstar nullglob extglob checkwinsize
'';
}

View file

@ -1,28 +1,22 @@
{ config, ... }:
{
{config, inputs, ...}: {
imports = [
inputs.lanzaboote.nixosModules.lanzaboote
];
fileSystems.${config.boot.loader.efi.efiSysMountPoint} = {
label = "BOOT";
fsType = "vfat";
};
boot = {
loader = {
systemd-boot = {
lanzaboote = {
enable = true;
consoleMode = "max";
pkiBundle = "/var/lib/sbctl";
};
efi = {
loader.efi = {
canTouchEfiVariables = true;
efiSysMountPoint = "/boot";
};
};
# TODO
tmp = {
useTmpfs = true;
tmpfsSize = "50%";
cleanOnBoot = true;
};
};
}

View file

@ -1,4 +1,6 @@
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.bottom ];
environment.systemPackages = [
pkgs.bottom
];
}

View file

@ -1,3 +1,8 @@
{ inputs, ... }:
{
imports = [
inputs.nix-index-database.nixosModules.nix-index
];
programs.nix-index-database.comma.enable = true;
}

View file

@ -1,4 +0,0 @@
{
# TODO
programs.command-not-found.enable = false;
}

View file

@ -1,3 +0,0 @@
{
services.dbus.implementation = "broker";
}

23
common/editor.nix Normal file
View file

@ -0,0 +1,23 @@
{
inputs,
lib,
pkgs,
...
}:
let
package = inputs.hxwrap.packages.${pkgs.system}.default;
in
{
environment = {
systemPackages = [ package ];
sessionVariables =
let
exe = builtins.baseNameOf (lib.getExe package);
in
{
EDITOR = exe;
VISUAL = exe;
};
};
}

View file

@ -1,6 +0,0 @@
{ pkgs, ... }:
{
programs.fish.enable = true;
users.defaultUserShell = pkgs.fish;
}

9
common/gc.nix Normal file
View file

@ -0,0 +1,9 @@
{
nix.gc = {
automatic = true;
dates = "daily";
options = "--delete-older-than 30d";
};
boot.loader.systemd-boot.configurationLimit = 5;
}

View file

@ -1,6 +1,10 @@
{
{pkgs, ...}: {
programs.git = {
enable = true;
lfs.enable = true;
};
environment.systemPackages = [
pkgs.gitui
];
}

View file

@ -1,6 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = [
pkgs.gitui
];
}

View file

@ -1,21 +0,0 @@
{
inputs,
lib,
pkgs,
...
}:
let
package = inputs.hxwrap.packages.${pkgs.system}.default;
in
{
environment.systemPackages = [ package ];
environment.sessionVariables =
let
exe = builtins.baseNameOf (lib.getExe package);
in
{
EDITOR = exe;
VISUAL = exe;
};
}

View file

@ -1,17 +0,0 @@
{
pkgs,
self,
...
}:
{
programs.nh = {
enable = true;
clean = {
enable = true;
extraArgs = "--keep 5 --keep-since 1w";
dates = "weekly";
};
};
environment.sessionVariables.NH_FLAKE = "git+https://forgejo@forgejo.helveticanonstandard.net/helvetica/puter.git"; # TODO
}

10
common/nini.nix Normal file
View file

@ -0,0 +1,10 @@
{inputs, ...}: {
imports = [
inputs.nini.nixosModules.default
];
programs.nini = {
enable = true;
flakeref = "git+https://forgejo.helveticanonstandard.net/helvetica/puter.git";
};
}

View file

@ -1,6 +0,0 @@
{ inputs, ... }:
{
imports = [
inputs.nix-index-database.nixosModules.nix-index
];
}

View file

@ -1,25 +0,0 @@
{
lib,
pkgs,
...
}:
{
#services.rsync = {
# enable = true;
# commonArgs = let
# rsh = "${lib.getExe pkgs.openssh} -i /etc/ssh/ssh_host_ed25519_key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
# in [
# "--verbose"
# "--verbose"
# "--archive"
# "--update"
# "--delete"
# "--mkpath"
# "--exclude"
# "lost+found"
# "--rsh"
# rsh
# ];
#};
}

12
common/secure-boot.nix Normal file
View file

@ -0,0 +1,12 @@
{self, attrName, config, lib, pkgs, ...}: let
inherit (config.age) secrets;
in{
age.secrets.secure-boot.file = self + /secrets/secure-boot/${attrName}.tar.age;
system.activationScripts.secureboot = let
target = config.boot.lanzaboote.pkiBundle;
in ''
mkdir --parents ${target}
${lib.getExe pkgs.gnutar} --extract --file ${secrets.secure-boot.path} --directory ${target}
'';
}

18
common/shell.nix Normal file
View file

@ -0,0 +1,18 @@
{ config, ... }:
{
programs = {
fish.enable = true;
bash.interactiveShellInit = ''
shopt -s autocd globstar nullglob extglob checkwinsize
'';
starship = {
enable = true;
interactiveOnly = true;
settings.format = "$all";
};
};
users.defaultUserShell = config.programs.fish.package;
}

View file

@ -1,7 +0,0 @@
{
programs.starship = {
enable = true;
interactiveOnly = true;
settings.format = "$all";
};
}

View file

@ -3,6 +3,8 @@
enable = true;
execWheelOnly = true;
wheelNeedsPassword = true;
extraConfig = "Defaults lecture=\"never\"";
extraConfig = ''
Defaults lecture="never"
'';
};
}

View file

@ -1,3 +1,6 @@
{
zramSwap.enable = true;
zramSwap = {
enable = true;
memoryPercent = 50;
};
}

View file

@ -3,13 +3,10 @@
services.tailscale = {
enable = true;
openFirewall = true;
useRoutingFeatures = "both"; # TODO
};
networking.firewall = {
trustedInterfaces = [
networking.firewall.trustedInterfaces = [
config.services.tailscale.interfaceName
];
# Required to connect to Tailscale exit nodes
checkReversePath = "loose";
};
}

6
common/tmp.nix Normal file
View file

@ -0,0 +1,6 @@
{
boot.tmp = {
useTmpfs = true;
tmpfsSize = "50%";
};
}

View file

@ -1,13 +1,13 @@
{
self,
config,
lib,
...
}:
let
inherit (config.users) mainUser;
in
{
age.secrets = lib.mkSecrets { "user-${mainUser}" = { }; };
age.secrets."user-${mainUser}".file = self + /secrets/users/${mainUser}.age;
users = {
mutableUsers = false;

View file

@ -1,3 +0,0 @@
{
programs.yazi.enable = true;
}

View file

@ -1,6 +0,0 @@
{ pkgs, ... }:
{
environment.systemPackages = [
pkgs.zellij
];
}

288
flake.lock generated
View file

@ -21,6 +21,21 @@
"type": "github"
}
},
"crane": {
"locked": {
"lastModified": 1731098351,
"narHash": "sha256-HQkYvKvaLQqNa10KEFGgWHfMAbWBfFp+4cAgkut+NNE=",
"owner": "ipetkov",
"repo": "crane",
"rev": "ef80ead953c1b28316cc3f8613904edc2eb90c28",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
@ -44,6 +59,22 @@
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1733328505,
@ -59,7 +90,7 @@
"type": "github"
}
},
"flake-compat_2": {
"flake-compat_3": {
"flake": false,
"locked": {
"lastModified": 1746162366,
@ -130,6 +161,27 @@
}
},
"flake-parts_4": {
"inputs": {
"nixpkgs-lib": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1730504689,
"narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "506278e768c2a08bec68eb62932193e341f55c90",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_5": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_4"
},
@ -147,7 +199,7 @@
"type": "github"
}
},
"flake-parts_5": {
"flake-parts_6": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_5"
},
@ -165,6 +217,24 @@
"type": "github"
}
},
"flake-parts_7": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_6"
},
"locked": {
"lastModified": 1743550720,
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"forgesync": {
"inputs": {
"flake-parts": "flake-parts_2",
@ -187,13 +257,35 @@
"url": "https://codeberg.org/helvetica/forgesync.git"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"lanzaboote",
"pre-commit-hooks-nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"hardware": {
"locked": {
"lastModified": 1746341346,
"narHash": "sha256-WjupK5Xpc+viJlJWiyPHp/dF4aJItp1BPuFsEdv2/fI=",
"lastModified": 1747129300,
"narHash": "sha256-L3clA5YGeYCF47ghsI7Tcex+DnaaN/BbQ4dR2wzoiKg=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "0833dc8bbc4ffa9cf9b0cbfccf1c5ec8632fc66e",
"rev": "e81fd167b33121269149c57806599045fd33eeed",
"type": "github"
},
"original": {
@ -242,9 +334,35 @@
"url": "https://codeberg.org/helvetica/hxwrap.git"
}
},
"lanzaboote": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts_4",
"nixpkgs": [
"nixpkgs"
],
"pre-commit-hooks-nix": "pre-commit-hooks-nix",
"rust-overlay": "rust-overlay"
},
"locked": {
"lastModified": 1737639419,
"narHash": "sha256-AEEDktApTEZ5PZXNDkry2YV2k6t0dTgLPEmAZbnigXU=",
"owner": "nix-community",
"repo": "lanzaboote",
"rev": "a65905a09e2c43ff63be8c0e86a93712361f871e",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "v0.4.2",
"repo": "lanzaboote",
"type": "github"
}
},
"musicomp": {
"inputs": {
"flake-parts": "flake-parts_4",
"flake-parts": "flake-parts_5",
"nixpkgs": "nixpkgs_4"
},
"locked": {
@ -263,7 +381,7 @@
},
"myphps": {
"inputs": {
"flake-parts": "flake-parts_5",
"flake-parts": "flake-parts_6",
"nixpkgs": "nixpkgs_5",
"phps": "phps"
},
@ -281,6 +399,25 @@
"url": "https://codeberg.org/helvetica/myphps.git"
}
},
"nini": {
"inputs": {
"flake-parts": "flake-parts_7",
"nixpkgs": "nixpkgs_7"
},
"locked": {
"lastModified": 1747493683,
"narHash": "sha256-SEszNrbvTzxjFM7apKnL8LaarvDAzcuuQXj8r+ikJdk=",
"ref": "refs/heads/main",
"rev": "a61825fc51a2b52cebd01ce58910707383e08b02",
"revCount": 2,
"type": "git",
"url": "https://codeberg.org/helvetica/nini.git"
},
"original": {
"type": "git",
"url": "https://codeberg.org/helvetica/nini.git"
}
},
"nix-index-database": {
"inputs": {
"nixpkgs": [
@ -288,11 +425,11 @@
]
},
"locked": {
"lastModified": 1746330942,
"narHash": "sha256-ShizFaJCAST23tSrHHtFFGF0fwd72AG+KhPZFFQX/0o=",
"lastModified": 1747470409,
"narHash": "sha256-R9TP2//BDKyjNzuZybplIZm7HQEnwL8khs7EmmTPYP4=",
"owner": "nix-community",
"repo": "nix-index-database",
"rev": "137fd2bd726fff343874f85601b51769b48685cc",
"rev": "c1f63a0c3bf1b2fe05124ccb099333163e2184a7",
"type": "github"
},
"original": {
@ -303,17 +440,17 @@
},
"nixos-cosmic": {
"inputs": {
"flake-compat": "flake-compat_2",
"nixpkgs": "nixpkgs_7",
"nixpkgs-stable": "nixpkgs-stable",
"rust-overlay": "rust-overlay"
"flake-compat": "flake-compat_3",
"nixpkgs": "nixpkgs_8",
"nixpkgs-stable": "nixpkgs-stable_2",
"rust-overlay": "rust-overlay_2"
},
"locked": {
"lastModified": 1746356902,
"narHash": "sha256-aV2pm+XKEoGE/BuqJwI1zDhtHclzC5BsbSO+SAMFEKk=",
"lastModified": 1747491978,
"narHash": "sha256-Jn7um1fnf2bI9N8gvG5jIHvIJxxLaXd+2+wHXyW0Frs=",
"owner": "lilyinstarlight",
"repo": "nixos-cosmic",
"rev": "22325997671e2a6f0a2e784db2746267868a33ed",
"rev": "2a7be063557ffc19ab1d8ab18bfd1721df8355c5",
"type": "github"
},
"original": {
@ -413,13 +550,44 @@
"type": "github"
}
},
"nixpkgs-lib_6": {
"locked": {
"lastModified": 1743296961,
"narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1746183838,
"narHash": "sha256-kwaaguGkAqTZ1oK0yXeQ3ayYjs8u/W7eEfrFpFfIDFA=",
"lastModified": 1730741070,
"narHash": "sha256-edm8WG19kWozJ/GqyYx2VjW99EdhjKwbY3ZwdlPAAlo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bf3287dac860542719fe7554e21e686108716879",
"rev": "d063c1dd113c91ab27959ba540c0d9753409edf3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1747335874,
"narHash": "sha256-IKKIXTSYJMmUtE+Kav5Rob8SgLPnfnq4Qu8LyT4gdqQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ba8b70ee098bc5654c459d6a95dfc498b91ff858",
"type": "github"
},
"original": {
@ -511,11 +679,27 @@
},
"nixpkgs_7": {
"locked": {
"lastModified": 1746232882,
"narHash": "sha256-MHmBH2rS8KkRRdoU/feC/dKbdlMkcNkB5mwkuipVHeQ=",
"lastModified": 1743964447,
"narHash": "sha256-nEo1t3Q0F+0jQ36HJfbJtiRU4OI+/0jX/iITURKe3EE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7a2622e2c0dbad5c4493cb268aba12896e28b008",
"rev": "063dece00c5a77e4a0ea24e5e5a5bd75232806f8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_8": {
"locked": {
"lastModified": 1747327360,
"narHash": "sha256-LSmTbiq/nqZR9B2t4MRnWG7cb0KVNU70dB7RT4+wYK4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e06158e58f3adee28b139e9c2bcfcc41f8625b46",
"type": "github"
},
"original": {
@ -527,7 +711,7 @@
},
"phps": {
"inputs": {
"flake-compat": "flake-compat",
"flake-compat": "flake-compat_2",
"nixpkgs": "nixpkgs_6",
"utils": "utils"
},
@ -545,6 +729,33 @@
"type": "github"
}
},
"pre-commit-hooks-nix": {
"inputs": {
"flake-compat": [
"lanzaboote",
"flake-compat"
],
"gitignore": "gitignore",
"nixpkgs": [
"lanzaboote",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1731363552,
"narHash": "sha256-vFta1uHnD29VUY4HJOO/D6p6rxyObnf+InnSMT4jlMU=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "cd1af27aa85026ac759d5d3fccf650abe7e1bbf0",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"pyproject-build-systems": {
"inputs": {
"nixpkgs": [
@ -602,8 +813,10 @@
"forgesync": "forgesync",
"hardware": "hardware",
"hxwrap": "hxwrap",
"lanzaboote": "lanzaboote",
"musicomp": "musicomp",
"myphps": "myphps",
"nini": "nini",
"nix-index-database": "nix-index-database",
"nixos-cosmic": "nixos-cosmic",
"nixpkgs": [
@ -613,6 +826,27 @@
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"lanzaboote",
"nixpkgs"
]
},
"locked": {
"lastModified": 1731897198,
"narHash": "sha256-Ou7vLETSKwmE/HRQz4cImXXJBr/k9gp4J4z/PF8LzTE=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "0be641045af6d8666c11c2c40e45ffc9667839b5",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"rust-overlay_2": {
"inputs": {
"nixpkgs": [
"nixos-cosmic",
@ -620,11 +854,11 @@
]
},
"locked": {
"lastModified": 1746326315,
"narHash": "sha256-IDqSls/r6yBfdOBRSMQ/noTUoigmsKnTQ7TqpsBtN4Y=",
"lastModified": 1747449297,
"narHash": "sha256-veyXchTz6eWwvuW5X49UluHkheHkFcqHJSwGuKBhrmQ=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "dd280c436961ec5adccf0135efe5b66a23d84497",
"rev": "f44db7d7cea4528288780c6347756173a8248225",
"type": "github"
},
"original": {

View file

@ -16,11 +16,11 @@
hxwrap.url = "git+https://codeberg.org/helvetica/hxwrap.git";
myphps.url = "git+https://codeberg.org/helvetica/myphps.git";
forgesync.url = "git+https://codeberg.org/helvetica/forgesync.git";
nini.url = "git+https://codeberg.org/helvetica/nini.git";
lanzaboote = {
url = "github:nix-community/lanzaboote/v0.4.2";
inputs.nixpkgs.follows = "nixpkgs";
};
nixConfig = {
extra-substituters = "https://cosmic.cachix.org";
extra-trusted-public-keys = "cosmic.cachix.org-1:Dya9IyXD4xdBehWjrkPv6rtxpmMdRel02smYzA85dPE=";
};
outputs =

View file

@ -1,21 +1,26 @@
{
self,
config,
lib,
pkgs,
...
}:
let
virtualHostName = "forgejo.helveticanonstandard.net";
cfg = config.services.forgejo;
inherit (config.age) secrets;
in
{
age.secrets = lib.mkSecrets {
age.secrets = {
forgejo-mailer = {
file = self + /secrets/forgejo/mailer.age;
mode = "400";
owner = "forgejo";
owner = cfg.user;
};
forgejo-admin = {
file = self + /secrets/forgejo/admin.age;
mode = "400";
owner = "forgejo";
owner = cfg.user;
};
};
@ -24,10 +29,15 @@ in
package = pkgs.forgejo;
database.type = "postgres";
lfs.enable = true;
dump = {
enable = true;
interval = "*-*-* 02:00:00";
backupDir = "/srv/backup/forgejo";
};
settings = {
server = {
DOMAIN = virtualHostName;
ROOT_URL = "https://${virtualHostName}/";
DOMAIN = "forgejo.helveticanonstandard.net";
ROOT_URL = "https://${cfg.settings.server.DOMAIN}/";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 8060;
};
@ -51,18 +61,19 @@ in
};
};
secrets.mailer.PASSWD = config.age.secrets.forgejo-mailer.path;
secrets.mailer.PASSWD = secrets.forgejo-mailer.path;
};
# TODO what
systemd.services.forgejo.preStart = lib.getExe pkgs.writeShellApplication {
# TODO
systemd.services.forgejo.preStart = lib.getExe (
pkgs.writeShellApplication {
name = "forgejo-init-admin";
runtimeInputs = [
config.services.forgejo.package
cfg.package
];
text =
let
passwordFile = config.age.secrets.forgejo-admin.path;
passwordFile = secrets.forgejo-admin.path;
in
''
admins=$(admin user list --admin)
@ -76,9 +87,10 @@ in
--password "$(cat -- ${passwordFile})"
fi
'';
};
}
);
services.nginx.virtualHosts.${virtualHostName} = {
services.nginx.virtualHosts.${cfg.settings.server.DOMAIN} = {
enableACME = true;
forceSSL = true;
@ -88,8 +100,8 @@ in
locations."/".proxyPass =
let
host = config.services.forgejo.settings.server.HTTP_ADDR;
port = builtins.toString config.services.forgejo.settings.server.HTTP_PORT;
host = cfg.settings.server.HTTP_ADDR;
port = builtins.toString cfg.settings.server.HTTP_PORT;
in
"http://${host}:${port}";
};

View file

@ -10,6 +10,11 @@ in
Port = 8050;
MusicFolder = "/srv/music";
EnableSharing = true;
Backup = {
Path = "/srv/backup/navidrome";
Count = 1;
Schedule = "0 2 * * *";
};
};
};

View file

@ -7,7 +7,7 @@
domain = "wrz.one";
interfaces.${interface}.ipv6.addresses = [
{
address = "2a01:4f9:c012:92b5::2";
address = "2a01:4f8:c013:e64a::2";
prefixLength = 64;
}
];

View file

@ -1,3 +1,4 @@
{ config, ... }:
{
services.nginx = {
enable = true;
@ -23,7 +24,7 @@
default = true;
rejectSSL = true;
globalRedirect = "wrz.one";
globalRedirect = config.networking.domain;
};
# Redirect www to non-www
${matchWww}.globalRedirect = "$domain";

View file

@ -0,0 +1,3 @@
{
profiles.server.enable = true;
}

View file

@ -18,8 +18,9 @@ in
config.services.vaultwarden.backupDir
config.services.syncthing.dataDir
config.services.forgejo.stateDir
config.services.forgejo.dump.backupDir
config.services.postgresqlBackup.location
config.services.postgresqlBackup.location
config.services.navidrome.settings.Backup.Path
# TODO: Add stateDir options for these
"/var/lib/headscale"
"/var/lib/navidrome"

View file

@ -1,3 +1,3 @@
{
system.stateVersion = "24.11";
system.stateVersion = "25.05";
}

View file

@ -5,26 +5,20 @@
}:
let
virtualHostName = "vault.wrz.one";
backupDir = "/srv/backup/vaultwarden";
in
{
age.secrets = lib.mkSecrets { vaultwarden = { }; };
services.vaultwarden = {
enable = true;
dbBackend = "sqlite";
inherit backupDir;
backupDir = "/srv/backup/vaultwarden";
config = {
DOMAIN = "https://${virtualHostName}";
SIGNUPS_ALLOWED = false;
INVITATIONS_ALLOWED = false;
ENABLE_WEBSOCKET = true;
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8000;
};

View file

@ -0,0 +1,9 @@
{
profiles = {
desktop.enable = true;
emulation.enable = true;
gaming.enable = true;
piracy.enable = true;
productivity.enable = true;
};
}

View file

@ -27,7 +27,6 @@
kernelModules = [ "amdgpu" ];
};
kernelModules = [ "kvm-amd" ];
binfmt.emulatedSystems = [ "aarch64-linux" ];
};
powerManagement.cpuFreqGovernor = "performance";

View file

@ -1,9 +1,9 @@
{
profiles = {
desktop = true;
emulation = true;
gaming = true;
piracy = true;
productivity = true;
desktop.enable = true;
emulation.enable = true;
gaming.enable = true;
piracy.enable = true;
productivity.enable = true;
};
}

View file

@ -0,0 +1,9 @@
{
profiles = {
desktop.enable = true;
emulation.enable = true;
gaming.enable = true;
piracy.enable = true;
productivity.enable = true;
};
}

View file

@ -1,22 +1,29 @@
{
boot.initrd.luks.devices = {
main.device = "/dev/disk/by-label/cryptmain";
vault.device = "/dev/disk/by-label/cryptvault";
void.device = "/dev/disk/by-label/cryptvoid";
sync.device = "/dev/disk/by-label/cryptsync";
};
fileSystems = {
"/" = {
label = "white";
device = "/dev/mapper/main";
fsType = "ext4";
options = [ "noatime" ];
};
"/srv/vault" = {
label = "black";
device = "/dev/mapper/vault";
fsType = "ext4";
options = [ "noatime" ];
};
"/srv/void" = {
label = "green";
device = "/dev/mapper/void";
fsType = "ext4";
options = [ "noatime" ];
};
"/srv/sync" = {
label = "red";
device = "/dev/mapper/sync";
fsType = "ext4";
options = [ "noatime" ];
};

View file

@ -0,0 +1,3 @@
{
profiles.server.enable = true;
}

View file

@ -2,7 +2,6 @@
attrName,
config,
lib,
pkgs,
...
}:
let

6
hosts/work/profiles.nix Normal file
View file

@ -0,0 +1,6 @@
{
profiles = {
desktop.enable = true;
productivity.enable = true;
};
}

19
lib.nix
View file

@ -1,13 +1,13 @@
lib: _: {
findModules = paths:
builtins.concatMap (path:
findModules =
paths:
builtins.concatMap (
path:
lib.pipe path [
(lib.fileset.fileFilter (
file: file.hasExt "nix"
))
(lib.fileset.fileFilter (file: file.hasExt "nix"))
lib.fileset.toList
])
paths;
]
) paths;
mkIfElse =
condition: trueContent: falseContent:
@ -48,13 +48,12 @@ lib: _: {
attrName = name;
};
modules =
(lib.findModules [
modules = lib.findModules [
modulesDir
profilesDir
commonDir
(hostsDir + /${name})
]);
];
};
hosts = lib.pipe hostsDir [

View file

@ -13,6 +13,7 @@
description = ''
Public keys.
'';
readOnly = true;
};
config.pubkeys = lib.mkForce (import (self + /pubkeys.nix));

View file

@ -15,5 +15,5 @@ writeShellApplication {
dosfstools
];
text = builtins.readFile ./disk.bash;
text = builtins.readFile ./disk;
}

View file

@ -1,11 +0,0 @@
{
writeShellApplication,
nixos-rebuild,
}:
writeShellApplication {
name = "puter";
runtimeInputs = [
nixos-rebuild
];
text = builtins.readFile ./puter.bash;
}

View file

@ -1,192 +0,0 @@
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
progname=$0
warn() {
local line
for line in "$@"; do
echo "$progname: $line" 1>&2
done
}
error() {
warn "$@"
exit 1
}
args=$(
getopt \
--options F:f:o:t:v \
--longoptions flakeref:,flake:,on:,to:,verbose \
--name "$progname" \
-- "$@"
)
eval set -- "$args"
if [[ -v PUTER_FLAKEREF && -n $PUTER_FLAKEREF ]]; then
flakeref=$PUTER_FLAKEREF
fi
flags=(
--refresh
--use-remote-sudo
--no-write-lock-file
)
verbose=false
while true; do
case $1 in
-F | --flakeref)
flakeref=$2
shift 2
;;
-f | --flake)
flake=$2
shift 2
;;
-o | --on)
flags+=(--build-host "$2")
shift 2
;;
-t | --to)
host=$2
flags+=(--target-host "$host")
shift 2
;;
-v | --verbose)
flags+=(--verbose)
verbose=true
shift
;;
--)
shift
break
;;
esac
done
if [[ ! -v flake ]]; then
if [[ -v flakeref ]]; then
warn "using flake reference $flakeref"
if [[ -v host ]]; then
hostname=$(ssh -- "$host" hostname)
else
hostname=$(hostname)
fi
if [[ -z $hostname ]]; then
error 'hostname could not be resolved and no flake specified'
fi
flake=$flakeref#$hostname
warn "resolved to $flake"
else
error 'no flake or flake reference specified'
fi
fi
flags+=(--flake "$flake")
if (($# == 0)); then
error 'a subcommand is required'
fi
run() {
cmd=(nixos-rebuild "${flags[@]}" "$@")
if "$verbose"; then
warn "running ${cmd[*]}"
fi
"${cmd[@]}"
}
sub=$1
case $sub in
s | switch)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run switch
;;
b | boot)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run boot
;;
t | test)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run test
;;
bld | build)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run build
;;
dbld | dry-build)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run dry-build
;;
da | dry-activate)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run dry-activate
;;
vm | build-vm)
shift
if (($# > 0)); then
error 'too many arguments'
fi
run build-vm
;;
i | img | build-image)
shift
if (($# < 1)); then
error 'image variant is required'
fi
if (($# > 1)); then
error 'too many arguments'
fi
variant=$1
flags+=("$variant")
run build-image
;;
*)
error 'invalid subcommand'
;;
esac

View file

@ -7,23 +7,12 @@ in
enable = lib.mkEnableOption "desktop";
};
# imports = lib.optionals cfg.enable (lib.findModules {} [./profile]);
config = lib.mkIf cfg.enable {
imports = lib.findModules { } [ ./profile ];
assertions = [
{
assertion = config.profiles.server.enable == false;
assertion = !config.profiles.server.enable;
message = "The desktop profile is not compatible with the server profile.";
}
];
};
# config.assertions = lib.mkIf cfg.enable [
# {
# assertion = config.profiles.server.enable == false;
# message = "The desktop profile is not compatible with the server profile.";
# }
# ];
}

View file

@ -7,8 +7,6 @@ in
enable = lib.mkEnableOption "gaming";
};
imports = lib.optionals cfg.enable (lib.findModules { } [ ./profile ]);
config.assertions = lib.mkIf cfg.enable [
{
assertion = config.profiles.desktop.enable;

View file

@ -1,3 +1,18 @@
{ config, lib, ... }:
let
cfg = config.profiles.server;
in
{
options.profiles.server = {
enable = lib.mkEnableOption "server";
};
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = !config.profiles.desktop.enable;
message = "The server profile is not compatible with the desktop profile.";
}
];
};
}

View file

@ -1,12 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw 1eOoURN0W33AUbKglRCVBNzW3RMTyLIwWMRdI/n0iHI
cE0GpXpRyHqxXotqgvEvYYue05yASNmKpPS7QDadVOQ
-> ssh-ed25519 S+dwQQ YAhXTqFh18wXzQ02TUvfZJvYdyCZcNufvNTJ7ZjByGk
T3bb0jOs9SL1/5cmsHbYrxYsW4DBOXWN3Bc93/bQ+c4
-> ssh-ed25519 bPbvlw isx3ppsjOWxJgp6w7m1+a1W5DsMWSrYmcwD/I7kfREY
zZBV0iGYfF5kRdwnXzeUYCaNxrDAFn97072kg2d6uaM
-> ssh-ed25519 ffmsLw K6sD34XppM8mIaFAB4h43J8miednzvR4W9KUczc0Hk0
pxOWAsf24bCVDTXeLgayKgqWB512Dzx/1+Gx17RT31I
--- JvtcFW8QYtA1PViXec9je99Shc/KVbACsvDZEfBV5kU
D2ǵ,j¬q«˙íˇŞŢ¤ 7L­Ü­
ĄˇµfGQľë4ŃS ËgŞá«<C3A1>·

View file

@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw rEjkYPlPge7UMzbYwPwH80iWaQqIhPHwq9UKpF1LdEE
hn+knYiTYUTobUnAx50E6S7kAwzOhJC3aTXp7tB6kVs
-> ssh-ed25519 S+dwQQ JHScT9expJ30xkXY/QZZs6fttyiUz81+xCnt4FCyLQs
m1OykPIXU1WI/7rL/0AroNBp1alYCo7PsmKn6dMjiTM
-> ssh-ed25519 bPbvlw IFnxf/jKXZptRpEY7F00agI3yEbztWL8jf8WK03bZ3U
djSqXIYLK+puHMUtVG2EOQyc1mwFRxUshkDPSNWVhkE
-> ssh-ed25519 ffmsLw S325emLg33EycUbKCVzD8nLYbVOrQoOhnW5HnJXATC4
IKBSnzg1BaHYtJhVc8FliY1XVB7P46GsuW/ffeuEa74
--- QK8UE0WcbtpaBKOZJ/X9n+ZH9Uq1i+y2axyX+zjosXY
G*9ßËk5åƒ>Ù\™Šu{<7B>ÃÅ<C383>ýáj<C2†ø~¢Ó<C2A2>„CÑZÅú:e

11
secrets/forgejo/admin.age Normal file
View file

@ -0,0 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw /Rn9mDfrW6WXvk2rHnvFRikKPKjytoZSxr7nIHfaYBQ
dk43RULffWoNdpcyg46PYoyp4+Se/P7hKOq9dlYKHQs
-> ssh-ed25519 S+dwQQ j6cPjS+jTJZ3vX3RtBgcdHDNYUpwHaK470znK3t2PAU
3x9YctUrApvED+9Z8RXRzYbYvzmWcY6OLySDViAAruY
-> ssh-ed25519 bPbvlw wLrlOsWNEhfkJS08IVvIRbuadsZj/mw+J3PmH9dlD1c
FZ2U3gdU2Y9LqCiQ1mz7beYSPyNY3tIEbsPGVfMjmHM
-> ssh-ed25519 ffmsLw aCodb4aiUqIlMGzR7YwQDb8eQh1BHvmUeQAcOaT7fgo
KxSrylhmv3aylhqUp4j9dO/z5judvI5CeRDXE0XqbyE
--- 3tsgl8nyTeB1+YqslwzwdENX1QbP47GZG4EbRPKy8r8
êqJI¨ä÷h£Œ .äHÍóû'àéOöÍ-èOb¦õá½ÙË_s6„ò ”Ö·¿¶

View file

@ -0,0 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw 6hEwUxHZ7YxTRZGxM+pGfKKtpt0KUME5onbtQqHdsxk
zUEng+GntP/LGygdZTPCsFK9Vmn++VODWR0lWCuC0kQ
-> ssh-ed25519 S+dwQQ eznFi6oeKUpS1VmkK3cVjcRFF3zI6o9zzFkukj1X6lY
KApBmW4r4AQwqv6DrBg8I4x2TCUjgGOzHOfsLP5NDx4
-> ssh-ed25519 bPbvlw 86J2AsTVgm3GAbLmlOi5n73b8qgHxsIlDZKtM96zcQo
SYR28elHJA6Z0NCo90bZVQvixpKGTWmeafqr0CrLhcM
-> ssh-ed25519 ffmsLw LdxVlRNsqwSZc0qXWC7N+q69PTIXY0q49upfuEk5GwM
Z73ga/GtcdDUgAWRteHat0gmtISjTbVvzjUaugtYwCY
--- D065LOfAd9xDAc2QMAmEZQeduBgIaYtpC/W/wgcwY7Q
½R~ˆÁØZåžJ¥wjÊø]°™ñ²1Ì~À«É9„ò¡QøûÃV²žm

Binary file not shown.

View file

@ -1,11 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw IS1zLmLNl5l0+IJoZObLSKzjg12V9hPCYOuD0ZJphk8
FipqdCWVqXZ9RdNPXUnyqM8xvktCbjUHyAbh8GRLLg0
-> ssh-ed25519 S+dwQQ 0oWHsd3MryyksSbUZEWdFw8kyLPaxko1bMUWbmSxlyM
xgu+2woj3pIRHcR3XasLaiMZqs2uj3VoDh8da9GQADs
-> ssh-ed25519 bPbvlw JwdTUP9poe45VREZKqDcqmM4Sgr8BMB3CrTw6rS+VFI
WWkM2uC2uovhB5ZkQVQ4xnNKhY3B+2Lus+3Qd+SZFKE
-> ssh-ed25519 Sm0lOA Nu0x8ec0G7N9Tc1JNRGzHWCCUIY9zUanTOgfZfxrUTQ
iueKqGbDunTkpgVsymj6yc7t7J1yhvg1ug0PJHRCyX4
--- 2ZAyA0YLFKg9DgbtmN4TVJPc6dLhrvu8UJMR0+DZItc
Ž<0E>Ê¡;Ö*Ô(KÙ7öG©Žy©,‰ï®°5˜dK>õ6ü”g“§
-> ssh-ed25519 SFHVrw nyWvoLnNXzbxV3pKyVFIJIdzO1WOCHThAEKe0dyDxgM
N6t8SrPsvLrIRG4iu9896ZN8Ebzez7/pLC4RnS1ZEhs
-> ssh-ed25519 S+dwQQ UPHt9CTJmM9VvubDx5XSnTusm4oSyq+/A2R5FLYKbj4
n5wDmZwRmyjunS7njesVc0PZKhC51x5xqDlrD/9d1VE
-> ssh-ed25519 bPbvlw /2b8HRR2KzTiiVQKxN82oQ8PqVcRKEJ6hwNfMhFaf2I
1cDwbIcK9VI65Rb84wN87SdkyVP357+WrKk04PfXNhU
-> ssh-ed25519 Sm0lOA LZ2gX5nnMF3xbo/dhGQa6Ms5ifheF4ulag8mKJp6YEs
atOPulZBoi5Xf2uJ+bAXVo3I+XIitkaFM6eoMa7oqwo
--- R15O8zIkvnQHp0FOz24YB0DPOaPWfkt3G4GbBs+lY2o
¹ÝÖV7]6¿ c”: ¤D“°*@z%M3Ô=å\B§Ò ÁŒZ¦´Û%2k¥»

View file

@ -3,19 +3,21 @@ let
inherit (pubkeys) users hosts;
in
{
"user-helvetica.age".publicKeys =
"users/helvetica.age".publicKeys =
(builtins.attrValues users) ++ (builtins.attrValues (builtins.removeAttrs hosts [ "insomniac" ]));
"user-insomniac.age".publicKeys = (builtins.attrValues users) ++ [ hosts.insomniac ];
"miniflux.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"users/insomniac.age".publicKeys = (builtins.attrValues users) ++ [ hosts.insomniac ];
"vaultwarden.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"forgejo-mailer.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"forgejo-admin.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"forgejo/mailer.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"forgejo/admin.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"restic-vessel.age".publicKeys = (builtins.attrValues users) ++ [ hosts.vessel ];
"restic-abacus.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"syncserver.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"secure-boot/glacier.tar.age".publicKeys = (builtins.attrValues users) ++ [ hosts.glacier ];
"secure-boot/abacus.tar.age".publicKeys = (builtins.attrValues users) ++ [ hosts.abacus ];
"secure-boot/flamingo.tar.age".publicKeys = (builtins.attrValues users) ++ [ hosts.flamingo ];
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,11 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw 5jjXKCP1LHhUGYyri1g04ZvmJCT3oaHKv3rrX17w2gc
7WncrC6u6edUne4VQGZb/9EnNsL4JRQ/7egfViuclpE
-> ssh-ed25519 S+dwQQ KwH9DQOT0uLanFKUkbppGIX9Q5aDjjZZYO7gsF19K0c
ese8sLUSS8c5FgMRITavOj6bqPWV0M3/zOnbyaSj6as
-> ssh-ed25519 bPbvlw ufEzOz5vppSomacvWoMe/RAKm6GKPNMjnGbhLpuID3o
HKh4+nBARw8pHhl1+p+hwdvXY+wG4448pnUarQp12rE
-> ssh-ed25519 8l76Rg dMN8haWgW3i0EXv2ki8EySvdGVTQ36b6JKC4zSRNWmA
6hoVTll3E8cYkRM1gNV4OU65dcYS/Ufy58xNOgppms8
--- jYMZqNR10eeeo2aUlSWM02A10ykvDB7mr+DZf7JxdDk
- /ezG`[(¿€¡K;~BŠUUZ½K|ÓHnéeÝÙ_“iÇVO§?œÿˆ-4Š5Ãw‡7¾Õ±ìQ7 /|&h÷rÐ(}¬ú—þO¯†L°C¥È(⬌hW5

Binary file not shown.

View file

@ -0,0 +1,20 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw 5O32JjIL6EnnFpSEWuqYSnlQXCi86TjEGU5hKxEVfUk
mnI5nBEyM/M4hiOEl0lBdBt0v4cthrIlnWd6kvgud5s
-> ssh-ed25519 S+dwQQ bOtKQWynZxYPRukkGBVJ8p6d7mU6J1LxDc7RbxRjxn8
ykEExNA0KIXWRS0oAME7c6lScb7P5PR6rcoao35dd6s
-> ssh-ed25519 bPbvlw mBeVkAPVjuPyiGZoWTtU9cZEJ7DjT06wS7+BbK8xrlY
l5yxGa/CH2pM6IL6SeWgtQg/nJvcU6vLZQp9f10eQCg
-> ssh-ed25519 ffmsLw LqpIMiGZF5DZwibH8hJD8V8yJfpaRddJRxFC+MWqaQQ
1mGrkOKPZ7ZOQ/kwHA0VigU9DUY8SYTxRiq5tZnaWqk
-> ssh-ed25519 d2fKsw L8PpoPH43jKLkC8tduV2ILAypnwfGP2eJUTjX5foLzs
/Hu7tHtq9m4MYV6K48KDk68HWJzzCCr1DL7dKCyvndo
-> ssh-ed25519 US6ATA XqSHAd4tAGQgfD5zZUgGi85F4WX3Uz3K72ZbSf1b7lI
EYfjkYeoG7fvskrKdUnp/Yz713QfF2Wb+zZyXC/0pHc
-> ssh-ed25519 Sm0lOA UTaaX0IZkosP/zU1s1a1ExcD0Y3lgru+RoAZq4vjaRY
CLFv9o3r3R5RFFlkglmvKQ0S1ROY6VI9yvMO43YjZf8
-> ssh-ed25519 bgFypQ 6YB0i3QUbaAbTim7e+KSBYUUCRLCbrE+Tg9iW8MG/Uw
EN/o6IgKLUjsNkCNfEeThJZWEmglRis3yWTVWkq0ATg
--- 6oBNTwtiKyo7lhARYSWj1t3pudr+m5ESdA95+Ij3orc
6TÃB—ä#ì§êgXš¼4QUçê¸ýª‰Júö˜V€(´éÙ32ZõÉŸD縪 Àª§/Û&9
<±ÜW<C39C>»®á÷\cmRsy”tŸ4Àp'èƒ/DÐPw4æ:ëçÖ×nš%"™3k3$䀫±!ˆ¼~¼IAo¿Ä¢™Ut*µ7ÙÖó]<5D>

View file

@ -0,0 +1,14 @@
age-encryption.org/v1
-> ssh-ed25519 SFHVrw iq1lz1cbf7HgkH5Iglb9j9JChuJQALY3JPltoh0DcR4
xHJ4UsmFymFb7f5mGR6Yj8GGqKQRmD8YLdqYv8wxJMU
-> ssh-ed25519 S+dwQQ wKenvkV4uWqPHN4PNBZ+hQhmtQwULS/Vft6UDYmeKhs
G6fLhpl3K4S/JREeUBnIPs+XOj1BO0S2pAhrOPeQSvI
-> ssh-ed25519 bPbvlw GRzNM9ZIwICpUEjEVl+3Sk4jBKTQ8LxmqLAyaILTUHU
2RLJirofLXeDyvYijMwW5VbDSq6a0iZpCZU7WYtvgFE
-> ssh-ed25519 8l76Rg KReunAJWnHAVMs6Se2MvkWtsnHJwyZA1ZXExvxD93zE
xJUkcjqO33R728mU0dmhBnmF45ZkuxXtW0XgwVf74HA
--- aNnE3YE/Oe/IcRUDuoMNNBeaIcEtPfCpy69bZX8TQg8
éù}ÛÔ'C¼Æ=vTЄq¤²
Ób.ö²Y÷îä?ö<>—ï4êÜY”e¸¦5¸æÉÜ|ôþÓ°³¨7A]+3‰ÊñÊo¹2Ÿ
õ±•&'ü0˜¹ÁÌØ”â°ºUâ¾
˜x»ó

Binary file not shown.