feat: refactor the modules/servers directory.

This commit is contained in:
CronyAkatsuki 2026-01-19 21:36:24 +01:00
parent 4e783c052b
commit 8b754d3a7e
69 changed files with 61 additions and 62 deletions

View file

@ -0,0 +1,8 @@
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
aria2
unzip
lm_sensors
neovim
];
}

View file

@ -0,0 +1,57 @@
{
config,
pkgs,
lib,
...
}:
lib.mkIf (config.networking.hostName != "tyr") {
systemd.services.beszel-agent = {
enable = true;
description = "Beszel Agent";
after = ["network.target"];
wants = ["network.target"];
serviceConfig = {
Type = "simple";
Restart = "always";
RestartSec = 3;
User = "beszel";
Group = "beszel";
WorkingDirectory = "/var/lib/beszel";
StateDirectory = "beszel-agent";
KeyringMode = "private";
LockPersonality = "yes";
NoNewPrivileges = "yes";
ProtectClock = "yes";
ProtectHome = "read-only";
ProtectHostname = "yes";
ProtectKernelLogs = "yes";
ProtectSystem = "strict";
RemoveIPC = "yes";
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
};
script = "${pkgs.beszel}/bin/beszel-agent -listen '45876' --key 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC+T3fFx+Sv8jBGr2gNUHfuwUCbGhj8Mr/h4pmkI2Zjn'";
wantedBy = ["multi-user.target"];
};
users = {
users.beszel = {
isSystemUser = true;
home = "/var/lib/beszel";
createHome = true;
group = "beszel";
};
groups.beszel = {};
};
networking.firewall.extraCommands = ''
iptables -N beszel # create a new chain named beszel
iptables -A beszel --src 65.21.241.194 -j ACCEPT # allow 65.21.241.194
iptables -A beszel -j DROP # drop everyone else
iptables -I INPUT -m tcp -p tcp --dport 45876 -j beszel # use chain beszel for packets coming to TCP port 45876
'';
}

View file

@ -0,0 +1,17 @@
{...}: {
imports = [
./openssh.nix
./user.nix
./traefik.nix
./secrets.nix
./podman.nix
./additional-pkgs.nix
./root.nix
./optimise-storage.nix
./restic.nix
./nix-features.nix
./shell.nix
./fail2ban.nix
./beszel-agent.nix
];
}

View file

@ -0,0 +1,16 @@
{...}: {
services.fail2ban = {
enable = true;
maxretry = 5;
ignoreIP = [
"65.21.241.194"
];
bantime = "24h"; # Ban IPs for one day on the first ban
bantime-increment = {
enable = true; # Enable increment of bantime after each violation
multipliers = "1 2 4 8 16 32 64";
maxtime = "168h"; # Do not ban for more than 1 week
overalljails = true; # Calculate the bantime based on all the violations
};
};
}

View file

@ -0,0 +1,4 @@
{
# Enable flakes
nix.settings.experimental-features = ["nix-command" "flakes"];
}

View file

@ -0,0 +1,32 @@
{
config,
lib,
...
}: {
services.openssh = {
enable = true;
settings = {
AllowUsers =
lib.mkIf (config.networking.hostName != "tyr")
[
"root@65.21.241.194"
"root@172.16.0.2"
"crony@65.21.241.194"
"crony@172.16.0.2"
];
X11Forwarding = false;
PasswordAuthentication = false;
};
extraConfig = ''
PubkeyAuthentication yes
PermitEmptyPasswords no
AddressFamily inet
MaxAuthTries 3
'';
};
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBJLduAXHWJiglmfRfkBGKffzVWkJP6porxIzw6+Zz3W crony@cronyakatsuki.xyz"
];
}

View file

@ -0,0 +1,19 @@
{...}: {
nix.optimise = {
automatic = true;
dates = "weekly";
};
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 10d";
};
nix.extraOptions = ''
min-free = ${toString (100 * 1024 * 1024)}
max-free = ${toString (1024 * 1024 * 1024)}
'';
boot.loader.grub.configurationLimit = 3;
}

View file

@ -0,0 +1,28 @@
{pkgs, ...}: {
virtualisation = {
podman = {
enable = true;
dockerCompat = true;
autoPrune = {
enable = true;
dates = "weekly";
flags = [
"--filter=until=24h"
"--filter=label!=important"
];
};
defaultNetwork.settings.dns.enable = true;
};
};
# Enable system podman autoupdate timer
systemd.timers.podman-auto-update = {
enable = true;
wantedBy = ["timers.target"];
};
environment.systemPackages = with pkgs; [
podman-compose
podman-tui
];
}

View file

@ -0,0 +1,40 @@
{config, ...}: let
opts = {
paths = [
"/var/lib/private"
];
pruneOpts = [
"--keep-last 10"
"--keep-daily 7"
"--keep-weekly 5"
"--keep-monthly 12"
];
pruneOptsLocal = [
"--keep-last 2"
];
checkOpts = [
"--read-data-subset=10%"
"--with-cache"
];
};
in {
services.restic.backups = {
local = {
initialize = true;
passwordFile = config.age.secrets.restic-server-local-pass.path;
repository = "/var/lib/backup";
paths = opts.paths;
pruneOpts = opts.pruneOptsLocal;
checkOpts = opts.checkOpts;
};
server = {
initialize = true;
passwordFile = config.age.secrets.restic-server-pass.path;
repositoryFile = config.age.secrets.restic-server-repo.path;
environmentFile = config.age.secrets.restic-server-env.path;
paths = opts.paths;
pruneOpts = opts.pruneOpts;
checkOpts = opts.checkOpts;
};
};
}

View file

@ -0,0 +1,6 @@
{config, ...}: {
users.users.root = {
hashedPasswordFile = "${config.age.secrets.root-passwd.path}";
};
users.mutableUsers = false;
}

View file

@ -0,0 +1,28 @@
{
age = {
secrets = {
traefik = {
file = ../../../secrets/traefik.age;
owner = "traefik";
};
crony-passwd = {
file = ../../../secrets/crony-passwd-servers.age;
};
root-passwd = {
file = ../../../secrets/root-passwd.age;
};
restic-server-local-pass = {
file = ../../../secrets/restic-server-local-pass.age;
};
restic-server-pass = {
file = ../../../secrets/restic-server-pass.age;
};
restic-server-repo = {
file = ../../../secrets/restic-server-repo.age;
};
restic-server-env = {
file = ../../../secrets/restic-server-env.age;
};
};
};
}

View file

@ -0,0 +1,11 @@
{pkgs, ...}: {
users.extraUsers.root = {
shell = pkgs.zsh;
};
users.extraUsers.crony = {
shell = pkgs.zsh;
};
programs.zsh.enable = true;
}

View file

@ -0,0 +1,82 @@
{config, ...}: {
services.traefik = {
enable = true;
staticConfigOptions = {
serversTransport.insecureSkipVerify = true;
log = {level = "DEBUG";};
experimental = {
plugins = {
fail2ban = {
moduleName = "github.com/tomMoulard/fail2ban";
version = "v0.8.7";
};
};
};
certificatesResolvers = {
porkbun = {
acme = {
email = "crony@cronyakatsuki.xyz";
storage = "/var/lib/traefik/acme.json";
caserver = "https://acme-v02.api.letsencrypt.org/directory";
dnsChallenge = {
provider = "porkbun";
resolvers = ["1.1.1.1" "8.8.8.8"];
propagation = {
delayBeforeChecks = 60;
disableChecks = true;
};
};
};
};
};
api = {};
entryPoints = {
web = {
address = ":80";
http.redirections.entryPoint = {
to = "websecure";
scheme = "https";
};
};
websecure = {
address = ":443";
http.middlewares = [
"fail2ban"
];
};
};
};
dynamicConfigOptions.http = {
middlewares = {
fail2ban = {
plugin = {
fail2ban = {
rules = {
bantime = "168h";
enabled = true;
findtime = "5m";
maxretry = 50;
statuscode = "400,401,403-499";
urlregexps = [
{
regexp = "/*";
mode = "allow";
}
];
};
allowlist = {
ip = ["65.21.241.194"];
};
};
};
};
};
};
};
systemd.services.traefik.serviceConfig = {
EnvironmentFile = ["${config.age.secrets.traefik.path}"];
};
networking.firewall.allowedTCPPorts = [80 443];
}

View file

@ -0,0 +1,17 @@
{config, ...}: {
# Not reall that safe but convenient af
security.sudo.wheelNeedsPassword = false;
users.users.crony = {
linger = true;
isNormalUser = true;
description = "crony";
hashedPasswordFile = "${config.age.secrets.crony-passwd.path}";
extraGroups = [
"wheel"
];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBJLduAXHWJiglmfRfkBGKffzVWkJP6porxIzw6+Zz3W crony@cronyakatsuki.xyz"
];
};
}