1 Basic work with nixops
Izorkin edited this page 2 years ago

Теперь ознакомимся с утилитой nixops для удалённого обслуживания систем на базе ОС NixOS. Так же поддерживается разворачивание систем на VirtualBox VM, Amazon EC2, Google Compute Engine, Microsoft Azure, Hetzner physical machines, Digital Ocean, Libvirtd (Qemu), Datadog resources. Подробнее об этих возможностях можно прочитать в мануале - https://releases.nixos.org/nixops/nixops-1.7/manual/manual.html. Сейчас мы разберём способ, как подкючить управление nixops к уже установленной удаленной системе на базе ОС NixOS, которая может быть установлена как на физической машине, так и на виртуальной в каком либо месте. Главное, чтобы был доступ к ней по IP адресу.

Посмотрим текущую версию nixops:

nixops --version
NixOps 1.7

Для тестирования и ознакомления с утилитой nixops создадим новую виртуальную машину и установим на неё ОС NixOS (смотрим статью по установке NixOS). Предварительно сгенерируем хэш пароля:

mkpasswd -m sha-512
Password:
$6$zejLDpVGQfekr$no6c35WweI7j59W8diZ2pZwA2xadi5NxJNacLkBBoOmyt/4Lqt/pDX2pO3vUw157eb59XUZ71GZcMXQs2FqKL/

И ssh ключ, которые будем использовать на удалённой системе:

ssh-keygen -a 128 -t ed25519 -f ~/.ssh/id_ed25519
Generating public/private ed25519 key pair.
Created directory '/home/rebrain/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/rebrain/.ssh/id_ed25519
Your public key has been saved in /home/rebrain/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:Wl3BrHR8/y3SBkM/fnuLdaxYT7B6yoHZRkHl2mHOMAA rebrain@NixOS-example
The key's randomart image is:
+--[ED25519 256]--+
|        E..+o..  |
|          .o*o.  |
|         . +=o+. |
|         ...oXo..|
|        S . o==.o|
|       o   =. =++|
|      .   o +oo+=|
|           o =+=o|
|            =+..+|
+----[SHA256]-----+

Где опции указывают:

  • -a 128 - указывает количество используемых раундов для KDF (функция получения ключа).
  • -t ed25519 - генерируем ключ на основе схемы сигнатур эллиптической кривой.
  • -f ~/.ssh/id_ed25519 - указываем куда сохранять ключ.
cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII5rqPqf/eFAyAEPZhwX/Hg7sNLZj4LWEexxsnv6izMW rebrain@NixOS-example

На удалённой системе используем такую упрощенную конфигурацию (смотрим статью по установке NixOS):

{ config, pkgs, ... }:
{
  imports = [
    ./hardware-configuration.nix
  ];

  boot.loader.grub.enable = true;
  boot.loader.grub.version = 2;
  boot.loader.grub.device = "/dev/vda";

  networking.hostName = "basic-nixops";

  environment.systemPackages = with pkgs; [
    wget vim mkpasswd
  ];

  services.openssh = {
    enable = true;
    passwordAuthentication = false;
    permitRootLogin = "yes";
  };

  users = {
    mutableUsers = false;
    users.root = {
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII5rqPqf/eFAyAEPZhwX/Hg7sNLZj4LWEexxsnv6izMW rebrain@NixOS-example"
      ];
      hashedPassword = null;
    };
    users.rebrain = {
      isNormalUser = true;
      uid = 51011;
      group = "rebrain";
      extraGroups = [ "wheel" "users" ];
      hashedPassword = "$6$zejLDpVGQfekr$no6c35WweI7j59W8diZ2pZwA2xadi5NxJNacLkBBoOmyt/4Lqt/pDX2pO3vUw157eb59XUZ71GZcMXQs2FqKL/";
    };
    groups.rebrain = {
     gid = 51011;
    };
  };

  system.stateVersion = "20.09";
}

Перепроверьте верно ли прописали openssh.authorizedKeys.keys, иначе не сможете попасть на удалённую систему. Имейте в виду, что у вас в конфигурурации значения hashedPassword и openssh.authorizedKeys.keys будут отличаться.

В итоге у нас готова удалённая система для использования с утилитой nixops.

На основной системе подготавливаем структуру для деплоя:

mkdir -p ~/works/nixops/{config-defs,deploy/labs/vm01-test}
ln -s /etc/nixos/nix-config/core.nix ~/works/nixops/config-defs/core.nix
ln -s /etc/nixos/nix-config/generic ~/works/nixops/config-defs/generic

Где:

  • config-defs - здесь создаём симлинк к нашей базовой конфигурации системы, которая будет использоваться на всех удаленных системах.
  • deploy - в этой папке будет храниться конфигурация удаленных систем.

Для нашей первой удаленной системе создаём следующие конфигурационные файлы:

nano ~/works/nixops/deploy/labs.nix
{
  network.description = "labs servers";
  network.enableRollback = true;

  vm01-test = { config, lib, pkgs, ... }: {
    require = [ ./labs/vm01-test/configuration.nix ];

    deployment.targetEnv = "none";
    deployment.targetHost = "192.168.0.221";
    deployment.targetPort = 22;
  };
}

Где deployment.targetHost = "192.168.0.221"; - указываем IP адрес, который назначен нашей установленной удаленной системе. В вашем случае IP адрес будет отличаться.

nano ~/works/nixops/deploy/labs/vm01-test/configuration.nix
{
  imports =[
    ./../../../config-defs/core.nix
    ./hardware-configuration.nix
    ./users.nix
  ];

  boot = {
    loader.grub.device = "/dev/vda";
    kernelParams = [ "lockdown=confidentiality" ];
  };

  networking.hostName = "vm01-test";
}

Внимание, содержимое hardware-configuration.nix копируем из удалённой системы. В вашем случае значения fileSystems."/" и swapDevices будут отличаться, остальные параметры тоже могут отличаться в зависимости от того, где и как подняли удалённую систему.

nano ~/works/nixops/deploy/labs/vm01-test/hardware-configuration.nix
{ config, lib, pkgs, modulesPath, ... }:
{
  imports = [
    (modulesPath + "/profiles/qemu-guest.nix")
  ];

  boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ ];
  boot.extraModulePackages = [ ];

  fileSystems."/" = {
    device = "/dev/disk/by-uuid/9fe5779b-f835-4faa-a26a-1b0e24885b53";
    fsType = "ext3";
  };

  swapDevices = [
    { device = "/dev/disk/by-uuid/1ad05bbc-f8aa-4233-8f25-e2d069088660"; }
  ];
}

В файле users.nix в разделе users.root.openssh.authorizedKeys.keys прописываем ssh ключ, который сгенерировали выше. В разделе users.rebrain.openssh.authorizedKeys.keys уже прописан ключ, который мы сгенерировали при первом знакомстве с NixOS.

nano ~/works/nixops/deploy/labs/vm01-test/users.nix
{ config, ... }:
let
  ssh-keys = import ./../../../config-defs/generic/security/ssh-keys.nix;

in {
  users = with ssh-keys; {
    users.root = {
      openssh.authorizedKeys.keys = [
        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII5rqPqf/eFAyAEPZhwX/Hg7sNLZj4LWEexxsnv6izMW rebrain@NixOS-example"
      ];
      hashedPassword = null;
    };
    users.rebrain = {
      isNormalUser = true;
      uid = config.uid-gid.rebrain;
      group = "rebrain";
      extraGroups = [ "wheel" "users" ];
      openssh.authorizedKeys.keys = [
        work.rebrain_example
      ];
      hashedPassword = "$6$zejLDpVGQfekr$no6c35WweI7j59W8diZ2pZwA2xadi5NxJNacLkBBoOmyt/4Lqt/pDX2pO3vUw157eb59XUZ71GZcMXQs2FqKL/";
    };
    groups.rebrain = {
      gid = config.uid-gid.rebrain;
    };
    groups.ssh-users = {
      members = [ "root" "rebrain" ];
    };
  };
}

Создаём новый деплой:

nixops create -d labs ~/works/nixops/deploy/labs.nix
created deployment ‘00bb8030-dd68-11ea-bffc-525400c283bd’
00bb8030-dd68-11ea-bffc-525400c283bd

Просмотрим информацию о нашем деплое:

nixops info -d labs
Network name: labs
Network UUID: 00bb8030-dd68-11ea-bffc-525400c283bd
Network description: labs servers
Nix expressions: /home/rebrain/works/nixops/deploy/labs.nix
Nix profile: /nix/var/nix/profiles/per-user/rebrain/nixops/00bb8030-dd68-11ea-bffc-525400c283bd

+-----------+---------+------+-------------+------------+
| Name      |  Status | Type | Resource Id | IP address |
+-----------+---------+------+-------------+------------+
| vm01-test | Missing | none |             |            |
+-----------+---------+------+-------------+------------+

Теперь можно развернуть нашу конфигурацию на удаленную систему:

nixops deploy -d labs

Если мы при генерации ssh ключа указывали пароль, то у нас eго затребует nixops, вводим его:

The authenticity of host '192.168.0.221 (192.168.0.221)' can't be established.
ED25519 key fingerprint is SHA256:OkVYhWyTXSqRhepssZl8wea9fyORTStMT5Hyyczpdao.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.0.221' (ED25519) to the list of known hosts.
Enter passphrase for key '/home/rebrain/.ssh/id_ed25519':

Запускается процесс сборки и настройки удалённой системы:

building all machine configurations...
unpacking 'https://github.com/nix-community/NUR/archive/master.tar.gz'...
copying path '/nix/store/jig041yhk4gjymfbm7l0r3cvhpc30abf-mirrors-list' from 'https://cache.nixos.org'...
copying path '/nix/store/70p2d9m74sxsrxqh255av99i6ww0l76y-curl-7.71.1-man' from 'https://cache.nixos.org'...
copying path '/nix/store/r2nywq3ziag55zi6dqcxkpb6yla044kq-libunistring-0.9.10' from 'https://cache.nixos.org'...
copying path '/nix/store/gn0xmlk9kb1dcnlh7naawq3warfbzgzx-nghttp2-1.40.0' from 'https://cache.nixos.org'...
copying path '/nix/store/arb8311fjm1dsrbsy8j7pdanwnz1qwxv-libidn2-2.3.0' from 'https://cache.nixos.org'...
copying path '/nix/store/mh78fk3x12q2a77srgkzv16h0irl8r61-glibc-2.31' from 'https://cache.nixos.org'...
copying path '/nix/store/kyi6558fwmxivw4j70b2nx36m6200mjp-attr-2.4.48' from 'https://cache.nixos.org'...
copying path '/nix/store/6737cq9nvp4k5r70qcgf61004r0l2g3v-bash-4.4-p23' from 'https://cache.nixos.org'...
copying path '/nix/store/jgfa1mslsw5ag1mgr5bggi1f30nn5zam-bzip2-1.0.6.0.1' from 'https://cache.nixos.org'...
copying path '/nix/store/zl08ih0skhpxnny9n1ydihmssfxxw5hr-acl-2.2.53' from 'https://cache.nixos.org'...
copying path '/nix/store/kxcwjq4sd5iiqgiqp39zqs4pczb1i2kj-bzip2-1.0.6.0.1-bin' from 'https://cache.nixos.org'...
copying path '/nix/store/jvvk8nfksihqvqyxgqygyg92a57aszba-c-ares-1.15.0' from 'https://cache.nixos.org'...
copying path '/nix/store/4d3487v9gdlcab84kvgnqsw5mp3f3678-ed-1.16' from 'https://cache.nixos.org'...
copying path '/nix/store/gd3nl6hcc8mzq8fmxdvl6czh3l0n4la5-coreutils-8.31' from 'https://cache.nixos.org'...
copying path '/nix/store/y4f6wp3p8wi304l7x47bh4qq7zf5cqjs-gawk-5.1.0' from 'https://cache.nixos.org'...
copying path '/nix/store/v589pqjhvxrj73g3r0xb41yr84z5pwb7-gcc-9.3.0-lib' from 'https://cache.nixos.org'...

...
vm01-test> copying path '/nix/store/brg8jlxnsfys729ji6vn8cswqf8y98pz-unit-dbus.service' to 'ssh://root@192.168.0.221'...
vm01-test> copying path '/nix/store/g0709d1vf3r431gmy5jvdz8pzlcz7rgg-system-units' to 'ssh://root@192.168.0.221'...
vm01-test> copying path '/nix/store/lz7ksa3ybgr1lq9sk4jc2d2fmc78kjib-user-units' to 'ssh://root@192.168.0.221'...
vm01-test> copying path '/nix/store/dazf67i0qf4515y8bw4xbfhdnnbvdkg8-etc' to 'ssh://root@192.168.0.221'...
vm01-test> copying path '/nix/store/8kddpssmnnasngg5dydvkx765l6nw3gh-nixos-system-vm01-test-20.09pre238361.33548111764' to 'ssh://root@192.168.0.221'...
labs> closures copied successfully
vm01-test> updating GRUB 2 menu...
vm01-test> stopping the following units: audit.service, firewall.service, kmod-static-nodes.service, network-local-commands.service, network-setup.service, nix-daemon.service, nix-daemon.socket, nscd.service, resolvconf.service, sshd.service, systemd-modules-load.service, systemd-sysctl.service, systemd-timesyncd.service, systemd-tmpfiles-clean.timer, systemd-tmpfiles-setup-dev.service, systemd-udev-trigger.service, systemd-udevd-control.socket, systemd-udevd-kernel.socket, systemd-udevd.service
vm01-test> NOT restarting the following changed units: getty@tty1.service, systemd-journal-flush.service, systemd-logind.service, systemd-random-seed.service, systemd-remount-fs.service, systemd-tmpfiles-setup.service, systemd-udev-settle.service, systemd-update-utmp.service, systemd-user-sessions.service, user-runtime-dir@0.service, user-runtime-dir@51011.service, user@0.service, user@51011.service
vm01-test> activating the configuration...
vm01-test> reviving group 'ssh-users' with GID 999
vm01-test> removing group ‘systemd-timesync’
vm01-test> reviving user 'unbound' with UID 998
vm01-test> removing user ‘systemd-timesync’
vm01-test> setting up /etc...
vm01-test> removing obsolete symlink ‘/etc/systemd/timesyncd.conf’...
vm01-test> restarting systemd...
vm01-test> reloading user units for root...
vm01-test>           ::::.    ':::::     ::::'           root@vm01-test
vm01-test>           ':::::    ':::::.  ::::'            OS: NixOS 20.09pre238361.33548111764 (Nightingale)
vm01-test>             :::::     '::::.:::::             Kernel: x86_64 Linux 5.4.55
vm01-test>       .......:::::..... ::::::::              Uptime: 15m
vm01-test>      ::::::::::::::::::. ::::::    ::::.      Packages: 1143
vm01-test>     ::::::::::::::::::::: :::::.  .::::'      Shell: sh
vm01-test>            .....           ::::' :::::'       Disk: 3,3G / 16G (22%)
vm01-test>           :::::            '::' :::::'        CPU: QEMU Virtual version 2.5+ @ 2x 2.195GHz
vm01-test>  ........:::::               ' :::::::::::.   GPU: Red Hat, Inc. Virtio GPU (rev 01)
vm01-test> :::::::::::::                 :::::::::::::   RAM: 292MiB / 1993MiB
vm01-test>  ::::::::::: ..              :::::
vm01-test>      .::::: .:::            :::::
vm01-test>     .:::::  :::::          '''''    .....
vm01-test>     :::::   ':::::.  ......:::::::::::::'
vm01-test>      :::     ::::::. ':::::::::::::::::'
vm01-test>             .:::::::: '::::::::::
vm01-test>            .::::''::::.     '::::.
vm01-test>           .::::'   ::::.     '::::.
vm01-test>          .::::      ::::      '::::.
vm01-test> reloading user units for rebrain...
vm01-test>           ::::.    ':::::     ::::'           rebrain@vm01-test
vm01-test>           ':::::    ':::::.  ::::'            OS: NixOS 20.09pre238361.33548111764 (Nightingale)
vm01-test>             :::::     '::::.:::::             Kernel: x86_64 Linux 5.4.55
vm01-test>       .......:::::..... ::::::::              Uptime: 15m
vm01-test>      ::::::::::::::::::. ::::::    ::::.      Packages: 1143
vm01-test>     ::::::::::::::::::::: :::::.  .::::'      Shell: sh
vm01-test>            .....           ::::' :::::'       Disk: 3,3G / 16G (22%)
vm01-test>           :::::            '::' :::::'        CPU: QEMU Virtual version 2.5+ @ 2x 2.195GHz
vm01-test>  ........:::::               ' :::::::::::.   GPU: Red Hat, Inc. Virtio GPU (rev 01)
vm01-test> :::::::::::::                 :::::::::::::   RAM: 294MiB / 1993MiB
vm01-test>  ::::::::::: ..              :::::
vm01-test>      .::::: .:::            :::::
vm01-test>     .:::::  :::::          '''''    .....
vm01-test>     :::::   ':::::.  ......:::::::::::::'
vm01-test>      :::     ::::::. ':::::::::::::::::'
vm01-test>             .:::::::: '::::::::::
vm01-test>            .::::''::::.     '::::.
vm01-test>           .::::'   ::::.     '::::.
vm01-test>          .::::      ::::      '::::.
vm01-test> setting up tmpfiles
vm01-test> reloading the following units: dbus.service, dev-hugepages.mount, dev-mqueue.mount, sys-kernel-debug.mount
vm01-test> restarting the following units: dhcpcd.service, systemd-journald.service
vm01-test> starting the following units: audit.service, kmod-static-nodes.service, network-local-commands.service, network-setup.service, nix-daemon.socket, nscd.service, resolvconf.service, systemd-modules-load.service, systemd-sysctl.service, systemd-tmpfiles-clean.timer, systemd-tmpfiles-setup-dev.service, systemd-udev-trigger.service, systemd-udevd-control.socket, systemd-udevd-kernel.socket
vm01-test> the following new units were started: chronyd.service, disable-kernel-module-loading.service, encrypted-links.target, logrotate.timer, nix-optimise.timer, qemu-guest-agent.service, sshd.socket, syslog-ng.service, unbound.service
vm01-test> warning: the following units failed: apparmor.service
vm01-test>
vm01-test> ● apparmor.service
vm01-test>      Loaded: loaded (/nix/store/5db40ssdzmzhwb26ii0247v08hl2l2qn-unit-apparmor.service/apparmor.service; enabled; vendor preset: enabled)
vm01-test>      Active: failed (Result: exit-code) since Thu 2020-08-13 16:35:50 MSK; 420ms ago
vm01-test>     Process: 2445 ExecStart=/nix/store/mlwjiwjw3x8pvq7gijy3wr28im7n5nx7-apparmor-parser-2.13.4/bin/apparmor_parser -rKv -I /nix/store/g4snl6w2bd6x5aaaabwvhza82ph6cfx2-apparmor-profiles-2.13.4/etc/apparmor.d /nix/store/h5jpz7vxiikfwy3in2fbi7gipzi2k49c-ping (code=exited, status=1/FAILURE)
vm01-test>    Main PID: 2445 (code=exited, status=1/FAILURE)
vm01-test>          IP: 0B in, 0B out
vm01-test>         CPU: 4ms
vm01-test>
vm01-test> Aug 13 16:35:50 vm01-test systemd[1]: Starting apparmor.service...
vm01-test> Aug 13 16:35:50 vm01-test apparmor_parser[2445]: Warning from stdin (line 1): config file '/etc/apparmor/parser.conf' not found
vm01-test> Aug 13 16:35:50 vm01-test apparmor_parser[2445]: Cache read/write disabled: interface file missing. (Kernel needs AppArmor 2.4 compatibility patch.)
vm01-test> Aug 13 16:35:50 vm01-test apparmor_parser[2445]: Warning: unable to find a suitable fs in /proc/mounts, is it mounted?
vm01-test> Aug 13 16:35:50 vm01-test apparmor_parser[2445]: Use --subdomainfs to override.
vm01-test> Aug 13 16:35:50 vm01-test systemd[1]: apparmor.service: Main process exited, code=exited, status=1/FAILURE
vm01-test> Aug 13 16:35:50 vm01-test systemd[1]: apparmor.service: Failed with result 'exit-code'.
vm01-test> Aug 13 16:35:50 vm01-test systemd[1]: Failed to start apparmor.service.
vm01-test> error: Traceback (most recent call last):
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 743, in worker
    raise Exception("unable to activate new configuration (exit code {})".format(res))
Exception: unable to activate new configuration (exit code 4)

Traceback (most recent call last):
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/bin/..nixops-wrapped-wrapped", line 991, in <module>
    args.op()
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/bin/..nixops-wrapped-wrapped", line 412, in op_deploy
    max_concurrent_activate=args.max_concurrent_activate)
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1063, in deploy
    self.run_with_notify('deploy', lambda: self._deploy(**kwargs))
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1052, in run_with_notify
    f()
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1063, in <lambda>
    self.run_with_notify('deploy', lambda: self._deploy(**kwargs))
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1019, in _deploy
    dry_activate=dry_activate, max_concurrent_activate=max_concurrent_activate)
  File "/nix/store/jc2mfpj70cwl0m2a3y6z9c5bcxdmgyxp-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 775, in activate_configs
    .format(len(failed), len(res), ", ".join(["‘{0}’".format(x) for x in failed])))
Exception: activation of 1 of 1 machines failed (namely on ‘vm01-test’)
Time: 0h:04m:50s

Как видим идёт копирования пакетов и конфигурационных файлов на удаленную систему. Затем, на их основе, собирается необходимая нам конфигурация системы. В конце у нас выскочит ошибка, что не стартовала служба apparmor, для её активации нужна перезагрузка удалённой системы:

nixops reboot -d labs
vm01-test> rebooting...
Enter passphrase for key '/home/rebrain/.ssh/id_ed25519':
vm01-test> waiting for the machine to finish rebooting....[down]................[up]
Enter passphrase for key '/home/rebrain/.ssh/id_ed25519':

Полученную конфигурацию добавим git репозиторий:

git config --global user.email "rebrain@NixOS-example"
git config --global user.name "rebrain"

cd ~/works/nixops/deploy
git init && git add -A && git commit -m "first commit"

Теперь добавим основные службы - файерволл, fail2ban и мониторинг netdata:

cp -r /etc/nixos/nix-config/servers/example/services ~/works/nixops/deploy/labs/vm01-test
nano ~/works/nixops/deploy/labs/vm01-test/configuration.nix
...
  imports =[
    ./../../../config-defs/core.nix
    ./services/fail2ban.nix
    ./services/firefall-nft.nix
    ./services/netdata.nix
    ./hardware-configuration.nix
    ./users.nix
  ];
...

Просмотрим изменения:

git diff
diff --git a/labs/vm01-test/configuration.nix b/labs/vm01-test/configuration.nix
index 2de8f9f..6db6ae3 100644
--- a/labs/vm01-test/configuration.nix
+++ b/labs/vm01-test/configuration.nix
@@ -1,6 +1,9 @@
 {
   imports =[
     ./../../../config-defs/core.nix
+    ./services/fail2ban.nix
+    ./services/firefall-nft.nix
+    ./services/netdata.nix
     ./hardware-configuration.nix
     ./users.nix
   ];

Добавляем изменения в git:

git add -A
git commit -m "add default services"

Теперь применяем изменения на удалённой системе:

nixops deploy -d labs
Enter passphrase for key '/home/rebrain/.ssh/id_ed25519':
building all machine configurations...
unpacking 'https://github.com/nix-community/NUR/archive/master.tar.gz'...
these derivations will be built:
  /nix/store/wrns0lc31461hbb991gmn9g3cbslx4rg-limits.conf.drv
  /nix/store/0cg6wayc42qp7ddz0ais1z7anj8qdyz7-chfn.pam.drv
  /nix/store/jh2g3hj3z0pfcqpmf75375g1r3nqmcqs-system-path.drv
  /nix/store/0kl6vw56zvd6vqq2rhsrg5c6csbbjn0l-unit-systemd-fsck-.service.drv
  /nix/store/2yc5b8dm50rrakhyyz1whda5ynr5vvm5-su.pam.drv
  /nix/store/2ym5y01lim5cb5snlam3cfzx0sb65gms-groupadd.pam.drv
  /nix/store/2zrn9wi4civwwkgminbg1si1ryrxlbsf-jail.local.drv
  /nix/store/37h285grnxxp6dkgm062hh8khyab48hb-i3lock-color.pam.drv
  /nix/store/4kknfy450ah0kpv4lqd4xv6diqlw8am4-groupmems.pam.drv
...
building '/nix/store/856w8snjlfyl6hi6fwa4pqw0ay5bbrd1-etc.drv'...
building '/nix/store/ssd95hnspmlaj2q843gxd0f9zpg95mkb-nixos-system-vm01-test-20.09pre238361.33548111764.drv'...
building '/nix/store/395rflzyqrdk8qwjqxxwaxnpxqrf3lyj-nixops-machines.drv'...
vm01-test> copying closure...
vm01-test> copying path '/nix/store/i65m49njwrdjqscpbrglva67993l9vx7-wrapped-plugins' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/01113j97n0pymlrlzwmrnsrrl9mm9fdy-freeipmi-1.6.5' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/i0zbc4g3h2qvyvc02h0d0gm0q6nv4dzg-jansson-2.13.1' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/j7fkg0x9zz8mvxg4wgzfxk3h7h6hyk6z-judy-1.0.5' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/qb1pp715km3i2sqwvdfpdi4ddhm3akwd-libnetfilter_acct-1.0.3' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/l0kvj1rh52ghffa585jqyg8mrlbw15dn-libuv-1.38.1' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/b3xwkfavjmflgyqxdkqkmsxcg913j3gr-lm-sensors-3.6.0' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/9557pxkkz4n0mv94c1x8ha1j0bryz3b0-netdata-go.d.plugin-0.20.0' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/kak7pfqf812da9psa0f98as94ak7k8yz-nftables-0.9.6' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/vsrwx91c4a54p1yiac9ps82dzvzl9il6-python3-3.8.5-env' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/84xhqx9d66jiy6flyvzkssg2dgqsy1y3-python3.8-systemd-234' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/k0g3nz1p4zd9bb7kgxvrj74c178ms1w3-fail2ban-0.11.1' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/8hmmhd45zgcykns5wb3s5l4a5cxj6kha-netdata-1.23.2' from 'https://cache.nixos.org'...
vm01-test> copying path '/nix/store/8wjd41ncr73w3zflwc7d3vfk2kkl91w7-netdata.conf' from 'https://cache.nixos.org'...
vm01-test> copying 48 paths...
vm01-test> copying path '/nix/store/3cnp3s91rx1famln69ac4i919fzyw5y1-unit-netdata.service' to 'ssh://root@192.168.0.221'...
vm01-test> copying path '/nix/store/7rpf25gvzmjsgfr6p4vzw7lj98qzqzp4-system-path' to 'ssh://root@192.168.0.221'...
vm01-test> copying path '/nix/store/9bdj9mvsvgihblx27yly0dap05hcihi7-limits.conf' to 'ssh://root@192.168.0.221'...
...
labs> closures copied successfully
vm01-test> updating GRUB 2 menu...
vm01-test> stopping the following units: systemd-modules-load.service
vm01-test> activating the configuration...
vm01-test> setting up /etc...
vm01-test> reloading user units for root...
vm01-test>           ::::.    ':::::     ::::'           root@vm01-test
vm01-test>           ':::::    ':::::.  ::::'            OS: NixOS 20.09pre238361.33548111764 (Nightingale)
vm01-test>             :::::     '::::.:::::             Kernel: x86_64 Linux 5.7.15-hardened
vm01-test>       .......:::::..... ::::::::              Uptime: 3h 22m
vm01-test>      ::::::::::::::::::. ::::::    ::::.      Packages: 1170
vm01-test>     ::::::::::::::::::::: :::::.  .::::'      Shell: sh
vm01-test>            .....           ::::' :::::'       Disk: 3,4G / 16G (23%)
vm01-test>           :::::            '::' :::::'        CPU: QEMU Virtual version 2.5+ @ 2x 2.195GHz
vm01-test>  ........:::::               ' :::::::::::.   GPU: Red Hat, Inc. Virtio GPU (rev 01)
vm01-test> :::::::::::::                 :::::::::::::   RAM: 350MiB / 1993MiB
vm01-test>  ::::::::::: ..              :::::
vm01-test>      .::::: .:::            :::::
vm01-test>     .:::::  :::::          '''''    .....
vm01-test>     :::::   ':::::.  ......:::::::::::::'
vm01-test>      :::     ::::::. ':::::::::::::::::'
vm01-test>             .:::::::: '::::::::::
vm01-test>            .::::''::::.     '::::.
vm01-test>           .::::'   ::::.     '::::.
vm01-test>          .::::      ::::      '::::.
vm01-test> reloading user units for rebrain...
vm01-test>           ::::.    ':::::     ::::'           rebrain@vm01-test
vm01-test>           ':::::    ':::::.  ::::'            OS: NixOS 20.09pre238361.33548111764 (Nightingale)
vm01-test>             :::::     '::::.:::::             Kernel: x86_64 Linux 5.7.15-hardened
vm01-test>       .......:::::..... ::::::::              Uptime: 3h 22m
vm01-test>      ::::::::::::::::::. ::::::    ::::.      Packages: 1170
vm01-test>     ::::::::::::::::::::: :::::.  .::::'      Shell: sh
vm01-test>            .....           ::::' :::::'       Disk: 3,4G / 16G (23%)
vm01-test>           :::::            '::' :::::'        CPU: QEMU Virtual version 2.5+ @ 2x 2.195GHz
vm01-test>  ........:::::               ' :::::::::::.   GPU: Red Hat, Inc. Virtio GPU (rev 01)
vm01-test> :::::::::::::                 :::::::::::::   RAM: 352MiB / 1993MiB
vm01-test>  ::::::::::: ..              :::::
vm01-test>      .::::: .:::            :::::
vm01-test>     .:::::  :::::          '''''    .....
vm01-test>     :::::   ':::::.  ......:::::::::::::'
vm01-test>      :::     ::::::. ':::::::::::::::::'
vm01-test>             .:::::::: '::::::::::
vm01-test>            .::::''::::.     '::::.
vm01-test>           .::::'   ::::.     '::::.
vm01-test>          .::::      ::::      '::::.
vm01-test> setting up tmpfiles
vm01-test> reloading the following units: dbus.service
vm01-test> starting the following units: systemd-modules-load.service
vm01-test> the following new units were started: fail2ban.service, netdata.service
vm01-test> warning: the following units failed: nftables.service
vm01-test>
vm01-test> ● nftables.service - nftables firewall
vm01-test>      Loaded: loaded (/nix/store/9ir93n0mzn57c9x8yrh1m28lbl6szs2a-unit-nftables.service/nftables.service; enabled; vendor preset: enabled)
vm01-test>      Active: failed (Result: exit-code) since Thu 2020-08-13 19:59:30 MSK; 50ms ago
vm01-test>     Process: 1437 ExecStart=/nix/store/0pns2jkqpv6pddrbimpxi6kr47xwsnm4-nftables-check (code=exited, status=1/FAILURE)
vm01-test>    Main PID: 1437 (code=exited, status=1/FAILURE)
vm01-test>          IP: 0B in, 0B out
vm01-test>         CPU: 23ms
vm01-test>
vm01-test> авг 13 19:59:30 vm01-test systemd[1]: Starting nftables firewall...
vm01-test> авг 13 19:59:30 vm01-test 0pns2jkqpv6pddrbimpxi6kr47xwsnm4-nftables-check[1437]: Unload ip_tables before using nftables!
vm01-test> авг 13 19:59:30 vm01-test systemd[1]: nftables.service: Main process exited, code=exited, status=1/FAILURE
vm01-test> авг 13 19:59:30 vm01-test systemd[1]: nftables.service: Failed with result 'exit-code'.
vm01-test> авг 13 19:59:30 vm01-test systemd[1]: Failed to start nftables firewall.
vm01-test> error: Traceback (most recent call last):
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 743, in worker
    raise Exception("unable to activate new configuration (exit code {})".format(res))
Exception: unable to activate new configuration (exit code 4)

Traceback (most recent call last):
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/bin/..nixops-wrapped-wrapped", line 991, in <module>
    args.op()
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/bin/..nixops-wrapped-wrapped", line 412, in op_deploy
    max_concurrent_activate=args.max_concurrent_activate)
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1063, in deploy
    self.run_with_notify('deploy', lambda: self._deploy(**kwargs))
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1052, in run_with_notify
    f()
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1063, in <lambda>
    self.run_with_notify('deploy', lambda: self._deploy(**kwargs))
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 1019, in _deploy
    dry_activate=dry_activate, max_concurrent_activate=max_concurrent_activate)
  File "/nix/store/ihb5kkmbds0f5zvxl7mb51mj4sgkcys8-nixops-1.7/lib/python2.7/site-packages/nixops/deployment.py", line 775, in activate_configs
    .format(len(failed), len(res), ", ".join(["‘{0}’".format(x) for x in failed])))
Exception: activation of 1 of 1 machines failed (namely on ‘vm01-test’)
Time: 0h:00m:57s

Служба nftables выдаёт ошибку, т.к. системе требуется перезагрузка:

nixops reboot -d labs

Для обновления удаленной системы, предварительно надо обновить на текущей системе основной канал и запустить обновление через nixops:

sudo nix-channel --update
unpacking channels...
nixops deploy -d labs
Enter passphrase for key '/home/rebrain/.ssh/id_ed25519':
building all machine configurations...
vm01-test> copying closure...
labs> closures copied successfully
vm01-test> updating GRUB 2 menu...
vm01-test> activating the configuration...
vm01-test> setting up /etc...
vm01-test> reloading user units for root...
vm01-test>           ::::.    ':::::     ::::'           root@vm01-test
vm01-test>           ':::::    ':::::.  ::::'            OS: NixOS 20.09pre238361.33548111764 (Nightingale)
vm01-test>             :::::     '::::.:::::             Kernel: x86_64 Linux 5.7.15-hardened
vm01-test>       .......:::::..... ::::::::              Uptime: 5m
vm01-test>      ::::::::::::::::::. ::::::    ::::.      Packages: 1170
vm01-test>     ::::::::::::::::::::: :::::.  .::::'      Shell: sh
vm01-test>            .....           ::::' :::::'       Disk: 3,4G / 16G (23%)
vm01-test>           :::::            '::' :::::'        CPU: QEMU Virtual version 2.5+ @ 2x 2.195GHz
vm01-test>  ........:::::               ' :::::::::::.   GPU: Red Hat, Inc. Virtio GPU (rev 01)
vm01-test> :::::::::::::                 :::::::::::::   RAM: 357MiB / 1993MiB
vm01-test>  ::::::::::: ..              :::::
vm01-test>      .::::: .:::            :::::
vm01-test>     .:::::  :::::          '''''    .....
vm01-test>     :::::   ':::::.  ......:::::::::::::'
vm01-test>      :::     ::::::. ':::::::::::::::::'
vm01-test>             .:::::::: '::::::::::
vm01-test>            .::::''::::.     '::::.
vm01-test>           .::::'   ::::.     '::::.
vm01-test>          .::::      ::::      '::::.
vm01-test> setting up tmpfiles
vm01-test> the following new units were started: logrotate.service
vm01-test> activation finished successfully
labs> deployment finished successfully
Time: 0h:00m:19s

Чтобы удалить наш деплой, предварительно удаляем все удаленные системы из него:

nixops destroy -d labs
these derivations will be built:
  /nix/store/py43280mq7bn7585yq9xwkvknnxblvpb-nixops-machines.drv
building '/nix/store/py43280mq7bn7585yq9xwkvknnxblvpb-nixops-machines.drv'...
Time: 0h:00m:04s

Потом уже сам деплой:

nixops delete -d labs

Таким способом можно централизованно управлять различными удалёнными системами на базе ОС NixOS с использованием общей базовой конфигурацией.