add aspects/hosts/ configurations
Host-specific NixOS configurations for: - alexandria (server) - io (desktop) - rotterdam (desktop) - trantor (server, aarch64) Each host has a main config file and _hostname/ directory with hardware-configuration and other host-specific modules. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
ad0aa14d14
commit
25c69e3c18
30 changed files with 1298 additions and 0 deletions
6
aspects/hosts/_trantor/boot.nix
Normal file
6
aspects/hosts/_trantor/boot.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
boot = {
|
||||
initrd.systemd.enable = true;
|
||||
loader.efi.efiSysMountPoint = "/boot/efi";
|
||||
};
|
||||
}
|
||||
64
aspects/hosts/_trantor/disko.nix
Normal file
64
aspects/hosts/_trantor/disko.nix
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{ inputs, ... }:
|
||||
|
||||
{
|
||||
imports = [ inputs.disko.nixosModules.default ];
|
||||
|
||||
disko.devices.disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/disk/by-id/scsi-360b207ed25d84372a95d1ecf842f8e20";
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
priority = 1;
|
||||
name = "ESP";
|
||||
start = "1MiB";
|
||||
end = "512MiB";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot/efi";
|
||||
mountOptions = [
|
||||
"noatime"
|
||||
"fmask=0077"
|
||||
"dmask=0077"
|
||||
];
|
||||
};
|
||||
};
|
||||
root = {
|
||||
priority = 2;
|
||||
name = "root";
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "btrfs";
|
||||
extraArgs = [ "-f" ];
|
||||
subvolumes = {
|
||||
"@root" = {
|
||||
mountpoint = "/";
|
||||
mountOptions = [
|
||||
"noatime"
|
||||
"compress=zstd"
|
||||
];
|
||||
};
|
||||
"@nix" = {
|
||||
mountpoint = "/nix";
|
||||
mountOptions = [
|
||||
"noatime"
|
||||
"compress=zstd"
|
||||
];
|
||||
};
|
||||
"@persistent" = {
|
||||
mountpoint = "/persistent";
|
||||
mountOptions = [
|
||||
"noatime"
|
||||
"compress=zstd"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
23
aspects/hosts/_trantor/fail2ban.nix
Normal file
23
aspects/hosts/_trantor/fail2ban.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
services.fail2ban = {
|
||||
enable = true;
|
||||
maxretry = 5;
|
||||
ignoreIP = [
|
||||
"127.0.0.0/8"
|
||||
"::1"
|
||||
"10.0.0.0/8"
|
||||
"172.16.0.0/12"
|
||||
"192.168.0.0/16"
|
||||
"100.64.0.0/10"
|
||||
];
|
||||
bantime = "1h";
|
||||
bantime-increment = {
|
||||
enable = true;
|
||||
multipliers = "1 2 4 8 16 32 64";
|
||||
maxtime = "10000h";
|
||||
overalljails = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
72
aspects/hosts/_trantor/forgejo.nix
Normal file
72
aspects/hosts/_trantor/forgejo.nix
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
utils = import ../../../utils.nix { inherit inputs lib; };
|
||||
inherit (utils) mkNginxVHosts;
|
||||
in
|
||||
|
||||
{
|
||||
services = {
|
||||
forgejo = {
|
||||
enable = true;
|
||||
settings = {
|
||||
session.COOKIE_SECURE = true;
|
||||
server = {
|
||||
PROTOCOL = "http+unix";
|
||||
DOMAIN = "git.baduhai.dev";
|
||||
ROOT_URL = "https://git.baduhai.dev";
|
||||
OFFLINE_MODE = true; # disable use of CDNs
|
||||
SSH_DOMAIN = "git.baduhai.dev";
|
||||
};
|
||||
log.LEVEL = "Warn";
|
||||
mailer.ENABLED = false;
|
||||
actions.ENABLED = false;
|
||||
service.DISABLE_REGISTRATION = true;
|
||||
oauth2_client = {
|
||||
ENABLE_AUTO_REGISTRATION = true;
|
||||
UPDATE_AVATAR = true;
|
||||
ACCOUNT_LINKING = "login";
|
||||
USERNAME = "preferred_username";
|
||||
};
|
||||
};
|
||||
};
|
||||
nginx.virtualHosts = mkNginxVHosts {
|
||||
domains."git.baduhai.dev".locations."/".proxyPass =
|
||||
"http://unix:${config.services.forgejo.settings.server.HTTP_ADDR}:/";
|
||||
};
|
||||
fail2ban.jails.forgejo = {
|
||||
settings = {
|
||||
enabled = true;
|
||||
filter = "forgejo";
|
||||
maxretry = 3;
|
||||
findtime = "10m";
|
||||
bantime = "1h";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment = {
|
||||
etc."fail2ban/filter.d/forgejo.conf".text = ''
|
||||
[Definition]
|
||||
failregex = .*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>
|
||||
ignoreregex =
|
||||
journalmatch = _SYSTEMD_UNIT=forgejo.service
|
||||
'';
|
||||
|
||||
persistence.main.directories = [
|
||||
{
|
||||
directory = config.services.forgejo.stateDir;
|
||||
inherit (config.services.forgejo) user group;
|
||||
mode = "0700";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Disable PrivateMounts to allow LoadCredential to work with bind-mounted directories
|
||||
systemd.services.forgejo.serviceConfig.PrivateMounts = lib.mkForce false;
|
||||
}
|
||||
20
aspects/hosts/_trantor/hardware-configuration.nix
Normal file
20
aspects/hosts/_trantor/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
lib,
|
||||
modulesPath,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
||||
|
||||
boot.initrd.availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"virtio_pci"
|
||||
"virtio_scsi"
|
||||
"usbhid"
|
||||
];
|
||||
|
||||
networking.useDHCP = lib.mkDefault true;
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
||||
}
|
||||
8
aspects/hosts/_trantor/networking.nix
Normal file
8
aspects/hosts/_trantor/networking.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
networking = {
|
||||
firewall = {
|
||||
allowedTCPPorts = [ 25566 ];
|
||||
allowedUDPPorts = [ 25566 ];
|
||||
};
|
||||
};
|
||||
}
|
||||
61
aspects/hosts/_trantor/nginx.nix
Normal file
61
aspects/hosts/_trantor/nginx.nix
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
utils = import ../../../utils.nix { inherit inputs lib; };
|
||||
inherit (utils) mkNginxVHosts services;
|
||||
|
||||
# Get all unique domains from shared services on trantor (host = "trantor")
|
||||
localDomains = lib.unique (
|
||||
map (s: s.domain) (lib.filter (s: s.host == "trantor") services)
|
||||
);
|
||||
|
||||
# Generate ACME cert configs for all local domains
|
||||
acmeCerts = lib.genAttrs localDomains (domain: {
|
||||
group = "nginx";
|
||||
});
|
||||
in
|
||||
|
||||
{
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults = {
|
||||
email = "baduhai@proton.me";
|
||||
dnsResolver = "1.1.1.1:53";
|
||||
dnsProvider = "cloudflare";
|
||||
credentialsFile = config.age.secrets.cloudflare.path;
|
||||
};
|
||||
certs = acmeCerts;
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
recommendedTlsSettings = true;
|
||||
virtualHosts = {
|
||||
"_" = {
|
||||
default = true;
|
||||
locations."/".return = "444";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users.users.nginx.extraGroups = [ "acme" ];
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
];
|
||||
|
||||
age.secrets.cloudflare = {
|
||||
file = ../../../secrets/cloudflare.age;
|
||||
owner = "nginx";
|
||||
group = "nginx";
|
||||
};
|
||||
}
|
||||
23
aspects/hosts/_trantor/openssh.nix
Normal file
23
aspects/hosts/_trantor/openssh.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
services = {
|
||||
openssh = {
|
||||
settings = {
|
||||
PasswordAuthentication = false;
|
||||
KbdInteractiveAuthentication = false;
|
||||
};
|
||||
};
|
||||
fail2ban.jails.sshd = {
|
||||
settings = {
|
||||
enabled = true;
|
||||
port = "ssh";
|
||||
filter = "sshd";
|
||||
logpath = "/var/log/auth.log";
|
||||
maxretry = 3;
|
||||
findtime = "10m";
|
||||
bantime = "1h";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
58
aspects/hosts/_trantor/unbound.nix
Normal file
58
aspects/hosts/_trantor/unbound.nix
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{ inputs, lib, ... }:
|
||||
|
||||
let
|
||||
utils = import ../../../utils.nix { inherit inputs lib; };
|
||||
in
|
||||
|
||||
{
|
||||
services.unbound = {
|
||||
enable = true;
|
||||
enableRootTrustAnchor = true;
|
||||
settings = {
|
||||
server = {
|
||||
interface = [
|
||||
"0.0.0.0"
|
||||
"::"
|
||||
];
|
||||
access-control = [
|
||||
"127.0.0.0/8 allow"
|
||||
"100.64.0.0/10 allow" # Tailscale CGNAT range
|
||||
"::1/128 allow"
|
||||
"fd7a:115c:a1e0::/48 allow" # Tailscale IPv6
|
||||
];
|
||||
|
||||
num-threads = 2;
|
||||
msg-cache-size = "50m";
|
||||
rrset-cache-size = "100m";
|
||||
cache-min-ttl = 300;
|
||||
cache-max-ttl = 86400;
|
||||
prefetch = true;
|
||||
prefetch-key = true;
|
||||
hide-identity = true;
|
||||
hide-version = true;
|
||||
so-rcvbuf = "1m";
|
||||
so-sndbuf = "1m";
|
||||
|
||||
# Tailnet DNS records from shared services
|
||||
local-zone = ''"baduhai.dev." transparent'';
|
||||
local-data = map (e: ''"${e.domain}. IN A ${e.tailscaleIP}"'') utils.services;
|
||||
};
|
||||
|
||||
forward-zone = [
|
||||
{
|
||||
name = ".";
|
||||
forward-addr = [
|
||||
"1.1.1.1@853#cloudflare-dns.com"
|
||||
"1.0.0.1@853#cloudflare-dns.com"
|
||||
];
|
||||
forward-tls-upstream = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ 53 ];
|
||||
allowedUDPPorts = [ 53 ];
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue