main
 1{
 2  lib,
 3  pkgs,
 4  globals,
 5  libx,
 6  hostname,
 7  ...
 8}:
 9let
10  machine = globals.machines.${hostname};
11  vpnServer = globals.machines.carthage;
12  hostsEntries = libx.hostConfigs globals.machines;
13  hostsFile = lib.concatStringsSep "\n" (
14    lib.mapAttrsToList (ip: names: "${ip} ${lib.concatStringsSep " " names}") hostsEntries
15  );
16in
17{
18  config = {
19    # Disable userborn — Fedora manages users/groups natively
20    # See: https://github.com/numtide/system-manager/issues/350
21    services.userborn.enable = false;
22
23    # System packages
24    environment.systemPackages = with pkgs; [
25      wireguard-tools
26      syncthing
27      vim
28      htop
29      curl
30      git
31    ];
32
33    # Nix custom config (Determinate installer includes nix.custom.conf)
34    environment.etc."nix/nix.custom.conf" = {
35      text = ''
36        trusted-users = root @wheel
37        extra-substituters = http://okinawa.vpn:5000
38        extra-trusted-public-keys = cache.okinawa.home:gp+IG0OaO4L/J0drL8OwmDtMPmdUq4kfLwg3mR8BkCs=
39      '';
40      mode = "0644";
41    };
42
43    # WireGuard: config managed by system-manager, service by Fedora native wg-quick@wg0
44    # Nix-store binaries lack proper SELinux context for network admin ops,
45    # so we use Fedora's wg-quick which runs with the correct domain.
46    # Enable with: sudo dnf install wireguard-tools && sudo systemctl enable --now wg-quick@wg0
47    # Private key is read at runtime from /etc/wireguard/private.key
48    environment.etc."wireguard/wg0.conf" = {
49      text = ''
50        [Interface]
51        PostUp = wg set %i private-key /etc/wireguard/private.key
52        Address = ${builtins.head machine.net.vpn.ips}/24
53
54        [Peer]
55        PublicKey = ${vpnServer.net.vpn.pubkey}
56        AllowedIPs = 10.100.0.0/24
57        Endpoint = ${globals.net.vpn.endpoint}:51820
58        PersistentKeepalive = 25
59      '';
60      mode = "0644";
61    };
62
63    # NetworkManager dispatcher: preserve WireGuard route when Red Hat VPN connects
64    # The VPN pushes 10.0.0.0/8 via tun0 in a higher-priority routing table,
65    # which captures our 10.100.0.0/24 WireGuard traffic. This adds a more
66    # specific route to keep WireGuard reachable.
67    environment.etc."NetworkManager/dispatcher.d/99-wireguard-route" = {
68      text = ''
69        #!/bin/bash
70        INTERFACE="$1"
71        ACTION="$2"
72        if [[ "$INTERFACE" == "tun0" && "$ACTION" == "vpn-up" ]]; then
73          # Find the VPN routing table (usually 75)
74          TABLE=$(ip rule show | grep -oP 'lookup \K[0-9]+' | head -1)
75          if [[ -n "$TABLE" && "$TABLE" != "local" ]]; then
76            ip route add 10.100.0.0/24 dev wg0 table "$TABLE" 2>/dev/null || true
77          fi
78        fi
79      '';
80      mode = "0755";
81      replaceExisting = true;
82    };
83
84    # /etc/hosts entries for VPN and home network hosts
85    environment.etc.hosts = {
86      text = ''
87        127.0.0.1 localhost
88        ::1 localhost
89        ${hostsFile}
90      '';
91      mode = "0644";
92      replaceExisting = true;
93    };
94
95    # Syncthing is managed by home-manager (user service with full folder config)
96  };
97}