Pull to refresh
19
0
Viacheslav Lotsmanov @unclechu

Haskell enthusiast

Send message

Отвечаю с большой задержкой, было не до этого. Не уверен что по прежнему актуально. Рекомендую обращаться в случае чего к Matrix-чату #nix:nixos.org

Я несколько запутался в описанной проблеме. Собственно проблемы не вижу.

Я могу, конечно, сделать home-manager.users.rdp1.home.file.".config/awesome/rc.lua".text = «весь существующий и нужный мне конфиг», но он там на 500 строк, и тащить это в configuration.nix в 11 вариантах совсем не хочется. Класть рядом 11 конфигов можно, но хочется обойтись одним маленьким configuration.nix, тем более, что весь функционал системы — это вот обслуживать эти 11 копий хрома на тонких клиентах.

Не понял дилемы. Можно же просто определить Nix-функцию где в качестве аргумента ваши специфичные для пользователя данные. Вроде этого (примерный код):

{ pkgs, ... }
let
  mkUserAwesomeConfig = idx: assert builtins.isInt idx; ''
    generic configuration
    local cmd = "chromium --noerrdialogs --kiosk 192.168.88.111:3006/rdp${toString idx}"
    generic configuration
  '';
in
{
  home-manager.users = {
    rdp1.home.file.".config/awesome/rc.lua".text = mkUserAwesomeConfig 1;
    rdp2.home.file.".config/awesome/rc.lua".text = mkUserAwesomeConfig 2;
  };
}

В чём собственно проблема? Можно даже написать функцию, которая по инткременту все 11 опций сгенерирует или сколько там их нужно (см. pkgs.lib.range 1 11, а там дальше пару маппингов и готово).

Плюс в конце-концов это же обычный Lua? Я Awesome не трогал много лет, не помню как там. Но если это обычный Lua, можно же в рантайме в одном общем конфиге считать $UID/$USER и на основании его подставить что-то специфичное для юзера?

Но лучше конечно этого не делать на территории РФ и вообще не притрагиваться к такому коду, т.к. законы в РФ существуют для частных репрессий по необходимости, а не для регулирования гражданских отношений. И если кому-то не понравится, что вы использовали дериватив от библиотеки на этой лицензии для портала знакомства гомосексуалов (нарушается закон о запрете пропоганды гомосексуализма среди молодёжи) или там открываете научный портал дарвинистов (нарушается закон об оскорблении чувств верующих), то вас притащат в т.н. «суд» и напишут всё, что *спустят сверху*. В лучшем случае ЕСПЧ через 10 лет вам присудит выплатить компенсацию, пока вы сидите в каком-нибудь СИЗО, возможно запытаный швабрами, и уже подписавший что-нибудь левое ещё лет на 10. Никого, кроме пары журналистов, не будет интересовать законность данных процедур. Так что я бы предостерёг всякого от вообще прикасания к коду, к которму кремль приложил руку.

В статье сказано: «Лицензия не требует распространять производную программу на условиях той же лицензии.» Значит ли это, что можно просто форкнуть, поменять имя проекта, выпустить его под MIT и это уже будет свободный проект? 🤔

а GitHub отмечают, что переход на Codespaces устранил хрупкость и однонаправленность локальных сред разработки, а также дал рычаг для улучшения опыта разработчиков.

Такую дичь мне ещё никто не впаривал. Это ваша творческая самодеятельность или это маркетологи из некрософта поднатужились так впарить проприетарного троянского SaaS-коня?

На мой взгляд, 2x-версия изображения, размер файла которого составляет 21,2 Кб, выглядит достаточно хорошо. Это — не то же самое, что и картинка размером 45,2 Кб, но сжатие эту картинку не испортило.

У меня страница с Хабром отмасштабирована до 170% (можно сказать, что вполне себе высокая плотносить пикселей). И на неё просто больно смотреть. Да и без всякого масштабирования, если автору кажется, что «сжатие эту картинку не испортило», то ему нужно либо выкинуть свой списанный дисплей, купленый 10 лет назад на радиорынке, либо идти лечить свою слепоту в терминальной стадии.

Ну вы в своём примере привели тип bool как множество из True и False. В Haskell этот тип описывается кстати аналогичным образом из моего примера:


data Bool = True | False

Это ведь по прежнему называется алгебраическим типом данных? Я могу быть не прав, но возможно определение алгебраических типов данных как композиция других типов это не исчерпывающее определение, а лишь описание одного из свойств этой сущности.

Итак, алгебраический тип данных — это такой тип данных, который является композицией других типов. Вот такое незатейливое определение.

data Foo = Bar | Baz

Какие типы я тут скомпозировал?


Или вот из вашего же примера:


Например, тип bool — это двухэлементное множество, которое содержит элементы True и False

Ох как аккуратно автор облизывает северокорейскую задницу, прямо по методичке. Видимо хорошо обработали во время поездок туда, может даже что-то кололи. Вот нам этом месте я уже надрываться начал:


Поэтому американцы не смогут воспользоваться тем, что северокорейцы устраняют баги в их коде

Прямо вижу, как толпы северокорейцев, поев супа с весенней травой со своей лужайки, уже бегут в своём интранете с запретом на регистрацию в соц. сетях контрибьютить в open source проекты дни напролёт. А конечно же не работать в военных интересах партии по указанию «свыше». Конечно же он ответит «нет» на такое предложение как настоящий свободный северокорейский Человек с большой буквы! Он выберет Open Source и мир! Да здравствует наш великий...

Кстати, если кому-то интересно, есть ещё функция в nixpkgs для создания FHS-sandbox-ов, что помогает запускать всякие бинарные левые тарболлы и прочие бинарные установщики. Вот например кто-то написал конфиг для запуска MatLab:


with import <nixpkgs> {};
buildFHSUserEnv
{
  name = "matlab-env";
  targetPkgs = p:
  (with p;
  [
    mesa.osmesa aspell portaudio pixman harfbuzz libxml2 qt5.
    qtbase libffi udev coreutils alsaLib dpkg gcc48 freetype glib fontconfig
    openssl which ncurses jdk11 pam dbus_glib dbus pango gtk2-x11
    atk gdk_pixbuf cairo ncurses5 mesa_glu zlib libglvnd libselinux
  ])
  ++ 
  (with p.xorg;
  [
    libX11
    libXcursor
    libXrandr
    libXext
    libSM
    libICE
    libX11
    libXrandr
    libXdamage
    libXrender
    libXfixes
    libXcomposite
    libXcursor
    libxcb
    libXi
    libXScrnSaver
    libXtst
    libXt
    libXft
    libXxf86vm
    libXpm
    libXp
    libXmu
  ]);
}

Источник: https://discourse.nixos.org/t/installing-matlab-on-nixos/8943/8


Также:


  1. https://nixos.wiki/wiki/Matlab
  2. https://nixos.org/manual/nixpkgs/stable/#sec-fhs-environments

У вас есть план/видение как между ними переключаться? Гипотетически можно сразу несколько версий оформить, главное понять как между ними переключаться.


Т.е. технически в пределах одного derivation можно написать.


"... ${openssl_1_0_2} ... ${openssl_1_1} ..."

Вообще вся система — это дерево зависимостей. Просто есть разные ветви. Т.е. то, о чём вы говорите и так происходит, тут нет противоречия.

Иногда хочется странного, обычно странное живет в chroot. Например, openssl, от которого зависит половина системы. Как будет выглядеть конфигурация NixOS с openssl 1.1 и openssl 1.0 одновременно?

Есть разные варианты, если например просто запустить:


NIXPKGS_ALLOW_INSECURE=1 nix run nixpkgs.openssl_1_0_2 -c openssl version
OpenSSL 1.0.2u  20 Dec 2019

nix run nixpkgs.openssl_1_1 -c openssl version
OpenSSL 1.1.1k  25 Mar 2021

Если вам условно нужно именно на всю систему, то тут могут быть разные техники. Можно использовать Nix Profiles, но это не идеальное на мой взгляд решение. Допустим у вас есть программа A, имя исполняемого файла будет конфликтовать с версиями, нужно это разрешить. Из вариантов — использовать wrapper с изменённым именем, а для отдельных пакетов, зависящих от OpenSSL делать override. А можно просто хитрый скрипт-обёртку сделать с переобределённым OpenSSL глобально для всего дерева зависимостей. Примерно накидал решение:


{ pkgs, lib, ... }:
let
  pkgsWithOldOpenSSL = import <nixpkgs> {
    overlays = [ (self: super: { openssl = super.openssl_1_0_2; }) ];
    config.allowInsecurePredicate = p: lib.getName p == "openssl";
  };

  dependencies = p: [
    p.tor
    # ... other programs
  ];

  with-old-openssl =
    let
      deps =
        map
          (pkg: lib.escapeShellArg "${pkg}/bin")
          (dependencies pkgsWithOldOpenSSL);
    in
    pkgs.writeShellScriptBin "with-old-openssl" ''
      set -Eeuo pipefail || exit
      PATH=${builtins.concatStringsSep ":" deps}:$PATH
      export PATH
      "$@"
    '';
in
{
  environment.systemPackages = dependencies pkgs ++ [ with-old-openssl ];
}

tor | head -1 | rg -io 'openssl[^,]+'
OpenSSL 1.1.1k

with-old-openssl tor | head -1 | rg -io 'openssl[^,]+'
OpenSSL 1.0.2u

Это универсальное решение, сразу для всех «установленных» программ.


Можно и более прицельно:


{ pkgs, lib, ... }:
let
  nixpkgs.config.allowInsecurePredicate = p: lib.getName p == "openssl";

  tor-with-old-openssl =
    let
      tor = pkgs.tor.override { openssl = pkgs.openssl_1_0_2; };
    in
    pkgs.writeShellScriptBin "tor-with-old-openssl" ''
      ${lib.escapeShellArg tor}/bin/tor "$@"
    '';
in
{
  environment.systemPackages = [
    pkgs.tor
    tor-with-old-openssl
  ];
}

tor | head -1 | rg -io 'openssl[^,]+'
OpenSSL 1.1.1k

tor-with-old-openssl | head -1 | rg -io 'openssl[^,]+'
OpenSSL 1.0.2u

Какой миллион, тут https://github.com/NixOS/nixpkgs уже тонна всего понаписано за почти 2 десятилетия. Почти 300 000 коммитов, и примерно 60 000 пакетов. В простых случаях использование программы или той или иной фичи в ОС ограничивается одной строчкой.


чем apt install $MY_PKG_LIST; cp $OLD_HOME $NEW_HOME

Опять же, сравнение космического корабля и корыта с веслом. Мне беседа в подобном шизофреническом ключе не очень интересна, я удаляюсь.

Пишешь конфигурационный скрипт и всё. Просто на баше а не на никсе.

Ну тут я даже не знаю что сказать. Когда идёт сравнение космического корабля и корыта с веслом, это уже выходит за рамки серьёзного обсуждения.


И как мне узнать, что нужна именно эта строчка? Чем это лучше генты?

Какая строка? Флаг? Ну если в конфиге предусмотрено, то это будет например флаг на уровне языка Nix.


У Генты нет концепции независимого дерева зависимостей. Это по сути apt-get install, только с USE-флагами. В Генте нельзя одновременно держать с десяток деревьев одних и тех же библиотек и программ.

Скажем так, я не встречал ни одного человека, и не читал ни об одной истории успеха, когда свои рабочие десктопные машины кто-то синхронизировать с помощью Ansible.


Полная воспроизводимость, с чек-суммами каждой ветви в дереве зависимостей, потом взяли и реплицировали одной командой на другом компьютере весь сетап разом.

Плюс вот этот пункт, про который в т.ч. шла речь он не покроет. Получив stateful, что сделать очень легко, если вы работаете за этой машиной, не говоря уже что и через Ansible можно его получить, вы теряете полную реплицируемость. Уж тем более ни о каких чек-суммах речи не идёт и кеше по этим чек-суммам.


Это подходит только для серверов, где вы ручных манипуляций производите по минимуму. Если я на локальном машине хочу какую-то программу, которая мне нужна временно, то я запущу nix run nixpkgs.program -c program --some-arg, на состояние общей системы я никак не повлияю, зависимость будет предоставлена контекстно. В случае с «обыным linux», обслуживаемым Ansible-ом я получу stateful и как следствие потеряю полную реплицируемость. Это не работает.

Для клонирования есть dd, например.

Я надеюсь это был жирный троллинг.


N.B. Не смешивайте клонирование и реплицирование с синхронизацией.


 Но как-то не совсем понятно, с какой целью это делается. backup? Переезд на другое железо? Клонирование настроек?

Не бекап. Если только бекап самой системы, а не личных файлов. У вас только один компьютер в пользовании? У меня вот несколько. Несколько своих и ещё рабочий. Я не пользуюсь системой «из коробки», у меня очень кастомный конфиг, везде свои горячие клавиши, свои программы со своими конфигами. У меня даже вопроса не стоит зачем это нужно, эта острая необходимость просто кричит о себе. Я до этого писал скрипты для синхронизации конфигов в домашней директории из Git-а, но эти конфиги — это только песчинка из всего того, что нужно синхронизировать.


Например, hostname, ключи хоста, hardware-related настройки — что с ними делать?

Вы не поверите, но это всё в NixOS предусмотрено. При генерации изначального конфига у вас сразу появляется дополнительный import для модуля hardware-configuration.nix, где собственно и хранится то, что вы описали. В т.ч. конфигурация grub, разметки разделов, со всяким luks-шифрованием.

Про Ansible слышал, и даже имел дело. Получить stateful там предельно легко. И Ansible вроде как не очень хорошое решение для домашнего десктопа. Ну и скоуп, который он покрывает сильно уже.

2, 4 — не понятно, что мешает так же сделать на обычном линуксе. Опять же, нужно это раз в пять лет, а разбираться со всеми конфигами, языком их написания и тд я буду неделю минимум.

Ээээ… Этого просто невозможно сделать на «обычном линуксе». Точнее сказать NixOS — это и есть «обычный линукс», где так сделано, и он единственный в своём роде. Ни о какой 100% воспроизводимости из конфига в одном фалйе парой команд на других системах речи никогда не шло. Ни о каком инкрементальном переносимом конфиге тоже речи не шло. Может вы готовы показать команду, которая реплицирует полное состояние системы, со всеми программами, конфигами в /etc, systemd-сервисами, доверенными ключами GPG/SSH, настройками firewall, selinux, udev rules, патчами для ядра, драйверами и модулями ядра, настройками Git-а в домашней директории, настройками sudoers? За пределами NixOS? И главное чтобы при этом сделав изменения на одном компьютере, вы получили точно такую же реплику на другом такой командой.


Короче говоря, мешает то, что на «обычном (не-NixOS) линуксе» (всяком другом дистрибутиве) такой возможности просто нет.


1 — не понятно, что конкретно мне это даёт.

Ну это скорее можно к реплицируемости отнести, т.к. это необходимый фактор, чтобы получить точный слепок с одного компьютера на другом. И потом при изменениях получать/синхронизировать их.


3 — appimage

Это решает очень узкий спект задач и имеет целый букет проблем. Из воспоминаний использования под Fedora помню что приложения отказывались наследовать системную тёмную тему, и выжигали глаза.


В Nix например можно переопределить зависимость одной строчкой, поменять флаг сборки.


callPackage ./graphviz.nix { gd = customgd; };

graphviz.override { gd = customgd; };

pkgs.vim_configurable.customize {
  name = "vim";
  vimrcConfig.packages.myplugins = {
    start = [pkgs.vimPlugins.vim-nix];
    opt = [];
  };
}

Вот к примеру я переопределяю версию в psi-plus (беря за основу уже существующий derivation) просто ссылаясь на другой коммит в Git-е, а также задаю флаги для включения плагинов и выключения вебкита:


super.psi-plus.overrideAttrs (srcAttrs: srcAttrs // rec {
    version = "1.4.1520"; # Latest on October 18, 2020

    src = super.fetchFromGitHub {
      owner = "psi-plus";
      repo = "psi-plus-snapshots";
      rev = version;
      sha256 = "17ih8c1k4wabrp172p4hsywil8ad5c53r4jh9zc1p7f499083srl";
    };

    cmakeFlags = [
      "-DENABLE_PLUGINS=ON"
      "-DCHAT_TYPE=BASIC"
    ];
  })

Насколько легко это сделать с appimage?

боюсь спросить, как именно. Разве только chroot делать.

Если программа не настаивает на руте. Ну я вот привёл пример с GOG инсталлером. Но вообще chroot в т.ч.


Так я вам про то и говорю. Только не до конца ясно, всегда ли это возможно и стоит ли того.

Трансформация NixOS в stateful-систему — это в корне неправильный путь. Этого делать не нужно, это рушит всю идею, потом при пересборке конфига на другом компьютере вы уже не получите такой же результат, а это плохо. Так или иначе Nix можно использовать и поверх других ОС, которые такую трансформацию не возбраняют (точнее возбраняют, но не сильно, это также рушит идею пакетных менеджеров, если напихивать в /usr/ это уже bad practice), например поверх Fedora или Ubuntu.


Ну, то есть, пока мне предлагается руками ковырять несвободные установщики ради того чтобы потом руками написать конфиг. Напомните, что мне это дает? Возможность писать еще больше конфигов? А еще?

Напоминаю:


  1. Stateless-система
  2. Полная воспроизводимость, с чек-суммами каждой ветви в дереве зависимостей, потом взяли и реплицировали одной командой на другом компьютере весь сетап разом.
  3. Возможность иметь одновременно сколько угодно разных версий программ, их библиотек и т.д. И это без ручно-педальных установок в /opt/, /usr/local и т.д.
  4. Инкрементальный конфиг, один раз написали, а потом переиспользуете на сотне компьютеров и расширяете по необходимости, не нужно каждый раз повторять ручные действия. Автоматизация одним словом. Конфиг для своей проприетарной бинарщины вы разобрав пишете один раз, потом переиспользуете сколько угодно раз. Более того, резльтат можно вытащить просто из бинарного кеша по чек-сумме (можно иметь свои собственные дополнительные сервера с бинарным кешем), на другом компьютере или на этом же после переустановки.
  5. Откат к предыдущей версии состояния системы предельно тривиален, что особенно важно если вы систему своими проприетарно-бинарными шалостями поломали (при условии что вы бинарные шалости осуществляете как положено, в sandboxed-среде, при сборке Nix-ом, а не через sudo make install).
Разумеется. Но похоже, что установщики нужно потрошить самому ручками.

Ну не всегда.


Во-первых это также актуально и за пределами NixOS, тут NixOS «погоды не делает». Например я помню как тот же Steam просто так было не запустить под Fedora, приходилось баш-команду найденную в интернете запускать для удаления некоторых разделяемых библиотек из директории ~/.steam, чтобы он запустился. Другие «бинарные установщики» тоже, берущие за основу какой-то другой дистрибутив, отказывались запускать без доп. манипуляций.


Во-вторых ничего не мешает установить программу локально. К примеру я через steam-run успешно пользовался установщиком GOG, устанавливая в ~/GOG Games/. Вполне себе бинарный установщик.


В случае когда установщик очень хочет запуститься от рута и нагадить в корневые разделы — на мой взгляд это хороший повод расковырять его и не делать так, как он это предполагает. Т.к. установка в корневые разделы — это уже трансформация в stateful-систему. Лучше сэмулировать то, что хочет установщик через chroot и держать систему чистой.

1
23 ...

Information

Rating
Does not participate
Registered
Activity