image
Как известно, большинство программ в мире Linux и частично в MacOS используют текстовые файлы для конфигурации.
Иногда случается необходимость в переносе своих настроек на новую систему. Также очень важно иметь одинаковое окружение дома и на работе.
Особенно важно это тем людям, которые как и я любят перенастраивать свое рабочее окружение.


Очень долгое время у меня был git репозиторий, синхронизированный с Github, Gitlab и Bitbucket.
Для некоторых конфигов я вручную делал симлинки, для других использовал vimdiff/meld для визуального сравнения файлов и переноса общих настроек.
Например я добавил настройку в свой .vimrc на домашнем компьютере. Запустил meld ~/.vimrc <git path>/.vimrc, просмотрел изменения, синхронизировал их и запушил в репозиторий.
Потом на работе уже нужно было скачать изменения и запустить такую же команду, чтобы синхронизировать изменения на рабочем компе.


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


Совсем недавно в ютубе я наткнулся на видео про использование GNU Stow для синхронизации дотфайлов и понял, что не только меня беспокоит эта ситуация и кто-то уже инвестировал свое время в ее решение. Как только вопрос сформулировался, как сразу нашелся на него ответ в виде отличной статьи на Archwiki. Так как у меня много файлов, которые немного отличаются на разных машинах, то все программы, не умеющие в шаблоны сразу отпали. Мой выбор пал на chezmoi, так как он написан на go и можно напрямую скачать один бинарник с Github курлом, если нужно перенести свои настройки на новую машину. Так же решается проблема синхронизации секретных данных интеграцией с разными менеджерами паролей(1Password, Bitwarden, gopass, KeePassXC, LastPass, pass, Vault, Keychain, Keyring) или шифрованием данных с помощью GnuPG/age.


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


Собственный конфиг


chezmoi как и любая другая программа в мире Linux имеет собственный конфиг, который должен быть по пути $XDG_CONFIG_HOME/chezmoi/config.toml.
Сам конфиг может быть 3 форматов — Toml, Yaml или Json. Для себя я выбрал Toml.
Можно хранить конфиг на каждой машине отдельно, но я предпочитаю синхронизировать его вместе с другими файлами. Поэтому я использую специальный файл .chezmoi.toml.tmpl в корне репозитория. Все файлы с расширением *.tmpl интерпретируются как шаблоны на языке go(также доступны все дополнительные функции шаблонизатора sprig). Вот мой шаблон конфига


{{- $type := "personal" -}}
{{- $kps_key := "" -}}
{{- $personal_ip := "" -}}

{{- if ne .chezmoi.hostname "personal" -}}
{{- $type = "work" -}}
{{- end -}}

{{- if (hasKey . "kps_key") -}}
{{-   $kps_key = .kps_key -}}
{{- else -}}
{{-   $kps_key = promptString "kps_key" -}}
{{- end -}}
{{- if (hasKey . "personal_ip") -}}
{{-   $personal_ip = .personal_ip -}}
{{- else -}}
{{-   $personal_ip = promptString "personal_ip" -}}
{{- end -}}

[data]
  type = {{ $type | quote }}
  kps_key = {{ $kps_key | quote }}
  personal_ip = {{ $personal_ip | quote }}
  {{ if eq .chezmoi.hostname "personal" -}}
  bluetooth_mac = "<mac>"
  cpu_format = "{utilization} {frequency}"
  eth_id = "<personal eth>"
  wifi_id = "<personal wifi>"
  {{- else }}
  cpu_format = "{barchart} {utilization} {frequency}"
  eth_id = "<work eth>"
  wifi_id = "<work wifi>"
  {{- end }}

color = "on"
format = "toml"
mode = "file"
pager = "bat"

[diff]
command = "meld"

[git]
autoAdd = true

[keepassxc]
database = "<path to db>.kdbx"
args = ["-k", "{{ .kps_key }}" ]

В конфиге есть общие настройки, типа color или format, а есть секция data.
В данной секции объявляется список ключей=значений, которые потом можно использовать в шаблонах. Пример использования — {{ .kps_key }}
Для общих данных есть файл .chezmoidata.<format>.


Создание конфига происходит командой chezmoi init


После этого можно добавлять файлы, которые будут синхронизироваться командой chezmoi add <path>


Чтобы посмотреть разницу между репозиторием и текущим состоянием системы есть команда chezmoi diff


Если вы вручную отредактировали файл, можно смержить командой chezmoi merge <path> или chezmoi merge-all.


Чтобы применить изменения — chezmoi apply.


Отдельно стоит выделить создание шаблонов.
Можно просто руками переименовать файл, добавив в конце суффикс .tmpl, но для этого лучше использовать специальные флаги при добавлении файлов.
При использовании флага --template файл сразу добавится с нужным расширением.
А если файл уже содержит значение, которое есть в конфиге в секции datachezmoi add --autotemplate <path> автоматически подставит нужный ключ, как переменную в созданный шаблон.


Кстати, все файлы, которые добавляются в репозиторий, вместо точки в начале имени файла используют префикс dot_.
Например команда chezmoi add ~/.bashrc создаст файл с именем dot_bashrc.


Скрипты


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


Например вам надо создать какую-то директорию, на которую потом будет ссылка в .bashrc


Надо создать скрипт с префиксом before_dot_basrc, например before_dot_bashrc_run.sh


#!/usr/bin/env bash

mkdir -p $HOME/.local/share/bash/functions

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


Есть разные другие полезные префиксы и для скриптов и для файлов


Например, вот как я создаю ssh ключ для github на новой машине


Файл private_dot_ssh/private_dot_ssh/create_private_github.tmpl с контентом


{{ keepassxcAttribute "/dotfiles/ssh/github" "private" }}

Префикс create_ создает файл, если его нету, private_ добавляет маску чтения файла владельцем.


Еще примеры


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


Например в моем .zshrc раньше были такие проверки


if [ -f $ZDOTDIR/aliases.local.zsh ]; then
  . $ZDOTDIR/aliases.local.zsh
fi

Сейчас я их заменил таким шаблоном


{{ if stat (expandenv "$ZDOTDIR/aliases.local.zsh") }}
. $ZDOTDIR/aliases.local.zsh
{{ end }}

Также можно проверять на наличие исполнительного файла в $PATH


{{- if (or (lookPath "cargo") (stat (expandenv "$HOME/.rustup"))) }}
alias crn='cargo run'
alias cup='cargo update'
alias cbd='cargo build'
alias cbr='cargo build --release'
setup_cargo () {
  rustup completions zsh cargo  > $LOCAL_ZSH_COMP_DIR/_cargo
  rustup completions zsh rustup > $LOCAL_ZSH_COMP_DIR/_rustup
}
setup_cargo_tools() {
  if ! command_exists cargo-expand; then
    cargo install cargo-expand
  fi
  if ! command_exists cargo-audit; then
    cargo install cargo-audit
  fi
  if ! command_exists cargo-outdated; then
    cargo install cargo-outdated
  fi
}
{{- end }}

Заключение


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


P.S. Так же посматриваю на различные системы установки необходимых пакетов, при переустановке системы. Пока в планах затестить Comtrya, как ориентированную на локалхост альтернативу Ansible.

Комментарии (15)


  1. aborouhin
    26.10.2021 15:37

    А чем ansible для этой задачи не угодил? С конфигами по шаблонам он не хуже справится, а вот с нуля на новой машине нужный софт chezmoi, как я понял, не установит, в отличие от. Раз в конце пишете, что ansible или аналог всё равно рассматриваете, то зачем плодить сущности?


    1. vtb_k Автор
      26.10.2021 15:44

      Ну chezmoi может установить любой софт, если написать bash скрипт для этого и добавить к нему префикс run_once_. Тогда он запустит этот скрипт при установке.


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


      1. aborouhin
        26.10.2021 16:08

        Ну на вкус и цвет, конечно... Но если есть более мощный инструмент, который может решить больше задач - то чем изучать два малопопулярных решения (chezmoi + comtrya), не проще ли освоить его? Для начала в рамках необходимого Вам функционала?
        А дальше когда появится потребность настраивать те самые удалённые сервера (хотя неужели у человека, использующего Linux на десктопе, нет ни домашнего сервера, ни виртуалки какой-нибудь в облаке? такое бывает? ;) ) - у Вас уже будет готовое решение для этой цели. И Ваши любимые zsh и vim на том сервере тоже сразу встанут в удобной Вам конфигурации.


        1. vtb_k Автор
          26.10.2021 16:18
          +2

          Но если есть более мощный инструмент, который может решить больше задач — то чем изучать два малопопулярных решения (chezmoi + comtrya), не проще ли освоить его?

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


          А дальше когда появится потребность настраивать те самые удалённые сервера

          Нету такой потребности и не предвидится в ближайшем будущем.


          1. aborouhin
            26.10.2021 16:27

            Ansible совсем не прост в изучении, не получится сесть и за неделю разобраться в нем

            За неделю? Нет, если Вы хотите продавать услуги по внедрению Ansible крупным компаниям, наверное, на обучение надо потратить не меньше... :)

            У меня первые несколько плейбуков (установка основного софта, конфиги, скрипты), которые до сих пор использую, появились через несколько часов после того, как я Ansible первый раз в жизни поставил и начал читать доки. Сложнее разобраться с best practices, что куда положить, чтобы всё было оптимально, т.к. Ansible позволяет одни и те же настройки выполнить разными способами. Но это как раз можно осваивать уже по ходу использования. Для нескольких однотипных машин, вполне вероятно, даже не самый архитектурно верный подход будет достаточен.


            1. vtb_k Автор
              26.10.2021 16:31

              Я буду весьма рад почитать статью, описывающую использование Ansible для синхронизации настроек, пока мне такие не попадались


              1. aborouhin
                26.10.2021 16:57

                Так, я, наверное, изначально Вашу задачу неправильно понял.

                Я привык, что все машины, на которых я работаю, включая ноутбуки и смартфоны, всегда имеют доступ по сети друг к другу. И в любой момент времени они всегда подключены либо к моей домашней сети, либо к рабочей, либо к моему VPN. Внутри каждой из этих доверенных сетей уже можно достаточно безопасно открывать SSH-доступ, в т.ч. для целей конфигурирования с помощью Ansible.

                Раз у Вас использование Ansible вызывает вопросы - то, похоже, у Вас не так. Если машины друг с другом не связаны (или вообще не бывают включены одновременно) и при этом запустить простенький VPS, на котором развернуть VPN+Ansible, для Вас по какой-то причине неприемлемо, - то да, получится та же синхронизация через Git или облачное хранилище, только уже не самих конфигов, а плейбуков и шаблонов Ansible, по экземпляру которого будет на каждой из синхронизируемых машин. Не самое изящное решение, соглашусь.


    1. cypa
      31.10.2021 00:48

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


  1. hard_sign
    27.10.2021 11:46
    +1

    Бр-р, как сложно.

    Храню конфиги на яндекс.диске, а настоящие файлы – хардлинки на них. Всё.


    1. vtb_k Автор
      27.10.2021 11:55

      Почему сложно то? Один раз настроил и оно все само работает. chezmoi даже сам запушит все, можно настроить. Проблема с хардлинками в том, что это подходит только для одного компа. А если хочется на рабочей машине иметь те же настройки, то всегда есть какие-то особенности, то пути другие, то сетевые интерфейсы по другому названы. Все еще зависит от объема конфигов. Если это парочка файлов, то проблем нету. Только у меня больше 1000 файлов, которые я синхронизирую. Делать это вручную занимает очень много времени.


  1. OkGoLove
    28.10.2021 08:51
    +1

    Спасибо, интересно было почитать про опыт использования одной из таких утилит. Сам пользуюсь yadm, нравится прямое использование git и система альтернативных файлов.


    1. vtb_k Автор
      28.10.2021 11:27

      Мне это тоже понравилось в chezmoi. Добавление файлов через add, сравнение через diff, можно смержить изменения через merge. Очень удобно, когда привык к гиту. Тоже смотрел на yadm, но в chezmoi понравилось, что можно скачать 1 бинарник на новую машину и сразу все установить.


  1. vtb_k Автор
    28.10.2021 11:26

    del


  1. cypa
    31.10.2021 00:56
    +1

    вы не пробовали https://dhall-lang.org/ ?


    1. vtb_k Автор
      31.10.2021 01:10

      Первый раз вижу такое. Напоминает хаскель. Для моих целей этот вариант не подойдет. Это выглядит как раз, как альтернатива ансибл, но еще больше pulumu. Конечно, если потратить достаточно времени, можно во всем этом разобраться, особенно если используешь эти технологии на работе. Но мне надо только синхронизировать свои текстовые конфиги. Что Ансибл, что этот dhall выглядят диким оверхедом для таких небольших требований. Я даже отказался от comtrya в пользу простого баш скрипта, для установки необходимых пакетов на новой машине