mirror of https://github.com/rapenne-s/bento
Compare commits
27 Commits
Author | SHA1 | Date |
---|---|---|
Solène Rapenne | 6418bd64ec | |
Solène Rapenne | 05c95104a9 | |
Solène Rapenne | 98361e3555 | |
Solène Rapenne | 189d476424 | |
Solène Rapenne | 6c9ae97537 | |
Markus Wamser | 428bd2d374 | |
Markus Wamser | 56b269cc5c | |
Solène Rapenne | 33fc1e2772 | |
Florian Brandes | 3e7125d32e | |
Solène Rapenne | f85a445532 | |
Bastien | b844a0b203 | |
Solène Rapenne | 220b3de622 | |
Florian Brandes | fcefd9e815 | |
Florian Brandes | 6ec3dd7b4e | |
Solene Rapenne | d8c28c8ebd | |
Solene Rapenne | 88f124b5b1 | |
Solene Rapenne | 018880d464 | |
Solene Rapenne | dbfd792609 | |
Solene Rapenne | be3183d764 | |
Solene Rapenne | 171e9cfe17 | |
Solene Rapenne | fcb949881a | |
Solene Rapenne | 2392b7720f | |
Solene Rapenne | a8ab5c476d | |
Solene Rapenne | ba692bbf34 | |
Solene Rapenne | 6b0eecb7f3 | |
Solene Rapenne | 80c0de326b | |
Solene Rapenne | 9223913444 |
19
README.md
19
README.md
|
@ -27,7 +27,7 @@ Bento has a different approach with a "pull" model:
|
|||
- organized 💼: system administrators have all configurations files in one repository to ease management
|
||||
- peace of mind 🧘🏿: configurations can be validated locally by system administrators
|
||||
- smart 💡: secrets (arbitrary files) can (soon) be deployed without storing them in the nix store
|
||||
- robustness in mind 🦾: clients ony need to connect to a remote ssh server, there are many ways to bypass firewalls (corkscrew, VPN, Tor hidden service, I2P, ...)
|
||||
- robustness in mind 🦾: clients only need to connect to a remote ssh server, there are many ways to bypass firewalls (corkscrew, VPN, Tor hidden service, I2P, ...)
|
||||
- extensible 🧰 🪡: you can change every component, if you prefer using GitHub repositories to fetch configuration files instead of a remote sftp server, you can change it
|
||||
- for all NixOS 💻🏭📱: it can be used for anything running NixOS: remote workstations, smartphones or servers in a datacenter
|
||||
|
||||
|
@ -35,7 +35,9 @@ Bento has a different approach with a "pull" model:
|
|||
|
||||
This setup need a machine to be online most of the time. NixOS systems (clients) will regularly check for updates on this machine over ssh.
|
||||
|
||||
**Bentoo** doesn't necesserarily require a public IP, don't worry, you can use tor hidden service, i2p tunnels, a VPN or whatever floats your boat given it permit to connect to ssh.
|
||||
**Bento** doesn't necesserarily require a public IP, don't worry, you can use tor hidden service, i2p tunnels, a VPN or whatever floats your boat given it permit to connect to ssh.
|
||||
|
||||
**Bento** will use `nvd` instead of `nix store diff-closures` if it's available in the `$PATH`.
|
||||
|
||||
# How it works
|
||||
|
||||
|
@ -64,24 +66,15 @@ There is a diagram showing the design pattern of **bento**:
|
|||
|
||||
## Major priority
|
||||
|
||||
- DONE ~~client should report their current version after an upgrade, we should be able to compute the same value from the config on the server side, this would allow to check if a client is correctly up to date~~
|
||||
- being able to create a podman compatible NixOS image that would be used as the chroot server, to avoid reconfiguring the host and use sudo to distribute files
|
||||
- DONE ~~auto rollback like "magicrollback" by deploy-rs in case of losing connectivity after an upgrade~~
|
||||
- DONE ~~`local_build.sh` and `populate_chroot` should be only one command installed in `$PATH`~~
|
||||
- DONE ~~upgrades could be triggered by the user by accessing a local socket, like opening a web page in a web browser to trigger it, if it returns output that'd be better~~
|
||||
- a way to tell a client (when using flakes) to try to update flakes every time even if no configuration changed, to keep them up to date
|
||||
- DONE ~~being able to use a single flakes with multiple hosts that **bento** will automatically assign to the nixosConfiguration names as hosts~~
|
||||
- DONE ~~handle automatic reboot if the kernel changed~~
|
||||
- automatic reboot should be scheduled if desired, this may require making bento a NixOS module to set a timer in it, if no timer then it would reboot immediately
|
||||
- being able to create a NixOS rootless container that would be used as the chroot server, to avoid reconfiguring the host and use sudo to distribute files
|
||||
- a way to allow remote client to update their flakes lock file every time even if no configuration changed, this would be useful to let them stay up to date
|
||||
- document config.sh in the reference
|
||||
- figure out how to make a tutorial for bento
|
||||
- DONE ~~sftp timeout should be configurable in `config.sh`~~
|
||||
- `config.sh` should have variables for the local / remote / both `nixos-rebuild` parameters (useful for `--fallback`)
|
||||
|
||||
## Minor
|
||||
|
||||
- a systray info widget could tell the user an upgrade has been done
|
||||
- DONE ~~updates should add a log file in the sftp chroot if successful or not~~
|
||||
- the sftp server could be on another server than the one with the configuration files
|
||||
- provide more useful modules in the utility nix file (automatically use the host as a binary cache for instance)
|
||||
- have a local information how to ssh to the client to ease the rebuild trigger (like a SSH file containing ssh command line)
|
||||
|
|
104
bento
104
bento
|
@ -1,11 +1,13 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
TIMEOUT=20
|
||||
REMOTE_PORT=22
|
||||
NOLOCALBUILD=0
|
||||
|
||||
# FUNCTION LIBRARIES
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: bento init | deploy | diff | build [dry-run|test|switch] | status [delay] | flake-update [input]
|
||||
usage: bento init | deploy | diff | build [dry-run|test|switch] | status | flake-update [input]
|
||||
|
||||
bento init
|
||||
: create the layout for bento in the current directory
|
||||
|
@ -19,8 +21,10 @@ bento diff
|
|||
bento build [dry-run|test|switch]
|
||||
: build configurations, can activate (test or switch) a build locally
|
||||
|
||||
bento status [delay]
|
||||
bento status
|
||||
: display information for remote hosts
|
||||
: if the script isn't run in an interactive terminal, exit after display
|
||||
: in an interactive terminal, display status and poll for changes to display again
|
||||
|
||||
bento flake-update [input]
|
||||
: recursively update flakes lock files
|
||||
|
@ -52,7 +56,6 @@ version_diff() {
|
|||
do
|
||||
test -d "${i}" || continue
|
||||
|
||||
# date calculation
|
||||
LASTLOG=$(find "${i}/logs/" -type f | sort -n | tail -n 1)
|
||||
LASTLOGVERSION="$(basename "$LASTLOG" | awk -F '_' '{ print $2 }' )"
|
||||
EXPECTED_CONFIG="$(awk -F '=' -v host="${i}" 'host == $1 { print $2 }' states.txt)"
|
||||
|
@ -65,7 +68,14 @@ version_diff() {
|
|||
if [ ! "${LASTLOGVERSION}" = "${EXPECTED_CONFIG}" ]
|
||||
then
|
||||
echo "Changes in $i between ${LASTLOGVERSION} and ${EXPECTED_CONFIG}"
|
||||
nix store diff-closures "/nix/store/${LASTLOGVERSION}" "/nix/store/${EXPECTED_CONFIG}"
|
||||
|
||||
# better output if nvd is available
|
||||
if type nvd 2>/dev/null >/dev/null
|
||||
then
|
||||
nvd diff "/nix/store/${LASTLOGVERSION}" "/nix/store/${EXPECTED_CONFIG}"
|
||||
else
|
||||
nix store diff-closures "/nix/store/${LASTLOGVERSION}" "/nix/store/${EXPECTED_CONFIG}"
|
||||
fi
|
||||
else
|
||||
echo "$i is running the latest version"
|
||||
fi
|
||||
|
@ -228,14 +238,14 @@ cd /var/bento || exit 5
|
|||
touch .state
|
||||
|
||||
# don't get stuck if we change the host
|
||||
ssh-keygen -F "${REMOTE_IP}" >/dev/null || ssh-keyscan "${REMOTE_IP}" >> /root/.ssh/known_hosts
|
||||
ssh-keygen -F "${REMOTE_IP}" >/dev/null || ssh-keyscan -p "${REMOTE_PORT}" "${REMOTE_IP}" >> /root/.ssh/known_hosts
|
||||
|
||||
STATEFILE="\$(mktemp /tmp/bento-state.XXXXXXXXXXXXXXXX)"
|
||||
echo "ls -l last_change_date" | sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP} >"\${STATEFILE}"
|
||||
echo "ls -l last_change_date" | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP} >"\${STATEFILE}"
|
||||
|
||||
if [ "\$?" -ne 0 ]
|
||||
then
|
||||
echo "There is certainly a network problem with ${REMOTE_IP}"
|
||||
echo "There is certainly a network problem with ${REMOTE_IP} on port ${REMOTE_PORT}"
|
||||
echo "Aborting"
|
||||
rm "\${STATEFILE}"
|
||||
exit 1
|
||||
|
@ -261,7 +271,7 @@ then
|
|||
fi
|
||||
else
|
||||
echo "update required"
|
||||
sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP}:/config/bootstrap.sh .
|
||||
sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP}:/config/bootstrap.sh .
|
||||
/bin/sh bootstrap.sh
|
||||
echo "\${STATE}" > "/var/bento/.state"
|
||||
fi
|
||||
|
@ -274,7 +284,7 @@ EOF
|
|||
#!/bin/sh
|
||||
|
||||
# accept the remote ssh fingerprint if not already known
|
||||
ssh-keygen -F "${REMOTE_IP}" >/dev/null || ssh-keyscan "${REMOTE_IP}" >> /root/.ssh/known_hosts
|
||||
ssh-keygen -F "${REMOTE_IP}" >/dev/null || ssh-keyscan -p "${REMOTE_PORT}" "${REMOTE_IP}" >> /root/.ssh/known_hosts
|
||||
|
||||
install -d -o root -g root -m 700 /var/bento
|
||||
cd /var/bento || exit 5
|
||||
|
@ -286,7 +296,7 @@ then
|
|||
find . -maxdepth 1 -type d -exec rm -fr {} \;
|
||||
find . -maxdepth 1 -type f -not -name .state -and -not -name update.sh -and -not -name bootstrap.sh -exec rm {} \;
|
||||
|
||||
printf "%s\n" "cd config" "get -R ." | sftp -oConnectTimeout="${TIMEOUT}" -r ${dest}@${REMOTE_IP}:
|
||||
printf "%s\n" "cd config" "get -R ." | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" -r ${dest}@${REMOTE_IP}:
|
||||
|
||||
# required by flakes
|
||||
test -d .git || git init
|
||||
|
@ -351,7 +361,7 @@ fi
|
|||
|
||||
# rollback if something is wrong
|
||||
# we test connection to the sftp server
|
||||
echo "ls -l last_change_date" | sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP} >"\${LOGFILE}"
|
||||
echo "ls -l last_change_date" | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP} >"\${LOGFILE}"
|
||||
if [ "\$?" -ne 0 ];
|
||||
then
|
||||
nixos-rebuild --rollback switch
|
||||
|
@ -364,9 +374,9 @@ if [ "\$SUCCESS" -eq 0 ]
|
|||
then
|
||||
if [ "\$autoupdate" -eq 1 ]
|
||||
then
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_autoupdate.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_autoupdate.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP}:
|
||||
else
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_success.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_success.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP}:
|
||||
fi
|
||||
|
||||
# handle auto reboot if kernel changed
|
||||
|
@ -384,9 +394,9 @@ else
|
|||
# check if we did a rollback
|
||||
if [ "\$SUCCESS" -eq 255 ]
|
||||
then
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_rollback.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_rollback.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP}:
|
||||
else
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_failure.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" ${dest}@${REMOTE_IP}:
|
||||
echo "put \${LOGFILE}.gz /logs/\$(date +%Y%m%d-%H%M)_\${OSVERSION}_failure.log.gz" | sftp -oConnectTimeout="${TIMEOUT}" -P "${REMOTE_PORT}" ${dest}@${REMOTE_IP}:
|
||||
fi
|
||||
fi
|
||||
rm "\${LOGFILE}.gz"
|
||||
|
@ -420,6 +430,12 @@ build_config()
|
|||
TMPLOG="$(mktemp /tmp/bento-build-log.XXXXXXXXXXXX)"
|
||||
rsync -rltgoDL "$SOURCES/" "$TMP/"
|
||||
|
||||
PARAMS=""
|
||||
if [ -n "$TARGET_IP" ]
|
||||
then
|
||||
PARAMS="--use-remote-sudo --target-host $TARGET_IP"
|
||||
fi
|
||||
|
||||
if [ -z "VERBOSE" ]
|
||||
then
|
||||
output="/dev/null"
|
||||
|
@ -438,9 +454,9 @@ build_config()
|
|||
test -d .git || git init >/dev/null 2>/dev/null
|
||||
git add . >/dev/null
|
||||
|
||||
$SUDO nixos-rebuild "${COMMAND}" --flake ".#${NAME}" | tee "${output}" 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
$SUDO env NIX_SSHOPTS=$NIX_SSHOPTS nixos-rebuild ${PARAMS} "${COMMAND}" --flake ".#${NAME}" | tee "${output}" 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
else
|
||||
$SUDO nixos-rebuild "${COMMAND}" --no-flake -I nixos-config="$TMP/configuration.nix" | tee "${output}" 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
$SUDO env NIX_SSHOPTS=$NIX_SSHOPTS nixos-rebuild ${PARAMS} "${COMMAND}" --no-flake -I nixos-config="$TMP/configuration.nix" | tee "${output}" 2>"${TMPLOG}" >"${TMPLOG}"
|
||||
fi
|
||||
if [ $? -eq 0 ]; then printf "success " ; else printf "failure " ; BAD_HOSTS="${NAME} ${BAD_HOSTS}" ; SUCCESS=$(( SUCCESS + 1 )) ; cat "${TMPLOG}" ; fi
|
||||
ELAPSED=$(elapsed_time $SECONDS)
|
||||
|
@ -509,12 +525,16 @@ deploy_files() {
|
|||
# only distribute changes if they changed
|
||||
# this avoids bumping the time and trigger a rebuild for nothing
|
||||
|
||||
diff -r "${STAGING_DIR}/${dest}/config/" "${CHROOT_DIR}/${dest}/config/" >/dev/null
|
||||
diff -r "${STAGING_DIR}/${dest}/config/" "${CHROOT_DIR}/${dest}/config/" >/dev/null 2>/dev/null
|
||||
CHANGES=$?
|
||||
|
||||
if [ "$CHANGES" -ne 0 ]
|
||||
then
|
||||
build_config "${STAGING_DIR}/${dest}/config/" "build" "" "${dest}"
|
||||
if [ $NOLOCALBUILD -eq 1 ]; then
|
||||
build_config "${STAGING_DIR}/${dest}/config/" "dry-build" "" "${dest}"
|
||||
else
|
||||
build_config "${STAGING_DIR}/${dest}/config/" "build" "" "${dest}"
|
||||
fi
|
||||
echo " update required"
|
||||
# copy files in the chroot
|
||||
install -d -o root -g sftp_users -m 755 "${CHROOT_DIR}"
|
||||
|
@ -547,10 +567,12 @@ elapsed_time() {
|
|||
|
||||
SEC=$RAW
|
||||
|
||||
if [ "$DAYS" -ne 0 ]; then DURATION="${DAYS}d " ; fi
|
||||
if [ "$HOURS" -ne 0 ]; then DURATION="${DURATION}${HOURS}h " ; fi
|
||||
if [ "$MINUTES" -ne 0 ]; then DURATION="${DURATION}${MINUTES}m " ; fi
|
||||
if [ "$SEC" -ne 0 ]; then DURATION="${DURATION}${SEC}s" ; fi
|
||||
ELEMENTS=0
|
||||
|
||||
if [ "$DAYS" -ne 0 ]; then DURATION="${DAYS}d " ; ELEMENTS=$(( ELEMENTS + 1 )) ; fi
|
||||
if [ "$HOURS" -ne 0 ]; then DURATION="${DURATION}${HOURS}h " ; ELEMENTS=$(( ELEMENTS + 1 )) ; fi
|
||||
if [ "$ELEMENTS" -lt 2 ] && [ "$MINUTES" -ne 0 ]; then DURATION="${DURATION}${MINUTES}m " ; ELEMENTS=$(( ELEMENTS + 1 )) ; fi
|
||||
if [ "$ELEMENTS" -lt 2 ] && [ "$SEC" -ne 0 ]; then DURATION="${DURATION}${SEC}s" ; fi
|
||||
|
||||
if [ -z "$DURATION" ]; then DURATION="0s" ; fi
|
||||
|
||||
|
@ -607,7 +629,7 @@ else
|
|||
MATCH=$(echo "$FLAKES" | awk -v name="${NAME}" 'BEGIN { sum = 0 } name == $1 { sum=sum+1 } END { print sum }')
|
||||
if [ "$MATCH" -ne 1 ]
|
||||
then
|
||||
echo "Found ${MATCH} system with this name"
|
||||
echo "Found ${MATCH} systems with this name"
|
||||
exit 2
|
||||
else
|
||||
for flakes in $(find . -name flake.nix)
|
||||
|
@ -674,10 +696,24 @@ then
|
|||
test -n "${SINGLE_FLAKE}" && ! [ "$host" = "${SINGLE_FLAKE}" ] && continue
|
||||
printf "%${PRETTY_OUT_COLUMN}s " "${host}"
|
||||
build_config "$i" "$COMMAND" "$SUDO" "$host"
|
||||
|
||||
# if build succeeded and we used TARGET_IP
|
||||
# populate the sftp directory with the new version
|
||||
if [ "$?" -eq 0 ] && [ -n "$TARGET_IP" ]
|
||||
then
|
||||
deploy_files "$i" "${host}" "${host}"
|
||||
fi
|
||||
done
|
||||
else
|
||||
printf "%${PRETTY_OUT_COLUMN}s " "${i}"
|
||||
build_config "$i" "$COMMAND" "$SUDO" "$i"
|
||||
|
||||
# if build succeeded and we used TARGET_IP
|
||||
# populate the sftp directory with the new version
|
||||
if [ "$?" -eq 0 ] && [ -n "$TARGET_IP" ]
|
||||
then
|
||||
deploy_files "$i" "$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
|
@ -708,13 +744,17 @@ then
|
|||
deploy_files "$i" "$i"
|
||||
fi
|
||||
|
||||
# the states files is used for the status function
|
||||
# we need to update it after each rebuild so if a
|
||||
# system updates while other configurations are building
|
||||
# the status will be correct
|
||||
if [ -f ../states.txt ]
|
||||
then
|
||||
cp ../states.txt "${CHROOT_DIR}/states.txt"
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# the states files is used for the status function
|
||||
if [ -f ../states.txt ]
|
||||
then
|
||||
cp ../states.txt "${CHROOT_DIR}/states.txt"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
@ -749,12 +789,14 @@ then
|
|||
. ./config.sh
|
||||
cd hosts || exit 5
|
||||
|
||||
if [ -n "$2" ]
|
||||
# if stdout is interactive
|
||||
# wait for changes and loop
|
||||
if [ -t 1 ]
|
||||
then
|
||||
while true
|
||||
do
|
||||
display_status
|
||||
sleep "$2"
|
||||
inotifywait -q -e 'modify,create' "${CHROOT_DIR}/states.txt" "${CHROOT_DIR}"/*/logs/ >/dev/null 2>/dev/null
|
||||
done
|
||||
else
|
||||
display_status
|
||||
|
|
|
@ -6,3 +6,8 @@ REMOTE_IP=myserver.example
|
|||
# maxium time waiting for the SFTP connection to connect
|
||||
# default value is 20
|
||||
#TIMEOUT=20
|
||||
# port to connect to the remote server
|
||||
# default is 22
|
||||
#REMOTE_PORT=22
|
||||
# don't build locally
|
||||
#NOLOCALBUILD=1
|
||||
|
|
|
@ -57,7 +57,7 @@ Here are the steps to add a server named `kikimora` to bento:
|
|||
1. generate a ssh-key on `kikimora` for root user
|
||||
2. add kikimora's public key to bento `fleet.nix` file
|
||||
3. reconfigure the ssh host to allow kikimora's key (it should include the `fleet.nix` file)
|
||||
4. copy kikimora's config (usually `/etc/nixos/` in bento `hosts/kikimora/` directory
|
||||
4. copy kikimora's config (usually `/etc/nixos/`) in bento `hosts/kikimora/` directory
|
||||
5. add utils/bento.nix to its config (in `hosts/kikimora` run `ln -s ../../utils .` and add `./utils/bento.nix` in `imports` list)
|
||||
6. check kikimora's config locally with `bento build dry-build`, you can check only `kikimora` with `env NAME=kikimora bento build dry-build`
|
||||
7. populate the chroot with `sudo bento deploy` to copy the files in `/home/chroot/kikimora/config/`
|
||||
|
@ -78,7 +78,9 @@ If you don't want to wait for the timer, you can ssh into the machine to run `sy
|
|||
|
||||
As each host is sending a log upon rebuild to tell if it failed or succeeded, the files are used to check what happened since the sftp file `last_time_changed` was created.
|
||||
|
||||
Using `bento status` you can track the current state of each hosts (time since last update, current NixOS version, status report)
|
||||
Using `bento status` you can track the current state of each hosts (time since last update, current NixOS version, status report).
|
||||
|
||||
Bento will display the current state of the fleet, and wait for a change in the chroot directory to display the status again.
|
||||
|
||||
[![asciicast](https://asciinema.org/a/520504.svg)](https://asciinema.org/a/520504)
|
||||
|
||||
|
@ -115,3 +117,17 @@ source: +701.9 KiB
|
|||
systemsettings: +62.6 KiB
|
||||
-------------
|
||||
```
|
||||
|
||||
# Push a configuration to a remote system
|
||||
|
||||
It's possible to use `bento` in a *push* model using `TARGET_IP`:
|
||||
|
||||
```
|
||||
env TARGET_IP=10.43.43.1 NAME=myserver bento build switch
|
||||
```
|
||||
|
||||
If the remote system is using a non-standard port, you need to define the according ssh option with `NIX_SSHOPTS`:
|
||||
|
||||
```
|
||||
env NIX_SSHOPTS="-p2222" TARGET_IP=10.43.43.1 NAME=laptop bento build switch
|
||||
```
|
||||
|
|
|
@ -11,9 +11,12 @@
|
|||
|
||||
- `bento build [dry-run|build|test|switch]`
|
||||
- dry-build or build configurations. Using `test` or `switch`, can be used to apply a configuration locally. Default is `build`.
|
||||
- when using `TARGET_IP`, the command is run on a remote server
|
||||
|
||||
- `bento status [delay]`
|
||||
- display information for remote hosts, if `delay` is set, loop infinitely to display the status every `delay` seconds. Default delay is `0` and doesn't loop.
|
||||
- `bento status`
|
||||
- display information for remote hosts
|
||||
- if the command is run in interactive mode, `bento` will run in an inifite loop the status display and wait for a change in the chroot directory
|
||||
- if the command isn't run in interactive mode, the status is only displayed once and `bento` exits
|
||||
|
||||
- `bento flake-update [input]`
|
||||
- recursively update flakes lock files
|
||||
|
@ -28,6 +31,7 @@ A local file `config.sh` is required for Bento, it contains variable used to gen
|
|||
|
||||
- `CHROOT_DIR`: the directory in which the SFTP server will be configured to serve files from
|
||||
- `REMOTE_IP`: the IP address or hostname used by SFTP client to reach the server with the configuration files
|
||||
- `REMOTE_PORT`: the port of the IP address or hostname used by SFTP client to reach the server with the configuration files. Defaults to 22.
|
||||
- `TIMEOUT`: time in seconds to wait until aborting when connecting to the SFTP server. Default value is `20` seconds.
|
||||
|
||||
# Environment variables
|
||||
|
@ -36,6 +40,8 @@ A local file `config.sh` is required for Bento, it contains variable used to gen
|
|||
- `BENTO_DIR`: contains the path of a bento directory, so you can run `bento` commands from anywhere
|
||||
- `NAME`: contains machine names (flake config or directory in `hosts/`) to restrict commands `deploy`, `diff` and `build` to this machine only
|
||||
- `VERBOSE`: if defined to anything, display `nixos-rebuild` output for local builds done with `bento build` or `bento deploy`
|
||||
- `TARGET_IP`: can be used to push a configuration closure to a remote system, it's wrapping `nixos-rebuild`. Only work with `bento build [switch|test]`.
|
||||
- `NIX_SSHOPTS`: parameters for ssh to be used when `TARGET_IP` is used. Example: `NIX_SSHOPTS=-p2222` to use port 2222 instead of the standard port 22.
|
||||
|
||||
# Self update mode
|
||||
|
||||
|
@ -49,7 +55,9 @@ This adds at least 8 kB of inbound bandwidth for each input when checking for ch
|
|||
|
||||
# Auto reboot
|
||||
|
||||
You can create a file named `REBOOT` in a host directory. When that host will rebuild the system, it will look at the new kernel, kernel modules and initrd, if they changed, a reboot will occur immediately after reporting a successful upgrade. A kexec is used for UEFI systems for a faster reboot (this avoids BIOS and bootloader steps).
|
||||
You can create a file named `REBOOT` in a host directory. When that host will rebuild the system, it will look at the new kernel, kernel modules and initrd, if they changed, a reboot will occur immediately after reporting a successful upgrade. A kexec is used for UEFI systems for a faster reboot (this avoids BIOS and bootloader steps).
|
||||
|
||||
Independently of the `REBOOT` file, in the provided `utils/bento.nix`, there is a systemd service that can be enabled to automatically reboot at a given systemd calendar if the kernel/mdoules/initrd changed. This is more convenient for servers.
|
||||
|
||||
# Status report of the fleet
|
||||
|
||||
|
|
40
flake.lock
40
flake.lock
|
@ -1,12 +1,30 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1687171271,
|
||||
"narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1662099760,
|
||||
"narHash": "sha256-MdZLCTJPeHi/9fg6R9fiunyDwP3XHJqDd51zWWz9px0=",
|
||||
"lastModified": 1664883812,
|
||||
"narHash": "sha256-wqBAcVRBxls2nVaNeQaOy9SRg/bvEUiD26TQDprIg8U=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "67e45078141102f45eff1589a831aeaa3182b41e",
|
||||
"rev": "fe76645aaf2fac3baaa2813fd0089930689c53b5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -18,8 +36,24 @@
|
|||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
|
48
flake.nix
48
flake.nix
|
@ -2,26 +2,36 @@
|
|||
description = "bento: an asynchronous NixOS deployment tool";
|
||||
|
||||
inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-22.05;
|
||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||
|
||||
outputs = { self, nixpkgs }: {
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system: let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
in {
|
||||
packages.default = pkgs.stdenv.mkDerivation {
|
||||
name = "bento";
|
||||
src = self;
|
||||
|
||||
packages.x86_64-linux.default =
|
||||
with import nixpkgs { system = "x86_64-linux"; };
|
||||
patchPhase = ''
|
||||
substituteInPlace bento --replace 'inotifywait' "${pkgs.inotify-tools}/bin/inotifywait";
|
||||
'';
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "bento-1.0.5";
|
||||
src = self;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
mkdir -p $out/share
|
||||
install -Dm555 bento $out/bin/
|
||||
install -Dm444 fleet.nix $out/share/
|
||||
install -Dm444 config.sh.sample $out/share/
|
||||
install -Dm444 LICENSE $out/share/
|
||||
install -Dm444 README.md $out/share/
|
||||
install -Dm444 utils/bento.nix $out/share/
|
||||
'';
|
||||
};
|
||||
};
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
mkdir -p $out/share
|
||||
install -Dm555 bento $out/bin/
|
||||
install -Dm444 fleet.nix $out/share/
|
||||
install -Dm444 config.sh.sample $out/share/
|
||||
install -Dm444 LICENSE $out/share/
|
||||
install -Dm444 README.md $out/share/
|
||||
install -Dm444 utils/bento.nix $out/share/
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,18 +5,9 @@
|
|||
}: let
|
||||
timer = "*:0/15";
|
||||
in {
|
||||
systemd.timers.bento-upgrade = {
|
||||
enable = true;
|
||||
timerConfig = {
|
||||
OnCalendar = "${timer}";
|
||||
Unit = "bento-upgrade.service";
|
||||
};
|
||||
wantedBy = ["timers.target"];
|
||||
after = ["network-online.target"];
|
||||
};
|
||||
|
||||
systemd.services.bento-upgrade = {
|
||||
enable = true;
|
||||
startAt = lib.mkDefault "${timer}";
|
||||
path = with pkgs; [openssh git nixos-rebuild nix gzip];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
|
@ -26,6 +17,24 @@ in {
|
|||
restartIfChanged = false;
|
||||
};
|
||||
|
||||
systemd.services.bento-reboot = {
|
||||
# this is disabled by default
|
||||
# to avoid wrong expectations from users
|
||||
enable = false;
|
||||
startAt = "04:00";
|
||||
path = with pkgs; [coreutils systemd];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = ''
|
||||
booted="$(readlink /run/booted-system/{initrd,kernel,kernel-modules})"
|
||||
built="$(readlink /nix/var/nix/profiles/system/{initrd,kernel,kernel-modules})"
|
||||
if [ ! "$booted" = "$built" ]
|
||||
then
|
||||
systemctl kexec || systemctl reboot
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
systemd.sockets.listen-update = {
|
||||
enable = true;
|
||||
wantedBy = ["sockets.target"];
|
||||
|
|
Loading…
Reference in New Issue