initial(ish) commit

This commit is contained in:
Philipp Hochkamp 2022-03-01 23:53:11 +01:00
commit b744693f0e
No known key found for this signature in database
GPG key ID: 3676AB4CB36E5641
88 changed files with 4925 additions and 0 deletions

25
darwin-common.nix Normal file
View file

@ -0,0 +1,25 @@
{config, pkgs, ...}: {
programs.gnupg.agent.enable = true;
services.nix-daemon.enable = true;
nix.package = pkgs.nixFlakes;
nix.buildCores = 0; # use all cores
nix.maxJobs = 10; # use all cores
system.defaults = {
NSGlobalDomain.AppleShowAllExtensions = true;
NSGlobalDomain.InitialKeyRepeat = 25;
NSGlobalDomain.KeyRepeat = 4;
NSGlobalDomain.NSNavPanelExpandedStateForSaveMode = true;
NSGlobalDomain.PMPrintingExpandedStateForPrint = true;
NSGlobalDomain."com.apple.mouse.tapBehavior" = 1;
NSGlobalDomain."com.apple.trackpad.trackpadCornerClickBehavior" = 1;
dock.autohide = true;
dock.mru-spaces = false;
dock.show-recents = false;
dock.static-only = true;
finder.AppleShowAllExtensions = true;
finder.FXEnableExtensionChangeWarning = false;
loginwindow.GuestEnabled = false;
};
}

31
data/monitoring.toml Normal file
View file

@ -0,0 +1,31 @@
[master]
hostname = "ds9"
ip = "10.0.0.2"
[hostOverrides]
wormhole = "10.0.0.1"
picard = "ragon.xyz"
[exporters.nginx]
hosts = [
"ds9",
"wormhole"
]
[exporters.node]
hosts = [ "ds9", "wormhole" ]
[exporters.smartctl]
hosts = [ "ds9" ]
[exporters.dnsmasq]
hosts = [ "wormhole" ]
[exporters.wireguard]
hosts = [ "wormhole"]
[exporters.smokeping]
hosts = [ "wormhole"]
[promtail]
hosts = [ "wormhole", "ds9" ]

26
data/pubkeys.nix Normal file
View file

@ -0,0 +1,26 @@
let
ragon =
let
user = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEJwOH1b6xWmEr1VZh48kBIYhW11vtPFR3my8stAHlSi" # saurier
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIuwQJY0H/fdu1UmGXAut7VfcvAk2Dm78tJpkyyv2in2" # daedalus
];
server = user ++ hosts.ds9 ++ hosts.wormhole ++ hosts.picard ++ hosts.octopi;
client = user ++ hosts.enterprise ++ hosts.voyager;
hosts = {
wormhole = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINzR5dq/2UosH3nLrc9PvJi3rzX917K2wICeOUAiDnl6" ];
daedalusvm = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL9gTeFNEO+Puf8j0rxq0qyR+OgH0eSqDYBR20aACkpP" ];
ds9 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ+BBXufXAJhyUHVfhqlk8Y4zEKJbKXgJQvsdE482lpV" ];
picard = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAm3UXZaN95WBUaS9SiHLNEuI1tP1x1w07qnYxPe+vdr" ];
};
in
{
inherit user server client;
computers = user ++ (builtins.foldl' (a: b: a ++ b) [ ] (builtins.attrValues hosts)); # everything
host = hn: (hosts.${hn} ++ user);
hosts = hn: ((map (x: hosts.${x}) hn) ++ user);
};
in
{
inherit ragon;
}

417
flake.lock generated Normal file
View file

@ -0,0 +1,417 @@
{
"nodes": {
"agenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1646105662,
"narHash": "sha256-jdXCZbGZL0SWWi29GnAOFHUh/QvvP0IyaVLv1ZTDkBI=",
"owner": "ryantm",
"repo": "agenix",
"rev": "297cd58b418249240b9f1f155d52b1b17f292884",
"type": "github"
},
"original": {
"owner": "ryantm",
"ref": "main",
"repo": "agenix",
"type": "github"
}
},
"agkozak-zsh-prompt": {
"flake": false,
"locked": {
"lastModified": 1636940431,
"narHash": "sha256-II7+pwMpXPB3MhYScALZcs/28CPQltEt1FCwen7CxSE=",
"owner": "agkozak",
"repo": "agkozak-zsh-prompt",
"rev": "87ea6db9375032a6a26496a7f4a6266804f6929a",
"type": "github"
},
"original": {
"owner": "agkozak",
"repo": "agkozak-zsh-prompt",
"type": "github"
}
},
"coc-nvim": {
"flake": false,
"locked": {
"lastModified": 1646003439,
"narHash": "sha256-9YYILWjYyEaNJPePkqEhBGlTPZ79zFb/p94TPlbq3pQ=",
"owner": "neoclide",
"repo": "coc.nvim",
"rev": "f1a027298cb58b8ddf12ff1193b9e2706b4909a2",
"type": "github"
},
"original": {
"owner": "neoclide",
"ref": "release",
"repo": "coc.nvim",
"type": "github"
}
},
"dart-vim": {
"flake": false,
"locked": {
"lastModified": 1643154552,
"narHash": "sha256-f4h4nWbAm6wL7c6gCVRvyXvzGwj0I4PAij579RoFitI=",
"owner": "dart-lang",
"repo": "dart-vim-plugin",
"rev": "42e6f57f2404b882cb7e491d50e525f8a8eb7f1f",
"type": "github"
},
"original": {
"owner": "dart-lang",
"ref": "master",
"repo": "dart-vim-plugin",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1645293039,
"narHash": "sha256-PwdDu+SkX8dreeuJ/4av1sEluNZdrpdXv8JsRKKg1Yc=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "1df878b6f8351795a3bebfbe4fd2d02e1e8b29d6",
"type": "github"
},
"original": {
"owner": "lnl7",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1641205782,
"narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1629481132,
"narHash": "sha256-JHgasjPR0/J1J3DRm4KxM4zTyAj4IOJY8vIl75v/kPI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "997f7efcb746a9c140ce1f13c72263189225f482",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1645970334,
"narHash": "sha256-6nn4YF9bPtkxkB7bM6yJO3m//p3sGilxNQFjm1epLEM=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "ea85f4b1fdf3f25cf97dc49f4a9ec4eafda2ea25",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"impermanence": {
"locked": {
"lastModified": 1644791231,
"narHash": "sha256-iDihsF1fUMK4xXiUudPnDM3veH1LXbbxfP9Lzekw9iU=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "635bcd2d88739197a0b584aa9fadaa53c717a853",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": [
"rnix-lsp",
"nixpkgs"
]
},
"locked": {
"lastModified": 1639947939,
"narHash": "sha256-pGsM8haJadVP80GFq4xhnSpNitYNQpaXk4cnA796Cso=",
"owner": "nix-community",
"repo": "naersk",
"rev": "2fc8ce9d3c025d59fee349c1f80be9785049d653",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"neovim-flake": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"neovim-nightly-overlay",
"nixpkgs"
]
},
"locked": {
"dir": "contrib",
"lastModified": 1646012280,
"narHash": "sha256-rgx3+Xkqm6E9oR1hXKmipyTmMQb8kyXEklDuHHplD/I=",
"owner": "neovim",
"repo": "neovim",
"rev": "e383543342db8e9dcf40f7d5237edeab29638880",
"type": "github"
},
"original": {
"dir": "contrib",
"owner": "neovim",
"repo": "neovim",
"type": "github"
}
},
"neovim-nightly-overlay": {
"inputs": {
"flake-compat": "flake-compat",
"neovim-flake": "neovim-flake",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1646036082,
"narHash": "sha256-dRTzOZszaNupxRUkEX11K4hzRCzcB2apNsyGx0WsmbU=",
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"rev": "c5d3b328cfe9c7414363f70d583dce6584a72251",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "neovim-nightly-overlay",
"type": "github"
}
},
"nixos-hardware": {
"locked": {
"lastModified": 1645855197,
"narHash": "sha256-0FvBpX/9n69vg+XgcMow0RIRYbTHav1uCbL9Xt9HvcA=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "c3c66f6db4ac74a59eb83d83e40c10046ebc0b8c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1645433236,
"narHash": "sha256-4va4MvJ076XyPp5h8sm5eMQvCrJ6yZAbBmyw95dGyw4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7f9b6e2babf232412682c09e57ed666d8f84ac2d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-master": {
"locked": {
"lastModified": 1646109749,
"narHash": "sha256-09nJZGDSoy+1LWX3AqjjQUJPpx9pYYhwOOI32sx7+Fg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "13e74fc7ff2f691da0791db67fe65930403b391d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
},
"nnn-vim": {
"flake": false,
"locked": {
"lastModified": 1641252513,
"narHash": "sha256-ZWvTTioLoA+/HXTghp1EH2PH4A0mLDLtqzPKGsGB+ZY=",
"owner": "mcchrish",
"repo": "nnn.vim",
"rev": "169951733371abd152d76d1ce65e2dd867156e2d",
"type": "github"
},
"original": {
"owner": "mcchrish",
"repo": "nnn.vim",
"type": "github"
}
},
"rnix-lsp": {
"inputs": {
"naersk": "naersk",
"nixpkgs": [
"nixpkgs"
],
"utils": "utils"
},
"locked": {
"lastModified": 1643586450,
"narHash": "sha256-BRIAc3+zavSlJPYSbov2n1W9/a4Iuh2swFPYRWjCm1g=",
"owner": "nix-community",
"repo": "rnix-lsp",
"rev": "41eb2f3366e3f351bf2563c2a7c46fd17e78dfe0",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "rnix-lsp",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"agkozak-zsh-prompt": "agkozak-zsh-prompt",
"coc-nvim": "coc-nvim",
"dart-vim": "dart-vim",
"darwin": "darwin",
"home-manager": "home-manager",
"impermanence": "impermanence",
"neovim-nightly-overlay": "neovim-nightly-overlay",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs",
"nixpkgs-master": "nixpkgs-master",
"nnn-vim": "nnn-vim",
"rnix-lsp": "rnix-lsp",
"utils": "utils_2",
"zsh-completions": "zsh-completions",
"zsh-syntax-highlighting": "zsh-syntax-highlighting",
"zsh-vim-mode": "zsh-vim-mode"
}
},
"utils": {
"locked": {
"lastModified": 1638122382,
"narHash": "sha256-sQzZzAbvKEqN9s0bzWuYmRaA03v40gaJ4+iL1LXjaeI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "74f7e4319258e287b0f9cb95426c9853b282730b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"utils_2": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"zsh-completions": {
"flake": false,
"locked": {
"lastModified": 1645684485,
"narHash": "sha256-4ny89Dlop6ZekKGcMHTSu9ltR2FP1Ymb8rhDS1cc1+M=",
"owner": "zsh-users",
"repo": "zsh-completions",
"rev": "6fbf5fc9a7033bc47d4c61b2d6b97fe0c74d9c45",
"type": "github"
},
"original": {
"owner": "zsh-users",
"repo": "zsh-completions",
"type": "github"
}
},
"zsh-syntax-highlighting": {
"flake": false,
"locked": {
"lastModified": 1645642093,
"narHash": "sha256-UqeK+xFcKMwdM62syL2xkV8jwkf/NWfubxOTtczWEwA=",
"owner": "zsh-users",
"repo": "zsh-syntax-highlighting",
"rev": "c5ce0014677a0f69a10b676b6038ad127f40c6b1",
"type": "github"
},
"original": {
"owner": "zsh-users",
"ref": "master",
"repo": "zsh-syntax-highlighting",
"type": "github"
}
},
"zsh-vim-mode": {
"flake": false,
"locked": {
"lastModified": 1616290526,
"narHash": "sha256-a+6EWMRY1c1HQpNtJf5InCzU7/RphZjimLdXIXbO6cQ=",
"owner": "softmoth",
"repo": "zsh-vim-mode",
"rev": "1f9953b7d6f2f0a8d2cb8e8977baa48278a31eab",
"type": "github"
},
"original": {
"owner": "softmoth",
"repo": "zsh-vim-mode",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

132
flake.nix Normal file
View file

@ -0,0 +1,132 @@
{
description = "ragons nix/nixos configs";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-master.url = "github:NixOS/nixpkgs/master";
agenix.url = "github:ryantm/agenix/main";
agenix.inputs.nixpkgs.follows = "nixpkgs";
home-manager.url = "github:nix-community/home-manager";
home-manager.inputs.nixpkgs.follows = "nixpkgs";
impermanence.url = "github:nix-community/impermanence";
impermanence.inputs.nixpkgs.follows = "nixpkgs";
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
darwin.url = "github:lnl7/nix-darwin/master";
darwin.inputs.nixpkgs.follows = "nixpkgs";
utils.url = "github:numtide/flake-utils";
## vim
neovim-nightly-overlay.url = "github:nix-community/neovim-nightly-overlay";
neovim-nightly-overlay.inputs.nixpkgs.follows = "nixpkgs";
coc-nvim.url = "github:neoclide/coc.nvim/release";
coc-nvim.flake = false;
nnn-vim.url = "github:mcchrish/nnn.vim";
nnn-vim.flake = false;
dart-vim.url = "github:dart-lang/dart-vim-plugin/master";
dart-vim.flake = false;
rnix-lsp.url = "github:nix-community/rnix-lsp";
rnix-lsp.inputs.nixpkgs.follows = "nixpkgs";
## zsh
zsh-completions.url = "github:zsh-users/zsh-completions";
zsh-completions.flake = false;
zsh-syntax-highlighting.url = "github:zsh-users/zsh-syntax-highlighting/master";
zsh-syntax-highlighting.flake = false;
zsh-vim-mode.url = "github:softmoth/zsh-vim-mode";
zsh-vim-mode.flake = false;
agkozak-zsh-prompt.url = "github:agkozak/agkozak-zsh-prompt";
agkozak-zsh-prompt.flake = false;
};
outputs = inputs @ { self, nixpkgs, nixpkgs-master, agenix, home-manager, impermanence, darwin, utils, neovim-nightly-overlay, ... }:
let
extraSystems = [ ];
lib = nixpkgs.lib.extend (self: super: {
my = import ./lib { inherit inputs; lib = self; };
});
genPkgs = system: import nixpkgs {
inherit system;
config.allowUnfree = true;
overlays = [
self.overlay
neovim-nightly-overlay.overlay
];
};
hmConfig = { pkgs, inputs, config, ...}: {
imports = lib.my.mapModulesRec' ./hm-imports (x: x);
};
nixosSystem = system: extraModules: let
pkgs = genPkgs system;
in nixpkgs.lib.nixosSystem
rec {
inherit system;
specialArgs = { inherit lib inputs pkgs system; };
modules = [
agenix.nixosModules.age
impermanence.nixosModules.impermanence
home-manager.nixosModules.home-manager
({ config, ...}: lib.mkMerge [{
system.configurationRevision = self.sourceInfo.rev;
services.getty.greetingLine =
"<<< Welcome to NixOS ${config.system.nixos.label} @ ${self.sourceInfo.rev} - \\l >>>";
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
}
(lib.mkIf (config.users.extraUsers.ragon != null) { # import hm stuff if enabled
home-manager.users.ragon = hmConfig;
})
])
./nixos-common.nix
] ++ self.nixosModules ++ extraModules;
};
darwinSystem = system: extraModules:
let
pkgs = genPkgs system;
in darwin.lib.darwinSystem
{
inherit system;
specialArgs = { inherit darwin lib pkgs inputs self; };
modules = [
home-manager.darwinModules.home-manager
({ config, inputs, self, ...}: lib.mkMerge [{
system.configurationRevision = (lib.traceVal (self.sourceInfo)).rev;
home-manager.useGlobalPkgs = true;
home-manager.useUserPackages = true;
home-manager.extraSpecialArgs = { inherit inputs; };
}
(lib.mkIf (config.users.extraUsers.ragon != null) { # import hm stuff if enabled
home-manager.users.ragon = hmConfig;
})
])
./darwin-common.nix
] ++ extraModules;
};
in
{
lib = lib.my;
overlay = final: prev: {
unstable = import nixpkgs-master {
system = prev.system;
config.allowUnfree = true;
};
my = self.packages."${prev.system}";
};
packages = [];
nixosModules = lib.my.mapModulesRec ./nixos-modules import;
darwinModules = [];
#darwinModules = lib.my.mapModulesRec ./darwin-modules import;
nixosConfigurations = {
picard = nixosSystem "x86-64-linux" [ ./hosts/picard/default.nix ]; # TODO
wormhole = nixosSystem "aarch64-linux" [ ./hosts/wormhole/default.nix ]; # TODO
ds9 = nixosSystem "x86-64-linux" [ ./hosts/ds9/default.nix ]; # TODO
};
darwinConfigurations = {
daedalus = darwinSystem "aarch64-darwin" [ ./hosts/daedalus/default.nix ]; # TODO
};
};
}

118
hm-imports/cli.nix Normal file
View file

@ -0,0 +1,118 @@
{ inputs, config, lib, pkgs, ... }:
{
home.packages = with pkgs; [
nnn
bat
htop
exa
curl
fd
file
lorri
fzf
git
neofetch
ripgrep
direnv # needed for lorri
unzip
pv
killall
lefthook
yt-dlp
aria2
libqalculate
]
home.shellAliases = {
v = "nvim";
vim = "nvim";
gpl = "git pull";
gp = "git push";
lg = "lazygit";
gc = "git commit -v";
kb = "git commit -m \"\$(curl -s http://whatthecommit.com/index.txt)\"";
gs = "git status -v";
gfc = "git fetch && git checkout";
gl = "git log --graph";
l = "exa -la --git";
la = "exa -la --git";
ls = "exa";
ll = "exa -l --git";
cat = "bat";
};
programs = {
gpg = {
enable = true;
settings = {
cert-digest-algo = "SHA512";
charset = "utf-8";
default-preference-list = "SHA512 SHA384 SHA256 AES256 AES192 AES ZLIB BZIP2 ZIP Uncompressed";
fixed-list-mode = true;
keyserver = "hkps://keyserver.ubuntu.com:443";
list-options = [ "show-uid-validity" "show-unusable-subkeys" ];
no-comments = true;
no-emit-version = true;
no-greeting = true;
no-symkey-cache = true;
personal-cipher-preferences = "AES256 AES192 AES";
personal-compress-preferences = "ZLIB BZIP2 ZIP Uncompressed";
personal-digest-preferences = "SHA512 SHA384 SHA256";
require-cross-certification = true;
s2k-cipher-algo = "AES256";
s2k-digest-algo = "SHA512";
throw-keyids = true;
use-agent = true;
verbose = true;
verify-options = "show-uid-validity";
with-fingerprint = true;
with-key-origin = true;
};
};
bat = {
enable = true;
config.theme = "gruvbox-dark";
};
fzf = {
enable = true;
enableZshIntegration = true;
defaultOptions = [
"--height 40%"
"--layout=reverse"
"--border"
"--inline-info"
];
};
git = {
enable = true;
lfs.enable = true;
# Default configs
extraConfig = {
commit.gpgSign = true;
user.name = "Philipp Hochkamp";
user.email = "git@phochkamp.de";
user.signingKey = "DA5D9235BD5BD4BD6F4C2EA868066BFF4EA525F1";
# Set default "git pull" behaviour so it doesn't try to default to
# either "git fetch; git merge" (default) or "git fetch; git rebase".
pull.ff = "only";
};
};
# Htop configurations
htop = {
enable = true;
settings = {
hide_userland_threads = true;
highlight_base_name = true;
shadow_other_users = true;
show_program_path = false;
tree_view = false;
};
};
};
}

12
hm-imports/files.nix Normal file
View file

@ -0,0 +1,12 @@
{ inputs, config, lib, pkgs, ... }:
{
home.file = {
# Home nix config.
".config/nixpkgs/config.nix".text = "{ allowUnfree = true; }";
".local/share/pandoc/templates/default.latex".source = "${inputs.pandoc-latex-template}/eisvogel.tex";
# empty zshrc to stop zsh-newuser-install from running
".zshrc".text = "";
};
}

View file

@ -0,0 +1,51 @@
{
"suggest.triggerCompletionWait": 50,
"suggest.enablePreview": true,
"html.enable": true,
"python.linting.enabled": true,
"html.format.enable": true,
"html.suggest.html5": true,
"html.suggest.ionic": true,
"html.validate.html": true,
"html.validate.styles": true,
"diagnostic-languageserver.mergeConfig": true,
"diagnostic-languageserver.filetypes": {
"vim": "vint",
"sh": "shellcheck",
"markdown": "write-good"
},
"diagnostic-languageserver.formatFiletypes": {
"sh": "shfmt"
},
"tabnine.disable_filetypes": ["pandoc"],
"flutter.provider.hot-reload": true,
"flutter.provider.enableSnippet": true,
"snippets.ultisnips.direcories": ["snippets"],
"rust-analyzer.procMacro.enable": true,
"rust-analyzer.cargo.allFeatures": true,
"rust-analyzer.inlayHints.refreshOnInsertMode": true,
"rust-analyzer.updates.channel": "nightly",
"html.validate.scripts": true,
"git.gitlab.hosts": [
"gitlab.com"
],
"git.addGBlameToVirtualText": true,
"languageserver": {
"nix": {
"command": "rnix-lsp",
"filetypes": [
"nix"
]
},
"terraform": {
"command": "terraform-ls",
"args": ["serve"],
"filetypes": [
"terraform",
"tf"
],
"initializationOptions": {},
"settings": {}
}
}
}

View file

@ -0,0 +1,145 @@
if system('id -u') > 500
let g:coc_global_extensions = [ 'coc-markdownlint', 'coc-diagnostic', 'coc-angular', 'coc-css', 'coc-docker', 'coc-flutter-tools', 'coc-git', 'coc-homeassistant', 'coc-html', 'coc-json', 'coc-marketplace', 'coc-prettier', 'coc-pyright', 'coc-rls', 'coc-rust-analyzer', 'coc-scssmodules', 'coc-sh', 'coc-snippets', 'coc-stylelintplus', 'coc-swagger', 'coc-tabnine', 'coc-eslint', 'coc-tsserver', 'coc-webpack', 'coc-yaml' ]
endif
" \coc Some servers have issues with backup files, see #649.
set nobackup
set nowritebackup
" \coc Don't pass messages to |ins-completion-menu|.
set shortmess+=c
" \coc Always show the signcolumn, otherwise it would shift the text each time
" diagnostics appear/become resolved.
set signcolumn=number
function! s:check_back_space() abort
let col = col('.') - 1
return !col || getline('.')[col - 1] =~# '\s'
endfunction
" c-space to trigger completion
inoremap <silent><expr> <c-space> coc#refresh()
" Make <CR> auto-select the first completion item and notify coc.nvim to
" format on enter, <cr> could be remapped by other vim plugin
inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
" Use `[g` and `]g` to navigate diagnostics
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
nmap <silent> [g <Plug>(coc-diagnostic-prev)
nmap <silent> ]g <Plug>(coc-diagnostic-next)
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
" GoTo code navigation.
nmap <silent> gd <Plug>(coc-definition)
nmap <silent> gy <Plug>(coc-type-definition)
nmap <silent> gi <Plug>(coc-implementation)
nmap <silent> gr <Plug>(coc-references)
" Use K to show documentation in preview window.
nnoremap <silent> K :call <SID>show_documentation()<CR>
function! s:show_documentation()
if (index(['vim','help'], &filetype) >= 0)
execute 'h '.expand('<cword>')
elseif (coc#rpc#ready())
call CocActionAsync('doHover')
else
execute '!' . &keywordprg . " " . expand('<cword>')
endif
endfunction
" Highlight the symbol and its references when holding the cursor.
autocmd CursorHold * silent call CocActionAsync('highlight')
" Symbol renaming.
nmap <leader>rn <Plug>(coc-rename)
" coc snippets
" Use <C-l> for trigger snippet expand.
imap <C-l> <Plug>(coc-snippets-expand)
" Use <C-j> for select text for visual placeholder of snippet.
vmap <C-j> <Plug>(coc-snippets-select)
" Use <C-j> for jump to next placeholder, it's default of coc.nvim
let g:coc_snippet_next = '<c-j>'
" Use <C-k> for jump to previous placeholder, it's default of coc.nvim
let g:coc_snippet_prev = '<c-k>'
" Use <C-j> for both expand and jump (make expand higher priority.)
imap <C-j> <Plug>(coc-snippets-expand-jump)
" Use <leader>x for convert visual selected code to snippet
xmap <leader>x <Plug>(coc-convert-snippet)
" Formatting selected code.
xmap <leader>f <Plug>(coc-format-selected)
nmap <leader>f <Plug>(coc-format-selected)
augroup mygroup
autocmd!
" Setup formatexpr specified filetype(s).
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
" Update signature help on jump placeholder.
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
augroup end
" Applying codeAction to the selected region.
" Example: `<leader>aap` for current paragraph
xmap <leader>a <Plug>(coc-codeaction-selected)
nmap <leader>a <Plug>(coc-codeaction-selected)
" Remap keys for applying codeAction to the current buffer.
nmap <leader>ac <Plug>(coc-codeaction)
" Apply AutoFix to problem on the current line.
nmap <leader>qf <Plug>(coc-fix-current)
nmap <leader>f :CocFix<CR>
" Map function and class text objects
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
xmap if <Plug>(coc-funcobj-i)
omap if <Plug>(coc-funcobj-i)
xmap af <Plug>(coc-funcobj-a)
omap af <Plug>(coc-funcobj-a)
xmap ic <Plug>(coc-classobj-i)
omap ic <Plug>(coc-classobj-i)
xmap ac <Plug>(coc-classobj-a)
omap ac <Plug>(coc-classobj-a)
" Remap <C-f> and <C-b> for scroll float windows/popups.
nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
" Use CTRL-S for selections ranges.
" Requires 'textDocument/selectionRange' support of language server.
nmap <silent> <C-a> <Plug>(coc-range-select)
xmap <silent> <C-a> <Plug>(coc-range-select)
" Add `:Format` command to format current buffer.
command! -nargs=0 Format :call CocAction('format')
" Add `:Fold` command to fold current buffer.
command! -nargs=? Fold :call CocAction('fold', <f-args>)
" Add `:OR` command for organize imports of the current buffer.
command! -nargs=0 OR :call CocAction('runCommand', 'editor.action.organizeImport')
" Mappings for CoCList
" Show all diagnostics.
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
" Manage extensions.
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
" Show commands.
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
" Find symbol of current document.
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
" Search workspace symbols.
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
" Do default action for next item.
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
" Do default action for previous item.
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
" Resume latest coc list.
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>

View file

@ -0,0 +1,47 @@
require('utils')
require('keybindings')
require('filetypes')
local opt = vim.opt
-- load plugin luas (idk how to do that autmagically)
require('plugin.nnn')
require('plugin.rainbow')
require('plugin.terminal')
-- plugins - coc
vim.cmd 'source /etc/nvim/coc.vim' -- too lazy to convert all the shit to lua
-- terminal
vim.cmd 'source /etc/nvim/terminal.vim' -- too lazy to convert all the shit to lua
-- color stuff
vim.g.gruvbox_italic = 1
vim.cmd ':colorscheme gruvbox'
opt.termguicolors = true -- 24bit color
opt.background = 'dark' -- dark gruvbox
-- general settings
vim.cmd [[
filetype plugin on
filetype indent plugin on
filetype plugin indent on
syntax on
]]
opt.encoding = 'utf-8'
opt.number = true
opt.relativenumber = true
opt.undofile = true -- save undo chages even after computer restart
opt.showcmd = true -- show (partial) command in status line
opt.showmatch = true -- show match brackets
opt.wildmenu = true -- visual autocomplete for command menu
-- Splits open at the bottom and right, which is non-retarded, unlike vim defaults.
opt.splitbelow = true
opt.splitright = true
-- indents
opt.expandtab = true
opt.shiftwidth = 2
opt.softtabstop = 2
-- buffers don't get unloaded when hidden
opt.hidden = true
-- low updatetime so it isnt as slow
opt.updatetime = 200
require('plugin.lualine')

View file

@ -0,0 +1,3 @@
vim.cmd [[
autocmd FileType yaml setlocal ts=2 sts=2 sw=2 expandtab
]]

View file

@ -0,0 +1,45 @@
local map = require('utils').map
-- split binds
map { 'n', '<A-h>', ':vertical resize -5<CR>', noremap = true, silent = true}
map { 'n', '<A-l>', ':vertical resize +5<CR>', noremap = true, silent = true}
map { 'n', '<A-j>', ':resize -5<CR>', noremap = true, silent = true}
map { 'n', '<A-k>', ':resize +5<CR>', noremap = true, silent = true}
map { 'n', '<A-=>', '<C-w> =', noremap = true, silent = true}
map { 'n', '<A-s>', ':vsp<CR>', noremap = true, silent = true}
map { 'n', '<C-s>', ':split<CR>', noremap = true, silent = true}
map { 'n', '<C-h>', '<C-w>h', noremap = true, silent = true}
map { 'n', '<C-j>', '<C-w>j', noremap = true, silent = true}
map { 'n', '<C-k>', '<C-w>k', noremap = true, silent = true}
map { 'n', '<C-l>', '<C-w>l', noremap = true, silent = true}
-- buffer binds
map { 'n', ',q', ':bd<CR>', noremap = false, silent = true}
map { 'n', ',b', ':Buffers<CR>', noremap = false, silent = true}
-- tab binds
map { 'n', '<C-t>', ':tabnew<CR>', noremap = false, silent = true}
-- copy paste
map { 'v', '<C-c>', '"+y', noremap = true, silent = true}
map { 'n', '<C-b>', '"+P', noremap = false, silent = true}
map { 'n', '<C-p>', ':registers<CR>', noremap = true, silent = true}
-- sudo :w
map { 'c', 'w!!', 'w !sudo tee > /dev/null %', noremap = false, silent = false}
-- terminal
map { 'n', '<leader>t', ':term<CR>', noremap = false, silent = true}
map { 't', '<C-b>', '<C-\\><C-n>', noremap = true, silent = true}
-- plugins - commentary
map { 'n', '<leader>c', ':Commentary<CR>', noremap = false, silent = true}
-- plugins - vista
map { 'n', '<leader>v', ':Vista!!<CR>', noremap = false, silent = true}
-- plugins - nnn
map { 'n', '<tab>', '::NnnPicker %:p:h<CR>', noremap = true, silent = true}
-- plugins - terminal
map {"n", "<leader>l", "<cmd>lua _lazygit_toggle()<CR>", {noremap = true, silent = true}}

View file

@ -0,0 +1,28 @@
require('lualine').setup {
options = {
icons_enabled = true,
theme = 'gruvbox',
component_separators = { left = '', right = ''},
section_separators = { left = '', right = ''},
disabled_filetypes = {},
always_divide_middle = true,
},
sections = {
lualine_a = {'mode'},
lualine_b = {'branch', 'diff', 'diagnostics'},
lualine_c = {'filename'},
lualine_x = {'encoding', 'fileformat', 'filetype'},
lualine_y = {'progress'},
lualine_z = {'location'}
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = {'filename'},
lualine_x = {'location'},
lualine_y = {},
lualine_z = {}
},
tabline = {},
extensions = {}
}

View file

@ -0,0 +1,11 @@
require('nnn').setup({
set_default_mappings = 0,
replace_netrw = 1,
layout = {
window = {
width = 0.9,
height = 0.6,
highlight = 'Debug'
}
}
})

View file

@ -0,0 +1 @@
vim.g.rainbow_active = 1

View file

@ -0,0 +1,22 @@
require('toggleterm').setup {
direction = 'window',
open_mapping = [[<c-n>]],
}
local Terminal = require('toggleterm.terminal').Terminal
local lazygit = Terminal:new {
cmd = "lazygit",
hidden = true,
direction = 'float'
}
function _lazygit_toggle()
lazygit:toggle()
end
-- local pipeline = Terminal:new {
-- cmd = "glab ci view",
-- hidden = true,
-- direction = 'float'
-- }

View file

@ -0,0 +1,21 @@
-- cool map funciton from https://vonheikemen.github.io/devlog/tools/configuring-neovim-using-lua/
utils = {}
utils.map = function(key)
-- get the extra options
local opts = {noremap = false}
for i, v in pairs(key) do
if (i) == 'string' then opts[i] = v end
end
-- basic support for buffer-scoped keybindings
local buffer = opts.buffer
opts.buffer = nil
if buffer then
vim.api.nvim_buf_set_keymap(0, key[1], key[2], key[3], opts)
else
vim.api.nvim_set_keymap(key[1], key[2], key[3], opts)
end
end
return utils

View file

@ -0,0 +1,121 @@
# This file contains snippets that are always defined. I personally
# have snippets for signatures and often needed texts
# sligthly lower priority than everything else since specialized versions
# should overwrite. The user needs to adjust her priority in her snippets to
# ~-55 so that other filetypes will still overwrite.
priority -60
global !p
def _parse_comments(s):
""" Parses vim's comments option to extract comment format """
i = iter(s.split(","))
rv = []
try:
while True:
# get the flags and text of a comment part
flags, text = next(i).split(':', 1)
if len(flags) == 0:
rv.append(('OTHER', text, text, text, ""))
# parse 3-part comment, but ignore those with O flag
elif 's' in flags and 'O' not in flags:
ctriple = ["TRIPLE"]
indent = ""
if flags[-1] in string.digits:
indent = " " * int(flags[-1])
ctriple.append(text)
flags, text = next(i).split(':', 1)
assert flags[0] == 'm'
ctriple.append(text)
flags, text = next(i).split(':', 1)
assert flags[0] == 'e'
ctriple.append(text)
ctriple.append(indent)
rv.append(ctriple)
elif 'b' in flags:
if len(text) == 1:
rv.insert(0, ("SINGLE_CHAR", text, text, text, ""))
except StopIteration:
return rv
def get_comment_format():
""" Returns a 4-element tuple (first_line, middle_lines, end_line, indent)
representing the comment format for the current file.
It first looks at the 'commentstring', if that ends with %s, it uses that.
Otherwise it parses '&comments' and prefers single character comment
markers if there are any.
"""
commentstring = vim.eval("&commentstring")
if commentstring.endswith("%s"):
c = commentstring[:-2]
return (c, c, c, "")
comments = _parse_comments(vim.eval("&comments"))
for c in comments:
if c[0] == "SINGLE_CHAR":
return c[1:]
return comments[0][1:]
endglobal
##########################
# LOREM IPSUM GENERATORS #
##########################
snippet lorem "Lorem Ipsum - 50 Words" b
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit amet.
endsnippet
##########################
# VIM MODELINE GENERATOR #
##########################
# See advice on `:help 'tabstop'` for why these values are set. Uses second
# modeline form ('set') to work in languages with comment terminators
# (/* like C */).
snippet modeline "Vim modeline"
vim`!v ':set '. (&expandtab ? printf('et sw=%i ts=%i', &sw, &ts) : printf('noet sts=%i sw=%i ts=%i', &sts, &sw, &ts)) . (&tw ? ' tw='. &tw : '') . ':'`
endsnippet
#########
# DATES #
#########
snippet date "YYYY-MM-DD" w
`!v strftime("%Y-%m-%d")`
endsnippet
snippet ddate "DD.MM.YYYY" w
`!v strftime("%d.%m.%Y")`
endsnippet
snippet diso "ISO format datetime" w
`!v strftime("%Y-%m-%d %H:%M:%S%z")`
endsnippet
snippet time "hh:mm" w
`!v strftime("%H:%M")`
endsnippet
snippet datetime "YYYY-MM-DD hh:mm" w
`!v strftime("%Y-%m-%d %H:%M")`
endsnippet
snippet todo "TODO comment" bw
`!p snip.rv=get_comment_format()[0]` ${2:TODO}: $1 ${3: <${4:`!v strftime('%d.%m.%y %H:%M')`}${5:, `git config --get user.name`}>} `!p snip.rv=get_comment_format()[2]`
endsnippet
##########
# Misc #
##########
snippet uuid "Random UUID" w
`!p if not snip.c: import uuid; snip.rv = uuid.uuid4()`
endsnippet
# vim:ft=snippets:

View file

@ -0,0 +1,115 @@
# Snippets for Go
priority -50
# when to abbriviate and when not?
# b doesn't work here, because it ignores whitespace
# optional local name?
snippet /^import/ "Import declaration" r
import (
"${1:package}"
)
endsnippet
snippet /^package/ "Package declaration" r
// Package $1 provides ...
package ${1:main}
endsnippet
# Mostly converted from: https://github.com/AlanQuatermain/go-tmbundle
snippet /^cons/ "Constants declaration" r
const (
${1:constant}${2/(.+)/ /}${2:type} = ${0:value}
)
endsnippet
snippet /^con/ "Constant declaration" r
const ${1:name}${2/(.+)/ /}${2:type} = ${0:value}
endsnippet
snippet iota "Iota constant generator" b
const (
${1:constant}${2/(.+)/ /}${2:type} = iota
)
endsnippet
snippet struct "Struct declaration" b
type ${1:Struct} struct {
${0:${VISUAL}}
}
endsnippet
snippet interface "Interface declaration" b
type ${1:Interface} interface {
${0:${VISUAL}}
}
endsnippet
snippet if "If statement" b
if ${1:condition}${1/(.+)/ /}{
${0:${VISUAL}}
}
endsnippet
snippet switch "Switch statement" b
switch ${1:expression}${1/(.+)/ /}{
case$0
}
endsnippet
# functions
snippet /^main/ "Main function" r
func main() {
${0:${VISUAL}}
}
endsnippet
snippet /^meth/ "Method" r
func (${1:receiver} ${2:type}) ${3:name}(${4:params})${5/(.+)/ /}${5:type} {
${0:${VISUAL}}
}
endsnippet
snippet func "Function" b
func ${1:name}(${2:params})${3/(.+)/ /}${3:type} {
${0:${VISUAL}}
}
endsnippet
snippet funch "HTTP handler" b
func ${1:handler}(${2:w} http.ResponseWriter, ${3:r} *http.Request) {
${0:${VISUAL}}
}
endsnippet
# types and variables
snippet map "Map type" b
map[${1:keytype}]${2:valtype}
endsnippet
snippet : "Variable declaration :=" b
${1:name} := ${0:value}
endsnippet
snippet var "Variable declaration" b
var ${1:name}${2/(.+)/ /}${2:type}${3: = ${0:value}}
endsnippet
snippet vars "Variables declaration" b
var (
${1:name}${2/(.+)/ /}${2:type}${3: = ${0:value} }
)
endsnippet
snippet json "JSON field"
\`json:"${1:displayName}"\`
endsnippet
# vim:ft=snippets:
# error handling
snippet err "Basic error handling" b
if err != nil {
log.${1:Fatal}(err)
}
endsnippet

View file

@ -0,0 +1,399 @@
###########################################################################
# TEXTMATE SNIPPETS #
###########################################################################
# Many of the snippets here use a global option called
# "g:ultisnips_java_brace_style" which, if set to "nl" will put a newline
# before '{' braces.
global !p
def junit(snip):
if snip.opt("g:ultisnips_java_junit", "") == "3":
snip += ""
else:
snip.rv += "@Test\n\t"
def nl(snip):
if snip.opt("g:ultisnips_java_brace_style", "") == "nl":
snip += ""
else:
snip.rv += " "
def getArgs(group):
import re
word = re.compile('[a-zA-Z><.]+ \w+')
return [i.split(" ") for i in word.findall(group) ]
def camel(word):
return word[0].upper() + word[1:]
endglobal
snippet sleep "try sleep catch" !b
try {
Thread.sleep(${1:1000});
} catch (InterruptedException e){
e.printStackTrace();
}
endsnippet
snippet /i|n/ "new primitive or int" !br
${1:int} ${2:i} = ${3:1};
$0
endsnippet
snippet /o|v/ "new Object or variable" !br
${1:Object} ${2:var} = new $1(${3});
endsnippet
snippet f "field" !b
${1:private} ${2:String} ${3:`!p snip.rv = t[2].lower()`};
endsnippet
snippet ab "abstract" b
abstract
endsnippet
snippet as "assert" b
assert ${1:test}${2/(.+)/(?1: \: ")/}${2:Failure message}${2/(.+)/(?1:")/};$0
endsnippet
snippet at "assert true" !b
assertTrue(${1:actual});
endsnippet
snippet af "assert false" !b
assertFalse(${1:actual});$0
endsnippet
snippet ae "assert equals" !b
assertEquals(${1:expected}, ${2:actual});
endsnippet
snippet br "break"
break;
endsnippet
snippet cs "case" b
case $1:
$2
$0
endsnippet
snippet ca "catch" b
catch (${1:Exception} ${2:e})`!p nl(snip)`{
$0
}
endsnippet
snippet cle "class extends" b
public class ${1:`!p
snip.rv = snip.basename or "untitled"`} ${2:extends ${3:Parent} }${4:implements ${5:Interface} }{
$0
}
endsnippet
snippet clc "class with constructor, fields, setter and getters"
public class `!p
snip.rv = snip.basename or "untitled"` {
`!p
import re
args = getArgs(t[1])
if len(args) == 0: snip.rv = ""
for i in args:
snip.rv += "\n\tprivate " + i[0] + " " + i[1]+ ";"
if len(args) > 0:
snip.rv += "\n"`
public `!p snip.rv = snip.basename or "unknown"`($1) { `!p
args = getArgs(t[1])
for i in args:
snip.rv += "\n\t\tthis." + i[1] + " = " + i[1] + ";"
if len(args) == 0:
snip.rv += "\n"`
}$0
`!p
args = getArgs(t[1])
if len(args) == 0: snip.rv = ""
for i in args:
snip.rv += "\n\tpublic void set" + camel(i[1]) + "(" + i[0] + " " + i[1] + ") {\n" + "\
\tthis." + i[1] + " = " + i[1] + ";\n\t}\n"
snip.rv += "\n\tpublic " + i[0] + " get" + camel(i[1]) + "() {\
\n\t\treturn " + i[1] + ";\n\t}\n"
`
}
endsnippet
snippet cl "class" b
public class ${1:`!p
snip.rv = snip.basename or "untitled"`} {
$0
}
endsnippet
snippet cos "constant string" b
public static final String ${1:var} = "$2";$0
endsnippet
snippet co "constant" b
public static final ${1:String} ${2:var} = $3;$0
endsnippet
snippet de "default" b
default:
$0
endsnippet
snippet elif "else if" b
else if ($1)`!p nl(snip)`{
$0
}
endsnippet
snippet else "else" b
else`!p nl(snip)`{
$0
}
endsnippet
snippet fi "final" b
final
endsnippet
snippet fore "for (each)" b
for ($1 : $2)`!p nl(snip)`{
$0
}
endsnippet
snippet fori "for with int i" b
for (int ${1:i} = 0; $1 < ${2:10}; $1++)`!p nl(snip)`{
$0
}
endsnippet
snippet for "for" b
for ($1; $2; $3)`!p nl(snip)`{
$0
}
endsnippet
snippet if "if" b
if ($1)`!p nl(snip)`{
$0
}
endsnippet
snippet imt "import junit_framework_TestCase;" b
import junit.framework.TestCase;
$0
endsnippet
snippet im "import" b
import ${1:java}.${2:util}.$0
endsnippet
snippet in "interface" b
interface ${1:`!p snip.rv = snip.basename or "untitled"`} ${2:extends ${3:Parent} }{
$0
}
endsnippet
snippet cc "constuctor call or setter body"
this.${1:var} = $1;
endsnippet
snippet list "Collections List" b
List<${1:String}> ${2:list} = new ${3:Array}List<$1>();
endsnippet
snippet map "Collections Map" b
Map<${1:String}, ${2:String}> ${3:map} = new ${4:Hash}Map<$1, $2>();
endsnippet
snippet set "Collections Set" !b
Set<${1:String}> ${2:set} = new ${3:Hash}Set<$1>();
endsnippet
snippet /Str?|str/ "String" !br
String
endsnippet
snippet cn "constructor, \w fields + assigments" b
`!p
import re
args = getArgs(t[1])
for i in args:
snip.rv += "\n\tprivate " + i[0] + " " + i[1]+ ";"
if len(args) > 0:
snip.rv += "\n"`
public `!p snip.rv = snip.basename or "unknown"`($1) { `!p
args = getArgs(t[1])
for i in args:
snip.rv += "\n\t\tthis." + i[1] + " = " + i[1]
if len(args) == 0:
snip.rv += "\n"`
}
endsnippet
snippet j.b "java_beans_" i
java.beans.
endsnippet
snippet j.i "java_io" i
java.io.
endsnippet
snippet j.m "java_math" i
java.math.
endsnippet
snippet j.n "java_net_" i
java.net.
endsnippet
snippet j.u "java_util_" i
java.util.
endsnippet
snippet main "method (main)" b
public static void main(String[] args)`!p nl(snip)`{
$0
}
endsnippet
snippet try "try/catch" !b
try {
$1
} catch(${2:Exception} ${3:e}){
${4:e.printStackTrace();}
}
endsnippet
snippet mt "method throws" b!
${1:private} ${2:void} ${3:method}(${4}) ${5:throws $6 }{
$0
}
endsnippet
snippet m "method" b
${1:private} ${2:void} ${3:method}(${4}) {
$0
}
endsnippet
snippet md "Method With javadoc" !b
/**
* ${7:Short Description}`!p
for i in getArgs(t[4]):
snip.rv += "\n\t * @param " + i[1] + " usage..."`
* `!p
if "throws" in t[5]:
snip.rv = "\n\t * @throws " + t[6]
else:
snip.rv = ""` `!p
if not "void" in t[2]:
snip.rv = "\n\t * @return object"
else:
snip.rv = ""`
**/
${1:public} ${2:void} ${3:method}($4) ${5:throws $6 }{
$0
}
endsnippet
snippet getter "getter"
public ${1:String} get${2:Name}() {
return `!p snip.rv = t[2].lower()`;
}
endsnippet
snippet setter "setter"
public void set${1:Name}(${2:String} $1) {
return this.`!p snip.rv = t[1].lower()` = `!p snip.rv = t[1].lower()`;
}
endsnippet
snippet setget "setter and getter"
public void set${1:Name}(${2:String} `!p snip.rv = t[1].lower()`) {
this.`!p snip.rv = t[1].lower()` = `!p snip.rv = t[1].lower()`;
}
public $2 get$1() {
return `!p snip.rv = t[1].lower()`;
}
endsnippet
snippet pa "package" b
package
endsnippet
snippet p "print" b
System.out.print($1);$0
endsnippet
snippet pl "println" b
System.out.println($1);$0
endsnippet
snippet pr "private" b
private
endsnippet
snippet po "protected" b
protected
endsnippet
snippet pu "public" b
public
endsnippet
snippet re "return" b
return
endsnippet
snippet st "static"
static
endsnippet
snippet sw "switch" b
switch ($1)`!p nl(snip)`{
case $2: $0
}
endsnippet
snippet sy "synchronized"
synchronized
endsnippet
snippet tc "test case"
public class ${1:`!p snip.rv = snip.basename or "untitled"`} extends ${2:TestCase}`!p nl(snip)`{
$0
}
endsnippet
snippet t "test" b
`!p junit(snip)`public void test${1:Name}() {
$0
}
endsnippet
snippet tt "test throws" b
`!p junit(snip)`public void test${1:Name}() ${2:throws Exception }{
$0
}
endsnippet
snippet th "throw" b
throw new $0
endsnippet
snippet wh "while" b
while ($1)`!p nl(snip)`{
$0
}
endsnippet
# vim:ft=snippets:

View file

@ -0,0 +1,172 @@
snippet limxa "lim from x to a" i
\lim_{${2:x} \rightarrow ${1:a}} $0
endsnippet
snippet liminf "lim from x to infinity" i
\lim_{${1:x} \rightarrow \infty} $0
endsnippet
snippet ddx "fr d dx" i
\frac{d}{dx}
endsnippet
snippet pm "Generate pmatrix" i
\begin{pmatrix} $0 \end{pmatrix}
endsnippet
snippet cd "cdot" i
\cdot
endsnippet
snippet lra "leftrightarrow" i
\leftrightarrow
endsnippet
snippet Lra "Leftrightarrow" i
\Leftrightarrow
endsnippet
snippet la "leftarrow" i
\leftarrow
endsnippet
snippet La "Leftarrow" i
\Leftarrow
endsnippet
snippet ra "rightarrow" i
\rightarrow
endsnippet
snippet Ra "Rightarrow" i
\Rightarrow
endsnippet
snippet gm "Generate pmatrix" i
\begin{gmatrix} $0 \end{gmatrix}
endsnippet
snippet bm "Creates a BMatrix" i
\begin{bmatrix} $0 \end{bmatrix}
endsnippet
snippet ta "add a tag"
\tag{${1:Tag Text}}
endsnippet
snippet fr "Fraction" i
\frac{$1}{$2}
endsnippet
snippet p "Programmiersprache" i
\`\`\`{${1:mips}}
$2
\`\`\`
endsnippet
snippet pi "Include Code from other file" i
\`\`\`{.${1:mips}include=${2:source.asm}}
\`\`\`
endsnippet
snippet head "Generates header with everything" b
---
title: '`!p pwd = os.getcwd()
if "mafi1" in pwd:
snip.rv = "Mafi1 Übung " + snip.basename[1:3] +" (Gruppe 10)"
elif "rs" in pwd:
snip.rv = "RS Übung " + snip.basename[1:3] + " (Gruppe 3)"
`'
date: `date +%d.%m.%Y`
author:
- 'Philipp Hochkamp (Mat. Nr. 211011)'
- 'Jonas Röger (Mat. Nr. 210435)'
- 'Nico Jansen (Mat. Nr. 210175)'
titlepage: true
---
endsnippet
snippet new "New Note"
- [${1:Title}](`!p
def getCategory():
w = vim.current.buffer
i = vim.current.window.cursor[0]-1
while i >= 0:
if w[i].split(" ")[0] == "##":
return w[i].split(" ")[1].lower()+"/"
i = i-1
return os.path.basename(w.name).split(".md")[0]+"/"
snip.rv = getCategory() + t[1].replace(" ", "-").lower()`.md)
endsnippet
snippet al "Align Block" i
\begin{align*}
${1:${VISUAL}}
\end{align*}
endsnippet
snippet eq "Equation Block" i
\begin{equation}
${1:${VISUAL}}
\end{equation}
endsnippet
snippet bl "Custom Block" i
\begin{${1:tabluar}}$2
$3
\end{$1}
endsnippet
snippet tab "tabular (or arbitrary) environment" i
\begin{${1:tabular}}{${2:c}}
${0:${VISUAL}}
\end{$1}
endsnippet
snippet mb "Math bold font text" i
\mathbb{${1:R}}
endsnippet
snippet mf "Math Fraktur text" i
\mathfrak{${1:P}}
endsnippet
snippet nt "No Tag and end line" i
\notag \\\\
endsnippet
snippet sum "\sum^{}_{}" i
\sum^{${1:n}}_{${2:i=1}} ${0}
endsnippet
snippet lr( "left( right)" i
\left( ${1:${VISUAL}} \right) ${0}
endsnippet
snippet lr| "left| right|" i
\left| ${1:${VISUAL}} \right| ${0}
endsnippet
snippet lr{ "left\{ right\}" i
\left\{ ${1:${VISUAL}} \right\} ${0}
endsnippet
snippet lr[ "left\[ right\]" i
\left [ ${0:${VISUAL}} \right ]
endsnippet
snippet refl "Reference Link" i
[${1:${VISUAL:Text}}][${2:id}]$0
[$2]:${4:http://${3:www.url.com}} "${5:$4}"
endsnippet
snippet fnt "Footnote" i
[^${1:${VISUAL:Footnote}}]$0
[^$1]:${2:Text}
endsnippet
snippet link "Link to something" i
[${1:${VISUAL:Text}}](${3:http://${2:www.url.com}})$0
endsnippet
snippet img "Image" i
![${1:pic alt}](${2:path}${3/.+/ "/}${3:opt title}${3/.+/"/})$0
endsnippet
snippet ilc "Inline Code" i
\`$1\`$0
endsnippet
snippet sqrt "square root" i
\sqrt{${1}} $2
endsnippet

View file

@ -0,0 +1,3 @@
snippet sh "Shebang" EndStuff
#!/usr/bin/env python
endsnippet

View file

@ -0,0 +1,5 @@
snippet sn "Snippet"
`echo snippet` ${1:Keys} "${2:Description}" ${3:EndStuff}
$4
`echo endsnippet`
endsnippet

View file

@ -0,0 +1,9 @@
augroup neovim_terminal
autocmd!
" Enter Terminal-mode (insert) automatically
autocmd TermOpen * startinsert
" Disables number lines on terminal buffers
autocmd TermOpen * :set nonumber norelativenumber
" allows you to use Ctrl-c on terminal window
autocmd TermOpen * nnoremap <buffer> <C-c> i<C-c>
augroup END

View file

@ -0,0 +1,84 @@
{pkgs, config, inputs, lib, ...}:
with lib;
with lib.my;
{
home.packages = [
python3 # ultisnips
lazygit
nodejs
inputs.rnix-lsp.packages."${pkgs.system}".rnix-lsp
shfmt
shellcheck
vim-vint
nodePackages.write-good
ctags
];
home.file.".config/nvim".source = ./config;
programs.neovim =
let
conf = inputs.self.nixosConfigurations.enterprise.config.programs.neovim.configure;
in
{
enable = true;
package = pkgs.neovim-nightly;
vimAlias = true;
viAlias = true;
extraConfig = ''
set runtimepath^=~/.config/nvim
lua dofile('~/.config/nvim/init.lua')
'';
plugins =
let
nnn-vim = pkgs.vimUtils.buildVimPlugin {
name = "nnn-vim";
src = inputs.nnn-vim;
};
coc-nvim = pkgs.vimUtils.buildVimPlugin {
name = "coc-nvim";
src = inputs.coc-nvim;
};
dart-vim = pkgs.vimUtils.buildVimPlugin {
name = "dart-vim";
src = inputs.dart-vim;
};
vim-pandoc-live-preview = pkgs.vimUtils.buildVimPlugin {
name = "vim-pandoc-live-preview";
src = inputs.vim-pandoc-live-preview;
};
orgmode-nvim = pkgs.vimUtils.buildVimPlugin {
name = "orgmode-nvim";
src = inputs.orgmode-nvim;
dontBuild = true;
};
in
map (x: { plugin = x; }) (with pkgs.vimPlugins; [
vim-tmux-navigator
galaxyline-nvim
nvim-web-devicons
nnn-vim
rainbow
vista-vim
polyglot
vim-commentary
vim-table-mode
vim-speeddating
vim-nix
gruvbox
incsearch-vim
vim-highlightedyank
vim-fugitive
fzf-vim
lualine-nvim
fzfWrapper
vim-devicons
toggleterm-nvim
undotree
vim-pandoc
vim-pandoc-live-preview
vim-pandoc-syntax
ultisnips
coc-nvim
dart-vim
]);
};
}

View file

@ -0,0 +1,16 @@
{ config, pkgs,...}:{
programs.tmux = {
enable = true;
keyMode = "vi";
clock24 = true;
historyLimit = 10000;
plugins = with pkgs.tmuxPlugins; [
vim-tmux-navigator
gruvbox
];
extraConfig = ''
new-session -s main
bind-key -n C-a send-prefix
'';
};
}

View file

@ -0,0 +1,34 @@
{ inputs, config, lib, pkgs, ... }:
let
cfg = config.ragon.cli;
in
{
programs.zsh = {
enable = true;
histSize = 10000;
enableCompletion = true;
initExtra =
let
zshrc = builtins.readFile ./zshrc;
sources = [
"${inputs.agkozak-zsh-prompt}/agkozak-zsh-prompt.plugin.zsh"
"${pkgs.oh-my-zsh}/share/oh-my-zsh/plugins/git/git.plugin.zsh"
"${pkgs.oh-my-zsh}/share/oh-my-zsh/plugins/globalias/globalias.plugin.zsh"
"${inputs.zsh-vim-mode}/zsh-vim-mode.plugin.zsh"
"${inputs.zsh-syntax-highlighting}/zsh-syntax-highlighting.plugin.zsh"
"${inputs.zsh-completions}/zsh-completions.plugin.zsh"
];
source = map (x: "source " + x) sources;
plugins = builtins.concatStringsSep "\n" (source);
in
''
${zshrc}
${plugins}
'';
};
}

62
hm-imports/zsh/zshrc Normal file
View file

@ -0,0 +1,62 @@
AGKOZAK_MULTILINE=0
AGKOZAK_PROMPT_CHAR=( "%F{red}N%f")
autoload -Uz history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey -M vicmd '^[[A' history-beginning-search-backward-end \
'^[OA' history-beginning-search-backward-end \
'^[[B' history-beginning-search-forward-end \
'^[OB' history-beginning-search-forward-end
bindkey -M viins '^[[A' history-beginning-search-backward-end \
'^[OA' history-beginning-search-backward-end \
'^[[B' history-beginning-search-forward-end \
'^[OB' history-beginning-search-forward-end
hash go 2>/dev/null && export PATH=$PATH:$(go env GOPATH)/bin
hash yarn 2>/dev/null && export PATH=$PATH:$HOME/.yarn/bin
hash direnv 2>/dev/null && eval "$(direnv hook zsh)" # needed for lorri
export PATH=$PATH:$HOME/scripts
export PATH=$PATH:$HOME/.config/rofi/bins
export PATH=$PATH:$HOME/.local/bin
export PATH=$PATH:$HOME/flutter/flutter/bin
hash kitty 2>/dev/null && alias ssh="kitty kitten ssh"
hash helm 2>/dev/null && . <(helm completion zsh)
hash kubectl 2>/dev/null && . <(kubectl completion zsh)
export NNN_ARCHIVE="\\.(7z|a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|rar|rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)$"
ssh() {
if [ -v TMUX ]; then
tmux set-option allow-rename off 1>/dev/null
tmux rename-window "ssh/$*"
command ssh "$@"
tmux set-option allow-rename on 1>/dev/null
else
command ssh "$@"
fi
}
n ()
{
# Block nesting of nnn in subshells
if [ -n $NNNLVL ] && [ "${NNNLVL:-0}" -ge 1 ]; then
echo "nnn is already running"
return
fi
export NNN_TMPFILE="$HOME/.config/nnn/.lastd"
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
# stty start undef
# stty stop undef
# stty lwrap undef
# stty lnext undef
nnn -d "$@"
if [ -f "$NNN_TMPFILE" ]; then
. "$NNN_TMPFILE"
rm -f "$NNN_TMPFILE" > /dev/null
fi
}

View file

@ -0,0 +1,62 @@
{ pkgs, inputs, lib, ... }:
with lib;
with lib.my;
{
users.users.ragon = {
name = "ragon";
home = "/Users/ragon";
};
programs.gnupg.agent.enable = true;
home-manager.users.ragon = { pkgs, lib, inputs, config, ... }: {
programs.home-manager.enable = true;
home.stateVersion = "21.11";
home.sessionVariables = {
EDITOR = "nvim";
VISUAL = "nvim";
PATH = "$PATH:$HOME/development/flutter/bin:/Applications/Android Studio.app/Contents/bin/:/Applications/Docker.app/Contents/Resources/bin:/Applications/Android Studio.app/Contents/jre/Contents/Home/bin:$HOME/.nix-profile/bin:/nix/var/nix/profiles/system/sw/bin";
JAVA_HOME = "/Applications/Android Studio.app/Contents/jre/Contents/Home/";
};
home.packages = with pkgs; [
terraform-ls
terraform
#tectonic
pandoc
yabai
google-cloud-sdk
];
home.activation = {
aliasApplications =
let
apps = pkgs.buildEnv {
name = "home-manager-applications";
paths = config.home.packages;
pathsToLink = "/Applications";
};
in
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
# Install MacOS applications to the user environment.
HM_APPS="$HOME/Applications/Home Manager Apps"
# Reset current state
[ -e "$HM_APPS" ] && $DRY_RUN_CMD rm -r "$HM_APPS"
$DRY_RUN_CMD mkdir -p "$HM_APPS"
# .app dirs need to be actual directories for Finder to detect them as Apps.
# The files inside them can be symlinks though.
$DRY_RUN_CMD cp --recursive --symbolic-link --no-preserve=mode -H ${apps}/Applications/* "$HM_APPS" || true # can fail if no apps exist
# Modes need to be stripped because otherwise the dirs wouldn't have +w,
# preventing us from deleting them again
# In the env of Apps we build, the .apps are symlinks. We pass all of them as
# arguments to cp and make it dereference those using -H
'';
};
};
}

213
hosts/ds9/default.nix Normal file
View file

@ -0,0 +1,213 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ config, inputs, pkgs, lib, ... }:
{
imports =
[
# Include the results of the hardware scan.
./hardware-configuration.nix
];
# Don't Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
services.syncthing.enable = true;
services.syncthing.user = "ragon";
security.sudo.wheelNeedsPassword = false;
networking.useDHCP = true;
networking.bridges."br0".interfaces = [ ];
networking.hostId = "7b4c2932";
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
boot.initrd.network = {
enable = true;
postCommands = ''
zpool import rpool
echo "zfs load-key -a; killall zfs" >> /root/.profile
'';
ssh = {
enable = true;
port = 2222;
hostKeys = [
"/persistent/etc/nixos/secrets/initrd/ssh_host_rsa_key"
"/persistent/etc/nixos/secrets/initrd/ssh_host_ed25519_key"
];
authorizedKeys = pkgs.pubkeys.ragon.computers;
};
};
# services.restic.backups."ds9" = {
# rcloneConfigFile = "/run/secrets/ds9rcloneConfig";
# passwordFile = "/run/secrets/ds9resticPassword";
# pruneOpts = [
# "--keep-daily 7"
# "--keep-weekly 5"
# "--keep-monthly 12"
# "--keep-yearly 75"
# ];
# initialize = true;
# repository = "rclone:ds9:/ds9";
# paths = [
# "/data"
# "/persistent/var/lib"
# ];
# };
ragon.agenix.secrets."ds9rcloneConfig" = { };
ragon.agenix.secrets."ds9resticPassword" = { };
# Enable Scanning
hardware.sane.enable = true;
hardware.sane.extraBackends = [ pkgs.sane-airscan ];
services.avahi.enable = true;
services.avahi.nssmdns = true;
services.avahi.publish.enable = true;
services.avahi.extraServiceFiles.smb = ''
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_smb._tcp</type>
<port>445</port>
<host-name>ds9.hailsatan.eu</host-name>
</service>
<service>
<type>_device-info._tcp</type>
<port>0</port>
<txt-record>model=MacPro7,1@ECOLOR=226,226,224</txt-record>
</service>
<service>
<type>_adisk._tcp</type>
<txt-record>sys=waMa=0,adVF=0x100</txt-record>
<txt-record>dk0=adVN=TimeMachine,adVF=0x82</txt-record>
<host-name>ds9.hailsatan.eu</host-name>
</service>
</service-group>
'';
# Webhook service to trigger scanning the ADF from HomeAssistant
systemd.services.scanhook = {
description = "webhook go server to trigger scanning";
documentation = [ "https://github.com/adnanh/webhook" ];
wantedBy = [ "multi-user.target" ];
path = with pkgs; [ bash ];
serviceConfig = {
TemporaryFileSystem = "/:ro";
BindReadOnlyPaths = [
"/nix/store"
"-/etc/resolv.conf"
"-/etc/nsswitch.conf"
"-/etc/hosts"
"-/etc/localtime"
];
BindPaths = [
"/data/applications/paperless-consumption"
];
LockPersonality = true;
NoNewPrivileges = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = true;
ProcSubset = "pid";
ProtectHome = true;
ProtectControlGroups = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
DynamicUser = true;
ExecStart =
let
scanScript = pkgs.writeScript "plscan.sh" ''
#!/usr/bin/env bash
export PATH=${lib.makeBinPath [ pkgs.strace pkgs.gnugrep pkgs.coreutils pkgs.sane-backends pkgs.sane-airscan pkgs.imagemagick ]}
export LD_LIBRARY_PATH=${config.environment.sessionVariables.LD_LIBRARY_PATH} # Adds SANE Libraries to the ld library path of this script
set -x
date="''$(date --iso-8601=seconds)"
filename="Scan ''$date.pdf"
tmpdir="''$(mktemp -d)"
pushd "''$tmpdir"
scanimage --batch=out%d.jpg --format=jpeg --mode Gray -d "airscan:e0:Canon MB5100 series" --source "ADF Duplex" --resolution 300
for i in $(ls out*.jpg | grep 'out.*[24680]\.jpg'); do convert $i -rotate 180 $i; done # rotate even stuff
convert out*.jpg /data/applications/paperless-consumption/"''$filename"
chmod 666 /data/applications/paperless-consumption/"''$filename"
popd
rm -r "''$tmpdir"
'';
hooksFile = pkgs.writeText "webhook.json" (builtins.toJSON [
{
id = "scan-webhook";
execute-command = "${scanScript}";
}
]);
in
"${pkgs.webhook}/bin/webhook -hooks ${hooksFile} -verbose";
};
};
networking.firewall.allowedTCPPorts = [ 9000 ];
# Immutable users due to tmpfs
users.mutableUsers = false;
services.samba.extraConfig = ''
min protocol = SMB3
vfs objects = acl_xattr catia fruit streams_xattr
fruit:nfs_aces = no
inherit permissions = yes
fruit:posix_rename = yes
fruit:model = MacPro7,1@ECOLOR=226,226,224
fruit:veto_appledouble = no
fruit:wipe_intentionally_left_blank_rfork = yes
fruit:delete_empty_adfiles = yes
fruit:metadata = stream
'';
ragon = {
cli.enable = true;
user.enable = true;
home-manager.enable = true;
persist.enable = true;
persist.extraDirectories = [ "/var/lib/syncthing" ];
services = {
samba.enable = true;
samba.shares = {
TimeMachine = {
path = "/backups/DaedalusTimeMachine";
comment = "DaedalusTimeMachine";
"write list" = "@wheel";
"fruit:time machine" = "yes";
"fruit:time machine max size" = "2050G";
"vfs objects" = "acl_xattr fruit streams_xattr";
"inherit acls" = "yes";
};
data = {
path = "/data";
comment = "some data for the people";
"write list" = "@wheel";
};
};
docker.enable = true;
ssh.enable = true;
nginx.enable = true;
jellyfin.enable = true;
tailscale.enable = true;
grafana.enable = true;
libvirt.enable = true;
paperless.enable = true;
unifi.enable = true;
};
};
}

View file

@ -0,0 +1,52 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [ "${modulesPath}/installer/scan/not-detected.nix" ];
boot.initrd.availableKernelModules = [ "r8169" "ahci" "vfio-pci" "xhci_pci" "ehci_pci" "nvme" "usbhid" "sd_mod" "sr_mod" ];
boot.kernelModules = [ "kvm-amd" ];
nix.maxJobs = lib.mkDefault 12;
powerManagement.cpuFreqGovernor = "performance";
services.zfs.autoScrub.enable = true;
ragon.system.fs = {
enable = true;
mediadata = false;
swap = false;
persistentSnapshot = false;
nix = "rpool/content/local/nix";
varlog = "rpool/content/local/journal";
persistent = "rpool/content/safe/persist";
arcSize = 8;
};
services.syncoid.enable = false; # TODO setup offsite backups
services.sanoid.datasets."rpool/content/safe".recursive = true;
services.sanoid.datasets."rpool/content/local/backups" = { };
services.sanoid.enable = true;
swapDevices = [ { device = "/dev/disk/by-id/nvme-eui.000000000000000100a075202c247839-part1"; randomEncryption = true; } ];
fileSystems."/boot".device = "/dev/disk/by-uuid/149F-23AA";
fileSystems."/data" = {
device = "rpool/content/safe/data";
fsType = "zfs";
};
fileSystems."/data/media" = {
device = "rpool/content/safe/data/media";
fsType = "zfs";
};
fileSystems."/backups" = {
device = "rpool/content/local/backups";
fsType = "zfs";
};
fileSystems."/data/media/nzbr" = {
device = "10.0.1.2:/storage/media";
fsType = "nfs";
options = [ "x-systemd.automount" "noauto" ];
};
}

63
hosts/picard/default.nix Normal file
View file

@ -0,0 +1,63 @@
# Edit this configuration file to define what should be installed on
# your system. Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running nixos-help).
{ inputs, config, pkgs, ... }:
{
imports =
[
# Include the results of the hardware scan.
./hardware-configuration.nix
];
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
boot.loader.grub.device = "/dev/sda";
boot.loader.systemd-boot.enable = false;
services.syncthing.enable = true;
networking.interfaces."ens3" = {
ipv6 = {
addresses = [
{
address = "2a03:4000:54:a98::1";
prefixLength = 64;
}
];
};
};
networking.defaultGateway6 = { address = "fe80::1"; interface = "enp0s3"; };
networking.nameservers = [ "1.1.1.1" "8.8.8.8" ];
# networking.interfaces.eno1.useDHCP = true;
networking.hostId = "7c21236a";
# Immutable users due to tmpfs
users.mutableUsers = false;
services.postgresql.package = pkgs.postgresql_13;
ragon = {
cli.enable = true;
user.enable = true;
home-manager.enable = true;
persist.enable = true;
persist.extraDirectories = [ "/var/lib/syncthing" ];
services = {
ssh.enable = true;
bitwarden.enable = true;
gitlab.enable = true; # TODO gitlab-runner
synapse.enable = true;
tailscale.enable = true;
hedgedoc.enable = true;
ts3.enable = true;
nginx.enable = true;
nginx.domain = "ragon.xyz";
};
};
}

View file

@ -0,0 +1,42 @@
# Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
{
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
boot.zfs.requestEncryptionCredentials = true;
ragon.system.fs.enable = true;
ragon.system.fs.nix = "rpool/nix";
ragon.system.fs.varlog = "rpool/varlog";
ragon.system.fs.persistent = "rpool/persist";
ragon.system.fs.swap = false;
ragon.system.fs.mediadata = false;
swapDevices = [
{ device = "/dev/sda2"; randomEncryption.enable = true; }
];
services.syncoid.enable = false; # disable failing zfs syncing
boot.initrd = {
network = {
enable = true;
postCommands = ''
zpool import rpool
echo "zfs load-key -a; killall zfs" >> /root/.profile
'';
ssh = {
enable = true;
port = 2222;
hostKeys = [
"/persistent/etc/nixos/secrets/initrd/ssh_host_rsa_key"
"/persistent/etc/nixos/secrets/initrd/ssh_host_ed25519_key"
];
authorizedKeys = pkgs.pubkeys.ragon.user;
};
};
};
powerManagement.cpuFreqGovernor = "performance";
}

View file

@ -0,0 +1,92 @@
{ config, inputs, pkgs, lib, ... }:
{
imports = [
"${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
"${inputs.nixos-hardware}/raspberry-pi/4/default.nix"
./router.nix
];
nixpkgs.overlays = [
(final: super: {
makeModulesClosure = x:
super.makeModulesClosure (x // { allowMissing = true; });
})
];
boot.loader.systemd-boot.enable = false;
boot.kernelPackages = pkgs.linuxPackages_rpi4;
boot.supportedFilesystems = lib.mkForce [ "reiserfs" "vfat" "zfs" "ext4" ]; # we dont need zfs here
boot.inird.supportedFilesystems = lib.mkForce [ "reiserfs" "vfat" "zfs" "ext4" ]; # we dont need zfs here
networking.hostId = "eec43f51";
# networking.usePredictableInterfaceNames = false;
documentation.enable = false;
documentation.nixos.enable = false;
nix = {
autoOptimiseStore = true;
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
# Free up to 1GiB whenever there is less than 100MiB left.
extraOptions = ''
min-free = ${toString (100 * 1024 * 1024)}
max-free = ${toString (1024 * 1024 * 1024)}
'';
};
powerManagement.cpuFreqGovernor = "ondemand";
# Assuming this is installed on top of the disk image.
fileSystems = {
"/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
options = [ "noatime" ];
};
};
ragon.networking.router.enable = true;
ragon.services.ssh.enable = true;
ragon.cli.enable = true;
ragon.cli.maximal = false;
services.lorri.enable = false;
ragon.services.ddns.enable = true;
ragon.services.tailscale.enable = true;
ragon.services.nginx.enable = true;
services.nginx.virtualHosts."h.hailsatan.eu" = {
forceSSL = true;
useACMEHost = "hailsatan.eu";
extraConfig = ''
proxy_buffering off;
'';
locations."/".proxyPass = "http://10.0.0.20:8123";
locations."/".proxyWebsockets = true;
};
services.nginx.virtualHosts."hailsatan.eu" = {
forceSSL = true;
useACMEHost = "hailsatan.eu";
root = pkgs.runCommand "homepage" { } ''
mkdir -p $out
echo "Hail Satan" > $out/index.html
echo "User-agent: *" > $out/robots.txt
echo "Disallow: /" >> $out/robots.txt
'';
};
services.nginx.virtualHosts."j.hailsatan.eu" = {
forceSSL = true;
useACMEHost = "hailsatan.eu";
extraConfig = ''
proxy_buffering off;
'';
locations."/".proxyPass = "https://j.hailsatan.eu";
locations."/".proxyWebsockets = true;
};
users.users.root.openssh.autorizedKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDiKJEYNUU+ZpbOyJf9k9ZZdTTL0qLiZ6fXEBVCjNfas"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIkFgHr6OMwsnGhdG4TwKdthlJC/B9ELqZfrmJ9Sf7qk"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCJVa1zAjR6stS4qIEysQbR9n0/AV2h62QRfsRvNfQiL19ExKFR7ZHaUFBr6jnGjzl5eyK0DtwZMlyaDlTR/AXiTZHJrvEPL1lna42wK252uZb66DXAG23L+iFeXySq3f+a6Prw8NU3HvIvC/YkEYwjjbqPKEjvnIHd2dJ1FZ9T9FeoKup3nMWYGDRqrja8NcRwCY9OpPd3ZKZJlNJcPfbfAipGAuQ6EGgGi0GzqoYP9OqZx9PBQQEY7a5+cUgYYEI75NJNuk4/WBm8fkFKrcOmvhTOEb90kbNmpHusDOrFEo8LATdpmJSG013DpPb1W7pMxMq+YgFF4INqIxrhBGht"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8RjUQ6DDDDgsVbqq+6zz1q6cBkus/BLUGa9JoWsqB4"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCWwrrROqkBEZi8t7Czu1jDDJjSqomGXx7dhIx73GTb3bBlgThqUSsrG+NpP9mxNl4sYgmJYQ9idpUW/RTX3/sXBvNQi4rOqv9z1qdEyzF86CcyWGk4f+D2hJffLlcIbvbDCJ92PF+k5NbH+PC/yVZKSIRC3ENBHf38l8n25ABuBcpCI16bPCIbqbpekqStXClug//uAyENuS6+orHFQg3muUihEedEhJly1QAfDhOzZRlBxTGQcDvZA/XMaIyjAqbXaNVRsDLmKezm/Dg5M3jMIRxApUd9hcuZlfemxUgD0qqnJSTahb9rMxUKk5jdY95EthAp0s2e6tc2O76sYPqb"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH99QITZa3hSa+7sMo4M5IC5mXWEjsRqXUSaYKKRyQfE"
];
}

422
hosts/wormhole/router.nix Normal file
View file

@ -0,0 +1,422 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
wgEnabled = hasAttrByPath [ "hosts" config.networking.hostName ] (importTOML ../../data/wireguard.toml);
cfg = config.ragon.networking.router;
waninterface = cfg.waninterface;
laninterface = cfg.laninterface;
prefixSize = cfg.prefixSize;
statics = cfg.statics;
domain = cfg.domain;
disableFirewallFor = cfg.disableFirewallFor;
lan = {
name = "lan";
internet = true;
allowipv6 = true;
ipv4addr = "10.0.0.1";
netipv4addr = "10.0.0.0";
dhcpv4start = "10.0.10.1";
dhcpv4end = "10.0.255.240";
routes = [
{ address = "10.12.0.0"; prefixLength = 16; via = "10.0.1.2"; }
{ address = "10.13.0.0"; prefixLength = 16; via = "10.0.1.2"; }
];
ipv4size = 16;
vlan = 4;
};
iot = {
name = "iot";
internet = false;
allowipv6 = false;
ipv4addr = "10.1.0.1";
netipv4addr = "10.1.0.0";
dhcpv4start = "10.1.1.1";
dhcpv4end = "10.1.255.240";
routes = [ ];
ipv4size = 16;
vlan = 2;
};
guest = {
name = "guest";
internet = true;
allowipv6 = false;
ipv4addr = "192.168.2.1";
netipv4addr = "192.168.2.0";
dhcpv4start = "192.168.2.10";
dhcpv4end = "192.168.2.240";
routes = [ ];
ipv4size = 24;
vlan = 3;
};
nets = [ lan iot guest ];
ipv6nets = builtins.filter (a: a.allowipv6) nets;
interfaceGenerator = obj: {
"${obj.name}".ipv4 = {
addresses = [{
address = obj.ipv4addr;
prefixLength = obj.ipv4size;
}];
routes = [{
address = obj.netipv4addr;
prefixLength = obj.ipv4size;
}] ++ obj.routes;
};
};
in
{
options.ragon.networking.router.enable = mkBoolOpt false;
options.ragon.networking.router.waninterface =
lib.mkOption {
type = lib.types.str;
default = "eth1";
};
options.ragon.networking.router.laninterface =
lib.mkOption {
type = lib.types.str;
default = "eth0";
};
options.ragon.networking.router.domain =
lib.mkOption {
type = lib.types.str;
default = "hailsatan.eu";
};
options.ragon.networking.router.prefixSize =
lib.mkOption {
type = lib.types.int;
default = 59;
};
options.ragon.networking.router.statics =
lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [
{ name = "j.hailsatan.eu"; ip = "10.0.0.2"; }
{ name = "paperless.hailsatan.eu"; ip = "10.0.0.2"; }
{ name = "unifi.hailsatan.eu"; ip = "10.0.0.2"; }
{ name = "nix.hailsatan.eu"; ip = "10.0.0.2"; }
{ name = "h.hailsatan.eu"; ip = "10.0.0.1"; }
{ name = "grafana.hailsatan.eu"; ip = "10.0.0.2"; }
{ name = "nzbr.de"; ip = "10.0.1.2"; }
{ name = "storm.nzbr.de"; ip = "45.9.63.165"; }
{ name = "avalanche.nzbr.de"; ip = "202.61.247.0"; }
];
};
options.ragon.networking.router.disableFirewallFor =
lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [
{ hostname = "enterprise"; mac = "d8:cb:8a:76:09:0a"; tcpports = [ 22 ]; udpports = [ ]; }
{ hostname = "earthquake"; mac = "78:24:af:bc:0c:07"; tcpports = [ 22 22000 ]; udpports = [ 22000 51820 ]; }
];
};
options.ragon.networking.router.staticDHCPs =
lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [
# ragon - machines
{ name = "enterprise"; ip = "10.0.0.9"; mac = "d8:cb:8a:76:09:0a"; }
{ name = "ds9"; ip = "10.0.0.2"; mac = "f4:b5:20:0e:21:d5"; }
# ragon - vms
{ name = "homeassistant"; ip = "10.0.0.20"; mac = "52:54:00:a1:04:14"; }
{ name = "enterprise-win"; ip = "10.0.0.201"; mac = "52:54:00:f3:ab:dd"; }
# ragon - iot
{ name = "zbbridge"; ip = "10.1.0.5"; mac = "98:f4:ab:e2:b6:a3"; }
{ name = "wled-Schrank-Philipp"; ip = "10.1.0.10"; mac = "2c:f4:32:20:74:60"; }
{ name = "wled-Betthintergrund-Phi"; ip = "10.1.0.11"; mac = "2c:3a:e8:0e:ab:71"; }
# nzbr - machines
{ name = "earthquake"; ip = "10.0.1.2"; mac = "78:24:af:bc:0c:07"; }
{ name = "comet"; ip = "10.0.1.4"; mac = "0c:98:38:d3:16:8f"; }
{ name = "meteor"; ip = "10.0.1.8"; mac = "54:27:1e:5c:1f:ed"; } # Wireless
{ name = "meteor"; ip = "10.0.1.16"; mac = "00:21:cc:5c:f5:dc"; } # Wired
{ name = "hurricane"; ip = "10.0.1.32"; mac = "f0:2f:74:1b:af:e0"; }
# nzbr - vms
{ name = "earthquake-macos"; ip = "10.0.1.201"; mac = "52:54:00:8e:e2:66"; }
{ name = "earthquake-win"; ip = "10.0.1.202"; mac = "52:54:00:97:37:69"; }
# nzbr - consoles
{ name = "xbox"; ip = "10.0.2.1"; mac = "58:82:a8:30:2d:1c"; }
{ name = "wii"; ip = "10.0.2.2"; mac = "00:23:cc:50:78:00"; }
{ name = "switch"; ip = "10.0.2.3"; mac = "dc:68:eb:bb:01:fc"; } # Wireless
];
};
options.ragon.networking.router.forwardedPorts =
lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [
#{ proto = "tcp"; sourcePort = "5060-5061"; destination = "10.0.0.11"; }
];
};
config = {
# https://www.willghatch.net/blog/2020/06/22/nixos-raspberry-pi-4-google-fiber-router/
# Youd better forward packets if you actually want a router.
boot.kernel.sysctl = {
"net.ipv4.ip_forward" = 1;
"net.ipv6.conf.all.forwarding" = 1;
"net.ipv6.conf.default.forwarding" = 1;
"net.ipv6.conf.6rdtun.forwarding" = 1;
};
networking.vlans =
let
genVlan = obj: {
"${obj.name}" = {
id = obj.vlan;
interface = laninterface;
};
};
in
lib.foldl (a: b: a // b) { } (map genVlan nets);
networking.interfaces =
let
genVlanConf = lib.foldl (a: b: a // b) { } (map interfaceGenerator nets);
in
{
"${waninterface}" = {
useDHCP = true;
};
} // genVlanConf;
networking.dhcpcd = {
enable = true;
allowInterfaces = [
"${waninterface}"
] ++ (map (a: a.name) ipv6nets);
extraConfig =
let
genDesc = obj: ''
# We dont want dhcpcd to give us an address on the ${obj.name} interface.
interface ${obj.name}
noipv4
'';
allGenIntDescs = builtins.concatStringsSep "\n" (map genDesc ipv6nets);
in
''
# The man page says that ipv6rs should be disabled globally when
# using a prefix delegation.
noipv6rs
interface ${waninterface}
# On the wan interface, we want to ask for a prefix delegation.
iaid 0
ipv6rs
ia_pd 0/::/${toString prefixSize} lan/0/${toString prefixSize}
${allGenIntDescs}
'';
runHook = ''
if [[ "$reason" == "BOUND6" ]] || [[ "$reason" == "REBIND6" ]]; then
${pkgs.python3}/bin/python3 ${pkgs.writeScript "dhcpcd-runHook.py" ''
import json
import sys
import subprocess
import os
prefix = os.environ.get("new_dhcp6_ia_pd1_prefix1")[:-1]
# https://stackoverflow.com/a/37316533/12852285
def mac2ipv6(mac):
# only accept MACs separated by a colon
parts = mac.split(":")
# modify parts to match IPv6 value
parts.insert(3, "ff")
parts.insert(4, "fe")
parts[0] = "%x" % (int(parts[0], 16) ^ 2)
# format output
ipv6Parts = []
for i in range(0, len(parts), 2):
ipv6Parts.append("".join(parts[i:i+2]))
ipv6 = "%s%s" % (prefix, ":".join(ipv6Parts))
return ipv6
data = json.loads("""${builtins.toJSON disableFirewallFor}""")
for host in data:
print('setting firewall rules for ' + host["hostname"])
IP = mac2ipv6(host["mac"])
if len(host["tcpports"]) > 0:
subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "tcp", "dport", f'{{ {", ".join(map(str, host["tcpports"]))} }}', "accept" ])
if len(host["udpports"]) > 0:
subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "udp", "dport", f'{{ {", ".join(map(str, host["udpports"]))} }}', "accept" ])
subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "icmpv6", "type", "{ destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert }", "accept"])
''}
fi
'';
};
networking.firewall.enable = false; # disable iptables cause it's ass to set up
networking.nftables.enable = true;
networking.nftables.ruleset =
let
unsafeInterfaces = (map (x: x.name) (filter (x: x.internet == false) nets));
safeInterfaces = (map (x: x.name) (filter (x: x.internet == true) nets)) ++ [ "lo" ] ++ (optionals (wgEnabled) [ "wg0" ]);
allInternalInterfaces = (map (x: x.name) nets) ++ [ "lo" ];
portForwards = concatStringsSep "\n" (map (x: "iifname ${waninterface} ${x.proto} dport ${toString x.sourcePort} dnat ${x.destination}") cfg.forwardedPorts);
dropUnsafe = concatStringsSep "\n" (map (x: "iifname ${x} drop") unsafeInterfaces);
allowSafe = concatStringsSep "\n" (map (x: "iifname ${x} accept") safeInterfaces);
allowSafeOif = concatStringsSep "\n" (map (x: "oifname ${x} ct state { established, related } accept") safeInterfaces);
allowAll = concatStringsSep "\n" (map (x: "iifname ${x} accept") (allInternalInterfaces ++ (optionals (wgEnabled) [ "wg0" ])));
in
''
define unsafe_interfaces = {
${concatStringsSep ",\n" unsafeInterfaces}
}
define safe_interfaces = {
lo,
${concatStringsSep ",\n" safeInterfaces}
}
define all_interfaces = {
lo,
${concatStringsSep ",\n" allInternalInterfaces}
}
table inet filter {
chain input {
type filter hook input priority 0;
# allow established/related connections
ct state { established, related } accept
# early drop of invalid connections
ct state invalid drop
# allow from loopback and internal nic
${allowAll}
# allow icmp
ip protocol icmp icmp type echo-request limit rate over 1/second burst 5 packets drop
ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 1/second burst 5 packets drop
ip protocol icmp icmp type { destination-unreachable, echo-reply, echo-request, source-quench, time-exceeded } accept
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, echo-reply, echo-request, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert, packet-too-big, parameter-problem, time-exceeded } accept
# open port 22, but only allow 2 new connections per minute from each ip
tcp dport 22 ct state new flow table ssh-ftable { ip saddr limit rate 2/minute } accept
tcp dport 80 accept
tcp dport 443 accept
udp dport 51820 accept
# everything else
reject with icmp type port-unreachable
}
chain forward {
type filter hook forward priority 0;
# allow from loopback and internal nic
${allowSafe}
# allow established/related connections
${allowSafeOif}
# Drop everything else
drop
}
chain output {
type filter hook output priority 0
# dont allow any trafic from iot and stuff to escape to the wild
${dropUnsafe}
}
}
table ip nat {
chain prerouting {
type nat hook prerouting priority 0
${portForwards}
}
chain postrouting {
type nat hook postrouting priority 0
oifname ${waninterface} masquerade
}
}
'';
services.dnsmasq = {
enable = true;
alwaysKeepRunning = true;
extraConfig =
let
inherit (pkgs) runCommand;
gen = obj: ''
interface=${obj.name}
dhcp-range=${obj.name},${obj.dhcpv4start},${obj.dhcpv4end},12h
'';
genHosts = obj: ''
dhcp-host=${obj.mac},${obj.ip},${obj.name}
'';
genall = builtins.concatStringsSep "\n" (map gen nets);
genallHosts = builtins.concatStringsSep "\n" (map genHosts cfg.staticDHCPs);
genstatics = builtins.concatStringsSep "\n" (map (a: "address=/${a.name}/${a.ip}") statics);
netbootxyz = builtins.fetchurl {
url = "https://github.com/netbootxyz/netboot.xyz/releases/download/2.0.40/netboot.xyz.efi";
sha256 = "1gvgvlaxhjkr9i0b2bjq85h12ni9h5fn6r8nphsag3il9kificcc";
};
netbootxyzpath = runCommand "netbootpath" { } ''
mkdir $out
ln -s ${netbootxyz} $out/netbootxyz.efi
'';
in
''
no-resolv
# unbound broke
# server=127.0.0.1#5353 # unbound
server=1.1.1.1
server=1.0.0.1
# https://hveem.no/using-dnsmasq-for-dhcpv6
# don't ever listen to anything on wan and stuff
except-interface=${waninterface},${laninterface}
listen-address=0.0.0.0,::
# don't send bogus requests out on the internets
bogus-priv
# enable IPv6 Route Advertisements
enable-ra
# Construct a valid IPv6 range from reading the address set on the interface. The :: part refers to the ifid in dhcp6c.conf. Make sure you get this right or dnsmasq will get confused.
dhcp-range=lan,::,constructor:lan, ra-names,slaac, 12h
# ra-names enables a mode which gives DNS names to dual-stack hosts which do SLAAC for IPv6.
# Add your local-only LAN domain
local=/${domain}/
# have your simple hosts expanded to domain
expand-hosts
# set your domain for expand-hosts
domain=${domain}
# forward .kube domains to coredns
server=/kube/10.13.0.10
${genall}
'' +
optionalString wgEnabled ''
interface=wg0
no-dhcp-interface=wg0
addn-hosts=/run/wireguard-hosts
'' + ''
interface=lo # otherwise localhost dns does not work
${genstatics}
${genallHosts}
dhcp-boot=netbootxyz.efi
enable-tftp
tftp-root=${netbootxyzpath}
# set authoritative mode
dhcp-authoritative
'';
};
};
}

26
lib/attrs.nix Normal file
View file

@ -0,0 +1,26 @@
{ lib, ... }:
with builtins;
with lib;
rec {
# attrsToList
attrsToList = attrs:
mapAttrsToList (name: value: { inherit name value; }) attrs;
# mapFilterAttrs ::
# (name -> value -> bool)
# (name -> value -> { name = any; value = any; })
# attrs
mapFilterAttrs = pred: f: attrs: filterAttrs pred (mapAttrs' f attrs);
# Generate an attribute set by mapping a function over a list of values.
genAttrs' = values: f: listToAttrs (map f values);
# anyAttrs :: (name -> value -> bool) attrs
anyAttrs = pred: attrs:
any (attr: pred attr.name attr.value) (attrsToList attrs);
# countAttrs :: (name -> value -> bool) attrs
countAttrs = pred: attrs:
count (attr: pred attr.name attr.value) (attrsToList attrs);
}

18
lib/default.nix Normal file
View file

@ -0,0 +1,18 @@
{ darwin, inputs, lib, pkgsBySystem, ... }:
let
inherit (lib) makeExtensible attrValues foldr;
inherit (modules) mapModules;
modules = import ./modules.nix {
inherit lib;
self.attrs = import ./attrs.nix { inherit lib; self = { }; };
};
mylib = makeExtensible (self:
with self; mapModules ./.
(file: import file { inherit self lib inputs; }));
in
mylib.extend
(self: super:
foldr (a: b: a // b) { } (attrValues super))

54
lib/modules.nix Normal file
View file

@ -0,0 +1,54 @@
{ self, lib, ... }:
let
inherit (builtins) attrValues readDir pathExists concatLists;
inherit (lib) id mapAttrsToList filterAttrs hasPrefix hasSuffix nameValuePair removeSuffix;
inherit (self.attrs) mapFilterAttrs;
in
rec {
mapModules = dir: fn:
mapFilterAttrs
(n: v:
v != null &&
!(hasPrefix "_" n))
(n: v:
let path = "${toString dir}/${n}"; in
if v == "directory" && pathExists "${path}/default.nix"
then nameValuePair n (fn path)
else if v == "regular" &&
n != "default.nix" &&
hasSuffix ".nix" n
then nameValuePair (removeSuffix ".nix" n) (fn path)
else nameValuePair "" null)
(readDir dir);
mapModules' = dir: fn:
attrValues (mapModules dir fn);
mapModulesRec = dir: fn:
mapFilterAttrs
(n: v:
v != null &&
!(hasPrefix "_" n))
(n: v:
let path = "${toString dir}/${n}"; in
if v == "directory"
then nameValuePair n (mapModulesRec path fn)
else if v == "regular" && n != "default.nix" && hasSuffix ".nix" n
then nameValuePair (removeSuffix ".nix" n) (fn path)
else nameValuePair "" null)
(readDir dir);
mapModulesRec' = dir: fn:
let
dirs =
mapAttrsToList
(k: _: "${dir}/${k}")
(filterAttrs
(n: v: v == "directory" && !(hasPrefix "_" n))
(readDir dir));
files = attrValues (mapModules dir id);
paths = files ++ concatLists (map (d: mapModulesRec' d id) dirs);
in
map fn paths;
}

18
lib/options.nix Normal file
View file

@ -0,0 +1,18 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
rec {
mkOpt = type: default:
mkOption { inherit type default; };
mkOpt' = type: default: description:
mkOption { inherit type default description; };
mkBoolOpt = default: mkOption {
inherit default;
type = types.bool;
example = true;
};
}

64
nixos-common.nix Normal file
View file

@ -0,0 +1,64 @@
{ inputs, config, lib, pkgs, ... }:
with lib;
with lib.my;
let
pubkeys = import ./data/pubkeys.nix {};
in
{
# Set your time zone.
time.timeZone = "Europe/Berlin";
console.font = "Lat2-Terminus16";
console.keyMap = "us";
users.users.root.openssh.authorizedKeys.keys = pubkeys.ragon.user;
# Select internationalisation properties.
i18n = {
defaultLocale = "en_DK.UTF-8";
};
# Configure nix and nixpkgs
environment.variables.NIXPKGS_ALLOW_UNFREE = "1";
nix =
let
filteredInputs = filterAttrs (n: _: n != "self") inputs;
nixPathInputs = mapAttrsToList (n: v: "${n}=${v}") filteredInputs;
registryInputs = mapAttrs (_: v: { flake = v; }) filteredInputs;
in
{
package = pkgs.unstable.nixFlakes;
settings = {
trusted-users = mkDefault [ "root" "@wheel" ];
allowed-users = mkDefault [ "root" "@wheel" ];
substituters = [
"https://nix-community.cachix.org"
];
trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
];
auto-optimise-store = true;
};
extraOptions = "experimental-features = nix-command flakes";
nixPath = nixPathInputs ++ [
"nixpkgs-overlays=${config.conf.dir}/overlays"
"conf=${config.conf.dir}"
];
registry = registryInputs // { conf.flake = inputs.self; };
};
system.configurationRevision = with inputs; mkIf (self ? rev) self.rev;
system.stateVersion = "21.05";
## Some reasonable, global defaults
# This is here to appease 'nix flake check' for generic hosts with no
# hardware-configuration.nix or fileSystem config.
fileSystems."/".device = mkDefault "/dev/disk/by-label/nixos";
boot = {
loader = {
efi.canTouchEfiVariables = mkDefault true;
systemd-boot.configurationLimit = 5;
};
};
}

View file

@ -0,0 +1,62 @@
{ config, lib, pkgs, inputs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.cli;
ragon = config.ragon;
in
{
options.ragon.cli.enable = lib.mkEnableOption "Enables ragons CLI stuff";
options.ragon.cli.maximal = mkBoolOpt true;
config = lib.mkIf cfg.enable {
security.sudo.extraConfig = "Defaults lecture = never";
# root shell
users.extraUsers.root.shell = pkgs.zsh;
environment.shellAliases = {
v = "nvim";
vim = "nvim";
gpl = "git pull";
gp = "git push";
lg = "lazygit";
gc = "git commit -v";
kb = "git commit -m \"\$(curl -s http://whatthecommit.com/index.txt)\"";
gs = "git status -v";
gfc = "git fetch && git checkout";
gl = "git log --graph";
l = "exa -la --git";
la = "exa -la --git";
ls = "exa";
ll = "exa -l --git";
cat = "bat";
};
environment.variables = {
EDITOR = "nvim";
VISUAL = "nvim";
};
environment.systemPackages = with pkgs; [
nnn
bat
htop
exa
curl
fd
file
fzf
git
neofetch
tmux
ripgrep
pv
direnv # needed for lorri
unzip
tmux
aria2
yt-dlp
neovim
];
};
}

View file

@ -0,0 +1,53 @@
{ inputs, config, lib, pkgs, ... }:
let
cfg = config.ragon.cli;
in
{
config = lib.mkIf cfg.enable {
ragon.user.persistent = {
extraDirectories = [
".config/zsh"
];
};
programs.zsh = {
enable = true;
histSize = 10000;
histFile = "$HOME/.config/zsh/history";
# autosuggestions.enable = true;
enableCompletion = true;
setOptions = [
"HIST_IGNORE_DUPS"
"SHARE_HISTORY"
"HIST_FCNTL_LOCK"
"AUTO_CD"
"AUTO_MENU"
];
# interactiveShellInit broke agkozak-zsh-prompt for some reaaaaaaaason
promptInit =
let
zshrc = builtins.readFile ./zshrc;
sources = [
"${inputs.agkozak-zsh-prompt}/agkozak-zsh-prompt.plugin.zsh"
"${pkgs.oh-my-zsh}/share/oh-my-zsh/plugins/git/git.plugin.zsh"
"${pkgs.oh-my-zsh}/share/oh-my-zsh/plugins/globalias/globalias.plugin.zsh"
"${inputs.zsh-vim-mode}/zsh-vim-mode.plugin.zsh"
"${inputs.zsh-syntax-highlighting}/zsh-syntax-highlighting.plugin.zsh"
"${inputs.zsh-completions}/zsh-completions.plugin.zsh"
];
source = map (x: "source " + x) sources;
plugins = builtins.concatStringsSep "\n" (source);
in
''
${zshrc}
${plugins}
'';
};
};
}

View file

@ -0,0 +1,46 @@
AGKOZAK_MULTILINE=0
AGKOZAK_PROMPT_CHAR=( "%F{red}N%f")
autoload -Uz history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey -M vicmd '^[[A' history-beginning-search-backward-end \
'^[OA' history-beginning-search-backward-end \
'^[[B' history-beginning-search-forward-end \
'^[OB' history-beginning-search-forward-end
bindkey -M viins '^[[A' history-beginning-search-backward-end \
'^[OA' history-beginning-search-backward-end \
'^[[B' history-beginning-search-forward-end \
'^[OB' history-beginning-search-forward-end
hash go 2>/dev/null && export PATH=$PATH:$(go env GOPATH)/bin
hash yarn 2>/dev/null && export PATH=$PATH:$HOME/.yarn/bin
hash direnv 2>/dev/null && eval "$(direnv hook zsh)" # needed for lorri
hash helm 2>/dev/null && . <(helm completion zsh)
hash kubectl 2>/dev/null && . <(kubectl completion zsh)
export NNN_ARCHIVE="\\.(7z|a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|rar|rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)$"
n ()
{
# Block nesting of nnn in subshells
if [ -n $NNNLVL ] && [ "${NNNLVL:-0}" -ge 1 ]; then
echo "nnn is already running"
return
fi
export NNN_TMPFILE="$HOME/.config/nnn/.lastd"
# Unmask ^Q (, ^V etc.) (if required, see `stty -a`) to Quit nnn
# stty start undef
# stty stop undef
# stty lwrap undef
# stty lnext undef
nnn -d "$@"
if [ -f "$NNN_TMPFILE" ]; then
. "$NNN_TMPFILE"
rm -f "$NNN_TMPFILE" > /dev/null
fi
}

View file

@ -0,0 +1,24 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.hardware.bluetooth;
in
{
options.ragon.hardware.bluetooth.enable = lib.mkEnableOption "Enables bluetooth stuff (tlp,...)";
config = lib.mkIf cfg.enable {
hardware.bluetooth.enable = true;
services.blueman.enable = true;
hardware.pulseaudio = {
extraModules = [ pkgs.pulseaudio-modules-bt ];
package = pkgs.pulseaudioFull;
};
ragon.gui.autostart = [
[ "${pkgs.blueberry}/bin/blueberry-tray" ]
];
environment.systemPackages = (if config.ragon.gui.enable then [ pkgs.blueberry ] else [ ]);
ragon.persist.extraDirectories = [
"/var/lib/bluetooth"
];
};
}

View file

@ -0,0 +1,23 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.hardware.laptop;
in
{
options.ragon.hardware.laptop.enable = lib.mkEnableOption "Enables laptop stuff (tlp,...)";
config = lib.mkIf cfg.enable {
services.tlp = {
enable = true;
settings = {
CPU_ENERGY_PERF_POLICY_ON_AC = "performance";
CPU_ENERGY_PERF_POLICY_ON_BAT = "poversave";
};
};
services.xserver.libinput = {
enable = true;
};
hardware.acpilight.enable = true;
services.thermald.enable = true;
ragon.gui.laptop = true;
ragon.hardware.bluetooth.enable = true; # laptops normally have BT
};
}

View file

@ -0,0 +1,12 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.hardware.nvidia;
in
{
options.ragon.hardware.nvidia.enable = lib.mkEnableOption "Enables nvidia stuff (why didnt i buy amd?)";
config = lib.mkIf cfg.enable {
# nivea
services.xserver.videoDrivers = [ "nvidia" ];
};
}

View file

@ -0,0 +1,36 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.hardware.rpi3;
in
{
options.ragon.hardware.rpi3.enable = lib.mkEnableOption "Enables rpi3 quirks";
config = lib.mkIf cfg.enable {
boot.loader.raspberryPi = {
enable = true;
version = 3;
};
boot.extraModprobeConfig = ''
options cfg80211 ieee80211_regdom="DE"
'';
hardware.firmware = [ pkgs.wireless-regdb ];
#boot.kernelPackages = pkgs.linux_rpi3;
nixpkgs.overlays = [
(self: super: {
firmwareLinuxNonfree = super.firmwareLinuxNonfree.overrideAttrs (old: {
version = "2020-12-18";
src = pkgs.fetchgit {
url =
"https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git";
rev = "b79d2396bc630bfd9b4058459d3e82d7c3428599";
sha256 = "1rb5b3fzxk5bi6kfqp76q1qszivi0v1kdz1cwj2llp5sd9ns03b5";
};
outputHash = "1p7vn2hfwca6w69jhw5zq70w44ji8mdnibm1z959aalax6ndy146";
});
})
];
networking.wireless.enable = true;
hardware.enableRedistributableFirmware = true;
networking.wireless.interfaces = [ "wlan0" ];
};
}

View file

@ -0,0 +1,45 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.tailscale;
in
{
options.ragon.services.tailscale.enable = lib.mkEnableOption "Enables tailscale";
config = lib.mkIf cfg.enable {
# enable the tailscale service
services.tailscale.enable = true;
ragon.agenix.secrets.tailscaleKey = {};
networking.firewall = {
# always allow traffic from your Tailscale network
trustedInterfaces = [ "tailscale0" ];
# allow the Tailscale UDP port through the firewall
allowedUDPPorts = [ config.services.tailscale.port ];
};
systemd.services.tailscale-autoconnect = {
description = "Automatic connection to Tailscale";
# make sure tailscale is running before trying to connect to tailscale
after = [ "network-pre.target" "tailscale.service" ];
wants = [ "network-pre.target" "tailscale.service" ];
wantedBy = [ "multi-user.target" ];
# set this service as a oneshot job
serviceConfig.Type = "oneshot";
# have the job run this shell script
script = with pkgs; ''
# wait for tailscaled to settle
sleep 2
# check if we are already authenticated to tailscale
status="$(${tailscale}/bin/tailscale status -json | ${jq}/bin/jq -r .BackendState)"
if [ $status = "Running" ]; then # if so, then do nothing
exit 0
fi
key=$(<${config.age.secrets.tailscaleKey.path})
# otherwise authenticate with tailscale
${tailscale}/bin/tailscale up -authkey $key
'';
};
};
}

View file

@ -0,0 +1,49 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.bitwarden;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.bitwarden.enable = lib.mkEnableOption "Enables the vaultwarden BitWarden Server";
options.ragon.services.bitwarden.domainPrefix =
lib.mkOption {
type = lib.types.str;
default = "bw";
};
config = lib.mkIf cfg.enable {
services.vaultwarden = {
enable = true;
# backupDir = "/backups/vaultwarden";
config = {
domain = "https://${cfg.domainPrefix}.${domain}";
signupsAllowed = false;
rocketPort = 8222;
rocketAddress = "127.0.0.1";
databaseUrl = "postgresql://%2Frun%2Fpostgresql/vaultwarden";
webVaultEnabled = true;
};
dbBackend = "postgresql";
};
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/".proxyPass = "http://${config.services.vaultwarden.config.rocketAddress}:${toString config.services.vaultwarden.config.rocketPort}";
};
services.postgresql = {
enable = true;
# Ensure the database, user, and permissions always exist
ensureDatabases = [ "vaultwarden" ];
ensureUsers = [
{
name = "vaultwarden";
ensurePermissions."DATABASE vaultwarden" = "ALL PRIVILEGES";
}
];
};
ragon.persist.extraDirectories = [
"/var/lib/vaultwarden"
];
};
}

View file

@ -0,0 +1,60 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.services.ddns;
domain = config.ragon.services.nginx.domain;
dataDir = "/var/lib/inadyn";
cacheDir = "/var/cache/inadyn";
in
{
options.ragon.services.ddns.enable = mkEnableOption "Enables CloudFlare DDNS to the domain specified in ragon.services.nginx.domain and all subdomains";
options.ragon.services.ddns.ipv4 = mkBoolOpt true;
options.ragon.services.ddns.ipv6 = mkBoolOpt true;
config = mkIf cfg.enable {
systemd.services.inadyn = {
description = "inadyn DDNS Client";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = rec {
Type = "simple";
ExecStart =
pkgs.writeScript "run-inadyn.sh" ''
#!${pkgs.bash}/bin/bash
export PATH=$PATH:${pkgs.bash}/bin/bash # idk if that helps
source ${config.age.secrets.cloudflareAcme.path}
cat >/run/${RuntimeDirectory}/inadyn.cfg <<EOF
period = 180
user-agent = Mozilla/5.0
allow-ipv6 = true
${optionalString cfg.ipv4 ''
# ipv4
provider cloudflare.com:1 {
checkip-server = ipv4.icanhazip.com
username = ${domain}
password = $CLOUDFLARE_DNS_API_TOKEN
hostname = ${domain}
}
''}
${optionalString cfg.ipv6 ''
# ipv6
provider cloudflare.com:2 {
checkip-server = ipv6.icanhazip.com
username = ${domain}
password = $CLOUDFLARE_DNS_API_TOKEN
hostname = ${domain}
}
''}
EOF
exec ${pkgs.inadyn}/bin/inadyn -n --cache-dir=${cacheDir} -f /run/${RuntimeDirectory}/inadyn.cfg
'';
RuntimeDirectory = StateDirectory;
StateDirectory = builtins.baseNameOf dataDir;
};
};
systemd.tmpfiles.rules = [
"d ${cacheDir} 1777 root root 10m"
];
ragon.agenix.secrets.cloudflareAcme = { };
};
}

View file

@ -0,0 +1,16 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.docker;
in
{
options.ragon.services.docker.enable = lib.mkEnableOption "Enables docker";
config = lib.mkIf cfg.enable {
virtualisation.oci-containers.backend = "docker";
virtualisation.docker.enable = true;
ragon.user.extraGroups = [ "docker" "podman" ];
ragon.persist.extraDirectories = [
"/var/lib/docker"
"/var/cache/docker"
];
};
}

View file

@ -0,0 +1,49 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.services.gitlab;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.gitlab.enable = mkEnableOption "Enables gitlab";
options.ragon.services.gitlab.domainPrefix =
mkOption {
type = lib.types.str;
default = "gitlab";
};
config = lib.mkIf cfg.enable {
services.gitlab = {
enable = true;
https = true;
initialRootPasswordFile = "${config.age.secrets.gitlabInitialRootPassword.path}";
port = 443;
host = "${cfg.domainPrefix}.${domain}";
secrets = {
dbFile = "${config.age.secrets.gitlabDBFile.path}";
jwsFile = "${config.age.secrets.gitlabJWSFile.path}";
otpFile = "${config.age.secrets.gitlabOTPFile.path}";
secretFile = "${config.age.secrets.gitlabSecretFile.path}";
};
};
ragon.agenix.secrets = foldl (a: b: a // b) { } (map (a: { ${a} = { owner = "gitlab"; }; }) [
"gitlabDBFile"
"gitlabInitialRootPassword"
"gitlabJWSFile"
"gitlabOTPFile"
"gitlabSecretFile"
]);
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
useACMEHost = "${domain}";
forceSSL = true;
locations."/".proxyPass = "http://unix:/run/gitlab/gitlab-workhorse.socket";
locations."/".extraConfig = "client_max_body_size 4G;";
};
ragon.persist.extraDirectories = [
"${config.services.postgresql.dataDir}"
"${config.services.gitlab.statePath}"
];
};
}

View file

@ -0,0 +1,32 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.grafana;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.grafana.enable = lib.mkEnableOption "Enables grafana";
options.ragon.services.grafana.domainPrefix =
lib.mkOption {
type = lib.types.str;
default = "grafana";
};
config = lib.mkIf cfg.enable {
services.grafana = {
enable = true;
domain = "${cfg.domainPrefix}.${domain}";
rootUrl = "https://${cfg.domainPrefix}.${domain}/";
};
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
useACMEHost = "${domain}";
addSSL = true;
locations = {
"/".proxyPass = "http://127.0.0.1:${toString config.services.grafana.port}";
"/".proxyWebsockets = true;
};
};
ragon.persist.extraDirectories = [
"${config.services.grafana.dataDir}"
];
};
}

View file

@ -0,0 +1,55 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.hedgedoc;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.hedgedoc.enable = lib.mkEnableOption "Enables the hedgedoc BitWarden Server";
options.ragon.services.hedgedoc.domainPrefix =
lib.mkOption {
type = lib.types.str;
default = "md";
};
config = lib.mkIf cfg.enable {
services.hedgedoc = {
enable = true;
environmentFile = "${config.age.secrets.hedgedocSecret.path}";
configuration = {
protocolUseSSL = true;
sessionSecret = "$SESSION_SECRET";
allowEmailRegister = false;
domain = "${cfg.domainPrefix}.${domain}";
db = {
dialect = "postgres";
host = "/run/postgresql";
database = "hedgedoc";
};
allowAnonymousEdits = false;
allowFreeURL = true;
};
};
ragon.agenix.secrets.hedgedocSecret.owner = "hedgedoc";
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/".proxyWebsockets = true;
locations."/".proxyPass = "http://127.0.0.1:${toString config.services.hedgedoc.configuration.port}";
};
services.postgresql = {
enable = true;
# Ensure the database, user, and permissions always exist
ensureDatabases = [ "hedgedoc" ];
ensureUsers = [
{
name = "hedgedoc";
ensurePermissions."DATABASE hedgedoc" = "ALL PRIVILEGES";
}
];
};
ragon.persist.extraDirectories = [
"${config.services.hedgedoc.workDir}"
];
};
}

View file

@ -0,0 +1,68 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.jellyfin;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.jellyfin.enable = lib.mkEnableOption "Enables jellyfin";
options.ragon.services.jellyfin.domainPrefix =
lib.mkOption {
type = lib.types.str;
default = "j";
};
config = lib.mkIf cfg.enable {
services.jellyfin.enable = true;
services.jellyfin.openFirewall = true;
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
useACMEHost = "${domain}";
addSSL = true;
locations = {
"= /".extraConfig = "return 302 https://$host/web/;";
"/" = {
extraConfig = ''
proxy_pass http://127.0.0.1:8096;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
'';
};
"= /web/" = {
extraConfig = ''
proxy_pass http://127.0.0.1:8096/web/index.html;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
'';
};
"/socket" = {
extraConfig = ''
proxy_pass http://127.0.0.1:8096;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Forwarded-Host $http_host;
'';
};
};
};
ragon.persist.extraDirectories = [
"/var/cache/jellyfin"
"/var/lib/jellyfin"
];
};
}

View file

@ -0,0 +1,17 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.libvirt;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.libvirt.enable = lib.mkEnableOption "Enables libvirt and stuff";
config = lib.mkIf cfg.enable {
virtualisation.libvirtd = {
enable = true;
};
ragon.user.extraGroups = [ "kvm" "libvirtd" ];
ragon.persist.extraDirectories = [
"/var/lib/libvirt"
];
};
}

View file

@ -0,0 +1,162 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = importTOML ../../data/monitoring.toml;
hostName = config.networking.hostName;
getHost = (y:
if (y == hostName)
then "127.0.0.1"
else
(
if (builtins.elem y (builtins.attrNames cfg.hostOverrides))
then cfg.hostOverrides.${y}
else "${y}.hailsatan.eu"
)
);
in
{
config = mkMerge ([
(mkIf (cfg.master.hostname == hostName) {
services.loki.enable = true;
networking.firewall.allowedTCPPorts = [ 3100 ];
services.loki.configFile = pkgs.writeText "loki.yml" ''
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
ingester:
wal:
enabled: true
dir: /tmp/wal
lifecycler:
address: 127.0.0.1
ring:
kvstore:
store: inmemory
replication_factor: 1
final_sleep: 0s
chunk_idle_period: 1h # Any chunk not receiving new logs in this time will be flushed
max_chunk_age: 1h # All chunks will be flushed when they hit this age, default is 1h
chunk_target_size: 1048576 # Loki will attempt to build chunks up to 1.5MB, flushing first if chunk_idle_period or max_chunk_age is reached first
chunk_retain_period: 30s # Must be greater than index read cache TTL if using an index cache (Default index read cache TTL is 5m)
max_transfer_retries: 0 # Chunk transfers disabled
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /tmp/loki/boltdb-shipper-active
cache_location: /tmp/loki/boltdb-shipper-cache
cache_ttl: 24h # Can be increased for faster performance over longer query periods, uses more disk space
shared_store: filesystem
filesystem:
directory: /tmp/loki/chunks
compactor:
working_directory: /tmp/loki/boltdb-shipper-compactor
shared_store: filesystem
limits_config:
reject_old_samples: true
reject_old_samples_max_age: 168h
chunk_store_config:
max_look_back_period: 0s
table_manager:
retention_deletes_enabled: false
retention_period: 0s
ruler:
storage:
type: local
local:
directory: /tmp/loki/rules
rule_path: /tmp/loki/rules-temp
alertmanager_url: http://localhost:9093
ring:
kvstore:
store: inmemory
enable_api: true
'';
services.prometheus = {
enable = true;
scrapeConfigs = foldl (a: b: a ++ b) [ ] (map
(x: (map
(y: {
job_name = "${x}_${y}";
static_configs = [
{
targets = [
''${getHost y}:${toString config.services.prometheus.exporters.${x}.port}''
];
}
];
})
cfg.exporters.${x}.hosts))
(builtins.attrNames cfg.exporters));
};
ragon.persist.extraDirectories = [
"/var/lib/${config.services.prometheus.stateDir}"
"${config.services.loki.dataDir}"
];
})
{
# some global settings
services.prometheus.exporters.node.enabledCollectors = [ "systemd" ];
services.prometheus.exporters.dnsmasq.leasesPath = "/var/lib/dnsmasq/dnsmasq.leases";
services.prometheus.exporters.smartctl.user = "root";
services.prometheus.exporters.smokeping.hosts = [ "1.1.1.1" ];
services.nginx.statusPage = true;
}
(mkIf (builtins.elem hostName cfg.promtail.hosts) {
services.promtail = {
enable = true;
configuration = {
server.http_listen_port = 28183;
positions.filename = "/tmp/positions.yaml";
clients = [{ url = "http://${getHost cfg.master.hostname}:3100/loki/api/v1/push"; }];
scrape_configs = [
{
job_name = "journal";
journal = {
max_age = "12h";
labels = {
job = "systemd-journal";
host = hostName;
};
};
relabel_configs = [{
source_labels = [ "__journal__systemd_unit" ];
target_label = "unit";
}];
}
];
};
};
})
] ++
(map
(x: {
services.prometheus.exporters.${x} = {
enable = (builtins.elem hostName cfg.exporters.${x}.hosts);
openFirewall = (hostName != cfg.master.hostname);
firewallFilter = if (hostName != cfg.master.hostname) then "-p tcp -s ${cfg.master.ip} -m tcp --dport ${toString config.services.prometheus.exporters.${x}.port}" else null;
};
})
(builtins.attrNames cfg.exporters))
);
}

View file

@ -0,0 +1,38 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.nginx;
in
{
options.ragon.services.nginx.enable = lib.mkEnableOption "Enables nginx";
options.ragon.services.nginx.domain =
lib.mkOption {
type = lib.types.str;
default = "hailsatan.eu";
};
config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = [ 80 443 ];
services.nginx = {
enable = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
};
security.acme.defaults.email = "nixosacme@phochkamp.de";
security.acme.acceptTerms = true;
security.acme.certs."${cfg.domain}" = {
dnsProvider = "cloudflare";
dnsResolver = "1.1.1.1:53";
group = "nginx";
extraDomainNames = [
"*.${cfg.domain}"
];
credentialsFile = "${config.age.secrets.cloudflareAcme.path}";
};
ragon.agenix.secrets.cloudflareAcme = { group = "nginx"; mode = "0440"; };
ragon.persist.extraDirectories = [
"/var/lib/acme"
];
};
}

View file

@ -0,0 +1,39 @@
{ config, inputs, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.services.paperless;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.paperless.enable = mkEnableOption "Enables paperless ng";
options.ragon.services.paperless.domainPrefix =
lib.mkOption {
type = lib.types.str;
default = "paperless";
};
config = mkIf cfg.enable {
services.paperless-ng = {
enable = true;
package = pkgs.paperless-ng.overrideAttrs (oldAttrs: rec { doCheck = false; doInstallCheck = false; });
mediaDir = mkDefault "/data/documents/paperless";
consumptionDir = mkDefault "/data/applications/paperless-consumption";
consumptionDirIsPublic = true;
passwordFile = "${config.age.secrets.paperlessAdminPW.path}";
extraConfig = {
PAPERLESS_OCR_LANGUAGE = "deu+eng";
};
};
ragon.agenix.secrets.paperlessAdminPW = { group = "${config.services.paperless-ng.user}"; mode = "0440"; };
services.nginx.clientMaxBodySize = "100m";
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
useACMEHost = "${domain}";
addSSL = true;
locations."/".proxyPass = "http://${config.services.paperless-ng.address}:${toString config.services.paperless-ng.port}";
locations."/".proxyWebsockets = true;
};
ragon.persist.extraDirectories = [
"${config.services.paperless-ng.dataDir}"
];
};
}

View file

@ -0,0 +1,28 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
with builtins;
let
cfg = config.ragon.services.samba;
allowedIPs = cfg.allowedIPs;
cfgExports = cfg.exports;
in
{
options.ragon.services.samba.enable = mkEnableOption "Enables Samba";
options.ragon.services.samba.shares = mkOption {
type = lib.types.attrs;
default = {};
};
config = mkIf cfg.enable {
services.samba = {
enable = true;
shares = cfg.shares;
};
ragon.persist.extraDirectories = [
"/var/lib/samba"
];
networking.firewall.allowedTCPPorts = [ 139 445 ];
networking.firewall.allowedUDPPorts = [ 137 138 ];
};
}

View file

@ -0,0 +1,12 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.ssh;
in
{
options.ragon.services.ssh.enable = lib.mkEnableOption "Enables sshd";
config = lib.mkIf cfg.enable {
services.openssh.permitRootLogin = "no";
services.openssh.enable = true;
services.openssh.passwordAuthentication = false;
};
}

View file

@ -0,0 +1,130 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.services.synapse;
fqdn = cfg.fqdn;
serverName = cfg.serverName;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.synapse.enable = mkEnableOption "Enables synapse";
options.ragon.services.synapse.fqdn =
lib.mkOption {
type = lib.types.str;
default = "m.ragon.xyz";
};
options.ragon.services.synapse.enableElement = mkBoolOpt true; # TODO fix
options.ragon.services.synapse.elementFqdn =
lib.mkOption {
type = lib.types.str;
default = "e.ragon.xyz";
};
options.ragon.services.synapse.serverName =
lib.mkOption {
type = lib.types.str;
default = "ragon.xyz";
};
config = lib.mkIf cfg.enable {
services.matrix-synapse = {
enable = true;
server_name = serverName;
listeners = [
{
port = 8008;
bind_address = "::1";
type = "http";
tls = false;
x_forwarded = true;
resources = [
{
names = [ "client" "federation" ];
compress = false;
}
];
}
];
};
services.postgresql = {
enable = true;
};
services.postgresql.initialScript = pkgs.writeText "synapse-init.sql" ''
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
'';
services.nginx.virtualHosts = {
"${cfg.elementFqdn}" = {
useACMEHost = "${domain}";
forceSSL = true;
root = pkgs.element-web.override {
conf = {
default_server_config."m.homeserver" = {
"base_url" = "https://${fqdn}";
"server_name" = "${domain}";
};
default_theme = "dark";
jitsi.preferredDomain = "${config.ragon.services.jitsi.domainPrefix}.${domain}";
}; # TODO make this less shit
};
};
"${cfg.serverName}" = {
forceSSL = true;
useACMEHost = "${domain}";
locations."= /.well-known/matrix/server".extraConfig =
let
# use 443 instead of the default 8448 port to unite
# the client-server and server-server port for simplicity
server = { "m.server" = "${fqdn}:443"; };
in
''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
locations."= /.well-known/matrix/client".extraConfig =
let
client = {
"m.homeserver" = { "base_url" = "https://${fqdn}"; };
"m.identity_server" = { "base_url" = "https://vector.im"; };
"im.vector.riot.jitsi" = { "preferredDomain" = "jitsi.${domain}"; };
};
# ACAO required to allow element-web on any URL to request this json file
in
''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
# Reverse proxy for Matrix client-server and server-server communication
"${fqdn}" = {
forceSSL = true;
useACMEHost = "${domain}";
# Or do a redirect instead of the 404, or whatever is appropriate for you.
# But do not put a Matrix Web client here! See the Element web section below.
locations."/".extraConfig = ''
return 404;
'';
# forward all Matrix API calls to the synapse Matrix homeserver
locations."/_matrix" = {
proxyPass = "http://[::1]:8008"; # without a trailing /
};
};
};
ragon.persist.extraDirectories = [
"${config.services.postgresql.dataDir}"
"${config.services.matrix-synapse.dataDir}"
];
};
}

View file

@ -0,0 +1,22 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.ts3;
in
{
options.ragon.services.ts3.enable = lib.mkEnableOption "Enables the Teamspeak 3 Server";
config = lib.mkIf cfg.enable {
services.teamspeak3 = {
enable = true;
};
networking.firewall.allowedTCPPorts = [
config.services.teamspeak3.queryPort
config.services.teamspeak3.fileTransferPort
];
networking.firewall.allowedUDPPorts = [
config.services.teamspeak3.defaultVoicePort
];
ragon.persist.extraDirectories = [
"${config.services.teamspeak3.dataDir}"
];
};
}

View file

@ -0,0 +1,26 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.services.unifi;
domain = config.ragon.services.nginx.domain;
in
{
options.ragon.services.unifi.enable = lib.mkEnableOption "Enables the unifi console";
options.ragon.services.unifi.domainPrefix =
lib.mkOption {
type = lib.types.str;
default = "unifi";
};
config = lib.mkIf cfg.enable {
services.unifi = {
enable = true;
};
services.nginx.virtualHosts."${cfg.domainPrefix}.${domain}" = {
forceSSL = true;
useACMEHost = "${domain}";
locations."/".proxyPass = "https://127.0.0.1:8443";
};
ragon.persist.extraDirectories = [
"/var/lib/unifi"
];
};
}

View file

@ -0,0 +1,39 @@
{ options, config, inputs, lib, pkgs, ... }:
with builtins;
with lib;
with lib.my;
let
inherit (inputs) agenix;
secretsDir = "${toString ../../secrets}";
secretsFile = "${secretsDir}/secrets.nix";
cfg = config.ragon.agenix;
in
{
imports = [ agenix.nixosModules.age ];
options.ragon.agenix = {
enable = mkBoolOpt true;
secrets = mkOption {
type = types.attrs;
default = { };
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ agenix.defaultPackage.${pkgs.system} ];
# Set passwords
users.users.root.passwordFile = config.age.secrets.rootPasswd.path;
age.identityPaths =
[
"/persistent/etc/ssh/ssh_host_ed25519_key"
];
age.secrets = mapAttrs (name: obj: ({ file = "${secretsDir}/${name}.age"; } // obj))
(cfg.secrets //
{
rootPasswd = { };
}
);
assertions = [
{ assertion = (pathExists secretsFile); message = "${secretsFile} does not exist"; }
];
};
}

View file

@ -0,0 +1,92 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.system.fs;
nix = cfg.nix;
varlog = cfg.varlog;
persistent = cfg.persistent;
persistentSnapshot = cfg.persistentSnapshot;
arcSize = cfg.arcSize;
hostName = config.networking.hostName;
in
{
options.ragon.system.fs = {
enable = lib.mkEnableOption "Enables ragons fs stuff, (tmpfs,zfs,backups,...)";
mediadata = mkBoolOpt true;
swap = mkBoolOpt true;
persistentSnapshot = mkBoolOpt true;
nix = lib.mkOption {
type = lib.types.str;
default = "pool/nix";
};
varlog = lib.mkOption {
type = lib.types.str;
default = "pool/varlog";
};
persistent = lib.mkOption {
type = lib.types.str;
default = "pool/persist";
};
arcSize = lib.mkOption {
type = lib.types.int;
default = 2;
description = "Sets the ZFS Arc Size (in GB)";
};
};
config = lib.mkIf cfg.enable {
services.zfs.autoScrub.enable = true;
services.sanoid = {
enable = mkDefault persistentSnapshot;
} // (if persistentSnapshot then { datasets."${persistent}" = { }; } else { });
services.syncoid = {
user = "root";
group = "root";
sshKey = /persistent/root/.ssh/id_rsa;
enable = mkDefault true;
commonArgs = [
];
commands."${persistent}" = {
target = "ragon@ds9:rpool/content/local/backups/${hostName}"; # FIXME extra user
recvOptions = "x encryption";
};
};
boot.kernelParams = [ "zfs.zfs_arc_max=${toString (arcSize * 1024 * 1024 * 1024)}" ];
fileSystems."/" =
{
device = "none";
fsType = "tmpfs";
options = [ "size=8G" "defaults" "mode=755" ];
};
fileSystems."/nix" =
{
device = "${nix}";
fsType = "zfs";
neededForBoot = true;
};
fileSystems."/persistent" =
{
device = "${persistent}";
fsType = "zfs";
neededForBoot = true;
};
fileSystems."/var/log" =
{
device = "${varlog}";
fsType = "zfs";
};
fileSystems."/boot" =
{
device = mkDefault "/dev/disk/by-label/boot";
fsType = "vfat";
options = [ "noauto" "x-systemd.automount" ];
};
swapDevices = mkIf cfg.swap [
{ device = "/persistent/pagefile.sys"; }
];
};
}

View file

@ -0,0 +1,34 @@
{ config, lib, pkgs, inputs, ... }:
let
cfg = config.ragon.persist;
in
{
options.ragon.persist.enable = lib.mkEnableOption "Enables persistence";
options.ragon.persist.extraFiles = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
options.ragon.persist.extraDirectories = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
config = lib.mkIf cfg.enable {
environment.persistence."/persistent" = {
directories = [
"/etc/nixos"
"/etc/NetworkManager/system-connections"
"/root/.ssh"
] ++ (lib.unique cfg.extraDirectories);
files = [
"/etc/machine-id"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
] ++ cfg.extraFiles;
};
};
}

View file

@ -0,0 +1,27 @@
{ config, lib, pkgs, ... }:
with lib;
with lib.my;
let
cfg = config.ragon.system.security;
in
{
options.ragon.system.security = {
enable = mkBoolOpt true;
};
config = mkIf cfg.enable {
security.sudo.execWheelOnly = true;
services.openssh = {
passwordAuthentication = false;
allowSFTP = false; # just use rsync, lol
kbdInteractiveAuthentication = false;
extraConfig = ''
AllowTcpForwarding yes
X11Forwarding no
AllowAgentForwarding no
AllowStreamLocalForwarding no
AuthenticationMethods publickey
'';
};
};
}

View file

@ -0,0 +1,65 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ragon.user;
uid = cfg.uid;
username = cfg.username;
extraGroups = cfg.extraGroups;
extraAuthorizedKeys = cfg.extraAuthorizedKeys;
pubkeys = import ../../data/pubkeys.nix {};
in
{
options.ragon.user = {
enable = lib.mkEnableOption "Enables my user.";
uid = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = 1000;
};
username = lib.mkOption {
type = lib.types.str;
default = "ragon";
description = "My username for this system.";
};
extraGroups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
extraAuthorizedKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Additional authorized keys";
};
persistent = {
homeDir = lib.mkOption {
type = lib.types.str;
default = "/persistent/home/${username}";
description = "Location of persistent home files";
};
extraFiles = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
extraDirectories = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
};
};
config = lib.mkIf cfg.enable {
# Let ~/bin/ be in $PATH
environment.homeBinInPath = true;
# Define my user account
users.extraUsers.${username} = {
isNormalUser = true;
uid = uid;
extraGroups = [ "wheel" ] ++ extraGroups;
shell = pkgs.zsh;
openssh.authorizedKeys.keys = pubkeys.ragon.computers ++ extraAuthorizedKeys;
passwordFile = config.age.secrets.ragonPasswd.path;
};
ragon.agenix.secrets.ragonPasswd = { };
};
}

View file

@ -0,0 +1,23 @@
age-encryption.org/v1
-> ssh-ed25519 EYWzzw s1ga0W2GlpxvKpJ5Kx9/mrpXuD4k/V/1uyfbFUcEdwU
ZIdAidep1f/sFMjHZdAjB1saoLQUctcOUx1XQGq1Q/U
-> ssh-ed25519 ugHWWw sCuDEuxoovkiU6b6Ww/pdvLmWsKOwoviTGGi62kmkyk
u3N+jIsrTQSwADhD4QcCPJ2jBt2/A0aiIK9L0Bn0e3U
-> ssh-ed25519 UDK5aw KYVDBaHIOdx0FpOjPPoDTS6diaufODfUYMke6wcMLis
hZK8nGvGrnMQNph+7zbF+LNG6W8UPNAMlOLvPLKDPY8
-> ssh-ed25519 UU9RSA yr2M8vpo3cHxTOv8JhnLj1qQiBMG4XZVQEimEEjqOXI
bsncvUeAodUjeUXA6h+r+DYdSWMn9Lp8bPRQuOdUj9M
-> ssh-ed25519 IbXxfw DjdQxpVTLUvha7TVaYBDrCTOZVrvKvxfUCoD2ZdMuAY
pRMtuOxmqRHC7TYBXX+MKW0fbD1qAzV4HBGtTTZQeJ0
-> ssh-ed25519 rQk6HA DJiT9I5C7KuzkQ3XwzjfFZSKHDPXGgbVfBcY1c9QJGE
TvvCAZkd8Mo+oxmwr5zXiwGdc0PynDpYI/1cnHxjcfQ
-> ssh-ed25519 WceKOQ UzyJi0AJRLXE3Jhgkee5NdAB2qFrykwZz9FUhWObC2M
vdCqdMB0+k+aLMIQFU0TjCZ80MnqWpnqzwuhNqH5sFI
-> ssh-ed25519 LUZRUw bFixT06NSFkfLHoOhuWzC7jUXAwwww+il1uZbfogGE8
eKP12b9v9TYNw0F1wfnAk7BgypUfsYMZVZGJLswP+FI
-> R5?8K38S-grease
HpSifTD/jnLUvi4PEfP4aWDuuiCUeZKN/RsP3P7C/8p/cipmpdcKOKDvi3AAeZ9V
8As01hN4UuHzSzaOc5CeVROrsA
--- HkOPg3vXo158UyTD+VNTkMpH6bkXWOXOMLtuuvVG06I
ÌÌHc}.úVNiÓ¢…Sóú…Ea]Aíküy%K?™&gÕ
[êêçÌ{$ª>C®ó×3)mu¥þöQ i¯,BÏøç!¦È0 <0C>ÜA™¤Èý¹å #õ¸

BIN
secrets/ds9rcloneConfig.age Normal file

Binary file not shown.

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> ssh-ed25519 IbXxfw XK4JR/3v6N7eW9xCvt4yxZj2zAhnqo1b6ou0v82gOzA
Tag0cu4RUD8LdqBqQcX8tjbCpDIqC2rK1+zG/F2kB04
-> ssh-ed25519 EYWzzw RVwN1oUaYweuKCGvcHuq2H3kUjNJmlnC0u6ZDLYk8VA
dOei5ZouQ/2tWCu5fjWD4VqaEod7ag8p3y3Yo4E+R3U
-> ssh-ed25519 ugHWWw 9O+v/f9NYZED2havMCBQI3aFk2+lkBl9O8O7Wny0Gmk
iPHKN5W4OEJqXKXTsil2mTcdsbG3CCSgQodhqBQCi2Y
-> ssh-ed25519 UDK5aw DBCXaQWwhk1GOFxZQcckAQ+QhJI9xc74J2x249RJMQM
RaoiO3QYjFY6CGAEGff1KLsaKqzRJc42UitJfGKe25U
-> ssh-ed25519 UU9RSA dwDPtrzsuxLOZ0gbIzQswfX6fqbtfgRY1WhX6rhP8D0
RcIeHO1535EbQKBU72EgaulDohMZbO4vM3VoSUBnIQ8
-> (cz;R:-grease i .rY6u!
gJQ8wOQJ6lBS7wnMZ1cu+mSDWxedwi0PUU8O6lZlnhyAqf5RQsfrvpWzNO3BrPx7
1cmlFDMkAFtNhWlDDEFVk/rV0jBSbOy1I+/oTTOn8d8karnmI6kaB+I
--- MCSRxrB6r/ju9i8A6cvglUNFhHOicaeeb38fsIa2ArU
楳fz─ヌフ梟朦ョ殊オ衰スnルcミヘナワb蛮#C訪汢峺オr<ク2[トヌ繕テ鵲メ憂。u1ェヘ

BIN
secrets/gitlabDBFile.age Normal file

Binary file not shown.

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> ssh-ed25519 WceKOQ O3wwFkrDb9osW2SXJqJGfEr9fi2rXmussWoM0+OUzyM
suoJbwFbIKxn7rslfzhZpNc7Pp6C9wkmPlE9GgBlZtY
-> ssh-ed25519 EYWzzw P9AGXvkFAjucxdoeD5qM2w5HfBwFG+FxZHDr9uyDFl0
oep6yVm9PxtRciEv9ILK0n2bH6x8KEl7eH/gjmCIef0
-> ssh-ed25519 ugHWWw om4WnbKKwkycHyNcivPBQEs6WB5KjEc/ZcF4Gsc94TM
fzwdcr78HfvlEgQscUvlKosetpF6pYAykwM8zgaxpYw
-> ssh-ed25519 UDK5aw ztMz33oaFDgY4V/KSJWLu7sYzZeNM8eesoKCcLVj2mg
J74Fe7dGPTceGjcLp+nwMewaiuu8kSFo1qVxvlMNmkI
-> ssh-ed25519 UU9RSA hiji4Kfll9Yhpj3BOuYf9argzE/GiIJUH5hDvFG60WE
SRPPaOnnALmcUjvt819IAuF1bRJjDaYmDvu5OGC2N+4
-> +e#q&Lk-grease LkPbm`t mB) O;V\6xU
sm/woJ9+G0+TIxfPi0MYAnZvSq/hnwaMYLhlNvkZNR1H8suywEy5CDPgcETNHGhD
jsJ9PMfW4ih1m1d21vo
--- WxnJsQtYXlF+FCYeK88SLwDiKSXhzrKBhomyPVrpqzI
•P dÙ@ÈÒ$ÖÖᜠÞÅÅ£T”H;ó[|]Œu-‡¾å,mùªôf°¸>•<>q

BIN
secrets/gitlabJWSFile.age Normal file

Binary file not shown.

16
secrets/gitlabOTPFile.age Normal file
View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> ssh-ed25519 WceKOQ R+pOKGMX6Uing364chthIWXmTJ3sQIL0hlXq0qxoGS8
gQLfoQGS9BQSn80qWmMzOVEcrCrHJ70/njWs2dcJs9s
-> ssh-ed25519 EYWzzw xXm/A3xntlVTDXqD2oQ/gFDGNT8H5PCQK834iO2RZTc
Qpon9sEGFzfWxeVltgZOfwhejrs8AWavgqDaquPPPig
-> ssh-ed25519 ugHWWw qEeU19yDAJaQOkv3hJLDZcs4xtKKOnMJzjEz9cZzeXc
yWFJrCJAX0qBJ9LPTUH/mVWAJAjyxPESNQJomGMjx7I
-> ssh-ed25519 UDK5aw /7QjG660+ZykYWsk0A12DxOKaUcSV7cqM2DA+bu4pzI
0aVVXQWcuOtCBg5HplO5VF2P2a/mIdPoBW+s+X8LRHk
-> ssh-ed25519 UU9RSA KCS1HxNT9Txrq05pL38j3oQQrrV/4qrPicV/UazgNXQ
9VvHtDp3ZXk8IYlyM80O+auJVTBf17qttbm6GAGyVT4
-> 6)BN-grease Jd1zY?T 4jN4F
Bmeg810ybQHwsjiCN7fwFxsLzmEkzSYFQzTtVtDq6PYRGIGGaHTnFPYxuWW8MsL2
V5A1aA
--- X+gMieEzMKcX50sXGVGL275TFp3ptHkMXQsDkQ2udsA
ÎÉb´<C2B4>œ¨ º“ž¿|´)3ZI™/ž¥°w\³mÎÔ¼\ao<'òÙìWÇëZb]¶|äxÑÞ/þbà¸y­1#ÜTä¬ÏÒÙÿ:7§ÇÞ˜¸H²\Ie#òX§“¤µ©Šcú<­$B•}ç

Binary file not shown.

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> ssh-ed25519 WceKOQ qPy80JxSrqMnprxN5RkVCzVPZi6C43sypfUc4rZ6li8
QTWC2VuFrpiByU9bsBkK2FnPnEcKRhd0w9EkT/MOrYI
-> ssh-ed25519 EYWzzw KWKmPzo3exCUCE/PMiPmrjcECpyAf3xF/hctVtnWmFE
SWAI3ypZqaBRLsOLGNiEqK17BweqgdB8/e5vbVy3ieI
-> ssh-ed25519 ugHWWw GfcgCYxD9rSrvYYmscVuvbVNKOtYrm2I1BikMf1vg3A
ZEugKdyNcNNxD4w6ea/Xz1Ab2UybvJXA4+F19NT0lfE
-> ssh-ed25519 UDK5aw EK0m2andEafwy5amZKIUeP5LZXjdlO60RkeTgf9+DlU
J59Tced+MQwDwiZhzOMTJwbRtoQpS8E2ElogX7qzqX4
-> ssh-ed25519 UU9RSA cbMRnpYp2ormxzmeqIuxUTh3BPU+tN/ETa+bf9KRBCE
POXnGDH+R2iIOUD1li9JIu01nBe1FJx+8bd1KVmAy0M
-> BP-grease
3dvL7FFeZerLMpkT8a7S6RW8KzmLAV4RmtbeA+r6+N2FoFLO2cdFlSbuPLThEmxB
yIreuiiiz2AwHCdLJgiwsL5HvgWffhv6b3bLUhmiG6EZKK3aaO6FtqfBU3b4Qg
--- UiMKeSciiCqOkSVKuwLbn1nnFDITH8+Ujj2f2tkiYJE
¶ñ?å¸ÄÙu÷Ï0<î}•w@µÀOáNëPî«K¥Aã( ½m ˆ/6æÕB¿ùýéØÃ/oàäøþl7±õ`à z"Þ—L êáEoXé

View file

@ -0,0 +1,15 @@
age-encryption.org/v1
-> ssh-ed25519 WceKOQ MbkajkkIy0oXTeZ/bSCEQztAUzyMJgEP7TeKqecFEH0
M/xDTLw3p66CXUrWNYymb/Rcx6zSJqtdwlCXqNKzfHU
-> ssh-ed25519 EYWzzw o2aUcPNvoAtmZL/KE2thMEmRGE87NazSaZQV1JfA81E
oy67nzTRX14GUgJPUFdBF9yRM5OAH0WKOqDCfE112z8
-> ssh-ed25519 ugHWWw xxY7ev4r58S7JAAu1L2dIMJAEqbj1sJgCBwvdetWoks
NCMrYUg9eJ41Era/85y0H3b6m3RogCK5FceJ2X/K/fA
-> ssh-ed25519 UDK5aw jKQWY0Odh882Q2NYjhg1wrXOEb/4KGKyRAhwcbmsWVI
U0F2g+Yt898YBM9P7uFpVAtkKEkJuGRhiv64jHL3mx8
-> ssh-ed25519 UU9RSA 4LSOqIvpui2kU8TypqZ/dbKSh9VfZYvjxCv7xg/faXo
QTOsnrpCaEofvDxg7oMnn1gK93ReF/6SFCpSrWpwcm8
-> "-grease
G4cNBeH2EPobBiBiU6BPy00FiFULUhedZxH8tFvrJqsyH2+p+cV4MznhAg
--- sQZVwEZzBiHlKnrj37A8DSYPPoJGav3TVIdxLOUi9C8
¬©­D|" b9{ö]{ѶÐâ8inèÖ'Šì<E2809A>ž¿jçqC€Þ<E282AC>ï ¼ÊáJاÌ@<40>Á•4f>½ŽÀÚD Õª

21
secrets/nextshot.age Normal file
View file

@ -0,0 +1,21 @@
age-encryption.org/v1
-> ssh-ed25519 EYWzzw tj5NW5ng7yfhKRm4dncnJ2xZ3o5pVAxqzQivvQ6mXDQ
ATihm128mF4HaeNbxplkrE7rdBV7A/VIlD11j79IhAE
-> ssh-ed25519 ugHWWw jVRjWi9tydm104QR2cs19taFWxi/zvxaXaLdIcAlyGs
8q3m4QoxhRZ11als4FJUjf9NUTqYGmndZnjc2vM077M
-> ssh-ed25519 UDK5aw 8mZY2owpK1lQIqLfMwjcXavVj8ScHG34isEA7l8vzF8
iwcZ6cNsmcWyDUTvnosBV8maNo0Fq0IGEDfri2/VooA
-> ssh-ed25519 UU9RSA Jbve4bnS4wfsIogRcntp9gOIAR4Zy1clQOpYYZ343h0
Y+kYG6bQzcYadkH5uhtwRCyVTPyPKcyLdSrZk27bXrE
-> ssh-ed25519 TCMRjQ cpzssF435zpqKx2ygNZhvq4DTvgL2f6RuWUsEbOQ9SE
FP1C3M8j1JvlJeOk7+ZXrMtqYn0u35ybt5Ri0rutREc
-> ssh-ed25519 A1vEZQ 5OtnAWr4AC6hhBKuh26uaLHhQvRkyMjnAF6gAsLwdmE
SU6IZ6yuZ5rcEQU26xFJ0jdr9/OdpGOdBn74Lfieu0I
-> i]-grease z7o| %'2
jJyVYxDbM0UrKXN29te7RrL1x60VX1119PmeW09g4nCd+YTCdD5u+U+T96EwkrIX
ndI0wzLzogzte7ARWi9TeSc
--- x06Im9OXtUo6qGrnJzQONcnHt+Id4qDsDWJ3KoMkVZw
&,¿¬ìcéÔwuÐ<75>
–ßžÿ ÝÝ8Dš¹)(K¬r[ËR?ª<E28093>nè·\g °1ébþ5òÉÞ¿…²YÚžn$žÓ{Ï‘×é@-ïùž[hŠØó±SdxïÊfÌ}O_<>ã·}
<EFBFBD>Éí5æËRía†O´îj•Èÿ¸òž€¢QÕ&)¹?La†óø<C3B3>ÎÎaBsEˆîCð÷3Ä\
О7„)Tç`†Õ,Ó,¬(öPä<>

View file

@ -0,0 +1,16 @@
age-encryption.org/v1
-> ssh-ed25519 IbXxfw 0vBEJFvcwF7hzeeRQzfDcEhKbzbxpjzO3YC/Sv1fJFE
UrHnc3CuXuUcl9K/K91K7lWdk/zdMaQ73f81G9PrmvE
-> ssh-ed25519 EYWzzw Zd8oNVysYcx1EpWyMj3ph4jYaB7Eq3gzC7v2GQbEfAA
g6jQnLAwHgprVuJWC/OUqQL8G1lpp0Nlc9auzfr4IqY
-> ssh-ed25519 ugHWWw Oi86lLhVSDcWwmZkw6q3s3IMWwUQbUHL/czBy3TFgC0
Wda3sTOmEaDZAhmb15XmClYCxc5/OaE5cpGvhs4Gj1g
-> ssh-ed25519 UDK5aw 7eMa9eCptwXJNa+oDE06kuLDLbZpA/MObAEC3v3fQU0
UbJW7NW8QFDqbbcqtWOzAggl1dwKfYItW2DqIwpstes
-> ssh-ed25519 UU9RSA 981DT5jhUQWsMRTtQeaIODB/2QhHbpnVTYXMUo4VTDI
L2WGEDRaw+9kk1BEcqlWiHuJ6blE5rQH7ft3zfU9lgU
-> 7KMg-grease }Bi!Bu
e3nIsNcarX6rZxTQUNvcKXNIBdLzaoq9pEujDdrz3d419fZcho4DFzfL9tH6KCTQ
0wxY6xHRWaceuScbLw3/Xp0eGTSKJCu2DgQEIlq2P+GsfI7UEzYzhyDMIbrfHdA
--- yVntoj9MmoKBcgku2dwseEuYKblBHOsnMdnJAQIweqg
3ª»•™\ZªàWlSS-ÜŽ}&Àfë îÀéö0¨bU %¡úÑüÖN$jŒ>רÉÊtË__

BIN
secrets/pulseLaunch.age Normal file

Binary file not shown.

30
secrets/ragonPasswd.age Normal file
View file

@ -0,0 +1,30 @@
age-encryption.org/v1
-> ssh-ed25519 EYWzzw LbEHSAdVBebfazL1rZjf5GyzMf1yP47mIP0LmhZwalE
o42K++wV+1LdVqpxMARnQwvBpeNl9rqjhTrMA9snHC8
-> ssh-ed25519 ugHWWw ajZwDkSl0AsFcC8D4J8wCi2M3zRTzaoHh91L/Hcl9kQ
HUxAdisSCHo7HU7zmCHdrB9RzLJzsvBViltf1jpnApA
-> ssh-ed25519 UDK5aw Y9o2xBOWsnNzh7aNSLpZ475Lpeejzj59CuHcCLLWVjE
lpojh/7y9sGhTDNIa0n4hPgzD7k21nN9Dy4AMuf6VU0
-> ssh-ed25519 UU9RSA LfaWl7nuN2GOwZIAHVyuN6ugAH5hQbXwoV4XVZs5Xys
VXM3UeUshSONLLtk4/u/+1ehFF87oQizAjZuyZmKrNg
-> ssh-ed25519 +5moNA U7Xc/WZNU9fG3N0F2FItc2N2DRjhctESKldopfYE8G8
ZJO8kKWKESx7SWCC9ov0Fl8id3G7p3fKkOpXfb+wj/0
-> ssh-ed25519 IbXxfw IuxBXiZDSMw1Z7UHkud2cZ8D0ODLgjFy6shfVooEWGA
agKSGMAhd2ddFqXRgyN3rXCkWy5YwZxORoMbpVVVLV4
-> ssh-ed25519 TCMRjQ M5C/XXI7ewoj3gR8OThBinECnnsJubtnQDjXi6TZIkA
bqwd+jfwHAXrvA4HNWk1kgBuOG027Jb39gN1A8cG8ac
-> ssh-ed25519 LUZRUw pcTrQk3BV6ybiye0SUdVRlEcCrBHYMGzbI/LVhZPDik
nmD5/hsc8tPIt89H1Rj9adS/Qs9LJxiOlvBA+eTKASc
-> ssh-ed25519 JiyliQ x4Eu+fH+AH1rOvzU4WT/2hLhMwuTd8ti9CmAPcoki1s
4vPL0xx5pAPzXqeORfrx0T5U/h+8O7ilDYB9/Njv3wM
-> ssh-ed25519 WceKOQ W3iu4XgTFLulYokT9KNYE/Msh9nGmz3qvC0L1uPQuDo
YpNMGLYJBQniMhYFuTT2LQyh/MtyxxpkKpbOW/ydU54
-> ssh-ed25519 A1vEZQ hgTnHuA5JYoFb2SgP6g2b1JdJUGmeOd4bXQjYT+3EAY
raawl2Q1vE8aapZtQPx8F6z8xjXefg6sGUq5GEJy6LQ
-> ssh-ed25519 rQk6HA 8g14/ad3zsoWVVpHsabC1G8fQGc1/zgdXn5vddy9sHo
I3osCkU8TRPSj8Q2pnKahKfb/pW45604RT+WUpSn6cA
-> WMXV_pP-grease mfm`1 K H58g1@ G#jL
--- zIvDzBi7eG6xi72O9H7PgwHhLmd632NULQixvMTIkfA
µŠ<EFBFBD>þ§0¶1éü¨‡,MNÙ\<5C>"/Uu¨˜J1(…Eâ<45><C3A2>Ì
_ò©àÉsíXüÍÇo<C387>³¼øw ]Ñú†,…` g {ðûä¹POL AôI¹%^ÒZžfyÓÆ^àLâÈ—%®{ $žë:¬ÿ¤@«ú 'n¥ï³Rfø˜ ý“Œ×

30
secrets/rootPasswd.age Normal file
View file

@ -0,0 +1,30 @@
age-encryption.org/v1
-> ssh-ed25519 EYWzzw dZmQekgsKFafQQhp7PwxDNqZDeaebBcWFKdvVu9kNHA
kVo8BSe/TspDiSrlY6c96pTDYKWI10W3eLmX7xFxaGo
-> ssh-ed25519 ugHWWw kJUdRcAS6A6DDBPIarIqOggxg/eEXh+jxH8LJSUTsQE
27in5J/hHjq+3jbYZcnEnHnjicEQAugZgb9TiqcJYPE
-> ssh-ed25519 UDK5aw ktCg7oNhGxECw6q8M8/JKXud1DhmDHD+xv0CfZ5Qwyg
9JlW/TozHaUbgBe1nLCHih/zj0vevp27O8TSNnrRvgs
-> ssh-ed25519 UU9RSA Tl1dJB11BCY9lcP1P0SsfLK/QSJfEX3dGHIT8UyIeDM
s2Buc+kl6x2OQ2r84SKgo9PpC+Eiejf/2AW8GRCd+Wo
-> ssh-ed25519 +5moNA 8UUbmm2Fa0GqH5gFWXtqX7E7aXcXVQk7xlqoV8xyDEM
PfdKnfMiuQFaEdHcn2cOh8WvrTygJfwm6BvOMrbQg5k
-> ssh-ed25519 IbXxfw 3GbBo0aiHormx1vaWepMNOxo5MMwfZY63SkpMsaYcy8
uatK0JPADzjsrsHBNw1Vk929lLGy6Xk66X6f4TzMwM8
-> ssh-ed25519 TCMRjQ ezup1/sMk6PVqAvB3M+GhrVQ8tv/NDKaH7+GYS8LBAQ
j3aISluVVvBKH+3Am4E8fitt60OoXNRl+fVccpK+o/0
-> ssh-ed25519 LUZRUw GcNbGgIb/hD7iKWOaHrcDVpSsL3WU4spuz+Vc4/10UY
79nb2p60oLD5Wk3zPhgtu+jzWKSC+5yLSntL8k1ifjU
-> ssh-ed25519 JiyliQ hhKOdm1yh5p20dmx2u7UN1jMe4do/DX7JABuG9ZWYVs
vjXNjwDRrKoblD+YvUZ5I5m3WiKhPVel5bVhq9oXAPg
-> ssh-ed25519 WceKOQ /nHYPRaI7sZ9n/Uwu+29G22eutdtFFbSpznCI6OvCSc
xPX2vM6DvY4qufPz5qBttlaP0+8T76q702RTBXzGO6I
-> ssh-ed25519 A1vEZQ xycFO6K3nIi5snUvFJuvaGF3jz494XEQgg4FNdKYlxU
8PIB1GitMv02dDN9/m8sL4Akky9G+urXBnmyd5FWseA
-> ssh-ed25519 rQk6HA duhoJYbtWugdP1mLfO+kwoJKJQJ25fO7xEPM+ggPaVM
nY3yWU9U2zOgpiR7LRHOF+xlIO/Un8axMcBA80TtwS0
-> k-grease "\MEjtT TJcP!x (s[ZZi
9LSNSacH0dnlqlFcH9KjOTv1vssUaQfnuYXWgAZDX/TCv8OIDlz3eSbGf19xZUhT
uvMMqWgj7pX568TcBSwB
--- h0XAcn8PIMXq9lHfZidKzvAMF4UfvVGs9uznenpCjFs
yÇSèq¸jxˆénš>9™;±jP¡¾Nsfº\Îxó=pÉLƒì<,ÂSY8°cƵ·êå­·ëOÚmZÄ\Ï-Sã†þL]]ιF §»pvã]œSx³]û\&l¬¯}YîÏ`X#]þ~,„xò«äíqd0VÈ^B#‡M\,&S

23
secrets/secrets.nix Normal file
View file

@ -0,0 +1,23 @@
let
pubkeys = import ../data/pubkeys.nix;
in
{
"cloudflareAcme.age".publicKeys = pubkeys.ragon.server;
"nextshot.age".publicKeys = pubkeys.ragon.client;
"pulseLaunch.age".publicKeys = pubkeys.ragon.client;
"rootPasswd.age".publicKeys = pubkeys.ragon.computers;
"ragonPasswd.age".publicKeys = pubkeys.ragon.computers;
"tailscaleKey.age".publicKeys = pubkeys.ragon.computers;
"paperlessAdminPW.age".publicKeys = pubkeys.ragon.host "ds9";
"ds9rcloneConfig.age".publicKeys = pubkeys.ragon.host "ds9";
"ds9resticPassword.age".publicKeys = pubkeys.ragon.host "ds9";
"hedgedocSecret.age".publicKeys = pubkeys.ragon.host "picard";
"gitlabInitialRootPassword.age".publicKeys = pubkeys.ragon.host "picard";
"gitlabSecretFile.age".publicKeys = pubkeys.ragon.host "picard";
"gitlabDBFile.age".publicKeys = pubkeys.ragon.host "picard";
"gitlabOTPFile.age".publicKeys = pubkeys.ragon.host "picard";
"gitlabJWSFile.age".publicKeys = pubkeys.ragon.host "picard";
"nextcloudAdminPass.age".publicKeys = pubkeys.ragon.host "picard";
"wireguardwormhole.age".publicKeys = pubkeys.ragon.host "wormhole";
"wireguardvoyager.age".publicKeys = pubkeys.ragon.host "voyager";
}

29
secrets/tailscaleKey.age Normal file
View file

@ -0,0 +1,29 @@
age-encryption.org/v1
-> ssh-ed25519 EYWzzw LqSrDXtVPoZ2wV/jLp61ffmZ97tdel5osqMHKJtqGkU
dEptsiFGUnChsdQ1e6zY1xy314jV2hM8mxT7DVTHixk
-> ssh-ed25519 ugHWWw UmcrgVBZh0Exi6nfSbVcoE7H/vShI5uH9YmwPZzJ2Fc
vwP7W4328N78+JB/0Pmf0bqaynObPJnqjldjykJoZkI
-> ssh-ed25519 UDK5aw lZziE8KVejhi9SGffw7ugATxpkkhjH0sK8mSsqtRDAw
/vIpnMLVME5BfXp9Htrx8BgwKdSmz+IaIE+CAfg3RWg
-> ssh-ed25519 UU9RSA mrr+VnPBczJzPDUXuiEB/xMsgobwLMJmzC+CkIhTODo
Ww0R9CWpBcIdhkMCmrwNZEwwGUUkQwaS39kZHkZg9Ok
-> ssh-ed25519 +5moNA 28WI14I3xfIaxAqR30V2IC/2plACYkPH+FdOZxsnj1Y
h1l07zNtcmuhA4JwsY3z4bK4f8zBj6fSE16G26OmWmc
-> ssh-ed25519 IbXxfw ShOPZhuck88CV1GW1JwFIEzrHhqowVWudQBJfFaYEzA
OGt4XWcsrEulshgktz29eRWUJjPhBK90JkrXML7gU2I
-> ssh-ed25519 TCMRjQ B6wbeY4htaQNbHoMj54Vm5u2Nv3/+hZJk0QJZYOPImE
/UXZlqF/Q1ZvdaHzxeaTNGe8NkUIF7mRA4qzL/JNVQM
-> ssh-ed25519 LUZRUw JiB/nTYhBCeiSoSCwJFnCf9hW1OGA4Y5KQpGzpzE72o
yVhuA50na8KM/pT/zPA0g23yYo3meJzsFPAodKsECh8
-> ssh-ed25519 JiyliQ fy2KrCXS9ufecu+NAY1Wv4dbcylOOLKs/UApA02V3Xc
Khn43o6SclqN7QJ7olSGa13KpaHe+EeKlXLkZiFMx5s
-> ssh-ed25519 WceKOQ eLn08w0EuZ3WQR0jQwwMLLaZ8/0S8dLSxc6ukzpJUj4
0A3UfxLcS0xkyrHZrPHU1K3/mEsph8f7fXJLOMNyvhs
-> ssh-ed25519 A1vEZQ 3IPoXmWMEHxXGJkIcgc+jNincRgmxjUR1w8lT67tkHI
QtupNb9H2SDsZ7SeLwim582KT3j2WYT97OKDWyghCw8
-> ssh-ed25519 rQk6HA pqCVNRPeh8DcQv688AmVfGVH9vFaO1ljCjZdQnmuLAs
UMFmukMw95sH94nMrIDCxA+Wu9rFqu/+HeaTSBAKk/w
-> s'-grease Vh0 HZ
eV4
--- v3hiCSVCZBClieGN5cbms9savGrjF5eJe2CX45+YisU
ÐxÎ ›‰J óTö…“;ÓAEûÊ"Ù¡õbˆ<62>פÏRñ´ „)%Ú©õx9e«w×®+Ív¨ÜBj<13>¿_

View file

@ -0,0 +1,15 @@
age-encryption.org/v1
-> ssh-ed25519 A1vEZQ 8WLhLDth0HYHsCpG9cE866tkxFtzw6PzJUNflx+iOjU
9i2/G8aJhu8WQCAVbYtlgMAuYj9Qgo0PEkATat6x0Lk
-> ssh-ed25519 EYWzzw mrxn2Mn3wPuUOE8usd2Q/NdyI/y+d8wURa4EzY9euBE
T8aonRzVP3HpMYLdj8Cs1ALDlf7StSqRqiOy02qCR9w
-> ssh-ed25519 ugHWWw DpCKx/h6Ys+XNqcIlYG8gcA7enZhE9zxOHDSR9zJYgI
TUAy5ZMoU6kr4g/+Ys3PYTQp00r0yk7B/+VpdFprsNQ
-> ssh-ed25519 UDK5aw iiIeZTy6eDMcekJyils7kJZWMRpO7pLi62lRPveoKg8
TnSrdTlda9O+0yhBytnY5VVmthU52L/nMCi9/aFiu1s
-> ssh-ed25519 UU9RSA M6ItkG991s5U2K1E70ruUP2iRL9+nB8p2eyDL9kX+TQ
HeoZW6BtgHcI3Qe/VUCUrcyhUbcMXlKa3HqNacv7uwc
-> kX_-grease f\e\ Rj+~oX7M 1
ewJ+jXh0vEgbDhpO0nmX+V+UwZSqkafKRoIB3hMrAwE+R5iuZSDWAx4XR0c
--- SiWIor3ehrAC3KTcgLCN+mYvsM+gOGAwj1e8Wud388M
±©?Æ`Yûõ"P‰ˆ½È]Èe´}WHŸØ+±!ŸfÅ ¼CsÉFšmcMôî:Øù2oQì6aM<61>ˆ † Õæ~=sµóšžœÅÛ

View file

@ -0,0 +1,17 @@
age-encryption.org/v1
-> ssh-ed25519 rQk6HA YDPQBl0whrw1zR+swhb+SExxqZ1dAyH/2VUaWSFpF2k
MYf8ZmjcHtZrBIvpTPgTpX4AxZb25RIwFnRmPA5HSsY
-> ssh-ed25519 EYWzzw uq0tQEgeKJ0QF8Gj+6Q3VKUX+4eZhaYZdn5ue7iVAE8
OhXcoh9inDGGs4pUMp4SJsBs9Wgof0Zasp2YDdNbYnU
-> ssh-ed25519 ugHWWw mCnwqprJ1LljTL7WMUWs+PAB1TIiTJJnS2H57WlGBxQ
6Dic87CJmMyNUb9cMLFb7X1b9OwKODGYDT4XJu79vPM
-> ssh-ed25519 UDK5aw llva4i1xwHbr2ObkMRKOL8nlKKHUAVngcI9YnSxQRwY
3Arn7SHDV549W9buHN1W178BZZI+LalSVONipZCJvrk
-> ssh-ed25519 UU9RSA roR+hhpCHjRWIhCMXE3Z2X8yY+UxmTh2CmzizUfPNA0
jSkLFAGZM4mwkAnNBhMqA37XFdEaIFLFo8CjtXFzpQc
-> 9P-grease lR x)Ox-
6cl7heMeTkRgUkm6tpeysLWDPf+ka5rPGlzvMZSkp5D7q3wzCq4vCXuq6EQHSxbi
vsN4NiAXQoBhrOz0lJnDZuH4zerlIdNwoUZzSiqkFJ26SbkVP3xPIYbCKrsBMbox
--- BfY866qs6AK/LY+dtGMfcsvQP/wiAO5fmRP4eZDORwY
÷%ó ßå+`4Nlœ¶ÊW{þ0äö¶Q»W«×üQ[¢ÊŽVëÿy„~lwtõÊF9œœ&î® âˆ%¡Ô…FW.ŠÏuª5wÆD