From 06f5beccfc5fd89e28f025625038938ad2a2200b Mon Sep 17 00:00:00 2001 From: gregorbednov Date: Wed, 19 Aug 2026 11:53:15 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=B2=20=C2=AB?= =?UTF-8?q?/=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- configuration.nix | 114 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 109 insertions(+), 5 deletions(-) diff --git a/configuration.nix b/configuration.nix index 5f204e6..50ec680 100644 --- a/configuration.nix +++ b/configuration.nix @@ -737,13 +737,66 @@ in nvidia.acceptLicense = true; }; nix.settings = { - extra-substituters = [ "http://nixos.builds.node" ]; - trusted-public-keys = [ "nixos.builds.node:E/XNkcdzB0EyTyEJuOTXJH8qynxgCfQ87JHkbD88uF8=" ]; + # Локальный кэш идёт первым — большинство пакетов уже собраны на build-ноде + substituters = [ + "http://nixos.builds.node" + "https://cache.nixos.org" + ]; + trusted-public-keys = [ + "nixos.builds.node:E/XNkcdzB0EyTyEJuOTXJH8qynxgCfQ87JHkbD88uF8=" + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + ]; + trusted-substituters = [ "http://nixos.builds.node" ]; auto-optimise-store = true; + # Если build-нода временно недоступна — переходим к cache.nixos.org, не зависаем + connect-timeout = 5; + experimental-features = [ "nix-command" "flakes" ]; + # На дисках 50 GiB автоматически запускать GC при нехватке места + min-free = 2147483648; # 2 GiB — порог запуска GC + max-free = 5368709120; # 5 GiB — цель освобождения }; - nix.extraOptions = '' - experimental-features = nix-command flakes - ''; + nix.gc = { + automatic = true; + dates = "weekly"; + randomizedDelaySec = "45min"; # машины не запускают GC одновременно + options = "--delete-older-than 14d"; + }; + # Хранить не более 5 поколений в меню GRUB + boot.loader.grub.configurationLimit = 5; + # Периодический TRIM для SSD (безопасен и на HDD — просто no-op) + services.fstrim.enable = true; + # nix-daemon стартует только после Yggdrasil, иначе nixos.builds.node недостижим + systemd.services.nix-daemon = { + after = [ "yggdrasil.service" ]; + wants = [ "yggdrasil.service" ]; + }; + # Уникальный hostname на основе последних 6 цифр MAC-адреса основного интерфейса. + # networking.hostName = "nixos" остаётся fallback-значением в /etc/hostname; + # сервис перекрывает его transient-именем при каждой загрузке. + systemd.services.hostname-from-mac = { + description = "Set unique hostname from primary NIC MAC address"; + wantedBy = [ "network-pre.target" ]; + before = [ "network-pre.target" ]; + after = [ "systemd-udev-settle.service" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + mac=$(${pkgs.iproute2}/bin/ip link show \ + | grep -v LOOPBACK \ + | grep -oE '([0-9a-f]{2}:){5}[0-9a-f]{2}' \ + | head -1 \ + | tr -d ':') + if [ -n "$mac" ]; then + ${pkgs.systemd}/bin/hostnamectl set-hostname --transient "nixos-''${mac: -6}" + fi + ''; + }; + # Директория для хранения данных о физическом расположении компьютера + systemd.tmpfiles.rules = [ + "d /var/lib/place 0755 student users -" + ]; ##### НАСТРОЙКИ ГРАФИКИ И РАБОЧЕГО СТОЛА ###### hardware.graphics = { @@ -871,6 +924,57 @@ in tree wget git + yad + # Утилита фиксации физического расположения компьютера в аудитории. + # Использование: place [АУДИТОРИЯ] (например: place А-101) + # Запись: /var/lib/place/location (JSON, доступен root по SSH) + # При запуске от root через SSH автоматически подключается к X-сессии student на :0 + (pkgs.writeShellApplication { + name = "place"; + runtimeInputs = [ yad coreutils util-linux ]; + text = '' + ROOM_ARG="''${1:-}" + PLACE_FILE="/var/lib/place/location" + + # Когда запускается от root по SSH — показать диалог на локальном X :0 + if [ -z "''${DISPLAY:-}" ]; then + export DISPLAY=":0" + export XAUTHORITY="/home/student/.Xauthority" + fi + + if ! result=$(yad \ + --title="Место компьютера" \ + --text="Зафиксируйте расположение этого компьютера в аудитории.\nДанные сохраняются в /var/lib/place/location." \ + --form \ + --field="Аудитория" \ + --field="Ряд:NUM" \ + --field="Место:NUM" \ + --button="Сохранить:0" \ + --button="Отмена:1" \ + --width=340 \ + -- "''${ROOM_ARG}" 1 1 \ + 2>/dev/null); then + exit 0 # Нажата «Отмена» — без ошибки + fi + + room=$(printf '%s' "''${result}" | cut -d'|' -f1) + row=$(printf '%s' "''${result}" | cut -d'|' -f2 | cut -d'.' -f1) + seat=$(printf '%s' "''${result}" | cut -d'|' -f3 | cut -d'.' -f1) + + if [ -z "''${room}" ]; then + echo "Ошибка: поле «Аудитория» не заполнено" >&2 + exit 1 + fi + + mkdir -p "$(dirname "''${PLACE_FILE}")" + printf '{"room":"%s","row":%s,"seat":%s,"host":"%s","at":"%s"}\n' \ + "''${room}" "''${row}" "''${seat}" "$(hostname)" "$(date -Iseconds)" \ + > "''${PLACE_FILE}" + + echo "Сохранено: аудитория ''${room}, ряд ''${row}, место ''${seat}" + echo "Файл: ''${PLACE_FILE}" + ''; + }) ]; # удаленный доступ в пределах нашей сети