holo-files - Holo plugin to provision files
When using Holo, configuration is usually stored in system packages, so files can be provisioned by just including them in a configuration package. This plugin extends this basic capability to allow one package (a configuration package) to overwrite or modify a file that has been installed by another package (an application package).
Configuration packages that want to use this plugin must place files in the resource directory at /usr/share/holo/files. Each resource file works on a certain target, as determined by its file name:
/usr/share/holo/files/20-webserver/etc/nginx/nginx.conf
\__________/\___________________/
| |
| `-- path to target
|
`-- disambiguator
The disambiguator is always required, and allows multiple resource files to operate on the same target (sorted alphabetically by their disambiguator). The pattern of putting a number at the start of the disambiguator is not required, but useful to control the ordering of resource files.
Each target file that has such resource files is an entity within Holo. Its entity ID is file:$target
where $target
is the absolute path to the target file.
Resource files are applied on the target base, the initial version of the target file that was found during the first holo apply
run. This target base is saved at /var/lib/holo/files/base/$target.
Resource files that are plain files or symlinks will just overwrite the target base (or all previous entries), whereas executable resource files with an extra .holoscript
suffix can be used to modify the target base (or the result of a previous application step). The target contents will be piped through the script. This is typically used when the default configuration for an application shall be used, but with some minor modifications. The following example uses the default configuration for pacman(8), but enables the "Color" and "TotalDownload" options:
$ cat /usr/share/holo/files/20-enable-color/etc/pacman.conf.holoscript
#!/bin/sh
sed 's/^#\s*Color$/Color/; s/^#\s*TotalDownload$/TotalDownload/'
$ sudo holo apply file:/etc/pacman.conf
Working on file:/etc/pacman.conf
store at /var/lib/holo/files/base/etc/pacman.conf
passthru /usr/share/holo/files/20-enable-color/etc/pacman.conf.holoscript
When writing the new target file, ownership and permissions will be copied from the target base, and thus from the original target file. Furthermore, a copy of the provisioned target file is written to /var/lib/holo/files/provisioned/$target for use by holo diff file:$target
.
In normal operation, holo-files will refuse to operate on a target file that has been modified or deleted by the user or by another program. Apply --force
to reset the target file to its defined state.
Each target file is originally installed by an application package. When that application package is upgraded, system package managers usually detect that the file has been modified, and store the new version contained in the application package next to the target file, in paths such as
$target.rpmnew # for RPM (Fedora, Mageia, openSUSE etc.)
$target.dpkg-dist # for dpkg (Debian, Ubuntu etc.)
$target.pacnew # for pacman (Arch Linux etc.)
$target.apk-new # for APK (Alpine Linux etc.)
When this happens, the next holo apply
run will detect this file and update its target base with this file:
$ sudo pacman -Syu
...
installing pacman ...
warning: /etc/pacman.conf installed as /etc/pacman.conf.pacnew
...
$ sudo holo apply file:/etc/pacman.conf
Working on file:/etc/pacman.conf
store at /var/lib/holo/files/base/etc/pacman.conf
passthru /usr/share/holo/files/20-enable-color/etc/pacman.conf.holoscript
>> found updated target base: /etc/pacman.conf.pacnew -> /var/lib/holo/files/base/etc/pacman.conf
(Unless disabled, it would not normally be nescessary to manually run sudo holo apply
in the above example, as holo-files provides a pacman hook that causes pacman to automatically call holo apply
to handle .pacnew
files. This is not (yet) true for other package managers.)
This means that when configuration is applied as a holoscript on top of the default configuration, future updates to the default configuration will automatically be picked up, as long as holo apply
is run after the system update.
When detecting these files, to know which suffixes to look for, holo-files inspects ID
and ID_LIKE
in os-release(5) to determine which family the operating system belongs to, and thus which package manager is used. It currently recognizes alpine
, arch
, debian
, fedora
and suse
.
If there exist target bases below /var/lib/holo/files for which there are no corresponding resource files below /usr/share/holo/files, these target bases are considered orphaned.
This usually occurs because a package has been removed from the system, or because a different package version were installed that do not contain the resource files in question anymore.
There are two subcases to consider, if only configuration packages were deleted, holo apply
will restore the target base (as installed by the application package):
Scrubbing file:/etc/resourcefile-deleted.conf (all repository files were deleted)
restore /var/lib/holo/files/base/etc/resourcefile-deleted.conf
If the application package (to whom the target file belongs) has also been deleted, the target base will be deleted instead of restored:
Scrubbing file:/etc/targetfile-deleted.conf (target was deleted)
delete /var/lib/holo/files/base/etc/targetfile-deleted.conf
This algorithm ensures that after any number of package installation and removal operations, a single holo apply
will converge all old and new target files to the desired state.
holo apply
will refuse to work on target files that have been modified by the user or another program, unless --force
is given:
$ sudo rm /etc/pacman.conf
$ sudo vim /etc/ssh/sshd_config
...
$ sudo holo apply
Working on file:/etc/pacman.conf
store at /var/lib/holo/files/base/etc/pacman.conf
apply /usr/share/holo/files/01-base/etc/pacman.conf
!! skipping target: file has been deleted by user (use --force to restore)
Working on file:/etc/ssh/sshd_config
store at /var/lib/holo/files/base/etc/ssh/sshd_config
apply /usr/share/holo/files/10-openssh/etc/ssh/sshd_config
!! skipping target: file has been modified by user (use --force to restore)
The holo diff
command can be used to produce a diff between the last provisioned and the current state of the target files. holo apply --force
can be used to reset the target files to their defined state.
holo(8) provides the user interface for using this plugin.
Stefan Majewsky
Further documentation is available at the project homepage: https://holocm.org
Please report any issues and feature requests at GitHub: https://github.com/holocm/holo/issues