yep, more dotfiles
at main 3.7 kB view raw
1{ self 2, config 3, pkgs 4, ... 5}: 6 7let 8 inherit (self.inputs) srvos; 9 10 ext-if = "eth0"; 11 external-ip = "91.99.55.74"; 12 external-netmask = 27; 13 external-gw = "144.x.x.255"; 14 external-ip6 = "2a01:4f8:c2c:76d2::1"; 15 external-netmask6 = 64; 16 external-gw6 = "fe80::1"; 17 18 website-hostname = "wiro.world"; 19 20 static-hostname = "static.wiro.world"; 21in 22{ 23 imports = [ 24 srvos.nixosModules.server 25 srvos.nixosModules.hardware-hetzner-cloud 26 srvos.nixosModules.mixins-terminfo 27 28 ./authelia.nix 29 ./goatcounter.nix 30 ./grafana.nix 31 ./headscale.nix 32 ./hypixel-bank-tracker.nix 33 ./lldap.nix 34 ./miniflux.nix 35 ./pds.nix 36 ./tangled.nix 37 ./thelounge.nix 38 ./tuwunel.nix 39 ./vaultwarden.nix 40 ./warrior.nix 41 ./webfinger.nix 42 ]; 43 44 config = { 45 boot.loader.grub.enable = true; 46 boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" "ext4" ]; 47 48 # Single network card is `eth0` 49 networking.usePredictableInterfaceNames = false; 50 51 networking.nameservers = [ "2001:4860:4860::8888" "2001:4860:4860::8844" ]; 52 53 networking = { 54 interfaces.${ext-if} = { 55 ipv4.addresses = [{ address = external-ip; prefixLength = external-netmask; }]; 56 ipv6.addresses = [{ address = external-ip6; prefixLength = external-netmask6; }]; 57 }; 58 defaultGateway = { interface = ext-if; address = external-gw; }; 59 defaultGateway6 = { interface = ext-if; address = external-gw6; }; 60 61 # Reflect firewall configuration on Hetzner 62 firewall.allowedTCPPorts = [ 22 80 443 ]; 63 }; 64 65 services.qemuGuest.enable = true; 66 67 services.openssh.enable = true; 68 69 # age.secrets.tailscale-authkey.file = secrets/tailscale-authkey.age; 70 services.tailscale = { 71 enable = true; 72 extraSetFlags = [ "--advertise-exit-node" ]; 73 # authKeyFile = config.age.secrets.tailscale-authkey.path; 74 authKeyParameters = { 75 baseURL = "https://headscale.wiro.world"; 76 ephemeral = true; 77 preauthorized = true; 78 }; 79 }; 80 81 security.sudo.wheelNeedsPassword = false; 82 83 local.fragment.nix.enable = true; 84 85 programs.fish.enable = true; 86 87 services.fail2ban = { 88 enable = true; 89 90 maxretry = 5; 91 ignoreIP = [ ]; 92 93 bantime = "24h"; 94 bantime-increment = { 95 enable = true; 96 multipliers = "1 2 4 8 16 32 64"; 97 maxtime = "168h"; 98 overalljails = true; 99 }; 100 101 jails = { }; 102 }; 103 104 age.secrets.caddy-env.file = secrets/caddy-env.age; 105 services.caddy = { 106 enable = true; 107 package = pkgs.caddy.withPlugins { 108 plugins = [ 109 "github.com/caddy-dns/hetzner/v2@v2.0.0-preview-1" 110 "github.com/tailscale/caddy-tailscale@v0.0.0-20251016213337-01d084e119cb" 111 ]; 112 hash = "sha256-muKwDYs5Jp4ib/psZxpp1Kyfsqz6wPz/lpHFGtx67uY="; 113 }; 114 115 environmentFile = config.age.secrets.caddy-env.path; 116 117 globalConfig = '' 118 tailscale { 119 # this caddy instance already proxies headscale but needs to access headscale to start 120 # control_url https://headscale.wiro.world 121 control_url http://localhost:3006 122 123 ephemeral 124 } 125 ''; 126 127 virtualHosts.${website-hostname}.extraConfig = 128 # TODO: host website on server with automatic deployment 129 '' 130 reverse_proxy https://mrnossiom.github.io { 131 header_up Host {http.request.host} 132 } 133 ''; 134 135 virtualHosts.${static-hostname}.extraConfig = '' 136 root /var/www/static 137 file_server browse 138 ''; 139 }; 140 141 # TODO: use bind to declare dns records declaratively 142 }; 143}