summary refs log tree commit diff stats
path: root/system
diff options
context:
space:
mode:
authorAlan Pearce2025-02-13 21:09:23 +0100
committerAlan Pearce2025-02-13 21:09:23 +0100
commit20d560a78a81e406a76220a36adc99cd112d12ff (patch)
tree146ea683efb87c476fc10f2e3f9b933c35ffb41d /system
parent10bf0a9c691a7d85ddd63de18def9865612e410e (diff)
downloadnixfiles-20d560a78a81e406a76220a36adc99cd112d12ff.tar.lz
nixfiles-20d560a78a81e406a76220a36adc99cd112d12ff.tar.zst
nixfiles-20d560a78a81e406a76220a36adc99cd112d12ff.zip
Add NanoPi R6C
Diffstat (limited to 'system')
-rw-r--r--system/nano-hardware.nix42
-rw-r--r--system/nano.nix542
2 files changed, 584 insertions, 0 deletions
diff --git a/system/nano-hardware.nix b/system/nano-hardware.nix
new file mode 100644
index 00000000..96a0a287
--- /dev/null
+++ b/system/nano-hardware.nix
@@ -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 + "/installer/scan/not-detected.nix")
+    ];
+
+  boot.initrd.availableKernelModules = [ "nvme" ];
+  boot.initrd.kernelModules = [ ];
+  boot.kernelModules = [ ];
+  boot.extraModulePackages = [ ];
+
+  fileSystems."/" =
+    {
+      device = "/dev/disk/by-uuid/3e2e984a-0f2d-4615-be50-cea40090b463";
+      fsType = "ext4";
+    };
+
+  fileSystems."/boot" =
+    {
+      device = "/dev/disk/by-uuid/96FE-219D";
+      fsType = "vfat";
+      options = [ "fmask=0022" "dmask=0022" ];
+    };
+
+  swapDevices =
+    [{ device = "/dev/disk/by-uuid/cfedef33-a711-42dd-8816-b1e119e20e55"; }];
+
+  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+  # (the default) this is the recommended approach. When using systemd-networkd it's
+  # still possible to use this option, but it's recommended to use it in conjunction
+  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+  networking.useDHCP = lib.mkDefault true;
+  # networking.interfaces.eth0.useDHCP = lib.mkDefault true;
+  # networking.interfaces.eth1.useDHCP = lib.mkDefault true;
+
+  nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
+}
diff --git a/system/nano.nix b/system/nano.nix
new file mode 100644
index 00000000..bda0b0d4
--- /dev/null
+++ b/system/nano.nix
@@ -0,0 +1,542 @@
+# vim: si ai sts=2 sw=2
+{ config, lib, pkgs, ... }:
+
+let
+  wan = "wan0";
+  lan = "lan0";
+  hostName = "nano";
+  domain = "home.arpa";
+  tailnet = "hydra-pinecone.ts.net";
+  dnsmasqEnable = true;
+in
+{
+  imports = [
+    ./settings/configuration/nix-linux.nix
+  ];
+  age.secrets = {
+    dyndns.file = ../secrets/dyndns.age;
+    acme.file = ../secrets/acme.age;
+    syncthing.file = ../secrets/syncthing.age;
+  };
+
+  boot.loader.timeout = lib.mkForce 1;
+  boot.loader.efi.canTouchEfiVariables = false; # is r/o for some reason
+  boot.loader.systemd-boot = {
+    installDeviceTree = true;
+    edk2-uefi-shell = {
+      enable = true;
+    };
+  };
+
+  srvos.boot.consoles = [ "ttyS2,1500000" ];
+  boot.kernelPackages = pkgs.linuxWithBSDDisklabel;
+  nixpkgs = {
+    overlays = [
+      (self: super: {
+        linuxWithBSDDisklabel = super.linuxPackagesFor (super.linux.override {
+          structuredExtraConfig = with lib.kernel; {
+            BSD_DISKLABEL = yes;
+          };
+          ignoreConfigErrors = false;
+        });
+      })
+    ];
+  };
+
+  hardware.deviceTree = {
+    enable = true;
+    name = "rockchip/rk3588s-nanopi-r6c.dtb";
+  };
+
+  boot.kernelModules = [
+    "tcp_lp"
+  ];
+  boot.kernel.sysctl = {
+    "net.ipv4.tcp_slow_start_after_idle" = 0;
+    "net.ipv4.tcp_ecn" = 1;
+    "net.ipv4.tcp_fastopen" = "0x3";
+    "net.ipv4.tcp_allowed_congestion_control" = "reno cubic lp";
+    "net.core.default_qdisc" = "fq";
+  };
+  networking = {
+    useDHCP = false;
+    inherit domain hostName;
+    hosts = {
+      "fd7a:115c:a1e0::53" = [ "tailscale" "ts" ];
+      "192.168.100.1" = [ "modem" "pyur" ];
+      "192.168.4.1" = [ "lte" ];
+    };
+    nameservers = [
+      "2620::fe:fe"
+      "2620::fe:9"
+      "9.9.9.9"
+      "149.112.112.112"
+    ];
+    firewall = {
+      trustedInterfaces = [
+        lan
+        "tailscale0"
+      ];
+      filterForward = true;
+    };
+    nftables.enable = true;
+    nat = {
+      enable = true;
+      externalInterface = wan;
+      internalInterfaces = [ lan ];
+    };
+    resolvconf.enable = false;
+  };
+  systemd.network = {
+    enable = true;
+    config = {
+      networkConfig = {
+        IPv6Forwarding = true;
+      };
+    };
+    links = {
+      "10-${lan}" = {
+        matchConfig.Path = "platform-a40c00000.pcie-pci-0003:31:00.0";
+        linkConfig.Name = lan;
+      };
+      "10-${wan}" = {
+        matchConfig.Path = "platform-fe1c0000.ethernet";
+        linkConfig.Name = wan;
+      };
+    };
+    networks = {
+      "50-${lan}" = {
+        matchConfig.Name = lan;
+        address = [
+          "10.0.0.1/16"
+          "fd12:d04f:65d:42::1/56"
+        ];
+        addresses = [
+          {
+            Address = "fe80::1/64";
+            Scope = "link";
+          }
+        ];
+        networkConfig = {
+          IPv6AcceptRA = false;
+          DHCPPrefixDelegation = true;
+          ConfigureWithoutCarrier = true;
+          LLMNR = true;
+          MulticastDNS = true;
+          Domains = [ config.networking.domain ];
+          IPv6SendRA = !dnsmasqEnable;
+          DHCPServer = !dnsmasqEnable;
+        };
+        dhcpPrefixDelegationConfig = {
+          UplinkInterface = wan;
+          SubnetId = "42";
+          Assign = true;
+          Token = "::1";
+        };
+        dhcpServerConfig = {
+          DefaultLeaseTimeSec = 86400;
+          MaxLeaseTimeSec = 86400;
+          DNS = "_server_address";
+          IPv6OnlyPreferredSec = 900;
+        };
+      };
+      "50-${wan}" = {
+        matchConfig.Name = wan;
+        networkConfig = {
+          DHCP = true;
+          IPv6AcceptRA = true;
+          IPv4Forwarding = true;
+          LLMNR = false;
+          MulticastDNS = false;
+        };
+        dhcpV4Config = {
+          UseDNS = false;
+          SendHostname = false;
+          UseHostname = false;
+          Label = "${wan}:1";
+        };
+        dhcpV6Config = {
+          UseDNS = false;
+          SendHostname = false;
+          RapidCommit = true;
+          PrefixDelegationHint = "::/56";
+        };
+        dhcpPrefixDelegationConfig = {
+          UplinkInterface = ":self";
+        };
+        ipv6AcceptRAConfig = {
+          UseDNS = false;
+        };
+        addresses = [{
+          Address = "192.168.100.10/24";
+          Peer = "192.168.100.1/32";
+          Label = "${wan}:0";
+          Scope = "link";
+        }];
+        cakeConfig = {
+          Bandwidth = "24M";
+          OverheadBytes = 18;
+          MPUBytes = 64;
+          CompensationMode = "none";
+          NAT = true;
+          PriorityQueueingPreset = "diffserv8";
+        };
+      };
+    };
+  };
+  services.resolved = {
+    enable = true;
+    llmnr = "false";
+    fallbackDns = config.networking.nameservers;
+  };
+
+  services.dnsmasq = {
+    enable = dnsmasqEnable;
+    alwaysKeepRunning = true;
+    resolveLocalQueries = true;
+    settings = {
+      inherit domain;
+      interface = lan;
+      bind-interfaces = true;
+      dhcp-fqdn = true;
+      dhcp-authoritative = true;
+      dhcp-rapid-commit = true;
+      dhcp-range = [
+        "10.0.1.10,10.0.250.250,48h"
+        "fd12:d04f:65d:42::,slaac,ra-names,48h"
+        "::,constructor:${lan},ra-stateless"
+      ];
+      quiet-dhcp = true;
+      quiet-dhcp6 = true;
+      quiet-ra = true;
+      enable-ra = true;
+
+      dnssec = true;
+      trust-anchor = ".,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D";
+      server = config.networking.nameservers;
+
+      expand-hosts = true;
+      localise-queries = true;
+      interface-name = [
+        "${hostName}.${domain},${lan}"
+        "ca.${domain},${lan}"
+        "wan.${domain},${wan}"
+      ];
+    };
+  };
+  systemd.services.dnsmasq.after = [ "network.target" ];
+
+  # TODO find script
+  # systemd.services.dynamic-dns-update = {
+  #   enable = true;
+  #   startAt = [ "hourly" ];
+  #   description = "Update IP addresses";
+  #   path = with pkgs; [ curl iproute2 dig.dnsutils miller ];
+  #   after = [ "sys-subsystem-net-devices-${wan}.device" ];
+  #   bindsTo = [ "sys-subsystem-net-devices-${wan}.device" ];
+  #   serviceConfig = {
+  #     Type = "oneshot";
+  #     ExecStart = "/bin/sh /etc/nixos/update-ip ${config.age.secrets.dyndns.path}";
+  #   };
+  # };
+  # services.networkd-dispatcher = {
+  #   # broken?
+  #   enable = true;
+  #   rules = {
+  #     update-home-address = {
+  #       onState = [ "configured" "configuring" ];
+  #       script = ''
+  #         #!${pkgs.runtimeShell}
+  #         set -eu
+
+  #         if [[ $IFACE == "${wan}" && $OperationalState == "routable" ]]
+  #         then
+  #           systemctl start dynamic-dns-update.service
+  #         fi
+  #         exit 0
+  #       '';
+  #     };
+  #     tailscale-subnet-router-optimisation = {
+  #       onState = [ "routable" ];
+  #       script = ''
+  #         #!${pkgs.runtimeShell}
+  #         set -eu
+
+  #         if [[ $IFACE == "${wan}" && $OperationalState == "routable" ]]
+  #         then
+  #           ${pkgs.ethtool}/bin/ethtool -K $IFACE rx-udp-gro-forwarding on rx-gro-list off
+  #         fi
+  #       '';
+  #     };
+  #   };
+  # };
+
+  services.tailscale = {
+    enable = true;
+    extraUpFlags = [
+      "--accept-dns=false"
+      "--advertise-exit-node"
+      "--advertise-routes=10.0.0.0/16,fd12:d04f:65d:42::/56"
+    ];
+  };
+
+  time.timeZone = "Europe/Berlin";
+  i18n.defaultLocale = "en_GB.UTF-8";
+
+  programs.vim.defaultEditor = false;
+  programs.neovim = {
+    enable = true;
+    defaultEditor = true;
+    vimAlias = true;
+    viAlias = true;
+  };
+
+  environment.systemPackages = with pkgs; [
+    file
+    tree
+    lsof
+    knot-dns
+  ];
+
+  programs.fish.enable = true;
+  users.defaultUserShell = pkgs.fish;
+  users.mutableUsers = lib.mkForce true;
+
+  users.users.alan = {
+    isNormalUser = true;
+    packages = with pkgs; [ ];
+    openssh.authorizedKeys.keys = [
+      "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJVREjPey2TOIPzfYJoG9yIR4Rui7tNJK2QIKa+pbgsyXg31hhPIw37LRRIic+l53mW8eahHxX3Y1IeTjcMw8IU= alan@secretive.marvin.local"
+    ];
+  };
+
+  users.users.root = {
+    openssh.authorizedKeys.keys = [
+      "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHYUyDdw92TNXguAxcmcmZmn/7ECGdRp6ckjxU+5zCw3BCnsS5+xEvHBVnnFdJRoH2XpfMeJjE+fi67zFVhlbn4= root@secretive.marvin.local"
+    ];
+  };
+
+  services.sshguard = {
+    enable = true;
+  };
+
+  services.caddy = {
+    enable = true;
+    globalConfig = ''
+      pki {
+        ca home {
+          name "Home CA"
+        }
+      }
+    '';
+    virtualHosts = {
+      "${hostName}.${domain}" = {
+        serverAliases = [ "${hostName}.${tailnet}" ];
+        extraConfig = ''
+          tls {
+            issuer internal {
+              ca home
+            }
+          }
+          root /var/lib/caddy/ca
+          file_server browse
+        '';
+      };
+      "ca.${domain}" = {
+        extraConfig = ''
+          tls {
+            issuer internal {
+              ca home
+            }
+          }
+          acme_server {
+            allow {
+              domains *.test *.${domain}
+            }
+          }
+        '';
+      };
+    };
+  };
+
+  users.groups.linde.members = [ ];
+  users.users.linde = {
+    group = "linde";
+    description = "Backup user for system 'linde'";
+    isSystemUser = true;
+    shell = "/bin/sh";
+    home = "/srv/backup/linde";
+    homeMode = "755";
+    createHome = true;
+    packages = with pkgs; [ rdiff-backup ];
+    openssh.authorizedKeys.keys = [
+      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ74cPdIX9OlDkzHb6Y1E5sWqtIqMaf0z/SN3Tfy1Fjl root@linde"
+      "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINNXwIdGcP1vKyjmgeLw/sJntn7lajaZivepgdzaXvOt rdiff-backup"
+    ];
+  };
+
+  systemd.services.backup-golink = {
+    enable = true;
+    startAt = "daily";
+    description = "Export short links from golink";
+    path = with pkgs; [ curl gitMinimal ];
+    script = ''
+      [ -d golink ] || git init --quiet golink --initial-branch=main --shared=world
+      git config --global user.email linde@alanpearce.eu
+      cd golink
+      curl https://go.${tailnet}/.export > links.json
+      git add links.json
+      git commit -m $(date +%F)
+    '';
+    serviceConfig = {
+      Type = "oneshot";
+      User = "linde";
+      WorkingDirectory = config.users.users.linde.home;
+    };
+  };
+
+  nix = {
+    distributedBuilds = true;
+    buildMachines = [
+      {
+        protocol = "ssh-ng";
+        sshUser = "nixremote";
+        hostName = "linde.alanpearce.eu";
+        system = "aarch64-linux";
+        # TODO make secret
+        sshKey = "/root/.ssh/id_buche.alanpearce.eu_nixremote";
+        maxJobs = 2;
+        speedFactor = 4;
+        supportedFeatures = [ ];
+      }
+    ];
+    settings = {
+      max-jobs = 2;
+      builders-use-substitutes = true;
+    };
+  };
+
+  system.autoUpgrade = {
+    dates = "04:15";
+    randomizedDelaySec = "59 min";
+    flake = "git+https://git.alanpearce.eu/nixfiles";
+    allowReboot = true;
+    rebootWindow = {
+      lower = "01:00";
+      upper = "06:00";
+    };
+  };
+
+  users.users.syncthing = {
+    isSystemUser = true;
+    group = "syncthing";
+    homeMode = "0755";
+  };
+  users.groups.syncthing.members = [ "alan" ];
+  services.syncthing = {
+    enable = true;
+    openDefaultPorts = true;
+    dataDir = "/srv/syncthing";
+    user = "syncthing";
+    group = "syncthing";
+    key = config.age.secrets.syncthing.path;
+    cert = toString (pkgs.writeText "syncthing.crt" ''
+      -----BEGIN CERTIFICATE-----
+      MIIBmjCCASCgAwIBAgIIUOEmXGFrrX0wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ
+      c3luY3RoaW5nMB4XDTIyMDcxMzEwMzIxOVoXDTQ5MTIzMTIzNTk1OVowFDESMBAG
+      A1UEAxMJc3luY3RoaW5nMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEPiJT41NqucQf
+      UXiBwt+yPYnMg9G8oTt9XNA72V99K46D7mIs1F/5oESlDiCSAngXPsajxRY7wyZV
+      VoiWegfiaBOGZmq+TyaLlQ5bq/hm/Mp/jVED/rUA+BggohoZZMa2oz8wPTAOBgNV
+      HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1Ud
+      EwEB/wQCMAAwCgYIKoZIzj0EAwIDaAAwZQIwLp4Gv5EEmjRO9EphbYJ4jxEJks7E
+      oblgnTmhfWmVWmf9avJyeGB212VYu4X8cCKDAjEAn7tTB9Y6LZvYPaLSwUKY3EzF
+      hKTYCb7VA/P1dU3tTR1vSQxnu1DsiliD/XcKe2IK
+      -----END CERTIFICATE-----
+    '');
+    overrideFolders = false;
+    overrideDevices = false;
+    settings = {
+      options = {
+        maxRecvKbps = 10240;
+        maxSendKbps = 1024;
+        globalAnnounceEnabled = false;
+        relaysEnabled = false;
+        natEnabled = false;
+        urAccepted = 4;
+        trafficClass = 1;
+      };
+    };
+  };
+
+  services.chrony = {
+    enable = true;
+    extraConfig = ''
+      rtcdevice /dev/rtc0
+      rtcfile /var/lib/chrony/rtc
+      rtcautotrim 30
+
+      allow 10.0.0.0/8
+      allow fd12:d04f:65d:42::0/56
+    '';
+  };
+
+  services.samba = {
+    # TODO restore /srv
+    enable = false;
+    nmbd.enable = false;
+    settings = {
+      global = {
+        "log level" = 1;
+
+        "interfaces" = lan;
+
+        "min protocol" = "SMB2";
+        "disable netbios" = true;
+        "smb ports" = 445;
+
+        "socket options" = "IPTOS_LOWDELAY TCP_NODELAY SO_KEEPALIVE SO_RCVBUF=65536 SO_SNDBUF=65536";
+        "max xmit" = 131072;
+        "min receivefile size" = 131072;
+
+        "aio read size" = 1;
+        "aio write size" = 1;
+
+        "load printers" = false;
+        "disable spoolss" = true;
+
+        "mdns name" = "mdns";
+
+        "follow symlinks" = true;
+
+        "veto files" = "/Thumbs.db/.DS_Store/._.DS_Store/.apdisk/";
+        "delete veto files" = true;
+      };
+      public = {
+        path = "/srv/public";
+        browseable = "yes";
+        "guest ok" = "yes";
+        "create mask" = "0666";
+        "directory mask" = "0777";
+        "read only" = "no";
+      };
+      Homes = {
+        "read only" = "no";
+        "valid users" = "%S";
+        "inherit acls" = "yes";
+      };
+      Videos = {
+        path = "/srv/videos";
+        "valid users" = "alan";
+        "create mask" = "0664";
+        "directory mask" = "0775";
+        "writeable" = "yes";
+      };
+    };
+  };
+  services.samba-wsdd = {
+    enable = true;
+    interface = lan;
+  };
+
+  system.stateVersion = "24.11";
+}