Синхронизация системных настроек

от автора

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.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Как вы синхронизируете свои конфиги?

16.22% Использую один из dotfiles менеджеров6
18.92% Использую git репозиторий и синхронизирую вручную7
64.86% Не использую синхронизацию вообще24

Проголосовали 37 пользователей. Воздержались 14 пользователей.

ссылка на оригинал статьи https://habr.com/ru/articles/585578/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *