nix-config/hosts/heather/default.nix

135 lines
5.8 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# heather — сервер на Yandex Cloud (NixOS 26.11).
# https://git.iscg.dev/mikl/nix-config
#
# Перенесено из muscari (переименование 2026-07-11).
# VM на Yandex Cloud, 2 vCPU / 8 GB / 64 GB SSD (network-ssd), Legacy BIOS.
# Образ NixOS собирается как qcow2 (см. ./image.nix, make-disk-image.nix) и
# заливается как boot disk в YC. НЕ через nixos-anywhere — kexec на YC хрупкий.
# См. memory/yandex-nixos-qcow2.md.
#
# Архитектура (2026-07-12, заменила k3s):
# Caddy (edge, TLS) → host-сервисы (syncthing) + docker-контейнеры (arion)
# Cilium/k3s выключены — overhead 1.3 GB был неоправдан для single-node.
# См. ./docker.nix, ./caddy.nix, ./syncthing.nix, ./arion-compose.nix.
{ config, pkgs, lib, ... }:
{
imports = [
./image.nix # YC guest profile + qcow2 build target
./docker.nix # docker + arion CLI (контейнеры)
./caddy.nix # edge proxy, TLS, роутинг по доменам
./syncthing.nix # sync + relay
./tuwunel-admin.nix # matrix admin web UI (systemd, статический бинарник)
./pi-web.nix # pi-web (web UI для pi coding agent, systemd + npm global)
./mesh-clients.nix # Sol-style client pool (wg-clients1)
];
# First server-to-server WireGuard backbone link: heather ↔ hyacinth.
# The private key is generated on the live host and stays outside the flake.
environment.systemPackages = [ pkgs.wireguard-tools ];
# NixOS uses scripted networking here (not systemd-networkd), so create the
# dummy identity interface through a small idempotent systemd unit.
systemd.services.mesh-identity = {
description = "Create mesh identity interface";
wantedBy = [ "network.target" ];
after = [ "wireguard-wg-mesh.service" "network-addresses-wg-mesh.service" ];
wants = [ "wireguard-wg-mesh.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = pkgs.writeShellScript "mesh-identity-up" ''
set -eu
${pkgs.iproute2}/bin/ip link show mesh0 >/dev/null 2>&1 || ${pkgs.iproute2}/bin/ip link add mesh0 type dummy
${pkgs.iproute2}/bin/ip addr replace 10.0.0.1/32 dev mesh0
${pkgs.iproute2}/bin/ip link set mesh0 up
'';
ExecStop = "${pkgs.iproute2}/bin/ip link del mesh0";
};
};
networking.wireguard.interfaces.wg-mesh = {
ips = [ "10.99.0.1/30" ];
listenPort = 51820;
privateKeyFile = "/var/lib/wireguard/wg-mesh.key";
# Keep WG as transport/crypto ACL; install the identity route explicitly below.
allowedIPsAsRoutes = false;
peers = [
{
publicKey = "BxTH8+MiA8Hv48UfpWJDVXIhbO5HgO2KTBEXIqqr23k=";
allowedIPs = [ "10.99.0.2/32" "10.0.0.2/32" ];
endpoint = "195.242.119.59:51820";
persistentKeepalive = 25;
}
];
};
networking.interfaces.wg-mesh.ipv4.routes = [
{ address = "10.0.0.2"; prefixLength = 32; }
];
# Needed later when this node becomes a transit/exit peer.
boot.kernel.sysctl."net.ipv4.ip_forward" = 1;
# Arion-проект как systemd-сервис: arion-compose.nix → docker-compose → up.
# NB: settings — это модуль с imports, НЕ `import ./arion-compose.nix`.
virtualisation.arion.backend = "docker";
virtualisation.arion.projects.heather = {
serviceName = "heather"; # systemd: arion-heather.service
settings = {
imports = [ ./arion-compose.nix ];
};
};
networking = {
hostName = "heather";
# Firewall выключен в ./image.nix (полагаемся на YC Security Groups).
# Порты тут только для документации — реально открывает YC SG.
firewall.allowedTCPPorts = [
22 # SSH
80 # HTTP (Caddy → redirect to HTTPS)
443 # HTTPS (Caddy, TLS termination)
2222 # forgejo git ssh (публично)
22000 # syncthing sync
22067 # strelaysrv (relay)
22070 # strelaysrv (status)
3478 # coturn TURN (tcp+udp)
8443 # xray VLESS+Reality (публичный прокси)
51820 # WireGuard mesh backbone
];
firewall.allowedUDPPorts = [
51820 # WireGuard mesh backbone
22000 # syncthing sync (QUIC)
10000 # jitsi jvb (RTP media)
3478 # coturn TURN
];
# coturn RTP relay range
firewall.allowedUDPPortRanges = [
{ from = 49152; to = 65535; } # coturn RTP relay
];
};
# useDHCP задаёт ./image.nix (mkDefault) — облачный профиль.
# SSH ключи для mikl: forgejo .keys endpoint с sha256-pinning.
# Poppy-ключ (этот ноутбук) лежит там последней строкой.
users.users.mikl.openssh.authorizedKeys.keyFiles = [
(pkgs.fetchurl {
url = "https://git.iscg.dev/mikl.keys";
sha256 = "sha256-Omc/3NJn0nM8SWeF33trFwOAVgSX0fXB5dfEakcRoTA=";
})
];
# Rescue-канал: root с тем же poppy-ключом. PermitRootLogin = prohibit-password
# (см. image.nix) пускает root только по ключу — парольного root-логина нет.
# Нужен, чтобы не оказаться запертым без root, если passwordless sudo сломается
# (как произошло на первом образе heather): ssh root@heather и nixos-rebuild.
users.users.root.openssh.authorizedKeys.keyFiles = [
(pkgs.fetchurl {
url = "https://git.iscg.dev/mikl.keys";
sha256 = "sha256-Omc/3NJn0nM8SWeF33trFwOAVgSX0fXB5dfEakcRoTA=";
})
];
# После первой установки 25.11 не трогаем (NixOS convention)
system.stateVersion = "25.11";
}