diff --git a/.forgejo/workflows/iso-nixos-installer.yaml b/.forgejo/workflows/iso-nixos-installer.yaml index d9a9373..29c346f 100644 --- a/.forgejo/workflows/iso-nixos-installer.yaml +++ b/.forgejo/workflows/iso-nixos-installer.yaml @@ -11,7 +11,8 @@ jobs: SERVER: ${{ forgejo.server_url }} REPO: ${{ forgejo.repository }} run: | - ISO="result/iso/mirea-nixos-installer.iso" + ISO_NAME=$(nix eval --raw ./installer#nixosConfigurations.installer.config.isoImage.isoName) + ISO="result/iso/$ISO_NAME" NEW_SHA=$(sha256sum "$ISO" | awk '{print $1}') LATEST_BODY=$(curl -sf \ @@ -37,7 +38,7 @@ jobs: curl -sf -X POST \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/octet-stream" \ - "$SERVER/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=mirea-nixos-installer.iso" \ + "$SERVER/api/v1/repos/$REPO/releases/$RELEASE_ID/assets?name=$ISO_NAME" \ --data-binary "@$ISO" echo "Published release $TAG (sha256: $NEW_SHA)" diff --git a/configuration.nix b/configuration.nix index 5ce423e..e8b747e 100644 --- a/configuration.nix +++ b/configuration.nix @@ -7,7 +7,12 @@ }: let serverIP = "10.0.174.12"; + serverAddress = "kafpi.local"; buildNodeYggIP = "200:ccc6:1361:5c84:aba0:1244:35f5:c903"; + + sshKeys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCyBYo/E/FkFZVABzMixLS2TWaipfN5T24y8f+E6Px1t+IG8PLnQ38dLJiCR8k971DOycLuJUfKWsC06BK3XLWTO0+PmpfGKNT4NI6dwP2REl/umaignP/QQSs2w9Ff49WqPjIYTSmATTsCNZSVB0VtM0eJ+Y9Ff4CXb1frtt4GYztk6XB3jc3TxV72qzB0g6DqrHkf6pT5YAq2UeuFGZYSZCqBvVXCGcvKHkO1KBubuo95itVA5XbzK3INQTZpQowbtK4ULhUYlaGBcX5tYq1bdiTCDlTcLt6MfxYfFHSFiHbJOzdGPd+mXM7urOQhq49uQOf07dHt9qAzQHajItQb+X3FOgyFt4n6Y9Q37gn/6KC3PH1zClldq9DtgttuG/Xk15q+uvCldji9YIgb80aRHBIp6DY8PlYodmGGesBLiBMGQ7hgKupfkqszjfMkxnMYIkZodUCQVgaqsxsEQ7lD84JJMgBY8HkNLxKhy+6dP6kTc4vTtrpjezq/Ph95PFE= bednov@kafpi-108-1-mainserver2" + ]; hasBootPartition = config.fileSystems ? "/boot"; isNvidia = (builtins.readFile ( @@ -15,14 +20,29 @@ let ${pkgs.pciutils}/bin/lspci | ${pkgs.busybox}/bin/grep NVIDIA | ${pkgs.busybox}/bin/grep VGA > $out || true '' )) != ""; - isAdata = # ADATA is a famous cheap troubleful NVMe controllers + isAdata = # ADATA is a famous cheap troubleful NVMe controllers (builtins.readFile ( pkgs.runCommandLocal "isAdata" { } '' ${pkgs.pciutils}/bin/lspci | ${pkgs.busybox}/bin/grep ADATA | ${pkgs.busybox}/bin/grep -i NVMe > $out || true '' )) != ""; + + # any MIREA Uuniversity specifics (apps, wallpapers) are located in ./mirea-specific + # other uuniversities can use their own files there + # + # всё, что специфично именно для МИРЭА (брендирование, герб, номер учебной недели), + # вынесено в mirea-specific/ — другой вуз может подставить свои значения/файлы. + university = import ./mirea-specific/university.nix; + mireaweek = pkgs.callPackage ./mirea-specific/mireaweek.nix { }; + desktop = inputs.mireadesktop.lib.mkDesktop { + wallpaper = university.wallpaper; + extraTint2Widgets = import ./mirea-specific/tint2-widget.nix { inherit mireaweek; }; + }; in { + + # local versions for stm32cubemx and staruml installers + # локальные версии stm32cubemx и staruml nixpkgs.overlays = [ (final: prev: { staruml = prev.staruml.overrideAttrs (old: { @@ -32,19 +52,32 @@ in }; }); stm32cubemx = prev.stm32cubemx.override { - fetchzip = args: prev.fetchzip (args // { + fetchzip = + args: + prev.fetchzip ( + args + // { url = "http://${serverIP}/stm32cube_mx_v6111-lin.zip"; hash = "sha256-By9T43GLM1J63TkRi3kl05h1RflBorU1QHgYOrXQ9N0="; - }); - buildFHSEnv = args: prev.buildFHSEnv ( args // { + } + ); + buildFHSEnv = + args: + prev.buildFHSEnv ( + args + // { unshareNet = true; - }); + } + ); }; }) ]; users.users.student = { isNormalUser = true; - initialPassword = "student"; # вход беспарольный, но пароль student + + # login is passwordless, however password is 'student' too + # вход беспарольный, но пароль student + initialPassword = "student"; extraGroups = [ "video" "sound" @@ -54,7 +87,8 @@ in ]; packages = let - # определение как скачивать плагины jetbrains (скачивать с нашего сервера копию) + # local copies of plugins + # скачивать с нашего сервера копии плагинов jetbrains customJBPlugin = nam: ver: sha: pkgs.stdenv.mkDerivation { @@ -73,8 +107,8 @@ in [ (pkgs.jetbrains.plugins.addPlugins pkgs.jetbrains.idea-community ( - # набор плагинов, я бы сказал, богат до избыточности, но главное есть Python - # и Database Nagivator. Остальное - любителям и любознательным. + # wide plugin set. PythonCore and Database Navigator is a key difference to stock IDEA CE + # богатый набор плагинов, главное есть Python и Database Nagivator. Остальное - любителям и любознательным. (with inputs.nix-jetbrains-plugins.plugins."${system}"; [ idea-community."2024.1"."mobi.hsz.idea.gitignore" #idea-community."2024.1"."org.jetbrains.erlang" @@ -96,53 +130,86 @@ in idea-community."2024.1"."com.redhat.devtools.lsp4ij" ]) ++ [ - # поддежка фреймворка Spring через opensource-плагин Explyt. пусть будет + # russian opensource Explyt Spring plugin out of Jetbrains Marketplace + # поддежка фреймворка Spring через opensource-плагин Explyt (customJBPlugin "spring-tool" "241-b3085-signed" "sha256-u9Hqy4BN1johA7e8proMekyERXkE6gXRnqGRNR7FouE=" ) ] )) - chromium # браузер - pinta # графический редактор - sakura # терминал - unzipNLS # поддержка zip - unrar # поддержка rar - mate.engrampa - gtk3 - whitesur-icon-theme # необходимо для иконок - (pkgs.writeShellScriptBin "powermenu" ( - builtins.readFile inputs.mireadesktop.packages.x86_64-linux.powermenu - )) - (pkgs.writeShellScriptBin "resethome" ( - builtins.readFile inputs.mireadesktop.packages.x86_64-linux.resethome - )) + # browser + # браузер + chromium - inputs.kompas3d.packages.${pkgs.system}.default # KOMPAS-3D - freecad elmerfem gmsh # FEM calculation + # graphics editor + # графический редактор + pinta + + # terminal emulator + # терминал + sakura + + # GUI archive/unarchive tool with zip and rar support + # Архиватор с поддержкой zip и rar + mate.engrampa + unzipNLS + unrar + + gtk3 + + # icon theme + # тема иконок + whitesur-icon-theme + + # powermenu GUI util for poweroff or reboot + # графическое меню выключения или перезагрузки компьютера + (pkgs.writeShellScriptBin "powermenu" (builtins.readFile desktop.powermenu)) + + # resethome reset student home, deleting most of files, user caches and configs, leaving only default options + # useful for resetting vandal settings + # + # resethome позволяет удалить содержимое домашней директории пользователя student, + # сбрасывая нефунциональные настройки, установленные студентами в том числе из хулиганских побуждений + (pkgs.writeShellScriptBin "resethome" (builtins.readFile desktop.resethome)) + + inputs.kompas3d.packages.${pkgs.system}.default # KOMPAS-3D CAD + freecad + elmerfem + gmsh # FEM calculation inputs.nix-wine-experiments.packages.x86_64-linux.nbdesigner pandoc onlyoffice-desktopeditors + # ----- + # Seafile client for department cloud drive + # Напоминаю что у нас есть СЕТЕВОЙ ДИСК по адресу 10.0.174.12 - # и для студентов пока есть единая учётка student@mirea.ru, - # рассматривается вариант авторизации через sso.mirea.ru. + # и для студентов пока есть единая учётка (домен и SSO — см. mirea-specific/university.nix), + # рассматривается вариант авторизации через SSO вуза. # Преподаватели могут зарегистрироваться ОТДЕЛЬНО seafile-client + # ------ + # developer utils # утилиты разработчика git cmakeWithGui gnumake + ###### PROGRAMMING LANGUAGES ##### ###### ЯЗЫКИ ПРОГРАММИРОВАНИЯ ##### + # Python enviroment, for full abilites list see + # https://forgejo.gregorbednov.ru/gregorbednov/mireapython + # поставка Python, полный список возможностей - # см. на github.com/gregorybednov/mireapython + # см. на https://forgejo.gregorbednov.ru/gregorbednov/mireapython inputs.mireapython.packages.x86_64-linux.mireapython + # basic C/C++ support and debug # базовая поддержка C/C++ и дебага clang clang-tools @@ -150,55 +217,82 @@ in valgrind cpplint cppcheck - gcc-arm-embedded # компиляция С/C++ под STM32 и прочие arm + + # C/C++ toolchain for STM32 and other ARM chips + # компиляция С/C++ под STM32 и прочие arm + gcc-arm-embedded octaveFull # GNU Octave - shellcheck # проверка шелл-кода (bash, POSIX sh, ...) + # static shell code analyzer (bash, POSIX sh, ...) + # проверка шелл-кода (bash, POSIX sh, ...) + shellcheck + # Other possible languages and tools, e.g.: # Другие возможные языки и инструменты, например: # rustc # - Rust # go gopls delve golint go-tools # - Go jdk - kotlin # - Java, Kotlin (идут вместе с IJ IDEA) + kotlin # - Java, Kotlin (needed for IJ IDEA) # ghc haskell-language-server # - Haskell # nodePackages.intelephense # - PHP # dotnet-sdk # - C# + ####### DB modeling and development ########## ####### Проектирование и разработка баз данных, ИУС, ... ####### + # EACH nixos has its own local mysql and postgres servers + # with root access by students, see below for details + # + # у КАЖДОГО nixos есть свой локальный сервер mysql и postgres, + # у студентов есть root-доступ, см. ниже по файлу + + # Workbench for ER modeling and wrigin MySQL code # Workbench для управления и ER-моделирования БД на mysql - # у КАЖДОГО nixos есть свой локальный сервер mysql, см. ниже по файлу mysql-workbench + # BPMN Modeler, just like Bizagi Modeler we used before, but cross-platform + # btw has web-version on https://bpmn.io + # # аналог Bizagi Modeler, расширенный вариант bpmn.io camunda-modeler + # GUI UML, BPMN, ER, etc. modeling + # # графическое моделирование UML-диаграмм # также доступно моделирование BPMN и ER (staruml.overrideAttrs (oldAttrs: { nativeBuildInputs = (oldAttrs.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ]; - postFixup = - (oldAttrs.postFixup or "") - + '' - # Rename the original binary - mv $out/bin/staruml $out/bin/.staruml-org - - # Create the wrapper script - makeWrapper ${pkgs.bash}/bin/bash $out/bin/staruml \ - --add-flags "-c 'rm -rf \$HOME/.config/StarUML && exec $out/bin/.staruml-org \"\$@\"'" - ''; + # бесконечный триал + postFixup = (oldAttrs.postFixup or "") + '' + mv $out/bin/staruml $out/bin/.staruml-org + makeWrapper ${pkgs.bash}/bin/bash $out/bin/staruml \ + --add-flags "-c 'rm -rf \$HOME/.config/StarUML && exec $out/bin/.staruml-org \"\$@\"'" + ''; })) + # declarative text to UML diagrams visualizer + # very useful for software developers (bc inserting diagrams into code) + # has VSCode and IJ IDEA CE support + # # Язык текстового описания UML-диаграмм # актуально для разработчиков ПО (встраивание диаграмм в код) # поддерживается нашей поставкой IJ IDEA CE plantuml + + # graph visualizer + # it is necessary for plantuml + # + # визуализатор графов общего назначения + # обязателен для plantuml graphviz - archi # поддержка archimate + # archimate diagrams support + # поддержка archimate + archi + ##### Utils and apps for STM32 ##### ##### Утилиты и программы для STM32 ##### stm32cubemx stlink @@ -206,19 +300,41 @@ in stm32loader openocd + ##### NETWORK APPS AND UTILS ###### ##### СЕТЕВЫЕ УТИЛИТЫ ###### - # установлен Cisco Packet Tracer, обернут в firejail чтобы не стучался на Netacad.com - nodePackages.node-red # - лоукод-платформа программирования устройств, в частности интернета вещей - httpie - httpie-desktop # - передовой клиент HTTP-запросов - netcat - socat # - низкоуровневые простейшие утилиты установления TCP или UDP между компьютерами или с ПЛК - opcua-client-gui # - простой графический клиент OPC UA + # Cisco Packet Tracer 7 was installed but it was firejailed to work without Netacad.com accounts + # установлен Cisco Packet Tracer 7, обернут в firejail чтобы не стучался на Netacad.com + + # lowcode for IoT programming used in IIoT and IoT practices in uuniversity + # лоукод-платформа программирования устройств, в частности интернета вещей + nodePackages.node-red + + # probably best http request client + # передовой клиент HTTP-запросов + httpie + httpie-desktop + + # simple network and socket level utils for practicing simple TCP and UDP between PCs, IoT devices and PLCs + # низкоуровневые простейшие утилиты установления TCP или UDP между компьютерами или с ПЛК + netcat + socat + + # simple OPC UA GUI client + # простой графический клиент OPC UA + opcua-client-gui + + ###### OTHER SOFTWARE #### ###### Другой софт ####### logisim-evolution - unityhub # UnityHub - 3D-моделирование, визуализация, геймдев, AR/VR + + # UnityHub - 3D modeling, visualisation, gamedev, AR/VR + # UnityHub - 3D моделирование, визуализация, геймдев, AR/VR + unityhub + + # DWSim for chemical techology simulation and modeling + # DWSIM - симулятор химических технологических процессов (pkgs.stdenv.mkDerivation rec { pname = "dwsim"; version = "9.0.5"; @@ -332,6 +448,8 @@ in ''; }) + + # shareware CNC VMC 3D-graphical simulator (pkgs.stdenv.mkDerivation rec { pname = "cnc_vmc_sim"; version = "1.0.0-share"; @@ -372,6 +490,9 @@ in startupNotify = false; }; }) + + # ramus educational for IDEF0 and DFD modeling + # ramus educational для моделирования в нотациях IDEF0, DFD (pkgs.stdenv.mkDerivation rec { pname = "ramus"; version = "0.1.3"; @@ -388,6 +509,10 @@ in ''; }) + # SimInTech (russian matlab simulink alternative) + # C code generation works, but dynamic libraries are NOT + # compatible with Windows DLL! + # # поставка SimInTech. Кодогенерация библиотек для ПК работает, # но несовместима с .dll из windows! (pkgs.stdenv.mkDerivation rec { @@ -441,6 +566,8 @@ in ''; }) + # ErLu is a modern Qt-based opensource alternative to Ramus and Erwin Process Modeler + # ErLu - современная альтернатива с октрытым исходным кодом для Ramus и Erwin Process Modeler (stdenv.mkDerivation { pname = "erlu-idef0-editor"; version = "1.0.1"; @@ -463,9 +590,9 @@ in ]; configurePhase = '' - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=$out \ - -DBUILD_COLORS_PLUGIN=ON + cmake -S . -B build -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX=$out \ + -DBUILD_COLORS_PLUGIN=ON ''; buildPhase = '' @@ -495,7 +622,11 @@ in runHook postInstall ''; - qtWrapperArgs = [ "--set" "QT_LOGGING_RULES" "qt.qpa.wayland.textinput=false" ]; + qtWrapperArgs = [ + "--set" + "QT_LOGGING_RULES" + "qt.qpa.wayland.textinput=false" + ]; meta = with lib; { description = "IDEF0 diagram editor built with Qt 6 Widgets"; license = licenses.lgpl3Plus; @@ -504,15 +635,19 @@ in }; }) + # student & teacher's userspace alias gcc = clang, g++ = clang++ + # i know it looks crazy but sometimes we have to match someone's wrong expectations. + # Of course you can delete this shit if you want to (pkgs.writeShellScriptBin "gcc" ''${pkgs.clang}/bin/clang "$@"'') (pkgs.writeShellScriptBin "g++" ''${pkgs.clang}/bin/clang++ "$@"'') + # VS Code (vscode-with-extensions.override { vscodeExtensions = with vscode-extensions; [ ms-vscode.cpptools-extension-pack - ms-dotnettools.csharp + #ms-dotnettools.csharp formulahendry.code-runner tomoki1207.pdf ms-vscode.hexeditor @@ -529,6 +664,7 @@ in ms-vscode-remote.remote-ssh timonwong.shellcheck ] + # QT, STM32, ARM, debug ++ pkgs.vscode-utils.extensionsFromVscodeMarketplace [ { name = "vscode-cppcheck"; @@ -537,72 +673,78 @@ in sha256 = "sha256-RDgO8/XenttOcYQSGEu4N2FKg9+FZaQe6HYkVjztH5o="; } { - name = "cortex-debug"; - publisher = "marus25"; - version = "1.12.1"; - sha256 = "sha256-ioK6gwtkaAcfxn11lqpwhrpILSfft/byeEqoEtJIfM0="; - } - { - name = "vscode-serial-monitor"; - publisher = "ms-vscode"; - version = "0.13.251128001"; - sha256 = "sha256-eTQcLyF6DMvzDByKLw2KR8PrjVwejsOU60Hew7IOmY8="; - } - { - name = "arm-assembly-syntax"; - publisher = "ciprianelies"; - version = "1.7.6"; - sha256 = "sha256-4vWw0ogtZ3mOw0lT95k/5I/7GMvU5kfaaztwc+eI/do="; - } - { - name = "stm32-for-vscode"; - publisher = "bmd"; - version = "3.2.13"; - sha256 = "sha256-Dzj++F0xTDOaL9VA3X/bVtAhkxd8kPPl3Oz8LWrXpAA="; - } - { - name = "qt-cpp-pack"; - publisher = "TheQtCompany"; - version = "1.0.2"; - sha256 = "sha256-Kd2/kk3qJUOahz71Uh3mUI1wDuwS8/t84tgdWorRPG4"; - } - { - name = "debug-tracker-vscode"; - publisher = "mcu-debug"; - version = "0.0.15"; - sha256 = "sha256-2u4Moixrf94vDLBQzz57dToLbqzz7OenQL6G9BMCn3I="; - } - { - name = "memory-view"; - publisher = "mcu-debug"; - version = "0.0.28"; - sha256 = "sha256-mQr/uLulKoPVXz0GaMMEHZ/ZSmSAEfO9UpFzy4MfcW4="; - } - { - name = "rtos-views"; - publisher = "mcu-debug"; - version = "0.0.13"; - sha256 = "sha256-eTEdZkHbAGSDXP9A06YL6jDBfO8rU1kC9RysxOUxI1U="; - } - { - name = "peripheral-viewer"; - publisher = "mcu-debug"; - version = "1.6.0"; - sha256 = "sha256-nKK8HRzeqDixpdKmgacjhNzanJaTsAnYLC6nCbmWXuU="; - } + name = "cortex-debug"; + publisher = "marus25"; + version = "1.12.1"; + sha256 = "sha256-ioK6gwtkaAcfxn11lqpwhrpILSfft/byeEqoEtJIfM0="; + } + { + name = "vscode-serial-monitor"; + publisher = "ms-vscode"; + version = "0.13.251128001"; + sha256 = "sha256-eTQcLyF6DMvzDByKLw2KR8PrjVwejsOU60Hew7IOmY8="; + } + { + name = "arm-assembly-syntax"; + publisher = "ciprianelies"; + version = "1.7.6"; + sha256 = "sha256-4vWw0ogtZ3mOw0lT95k/5I/7GMvU5kfaaztwc+eI/do="; + } + { + name = "stm32-for-vscode"; + publisher = "bmd"; + version = "3.2.13"; + sha256 = "sha256-Dzj++F0xTDOaL9VA3X/bVtAhkxd8kPPl3Oz8LWrXpAA="; + } + { + name = "debug-tracker-vscode"; + publisher = "mcu-debug"; + version = "0.0.15"; + sha256 = "sha256-2u4Moixrf94vDLBQzz57dToLbqzz7OenQL6G9BMCn3I="; + } + { + name = "memory-view"; + publisher = "mcu-debug"; + version = "0.0.28"; + sha256 = "sha256-mQr/uLulKoPVXz0GaMMEHZ/ZSmSAEfO9UpFzy4MfcW4="; + } + { + name = "rtos-views"; + publisher = "mcu-debug"; + version = "0.0.13"; + sha256 = "sha256-eTEdZkHbAGSDXP9A06YL6jDBfO8rU1kC9RysxOUxI1U="; + } + { + name = "peripheral-viewer"; + publisher = "mcu-debug"; + version = "1.6.0"; + sha256 = "sha256-nKK8HRzeqDixpdKmgacjhNzanJaTsAnYLC6nCbmWXuU="; + } + { + name = "qt-cpp-pack"; + publisher = "TheQtCompany"; + version = "1.0.2"; + sha256 = "sha256-Kd2/kk3qJUOahz71Uh3mUI1wDuwS8/t84tgdWorRPG4"; + } ]; }) + # QT qtcreator qt6.full qt6.qtbase + + # debugging gdb - isort black + # Python-related things + # доп.утилиты для Python + isort + black - - # POSIX утилиты для совместимости + # POSIX утилиты для совместимости с предметами про POSIX + # POSIX utils to align POSIX-related university courses and subjects om4 pax mailutils @@ -618,15 +760,18 @@ in ]; }; + # inserted USB sticks mounts automatically # вставленные флешки автоматически монтируются services.devmon.enable = true; + # POSIX at # необходимо для совместимости с POSIX по команде at, при отсутствии необходимости можно удалить services.atd = { enable = true; allowEveryone = true; }; + # each PC has its own mysql and postgresql # на каждой машине свой сервер mysql и postgresql services.mysql = { enable = true; @@ -640,6 +785,7 @@ in ''; }; + # each mysql and psql support root without password for student # и оба поддерживают вход без пароля в "руты" system.userActivationScripts.mycnf = { text = '' @@ -648,37 +794,42 @@ in ''; deps = [ ]; }; - environment = { - etc."gtk-3.0/settings.ini" = { - text = '' - [Settings] - gtk-icon-theme-name = WhiteSur - ''; - mode = "0644"; - }; - variables = { - PGUSER = "postgres"; - }; + environment.variables = { + PGUSER = "postgres"; }; + # whitesur icons + environment.etc."gtk-3.0/settings.ini" = { + text = '' + [Settings] + gtk-icon-theme-name = WhiteSur + ''; + mode = "0644"; + }; - + # STM32CubeMX STM32F107VCT6 automatic on-login firmware setup systemd.user.services.stm32cubemx-repo = - let - stm32f1-v180 = builtins.fetchTarball { url = "http://${serverIP}/STM32Cube.tar.gz"; sha256 = "sha256:1zlcp82xq16anx02ghiv9xa5bi2fsz78h945miqmi26bwcjxdagn"; }; + let + stm32f1-v180 = builtins.fetchTarball { + url = "http://${serverIP}/STM32Cube.tar.gz"; + sha256 = "sha256:1zlcp82xq16anx02ghiv9xa5bi2fsz78h945miqmi26bwcjxdagn"; + }; - in { - description = "STM32CubeMX firmware repository setup"; - wantedBy = [ "default.target" ]; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = true; - ExecStart = pkgs.writeShellScript "stm32cubemx-repo-setup" '' - cp -r ${stm32f1-v180}/. "$HOME/STM32Cube" - chmod -R u+w "$HOME/STM32Cube" - ''; + in + { + description = "STM32CubeMX firmware repository setup"; + wantedBy = [ "default.target" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = pkgs.writeShellScript "stm32cubemx-repo-setup" '' + cp -r ${stm32f1-v180}/. "$HOME/STM32Cube" + chmod -R u+w "$HOME/STM32Cube" + ''; + }; }; - }; + + # russian licensing service for Kompas-3D CAD services.grdcontrol.enable = true; imports = [ @@ -706,8 +857,14 @@ in }; }; + # if it also has Windows partition, then it should allow + # choose OS for 30 sec + # + # otherwise, it should boot in 5 sec + # ---------- # если машина установлена на диск с Windows, # то она позволяет "увидеть" и выбрать Windows в течение 30 с + # # иначе - 5 c таймаута (для виртуалок) boot.loader = if hasBootPartition then @@ -741,12 +898,13 @@ in }; time.hardwareClockInLocalTime = hasBootPartition; - # настройки Nix + # Nix settings nixpkgs.config = { allowUnfree = true; nvidia.acceptLicense = true; }; nix.settings = { + # Local cache is asked before global because most of packages are already built # Локальный кэш идёт первым — большинство пакетов уже собраны на build-ноде substituters = [ "http://nixos.builds.node" @@ -758,27 +916,40 @@ in ]; trusted-substituters = [ "http://nixos.builds.node" ]; auto-optimise-store = true; + # If build node is unavailiable then go to cache.nixos.org with no hanging # Если build-нода временно недоступна — переходим к cache.nixos.org, не зависаем connect-timeout = 5; - experimental-features = [ "nix-command" "flakes" ]; + experimental-features = [ + "nix-command" + "flakes" + ]; + + # For 50 GiB partition use auto-GC if no space left # На дисках 50 GiB автоматически запускать GC при нехватке места - min-free = 2147483648; # 2 GiB — порог запуска GC - max-free = 5368709120; # 5 GiB — цель освобождения + min-free = 2147483648; # 2 GiB — порог запуска GC + max-free = 5368709120; # 5 GiB — цель освобождения }; nix.gc = { automatic = true; dates = "weekly"; - randomizedDelaySec = "45min"; # машины не запускают GC одновременно + randomizedDelaySec = "45min"; # PCs don't launch GC at the same time options = "--delete-older-than 14d"; }; - # Периодический TRIM для SSD (безопасен и на HDD — просто no-op) + # periodic TRIM for SSD (safe for HDD) + # Периодический TRIM для SSD (безопасен на HDD) services.fstrim.enable = true; + + # nix-daemon starts after Yggdrasil does, otherwise nixos.builds.node will be unavailiable # nix-daemon стартует только после Yggdrasil, иначе nixos.builds.node недостижим systemd.services.nix-daemon = { after = [ "yggdrasil.service" ]; wants = [ "yggdrasil.service" ]; }; + + # unique hostname based on 6 last MAC address digits + # networking.hostName = "nixos" leaves back as default fallback + # # Уникальный hostname на основе последних 6 цифр MAC-адреса основного интерфейса. # networking.hostName = "nixos" остаётся fallback-значением в /etc/hostname; # сервис перекрывает его transient-именем при каждой загрузке. @@ -802,11 +973,14 @@ in fi ''; }; + + # Place location service # Директория для хранения данных о физическом расположении компьютера systemd.tmpfiles.rules = [ "d /var/lib/place 0755 student users -" ]; + ##### GRAPHICS & DE & DM SETTINGS ###### ##### НАСТРОЙКИ ГРАФИКИ И РАБОЧЕГО СТОЛА ###### hardware.graphics = { enable = true; @@ -844,12 +1018,23 @@ in nvidiaSettings = false; }; - services.udev.packages = [ pkgs.stlink pkgs.openocd ]; - services.udev.extraRules = if isAdata then '' - ACTION=="add|change",KERNEL=="nvme[0-9]", ATTR{queue/scheduler}="none" - '' else ""; - boot.kernelParams = lib.optionals isNvidia [ "nvidia-drm.modeset=1" ] - ++ lib.optionals isAdata [ "nvme_core.default_ps_max_latency_us=0" "nvme_core.io_timeout=4294967295" ]; + services.udev.packages = [ + pkgs.stlink + pkgs.openocd + ]; + services.udev.extraRules = + if isAdata then + '' + ACTION=="add|change",KERNEL=="nvme[0-9]", ATTR{queue/scheduler}="none" + '' + else + ""; + boot.kernelParams = + lib.optionals isNvidia [ "nvidia-drm.modeset=1" ] + ++ lib.optionals isAdata [ + "nvme_core.default_ps_max_latency_us=0" + "nvme_core.io_timeout=4294967295" + ]; boot.blacklistedKernelModules = lib.optionals isNvidia [ "nouveau" ]; boot.extraModprobeConfig = if isNvidia then @@ -866,17 +1051,16 @@ in services.getty.autologinUser = "student"; services.xserver.displayManager.lightdm.enable = true; services.xserver.displayManager.startx.enable = true; - services.displayManager.defaultSession = "MIREA-WindowsLike+Metacity"; + services.displayManager.defaultSession = "${university.shortName}-WindowsLike+Metacity"; services.xserver.displayManager.session = [ { manage = "desktop"; - name = "MIREA-WindowsLike"; - # подробности настроек рабочего стола см. на github.com/gregorybednov/mireadesktop + name = "${university.shortName}-WindowsLike"; start = '' - ${inputs.mireadesktop.packages.x86_64-linux.tint2} & - ${inputs.mireadesktop.packages.x86_64-linux.pcmanfm} & - ${inputs.mireadesktop.packages.x86_64-linux.sxhkd} & - #${inputs.mireadesktop.packages.x86_64-linux.xcape} & + ${desktop.tint2} & + ${desktop.pcmanfm} & + ${desktop.sxhkd} & + #${desktop.xcape} & waitPID=$! ''; } @@ -890,7 +1074,17 @@ in } ]; + ##### NETWORKING SETTINGS ##### ##### СЕТЕВЫЕ НАСТРОЙКИ ####### + + # Yggdrasil-маршрутизация позволяет целевым ПК автоматически получать статический IPv6 даже в сетях DHCP, + # что также запускается на установщике для максимальной гибкости. + # Благодаря Yggdrasil может быть доступно удаленнное управление и локальный кэш сборок + + # Yggdrasil routing above network allows any target PC to get automatically static IPv6 even on DHCP, + # so installer is recommended to use Yggdrasil too for maximum scalability + # With Yggdrasil routing it's easy to connect remotely, and you can use + # nix build cache nodes with DHCP-addresses (e.g. other PCs) services.yggdrasil = { enable = true; persistentKeys = true; @@ -899,16 +1093,31 @@ in }; }; + # each computer has internet connection # каждый компьютер имеет выход в интернет - networking.networkmanager.enable = ! config.services.harmonia.enable; + + # our buildnode caught a bug on launching with networkmanager, + # so I had to disable it + # + # наша build-нода не работала с networkmanager, отключалась от сети, + # так что пришлось ее отключить + networking.networkmanager.enable = !config.services.harmonia.enable; networking.hostName = "nixos"; - networking.firewall.allowedTCPPorts = [ 22 ] ++ lib.optionals config.services.harmonia.enable [ 80 ]; + networking.firewall.allowedTCPPorts = [ + 22 + ] + ++ lib.optionals config.services.harmonia.enable [ 80 ]; - - # каждый компьютер знает, что kafpi.local - это адрес нашего сервера - networking.hosts."${serverIP}" = [ "kafpi.local" ]; + # each computer knows where is ${serverAddress} (at ${serverIP}) - useful for self-signed HTTPS + # and where is nixos.builds.node (at ${buildNodeYggIP}) - userful for nix caching via harmonia server + # + # каждый компьютер знает, что ${serverAddress} - это адрес нашего сервера + # полезно для self-signed HTTPS + networking.hosts."${serverIP}" = [ serverAddress ]; networking.hosts."${buildNodeYggIP}" = [ "nixos.builds.node" ]; + #### LOCALIZATION #### + # (if you're foreign you probably would like to change it) #### ЛОКАЛИЗАЦИЯ ##### time.timeZone = "Europe/Moscow"; @@ -918,6 +1127,12 @@ in useXkbConfig = true; }; + # installed: + # - Microsoft corefonts + # - GOST Type A (for learning CADs and manufacturing documents) + # - basic freetype fonts + # - JetBrains Mono + # # установлены шрифты Microsoft (corefonts), # установлен ГОСТ Тип А (задел на будущее), # установлены базовые свободные шрифты, @@ -929,6 +1144,7 @@ in liberation_ttf ]; + ####### OTHER SETTINGS ####### ####### ПРОЧИЕ НАСТРОЙКИ ####### environment.systemPackages = with pkgs; [ vim @@ -942,7 +1158,11 @@ in # При запуске от root через SSH автоматически подключается к X-сессии student на :0 (pkgs.writeShellApplication { name = "place"; - runtimeInputs = [ yad coreutils util-linux ]; + runtimeInputs = [ + yad + coreutils + util-linux + ]; text = '' ROOM_ARG="''${1:-}" PLACE_FILE="/var/lib/place/location" @@ -988,12 +1208,14 @@ in }) ]; + # remote-control inside our local networking # удаленный доступ в пределах нашей сети services.openssh = { enable = true; - settings.PermitRootLogin = "yes"; + settings.PermitRootLogin = "yes"; # TODO }; - users.users.root.openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCyBYo/E/FkFZVABzMixLS2TWaipfN5T24y8f+E6Px1t+IG8PLnQ38dLJiCR8k971DOycLuJUfKWsC06BK3XLWTO0+PmpfGKNT4NI6dwP2REl/umaignP/QQSs2w9Ff49WqPjIYTSmATTsCNZSVB0VtM0eJ+Y9Ff4CXb1frtt4GYztk6XB3jc3TxV72qzB0g6DqrHkf6pT5YAq2UeuFGZYSZCqBvVXCGcvKHkO1KBubuo95itVA5XbzK3INQTZpQowbtK4ULhUYlaGBcX5tYq1bdiTCDlTcLt6MfxYfFHSFiHbJOzdGPd+mXM7urOQhq49uQOf07dHt9qAzQHajItQb+X3FOgyFt4n6Y9Q37gn/6KC3PH1zClldq9DtgttuG/Xk15q+uvCldji9YIgb80aRHBIp6DY8PlYodmGGesBLiBMGQ7hgKupfkqszjfMkxnMYIkZodUCQVgaqsxsEQ7lD84JJMgBY8HkNLxKhy+6dP6kTc4vTtrpjezq/Ph95PFE= bednov@kafpi-108-1-mainserver2" ]; + + users.users.root.openssh.authorizedKeys.keys = sshKeys; # TODO root services.gnome.gnome-keyring.enable = true; programs = { @@ -1014,9 +1236,13 @@ in enable = true; enableSSHSupport = true; }; - udevil.enable = true; # тоже нужно для флешек + + # required for flash stick support + # требуется для поддержки флеш-накопителей + udevil.enable = true; }; + # DO NOT CHANGE THIS IF YOU'RE UPDATING OLD COMPUTERS # НЕ МЕНЯТЬ, иначе придётся все компы переустанавливать, а не обновлять system.stateVersion = "24.05"; } diff --git a/installer/flake.nix b/installer/flake.nix index e2e0d01..d7c5626 100644 --- a/installer/flake.nix +++ b/installer/flake.nix @@ -1,5 +1,7 @@ { - description = "MIREA NixOS USB Installer"; + description = + let university = import ../mirea-specific/university.nix; + in "${university.shortName} NixOS USB Installer"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; diff --git a/installer/installer-configuration.nix b/installer/installer-configuration.nix index 1836847..9ba80d0 100644 --- a/installer/installer-configuration.nix +++ b/installer/installer-configuration.nix @@ -1,11 +1,63 @@ -{ pkgs, lib, config, ... }: +{ + pkgs, + lib, + config, + ... +}: + let + + # static server IP address, it must be always online and serve as Yggdrasil peer + # (see config.services.ygggdrasil.settings.peers for details) + # WARN: the peer should NOT connect Yggdrasil worldwide network + # if your PC fleet shouldn't be globally accessible around the world + # + # статический IP адрес сервера, который должен быть всегда онлайн и служить пиром Yggdrasil + # (см. подробности config.services.ygggdrasil.settings.peers) + # ПРЕДУПРЕЖДЕНИЕ: этот пир не должен быть подключен к мировой сети Yggdrasil, + # если конечно вы не хотите чтобы весь компьютерный парк был доступен из любой точки мира serverIP = "10.0.174.12"; + + # ------- + # Yggdrasil address cache build node. It should use the same NixOS config as others + # It's NOT required to be the same server as ${serverIP} but it also should be always online + # It CAN be a NixOS VM installed on the same server ${serverIP} autostarted + # + # Yggdrasil-адрес кэширующего сервера. На нем должна быть установлена NixOS с той + # же конфигурацией, что и у остальных машин. Не обязательно, чтобы эта машина была той же, + # что сервер ${serverIP}, но она также должна быть онлайн. + # Это может быть виртуальная NixOS-машина, установленная на сервере ${serverIP} в режим автозапуска + buildNodeYggIP = "200:ccc6:1361:5c84:aba0:1244:35f5:c903"; + + # ------- + # here is your configuration repo URL. fork it and change it on your own if you want + # + # здесь требуется указать ваш URL-адрес репозитория с конфигурацией. fork-аете, и меняете на свой + configRepoUrl = "https://forgejo.gregorbednov.ru/gregorbednov/configuration.nix.git"; + + # ------- + # here is some university specifics, apps and resources + # e.g. for MIREA it's wallpaper, university logo, utils to show uuniversity schedule week number and so on + # + # LEGALS: I am NOT a creator on wallpaper.svg, + # I do NOT own wallpaper.svg, this doesn't represent any of my ideas or views, + # that's just a logo (a coat of arms to be precise) of a university, + # and it is in the public domain. + # + # здесь могут быть специфические вузовские данные и ресурсы, + # например, обои, логотип университета, утилита для показа номера недели по расписанию, и так далее + # + # ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: + # Я не являюсь владельцем файла wallpaper.svg, его добавление не репрезентует моих идей или взглядов, + # это просто логотип (точнее герб) университета, и он является общественным достоянием. + + university = import ../mirea-specific/university.nix; + in { - isoImage.isoName = lib.mkForce "mirea-nixos-installer.iso"; + isoImage.isoName = lib.mkForce university.isoName; isoImage.squashfsCompression = "zstd -Xcompression-level 6"; services.getty.autologinUser = lib.mkForce "root"; @@ -19,15 +71,22 @@ in git pv curl - (writeShellScriptBin "mirea-install" ( + (writeShellScriptBin university.installerBin ( builtins.replaceStrings - [ "@CONFIG_REPO_URL@" ] - [ configRepoUrl ] + [ "@CONFIG_REPO_URL@" "@DISTRO_TITLE@" ] + [ configRepoUrl university.shortName ] (builtins.readFile ./mirea-install.sh) )) ]; - # Yggdrasil запускается на установщике — благодаря ему доступен локальный кэш сборок + # Yggdrasil-маршрутизация позволяет целевым ПК автоматически получать статический IPv6 даже в сетях DHCP, + # что также запускается на установщике для максимальной гибкости. + # Благодаря Yggdrasil может быть доступно удаленнное управление и локальный кэш сборок + + # Yggdrasil routing above network allows any target PC to get automatically static IPv6 even on DHCP, + # so installer is recommended to use Yggdrasil too for maximum scalability + # With Yggdrasil routing it's easy to connect remotely, and you can use + # nix build cache nodes with DHCP-addresses (e.g. other PCs) services.yggdrasil = { enable = true; persistentKeys = false; @@ -49,7 +108,10 @@ in ]; trusted-substituters = [ "http://nixos.builds.node" ]; connect-timeout = 5; - experimental-features = [ "nix-command" "flakes" ]; + experimental-features = [ + "nix-command" + "flakes" + ]; }; systemd.services.nix-daemon = { @@ -64,10 +126,13 @@ in environment.etc."issue".text = '' ┌─────────────────────────────────────────┐ - │ Установщик NixOS MIREA │ - │ Запустите: mirea-install │ + │ Установщик NixOS ${university.shortName} + │ Запустите: ${university.installerBin} + └─────────────────────────────────────────┘ + ┌─────────────────────────────────────────┐ + │ NixOS Installer ${university.shortName} + │ Run: ${university.installerBin} └─────────────────────────────────────────┘ - ''; system.stateVersion = "24.11"; diff --git a/installer/mirea-install.sh b/installer/mirea-install.sh index 00d8e46..92fadbb 100644 --- a/installer/mirea-install.sh +++ b/installer/mirea-install.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# MIREA NixOS Installer +# @DISTRO_TITLE@ NixOS Installer # Устанавливает NixOS рядом с Windows или на чистый диск. # NixOS root: 50 GiB, EFI (при чистой установке): 512 MiB. # Идемпотентен: если установка прервалась, просто запустите повторно. @@ -331,9 +331,9 @@ else info "noatime добавлен к ext4 разделам" fi -step "Загрузка конфигурации MIREA" +step "Загрузка конфигурации @DISTRO_TITLE@" if [[ -f "$MNT/etc/nixos/flake.nix" ]]; then - skip "конфигурация MIREA уже загружена" + skip "конфигурация @DISTRO_TITLE@ уже загружена" else tmpconf=$(mktemp -d) git clone --depth=1 "$CONFIG_REPO_URL" "$tmpconf/config" \ @@ -342,7 +342,7 @@ else cp "$tmpconf/config/flake.lock" "$MNT/etc/nixos/" cp "$tmpconf/config/configuration.nix" "$MNT/etc/nixos/" rm -rf "$tmpconf" - info "Конфигурация MIREA установлена" + info "Конфигурация @DISTRO_TITLE@ установлена" fi # ── Установка ───────────────────────────────────────────────────────────────── diff --git a/mirea-specific/mireaweek.nix b/mirea-specific/mireaweek.nix new file mode 100644 index 0000000..6c1a776 --- /dev/null +++ b/mirea-specific/mireaweek.nix @@ -0,0 +1,19 @@ +# Утилита расчёта номера учебной недели. +# Даты отсечки семестров (9 февраля / 1 сентября) специфичны для МИРЭА, +# поэтому пакет живёт здесь, а не в общем mireadesktop. +{ pkgs }: +pkgs.stdenv.mkDerivation rec { + pname = "mireaweek"; + version = "0.1.0"; + src = ./weekday.kt; + dontInstall = true; + dontUnpack = true; + nativeBuildInputs = [ pkgs.kotlin ]; + buildPhase = '' + mkdir -p $out/{bin,lib} + kotlinc $src -include-runtime -d mireaweek.jar + mv mireaweek.jar $out/lib + printf "${pkgs.jre}/bin/java -jar $out/lib/mireaweek.jar" > $out/bin/mireaweek + chmod +x $out/bin/mireaweek + ''; +} diff --git a/mirea-specific/tint2-widget.nix b/mirea-specific/tint2-widget.nix new file mode 100644 index 0000000..3c7ef43 --- /dev/null +++ b/mirea-specific/tint2-widget.nix @@ -0,0 +1,15 @@ +# Виджет панели tint2, показывающий номер учебной недели МИРЭА. +# Подставляется в mireadesktop через параметр extraTint2Widgets. +{ mireaweek }: +'' + #------------------------------------- + execp = new + execp_name = mireaweek + execp_command = ${mireaweek}/bin/mireaweek + execp_interval = 0 + execp_font = mono 10 + execp_font_color = #dddddd 100 + execp_centered = 1 + execp_has_icon = 0 + execp_padding = 5 5 +'' diff --git a/mirea-specific/university.nix b/mirea-specific/university.nix new file mode 100644 index 0000000..1e45e80 --- /dev/null +++ b/mirea-specific/university.nix @@ -0,0 +1,27 @@ +{ + # University names + # May be written any language + # + # Название университета + # Может быть на любом языке + name = "МИРЭА — Российский технологический университет"; + + # short name should be in english + # короткое название должно быть на английском + shortName = "MIREA"; + + # NixOS installer branding + # Брендирование установщика NixOS + isoName = "mirea-nixos-installer.iso"; + installerBin = "mirea-install"; + + # LEGALS: I am NOT a creator on wallpaper.svg, + # I do NOT own wallpaper.svg, this doesn't represent any of my ideas or views, + # that's just a logo (a coat of arms to be precise) of a university, + # and it is in the public domain. + # + # ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: + # Я не являюсь владельцем файла wallpaper.svg, его добавление не репрезентует моих идей или взглядов, + # это просто логотип (точнее герб) университета, и он является общественным достоянием. + wallpaper = ./wallpaper.svg; +} diff --git a/mirea-specific/wallpaper.svg b/mirea-specific/wallpaper.svg new file mode 100644 index 0000000..103b5b1 --- /dev/null +++ b/mirea-specific/wallpaper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mirea-specific/weekday.kt b/mirea-specific/weekday.kt new file mode 100644 index 0000000..948b510 --- /dev/null +++ b/mirea-specific/weekday.kt @@ -0,0 +1,52 @@ +import java.time.DayOfWeek +import java.time.LocalDate +import java.time.Month + +enum class Period { + Autumn, + Winter, + Spring +} + +fun determinePeriod(today: LocalDate): Period { + val februaryCutoff = LocalDate.of(today.year, Month.FEBRUARY, 9) + val septemberCutoff = LocalDate.of(today.year, Month.SEPTEMBER, 1) + + return when { + today.isBefore(februaryCutoff) -> Period.Winter + today.isAfter(septemberCutoff.minusDays(1)) -> Period.Autumn + else -> Period.Spring + } +} + +fun calculateWeek(period: Period, date: LocalDate): String { + return when { + period == Period.Winter -> "Хороших праздников, удачной сессии!" + date.dayOfWeek == DayOfWeek.SUNDAY -> "Сегодня воскресенье, лучше иди домой" + else -> { + val currentWeek = date.getWeekOfYear() + val periodLimit = when (period) { + Period.Spring -> LocalDate.of(date.year, Month.FEBRUARY, 9) + Period.Autumn -> LocalDate.of(date.year, Month.SEPTEMBER, 1) + else -> throw IllegalStateException("Unexpected period") + } + val limitWeek = periodLimit.getWeekOfYear() + val isLimitSunday = periodLimit.dayOfWeek == DayOfWeek.SUNDAY + + val weekOffset = if (isLimitSunday) 1 else 0 + val weekNumber = 1 + currentWeek - limitWeek - weekOffset + "$weekNumber неделя" + } + } +} + +fun LocalDate.getWeekOfYear(): Int { + return this.get(java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR) +} + +fun main() { + val today = LocalDate.now() + val period = determinePeriod(today) + val weekInfo = calculateWeek(period, today) + println(weekInfo) +}