feat: Add Chezmoi module (#215)
* build: Added cosign.pub * Feat: Add chezmoi module * Excaped characters making build fail * Switch ` for ' * Fixed syntax issues * Fixed bash syntax and systemctl parameters * Update modules/chezmoi/module.yml to correct README url Co-authored-by: Gerald Pinder <gmpinder@gmail.com> * Used -z instead of `! -n` * Fixed default settings * Made script more verbose to ease debugging * Fixed wrong default values * Changed output to be more meaningful for the end user, instead of the developer. * Added debugging function * Rename `install` > `install_chezmoi`, imrpove docs Gave `install` a clearer name. Added information to docs and improved readability. * Fixed conditional check for set variable * Removed unneeded commands and updated output. * Change to official public key * Fixed invalid systemd targets * Fix chezmoi dir being created but not populated ~/.local/share/chezmoi is created before this service runs, failing `ConditionPathExists=!%h/.local/share/chezmoi`. `.git` only exists if a repository has been cloned there. * Made variable naming conform to project style * fix: Redo suggested commits I accidently overwrote some commits. * docs: Explain what lingering does * docs: fix typo in shortdesc (oops my fault) --------- Co-authored-by: Gerald Pinder <gmpinder@gmail.com> Co-authored-by: xyny <60004820+xynydev@users.noreply.github.com>
This commit is contained in:
parent
3a33f7706b
commit
824fa565e5
3 changed files with 241 additions and 0 deletions
67
modules/chezmoi/README.md
Normal file
67
modules/chezmoi/README.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# `chezmoi`
|
||||
|
||||
The `chezmoi` module takes care of installing, initializing and updating you dotfiles.
|
||||
Each feature can be enabled or disabled individually.
|
||||
|
||||
Installation of the `chezmoi` binary happens at build time and is done by downloading the `amd64` binary from the latest release to `/usr/bin/chezmoi`.
|
||||
This can be disabled by setting `install` to false. (defaults: true)
|
||||
|
||||
A systemd user service is installed that will initialize a `chezmoi` repository on chezmoi's default path (`~/.local/share/chezmoi`) for any user when it logs in, or at boot if it has lingering enabled.
|
||||
The service will only run if `~/.local/share/chezmoi` does not exist.
|
||||
Set `repository` to the URL of your dotfiles repository. (eg. `repository: https://example.org/user/dotfiles`)
|
||||
:::note
|
||||
The value of `repository` will be passed directly to `chezmoi init --apply ${repository}`.
|
||||
See the [`chezmoi init` documenation](https://www.chezmoi.io/reference/commands/init/) for detailed syntax.
|
||||
:::
|
||||
Set `disable_init` to `true` if you do not want to install the init service.
|
||||
|
||||
:::caution
|
||||
If `repository` is not set, and `disable_init` is false the module will fail, due to not being able to initialize the repository.
|
||||
:::
|
||||
|
||||
Set `enable_all_users` to `false` if you want to install the update and initialization services, but do not want them enabled for all users.
|
||||
You can enable them manually instead when the system has been installed:
|
||||
|
||||
To enable the services for a single user, run the following command as that user:
|
||||
|
||||
```bash
|
||||
systemctl enable --user chezmoi-init.service chezmoi-update.timer`
|
||||
```
|
||||
|
||||
To manually enable the services for all users, run the following command with sudo:
|
||||
|
||||
```bash
|
||||
sudo systemctl enable --user chesmoi-init.service chezmoi-update.timer
|
||||
```
|
||||
|
||||
To turn on lingering for a given user, run the following commmand with sudo:
|
||||
|
||||
:::note
|
||||
By default, any systemd units in a user's namespace will run after the user logs in, and will close after the user closes their last session.
|
||||
When you enable lingering for a user, that user's units will run at boot and will continue running even if the user has no active sessions.
|
||||
|
||||
If your dotfiles only contain things used by humans, such as cosmetic settings and aliases, you shouldn't need this.
|
||||
If you understand the above implications, and decide you need this feature, you can enable it with the following command, after installation:
|
||||
:::
|
||||
|
||||
```bash
|
||||
sudo loginctl enable-linger <username>`
|
||||
```
|
||||
|
||||
You can configure the interval between updates of your dotfiles by setting the value of `run_every`.
|
||||
The string is passed directly to OnUnitInactiveSec. (default: '1d')
|
||||
See [`systemd.time` documenation](https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html) for detailed syntax.
|
||||
Examples: '1d' (1 day - default), '6h' (6 hours), '10m' (10 minutes)
|
||||
|
||||
Likewise, `wait_after_boot` configures the delay between the system booting and the update service starting.
|
||||
This follows the same syntax as `run_every`. (default: '5m')
|
||||
|
||||
The installation of the initialization service and the update service can be disabled separately by setting `disable_init` and/or `disable_update` to `true`. (Both default: false)
|
||||
|
||||
:::caution
|
||||
Note that this will skip the installation of the services completely. If you want them installed but disabled, see `enable_all_users` instead.
|
||||
:::
|
||||
|
||||
## Development
|
||||
|
||||
Setting `DEBUG=true` inside `chezmoi.sh` will enable additional output in bash useful for debugging.
|
||||
155
modules/chezmoi/chezmoi.sh
Normal file
155
modules/chezmoi/chezmoi.sh
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# Tell build process to exit if there are any errors.
|
||||
set -euo pipefail
|
||||
|
||||
# '-I=0' makes sure the output isn't indented
|
||||
|
||||
# Activates debugging output. This should only be true if you changed it yourself.
|
||||
# -v = Verbose output. Outputs every line before executing.
|
||||
# -u = Treat unset variables as errors. Useful for spotting typos.
|
||||
# -x = Show expanded input for conditional statements.
|
||||
DEBUG=false
|
||||
if [[ $DEBUG ]]; then
|
||||
echo "Running in debug mode. If you didn't enable this yourself, this is a bug."
|
||||
set -vux
|
||||
fi
|
||||
|
||||
# If true, downloads the chezmoi binary from the latest Github release and moves it to /usr/bin/. (default: true)
|
||||
INSTALL_CHEZMOI=$(echo "$1" | yq -I=0 ".install-chezmoi") # (boolean)
|
||||
if [[ -z $INSTALL_CHEZMOI || $INSTALL_CHEZMOI == "null" ]]; then
|
||||
INSTALL_CHEZMOI=true
|
||||
fi
|
||||
|
||||
# The repository with your chezmoi dotfiles. (default: null)
|
||||
DOTFILE_REPOSITORY=$(echo "$1" | yq -I=0 ".repository") # (string)
|
||||
|
||||
# If true, chezmoi services will be enabled for all logged in users, and users with lingering enabled. (default: true)
|
||||
# If false, chezmoi services will not be enabled for any users, but can be enabled manually, after installation.
|
||||
#
|
||||
# To enable the services for a single user, run the following command as that user:
|
||||
# 'systemctl enable --user chezmoi-init.service chezmoi-update.timer'
|
||||
#
|
||||
# To manually enable the services for all users, run the following command with sudo:
|
||||
# 'sudo systemctl enable --user chesmoi-init.service chezmoi-update.timer'
|
||||
#
|
||||
# To turn on lingering for a given user, run the following commmand with sudo:
|
||||
# 'sudo loginctl enable-linger <username>'
|
||||
ENABLE_ALL_USERS=$(echo "$1" | yq -I=0 ".enable-all-users") # (boolean)
|
||||
if [[ -z $ENABLE_ALL_USERS || $ENABLE_ALL_USERS == "null" ]]; then
|
||||
ENABLE_ALL_USERS=true
|
||||
fi
|
||||
|
||||
# chezmoi-update.service will run with this interval
|
||||
# This string is passed on directly to systemd's OnUnitInactiveSec. Complete syntax is described here:
|
||||
# https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html#
|
||||
# Examples: '1d' (1 day - default), '6h' (6 hours), '10m' (10 minutes)
|
||||
RUN_EVERY=$(echo "$1" | yq -I=0 ".run-every") # (string)
|
||||
if [[ -z $RUN_EVERY || $RUN_EVERY == "null" ]]; then
|
||||
RUN_EVERY="1d"
|
||||
fi
|
||||
# chezmoi-update.service will also run this much time after the system has booted.
|
||||
# Same syntax as RUN_EVERY (default: '5m')
|
||||
WAIT_AFTER_BOOT=$(echo "$1" | yq -I=0 ".wait-after-boot") # (string)
|
||||
if [[ -z $WAIT_AFTER_BOOT || $WAIT_AFTER_BOOT == "null" ]]; then
|
||||
WAIT_AFTER_BOOT="5m"
|
||||
fi
|
||||
|
||||
# If true, disables automatic initialization of chezmoi if no dotfile directory is found. (default: false)
|
||||
DISABLE_INIT=$(echo "$1" | yq -I=0 ".disable-init") # (boolean)
|
||||
if [[ -z $DISABLE_INIT || $DISABLE_INIT == "null" ]]; then
|
||||
DISABLE_INIT=false
|
||||
fi
|
||||
# If true, disables automatic activation of 'chezmoi-update.timer'. (default: false)
|
||||
DISABLE_UPDATE=$(echo "$1" | yq -I=0 ".disable-update") # (boolean)
|
||||
if [[ -z $DISABLE_UPDATE || $DISABLE_UPDATE == "null" ]]; then
|
||||
DISABLE_UPDATE=false
|
||||
fi
|
||||
|
||||
echo "Checking for conflicting arguments"
|
||||
if [[ (-z $DOTFILE_REPOSITORY || $DOTFILE_REPOSITORY == "null") && $DISABLE_INIT == false ]]; then
|
||||
echo "ERROR: Invalid Config: 'repository' is not set, but initialization is not disabled."
|
||||
echo "Set a value for 'repository' or set 'disable_update' to true, if you do not wish to initialize a chezmoi directory using this module"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $INSTALL_CHEZMOI == true ]]; then
|
||||
echo "Checking if curl is installed and executable at /usr/bin/curl"
|
||||
if [ -x /usr/bin/curl ]; then
|
||||
echo "Downloading chezmoi binary from the latest Github release"
|
||||
/usr/bin/curl -Ls https://github.com/twpayne/chezmoi/releases/latest/download/chezmoi-linux-amd64 -o /usr/bin/chezmoi
|
||||
echo "Ensuring chezmoi is executable"
|
||||
/usr/bin/chmod 755 /usr/bin/chezmoi
|
||||
else
|
||||
echo "ERROR: curl could not be found in /usr/bin/."
|
||||
echo "Please make sure curl is installed on the system you are building your image."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping install of chezmoi binary"
|
||||
fi
|
||||
|
||||
if [[ $DISABLE_INIT == false ]]; then
|
||||
# Write the service to initialize Chezmoi, and insert the repo url in the file
|
||||
echo "Writing init service to user unit directory"
|
||||
cat >>/usr/lib/systemd/user/chezmoi-init.service <<EOF
|
||||
[Unit]
|
||||
Description=Initializes Chezmoi if directory is missing
|
||||
|
||||
# This service will not execute for a user with an existing chezmoi directory
|
||||
ConditionPathExists=!%h/.local/share/chezmoi/.git/
|
||||
[Service]
|
||||
ExecStart=/usr/bin/chezmoi init --apply ${DOTFILE_REPOSITORY}
|
||||
Type=oneshot
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
EOF
|
||||
else
|
||||
echo "Skipping install of chezmoi-init.service"
|
||||
fi
|
||||
|
||||
if [[ $DISABLE_UPDATE == false ]]; then
|
||||
# Write the service and timer to update chezmoi for all logged in users and users with lingering enabled
|
||||
echo "Writing update service to user unit directory"
|
||||
cat >>/usr/lib/systemd/user/chezmoi-update.service <<EOF
|
||||
[Unit]
|
||||
Description=Chezmoi Update
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/chezmoi update
|
||||
Type=oneshot
|
||||
EOF
|
||||
|
||||
echo "Writing update timer to user unit directory"
|
||||
cat >>/usr/lib/systemd/user/chezmoi-update.timer <<EOF
|
||||
[Unit]
|
||||
Description=Timer for Chezmoi Update
|
||||
# This service will only execute for a user with an existing chezmoi directory
|
||||
ConditionPathExists=%h/.local/share/chezmoi
|
||||
|
||||
[Timer]
|
||||
OnBootSec=${WAIT_AFTER_BOOT}
|
||||
OnUnitInactiveSec=${RUN_EVERY}
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
EOF
|
||||
else
|
||||
echo "Skipping install of chezmoi-update.service"
|
||||
fi
|
||||
|
||||
# Enable services
|
||||
echo "Checking which services to enable"
|
||||
if [[ $ENABLE_ALL_USERS == true && $DISABLE_INIT == false && $DISABLE_UPDATE == false ]]; then
|
||||
echo "Enabling init timer and update service"
|
||||
systemctl --global enable chezmoi-init.service chezmoi-update.timer
|
||||
elif [[ $ENABLE_ALL_USERS == true && $DISABLE_INIT == true && $DISABLE_UPDATE == false ]]; then
|
||||
echo "Enabling update timer"
|
||||
systemctl --global enable chezmoi-update.timer
|
||||
elif [[ $ENABLE_ALL_USERS == true && $DISABLE_INIT == false && $DISABLE_UPDATE == true ]]; then
|
||||
echo "Enabling init service"
|
||||
systemctl --global enable chezmoi-init.service
|
||||
else
|
||||
echo "No services were enabled"
|
||||
fi
|
||||
19
modules/chezmoi/module.yml
Normal file
19
modules/chezmoi/module.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
name: chezmoi
|
||||
shortdesc: The chezmoi module installs the latest chezmoi release at build time, along with services to clone a dotfile repository and keep it up-to-date.
|
||||
readme: https://raw.githubusercontent.com/blue-build/modules/main/modules/chezmoi/README.md
|
||||
example: |
|
||||
type: chezmoi
|
||||
# Installs chezmoi to /usr/bin/chezmoi from latest Github release
|
||||
install_chezmoi: true # Optional - Default: true - Expects type: boolean
|
||||
# () Git repository to initialize
|
||||
repository: "https://example.org/user/dotfiles" # Required - Default: n/a - Expects type: string
|
||||
# Enable the modules services globally for all users
|
||||
enable_all_users: true # Optional - Default: true - Expects type: boolean
|
||||
# Dotfiles will be updated with this interval
|
||||
run_every: '1d' # Optional - Default: '1d' - Expects type: string
|
||||
# Dotfile updates will wait this long after a boot before running
|
||||
wait_after_boot: '5m' # Optional - Default: '5m' - Expects type: string
|
||||
# Disable the service that initializes `repository` on users that are logged in or has linger enabled
|
||||
disable_init: false # Optional - Default: false - Expects type: boolean
|
||||
# Disable the timer that updates chezmoi with the interval set above
|
||||
disable_update: false # Optional - Default: false - Expects type: boolean
|
||||
Loading…
Add table
Add a link
Reference in a new issue