Files
infra/machines/stellio/configuration.nix
T
kurogeek 7469976750 stellio: allow ssh over yggdrasil
The router service only opens SSH to the mgmt VLAN, the staging port
and the ZeroTier mesh. Also admit it on the yggdrasil interface (`ygg`,
as named by clan-core's service) so the box stays reachable when
ZeroTier is down. Interface-scoped, so a spoofed 200::/7 source on the
WAN never matches.
2026-10-02 07:53:47 +00:00

117 lines
4.4 KiB
Nix

{
config,
inputs,
lib,
pkgs,
...
}:
{
imports = [
inputs.matthew-hardware.nixosModules.mt7986a-glinet-gl-mt6000
];
# matthew-hardware's common/generic-uefi-image.nix still sets
# `image.repart.enable = true`; nixpkgs removed that option (importing
# image/repart.nix now always defines system.build.image). Declare it so the
# definition has somewhere to land. Drop once upstream stops setting it.
options.image.repart.enable = lib.mkOption {
type = lib.types.bool;
default = true;
internal = true;
};
config = {
hardware.mt7986a-glinet-gl-mt6000.enable = true;
hardware.mt7986a-glinet-gl-mt6000.zealous = true;
hardware.mt7986a-glinet-gl-mt6000.image.repart.enable = true;
nixpkgs.hostPlatform.system = "aarch64-linux";
nixpkgs.buildPlatform.system = "x86_64-linux";
system.stateVersion = "26.11";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.settings.name = "stellio";
clan.core.settings.machine.description = "Flint-2 router";
# Root is ext4 on the Flint 2's eMMC: keep steady-state writes off it.
# The journal is persistent but bounded (256M) and synced once a minute
# (the router needs logs for pppd/kea debugging and, after the Sep 2026
# unlogged reboots, for post-mortem; volatile storage left nothing).
# /tmp is tmpfs, no core dumps, and ext4 skips atime updates and
# flushes its journal every 60 s instead of 5 s so the small periodic
# writes (Kea leases, timesyncd clock, speedtest textfile, journal)
# coalesce. A power cut loses at most a minute of that state.
fileSystems."/".options = [
"noatime"
"commit=60"
];
boot.tmp.useTmpfs = true;
services.journald.settings.Journal = {
Storage = "persistent";
SystemMaxUse = "256M";
SyncIntervalSec = "1m";
};
systemd.coredump.enable = false;
# Upstream 07d9958739 (mainline 2026-05, not in linux-6.18.y). The MT7531
# switch on the Flint 2 hangs off MDIO, and mt7530_get_stats64 took the
# MDIO mutex under the RCU read lock that /proc/net/dev holds, so any
# stats reader (zerotier-one, node exporter, `ip -s link`) that raced a
# PHY access oopsed the box: "BUG: scheduling while atomic" ->
# "Unable to handle kernel paging request" on 2026-09-20 09:02 UTC.
# Drop once boot.kernelPackages moves to a kernel that carries it.
boot.kernelPatches = [
{
name = "mt7530-get-stats64-atomic";
patch = ./mt7530-get-stats64-atomic.patch;
}
];
# nixpkgs' services.blocky check runs the aarch64 blocky in a
# system.checks derivation, which an x86_64 builder without binfmt cannot
# execute (`--max-jobs 0` -> Exec format error). Validate the same YAML
# with the build host's blocky instead. Drop once cnx-network's router
# service carries this itself (router/dns: validate the Blocky config
# with the build host's binary).
services.blocky.enableConfigCheck = false;
system.checks = [
(pkgs.runCommand "check-blocky-config" { } ''
${lib.getExe pkgs.buildPackages.blocky} --config ${
(pkgs.formats.yaml { }).generate "blocky-config.yaml" config.services.blocky.settings
} validate && touch $out
'')
];
# The router service opens SSH only to the mgmt VLAN, the staging port
# and the ZeroTier mesh (inventories/router.nix). Also admit it over
# Yggdrasil (fleet-wide instance in inventories/default.nix) so the box
# stays reachable when ZeroTier's controller/relays are down. Scoped to
# the tunnel interface (clan-core's yggdrasil service names it `ygg`):
# only decrypted 200::/7 traffic arrives there, so a spoofed source on
# the WAN never matches.
networking.firewall.interfaces.${config.services.yggdrasil.settings.IfName}.allowedTCPPorts = [
22
];
systemd.services.heartbeat-push = {
description = "Heartbeat push to uptime monitor";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.curl}/bin/curl -s -o /dev/null https://uptime.b4l.co.th/api/push/X0WCHAcY5gPf1U8If7BT1FLjpacZqGZu?status=up&msg=OK&ping=";
};
};
systemd.timers.heartbeat-push = {
description = "Heartbeat push timer";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "60s";
OnUnitActiveSec = "60s";
Unit = "heartbeat-push.service";
};
};
};
}