Как известно, большинство программ в мире 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
файл сразу добавится с нужным расширением.
А если файл уже содержит значение, которое есть в конфиге в секции data
— chezmoi 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)
hard_sign
27.10.2021 11:46+1Бр-р, как сложно.
Храню конфиги на яндекс.диске, а настоящие файлы – хардлинки на них. Всё.
vtb_k Автор
27.10.2021 11:55Почему сложно то? Один раз настроил и оно все само работает.
chezmoi
даже сам запушит все, можно настроить. Проблема с хардлинками в том, что это подходит только для одного компа. А если хочется на рабочей машине иметь те же настройки, то всегда есть какие-то особенности, то пути другие, то сетевые интерфейсы по другому названы. Все еще зависит от объема конфигов. Если это парочка файлов, то проблем нету. Только у меня больше 1000 файлов, которые я синхронизирую. Делать это вручную занимает очень много времени.
OkGoLove
28.10.2021 08:51+1Спасибо, интересно было почитать про опыт использования одной из таких утилит. Сам пользуюсь yadm, нравится прямое использование git и система альтернативных файлов.
vtb_k Автор
28.10.2021 11:27Мне это тоже понравилось в
chezmoi
. Добавление файлов черезadd
, сравнение черезdiff
, можно смержить изменения черезmerge
. Очень удобно, когда привык к гиту. Тоже смотрел наyadm
, но вchezmoi
понравилось, что можно скачать 1 бинарник на новую машину и сразу все установить.
cypa
31.10.2021 00:56+1вы не пробовали https://dhall-lang.org/ ?
vtb_k Автор
31.10.2021 01:10Первый раз вижу такое. Напоминает хаскель. Для моих целей этот вариант не подойдет. Это выглядит как раз, как альтернатива ансибл, но еще больше pulumu. Конечно, если потратить достаточно времени, можно во всем этом разобраться, особенно если используешь эти технологии на работе. Но мне надо только синхронизировать свои текстовые конфиги. Что Ансибл, что этот dhall выглядят диким оверхедом для таких небольших требований. Я даже отказался от
comtrya
в пользу простого баш скрипта, для установки необходимых пакетов на новой машине
aborouhin
А чем ansible для этой задачи не угодил? С конфигами по шаблонам он не хуже справится, а вот с нуля на новой машине нужный софт chezmoi, как я понял, не установит, в отличие от. Раз в конце пишете, что ansible или аналог всё равно рассматриваете, то зачем плодить сущности?
vtb_k Автор
Ну
chezmoi
может установить любой софт, если написать bash скрипт для этого и добавить к нему префиксrun_once_
. Тогда он запустит этот скрипт при установке.Что же касается Ansible, то в нем очень много функционала, если с ним специально не работать, то учить его для этого напряжно, нужно фильтровать много информации, он ведь предназначен для управления удаленными хостами.
aborouhin
Ну на вкус и цвет, конечно... Но если есть более мощный инструмент, который может решить больше задач - то чем изучать два малопопулярных решения (chezmoi + comtrya), не проще ли освоить его? Для начала в рамках необходимого Вам функционала?
А дальше когда появится потребность настраивать те самые удалённые сервера (хотя неужели у человека, использующего Linux на десктопе, нет ни домашнего сервера, ни виртуалки какой-нибудь в облаке? такое бывает? ;) ) - у Вас уже будет готовое решение для этой цели. И Ваши любимые zsh и vim на том сервере тоже сразу встанут в удобной Вам конфигурации.
vtb_k Автор
Ansible совсем не прост в изучении, не получится сесть и за неделю разобраться в нем. По крайней мере мне он не подошел из-за этого, нету свободного времени на это. Конечно же никто не запрещает его использовать для этих целей. Личный выбор каждого.
Нету такой потребности и не предвидится в ближайшем будущем.
aborouhin
За неделю? Нет, если Вы хотите продавать услуги по внедрению Ansible крупным компаниям, наверное, на обучение надо потратить не меньше... :)
У меня первые несколько плейбуков (установка основного софта, конфиги, скрипты), которые до сих пор использую, появились через несколько часов после того, как я Ansible первый раз в жизни поставил и начал читать доки. Сложнее разобраться с best practices, что куда положить, чтобы всё было оптимально, т.к. Ansible позволяет одни и те же настройки выполнить разными способами. Но это как раз можно осваивать уже по ходу использования. Для нескольких однотипных машин, вполне вероятно, даже не самый архитектурно верный подход будет достаточен.
vtb_k Автор
Я буду весьма рад почитать статью, описывающую использование Ansible для синхронизации настроек, пока мне такие не попадались
aborouhin
Так, я, наверное, изначально Вашу задачу неправильно понял.
Я привык, что все машины, на которых я работаю, включая ноутбуки и смартфоны, всегда имеют доступ по сети друг к другу. И в любой момент времени они всегда подключены либо к моей домашней сети, либо к рабочей, либо к моему VPN. Внутри каждой из этих доверенных сетей уже можно достаточно безопасно открывать SSH-доступ, в т.ч. для целей конфигурирования с помощью Ansible.
Раз у Вас использование Ansible вызывает вопросы - то, похоже, у Вас не так. Если машины друг с другом не связаны (или вообще не бывают включены одновременно) и при этом запустить простенький VPS, на котором развернуть VPN+Ansible, для Вас по какой-то причине неприемлемо, - то да, получится та же синхронизация через Git или облачное хранилище, только уже не самих конфигов, а плейбуков и шаблонов Ansible, по экземпляру которого будет на каждой из синхронизируемых машин. Не самое изящное решение, соглашусь.
cypa
ansible весьма сложный, а главное не понятно зачем изобретены все эти новые конструкции со своим особым синтаксисом и неповторимой логикой