Skip to content

Commit 70752e2

Browse files
committed
feat: improve gitops workflow
1 parent 27ad384 commit 70752e2

12 files changed

+204
-75
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ jobs:
2626

2727
- name: Run build tool for ${{ matrix.arch }}-bit disk image
2828
run: |
29-
export ANSIBLE_HOSTNAME='example.fritz.box'
30-
export ANSIBLE_REPOSITORY_URL='https://github.com/escalate/ansible-gitops-example-repository.git'
29+
export ANSIBLE_HOSTNAME=example.fritz.box
30+
export ANSIBLE_HOSTGROUP=example
31+
export ANSIBLE_REPOSITORY_URL=https://github.com/escalate/ansible-gitops-example-repository.git
3132
export ANSIBLE_VAULT_PASSWORD='REDACTED'
3233
make build-${{ matrix.arch }}bit

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ SHELL = /bin/bash
44
.PHONY: build-32bit
55
build-32bit:
66
test -n "$(ANSIBLE_HOSTNAME)" # check env variable $$ANSIBLE_HOSTNAME
7+
test -n "$(ANSIBLE_HOSTGROUP)" # check env variable $$ANSIBLE_HOSTGROUP
78
test -n "$(ANSIBLE_REPOSITORY_URL)" # check env variable $$ANSIBLE_REPOSITORY_URL
89
test -n "$(ANSIBLE_VAULT_PASSWORD)" # check env variable $$ANSIBLE_VAULT_PASSWORD
910
./build.sh 32
1011

1112
.PHONY: build-64bit
1213
build-64bit:
1314
test -n "$(ANSIBLE_HOSTNAME)" # check env variable $$ANSIBLE_HOSTNAME
15+
test -n "$(ANSIBLE_HOSTGROUP)" # check env variable $$ANSIBLE_HOSTGROUP
1416
test -n "$(ANSIBLE_REPOSITORY_URL)" # check env variable $$ANSIBLE_REPOSITORY_URL
1517
test -n "$(ANSIBLE_VAULT_PASSWORD)" # check env variable $$ANSIBLE_VAULT_PASSWORD
1618
./build.sh 64

README.md

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,37 @@
22

33
# Ansible GitOps - Raspberry Pi OS custom disk image
44

5-
A build tool based on [CustoPiZe](https://github.com/OctoPrint/CustoPiZer) to create a customized Raspberry Pi OS disk image which initiates the Ansible GitOps workflow on first boot.
5+
A build tool based on [CustoPiZe](https://github.com/OctoPrint/CustoPiZer) to create a custom Raspberry Pi OS disk image that starts the Ansible GitOps workflow on first boot.
66

77
## How does it work?
88

9-
The build tool downloads the latest [Raspberry Pi OS Lite (32-bit / 64-bit)](https://www.raspberrypi.com/software/operating-systems/) disk image and creates a systemd service inside it to bootstrap the Ansible GitOps workflow on first boot.
9+
The build tool downloads the latest [Raspberry Pi OS Lite (32-bit / 64-bit)](https://www.raspberrypi.com/software/operating-systems/) disk image and creates a systemd service in it that starts the Ansible GitOps workflow on first boot.
1010

11-
After the Raspberry Pi boots successfully with the customized disk image, the systemd service prepares all needed dependencies and runs [ansible-pull](https://docs.ansible.com/ansible/latest/cli/ansible-pull.html) with the user pre-configured environment variables.
11+
After the Raspberry Pi has successfully booted with the customized disk image, the systemd service prepares all required [dependencies](https://github.com/escalate/ansible-gitops-raspberry-pi-os-custom-disk-image/blob/master/scripts/files/gitops-preparation.sh) and executes a [bootstrap script](https://github.com/escalate/ansible-gitops-raspberry-pi-os-custom-disk-image/blob/master/scripts/files/gitops-bootstrap.sh) with the settings preconfigured by the user.
1212

13-
Ansible-pull checks out the pre-configured [Git repository](https://github.com/escalate/ansible-gitops-example-repository/) and runs the playbook `bootstrap.yml`.
14-
All steps for the further process must be stored in the `bootstrap.yml` playbook e.g. the preparation of an external USB drive as well as a cronjob for the periodical execution of ansible-pull.
13+
The [bootstrap script](https://github.com/escalate/ansible-gitops-raspberry-pi-os-custom-disk-image/blob/master/scripts/files/gitops-bootstrap.sh) checks out the preconfigured [Git repository](https://github.com/escalate/ansible-gitops-example-repository/), installs required roles and collections and runs the `bootstrap.yml` playbook.
14+
The `bootstrap.yml` playbook must contain all steps for the further process, e.g. the preparation of an external USB drive and a cronjob for the regular execution of the [deployment script](https://github.com/escalate/ansible-gitops-raspberry-pi-os-custom-disk-image/blob/master/scripts/files/gitops-deployment.sh).
1515

16-
After the successful run of the playbook, a marker is set to prevent the systemd service from starting again at the next boot. Finally, the system is rebooted to complete all changes.
16+
After the successful run of the `bootstrap.yml` playbook, markers are set to prevent the scripts from being restarted at the next system start. Finally, the system is rebooted to complete all changes.
1717

18-
Any configuration change of the Raspberry Pi should now be possible via the configured Git repository.
18+
All configuration changes on the Raspberry Pi should now be possible via the `site.yml` of the configured [Git repository](https://github.com/escalate/ansible-gitops-example-repository/).
1919

2020
## How to create a customized disk image?
2121

22-
1. Define necessary environment variables needed for the later ansible-pull run.
22+
1. Define necessary environment variables needed for the later ansible-playbook run.
2323

2424
```
25-
export ANSIBLE_HOSTNAME='testserver.fritz.box'
26-
export ANSIBLE_REPOSITORY_URL='https://github.com/escalate/ansible-gitops-example-repository.git'
27-
export ANSIBLE_VAULT_PASSWORD='s3cret'
25+
# The Fully Qualified Domain Name (FQDN) of your server
26+
export ANSIBLE_HOSTNAME="testserver.fritz.box"
27+
"
28+
# The Ansible inventory group name where your server belongs to. For more information see https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
29+
export ANSIBLE_HOSTGROUP="testing"
30+
31+
# The URL of your Ansible control repository
32+
export ANSIBLE_REPOSITORY_URL"=https://github.com/escalate/ansible-gitops-example-repository.git"
33+
34+
# The secret password to decrypt your Ansible Vault file. For more information see https://docs.ansible.com/ansible/latest/user_guide/vault.html
35+
export ANSIBLE_VAULT_PASSWORD="s3cret"
2836
```
2937

3038
2. Start the build process with one of the following commands.

build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ echo "Define customization environment variables"
7373
{
7474
echo "DOWNLOAD_IMAGE_ARCHIVE=${DOWNLOAD_IMAGE_ARCHIVE}"
7575
echo "ANSIBLE_HOSTNAME=${ANSIBLE_HOSTNAME}"
76+
echo "ANSIBLE_HOSTGROUP=${ANSIBLE_HOSTGROUP}"
7677
echo "ANSIBLE_REPOSITORY_URL=${ANSIBLE_REPOSITORY_URL}"
7778
echo "ANSIBLE_VAULT_PASSWORD=${ANSIBLE_VAULT_PASSWORD}"
7879
} >"workspace/${ARCH}/gitops-config.env"

scripts/customize.sh

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set -e
44

55
export LC_ALL=C
66

7-
# shellcheck disable=SC1091
7+
# shellcheck source=/dev/null
88
source /common.sh
99
install_cleanup_trap
1010

@@ -15,27 +15,30 @@ echo "Add default user pi with password raspberry"
1515
# shellcheck disable=SC2016
1616
echo 'pi:$6$MVEGdHTqed7c7za0$ESdhSXBIjSTVWKY7YWBII3UjQM6LhFur1alIXWJ9/Hf4mxgZqIuyX1yEsVf/qct4/sT0NStmvIPZs5de3SNNy0' >"${BOOT_PATH}/userconf.txt"
1717

18-
echo "Copy original image archive"
18+
echo "Copy original disk image archive"
1919
cp "/files/${DOWNLOAD_IMAGE_ARCHIVE}" "/var/tmp/${DOWNLOAD_IMAGE_ARCHIVE}"
2020
cp "/files/${DOWNLOAD_IMAGE_ARCHIVE}.sha256" "/var/tmp/${DOWNLOAD_IMAGE_ARCHIVE}.sha256"
2121

2222
echo "Set hostname"
2323
echo "${ANSIBLE_HOSTNAME}" >"/etc/hostname"
2424
sed --in-place "s/raspberrypi/${ANSIBLE_HOSTNAME}/g" "/etc/hosts"
2525

26+
echo "Create GitOps scripts"
27+
cp "/files/gitops-bootstrap.sh" "/usr/local/bin/gitops-bootstrap.sh"
28+
cp "/files/gitops-deployment.sh" "/usr/local/bin/gitops-deployment.sh"
29+
cp "/files/gitops-preparation.sh" "/usr/local/bin/gitops-preparation.sh"
30+
cp "/files/gitops-utils.sh" "/usr/local/bin/gitops-utils.sh"
31+
32+
echo "Define GitOps environment variables"
33+
tee "${BOOT_PATH}/gitops.env" <<EOT
34+
ANSIBLE_HOSTNAME="${ANSIBLE_HOSTNAME}"
35+
ANSIBLE_HOSTGROUP="${ANSIBLE_HOSTGROUP}"
36+
ANSIBLE_REPOSITORY_URL="${ANSIBLE_REPOSITORY_URL}"
37+
ANSIBLE_VAULT_PASSWORD="${ANSIBLE_VAULT_PASSWORD}"
38+
EOT
39+
2640
echo "Create GitOps bootstrap systemd service"
2741
cp "/files/gitops-bootstrap.service" "/etc/systemd/system/gitops-bootstrap.service"
2842

2943
echo "Enable GitOps bootstrap systemd service on startup"
3044
ln --symbolic "/etc/systemd/system/gitops-bootstrap.service" "/etc/systemd/system/multi-user.target.wants/gitops-bootstrap.service"
31-
32-
echo "Create GitOps bootstrap scripts"
33-
cp "/files/gitops-install-and-configure-ansible.sh" "${BOOT_PATH}/gitops-install-and-configure-ansible.sh"
34-
cp "/files/gitops-run-ansible-playbook-and-reboot.sh" "${BOOT_PATH}/gitops-run-ansible-playbook-and-reboot.sh"
35-
36-
echo "Define Ansible environment variables"
37-
tee "${BOOT_PATH}/gitops-bootstrap.env" <<EOT
38-
ANSIBLE_HOSTNAME=${ANSIBLE_HOSTNAME}
39-
ANSIBLE_REPOSITORY_URL=${ANSIBLE_REPOSITORY_URL}
40-
ANSIBLE_VAULT_PASSWORD=${ANSIBLE_VAULT_PASSWORD}
41-
EOT

scripts/files/gitops-bootstrap.service

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
[Unit]
22
Description=GitOps Bootstrap
33
After=network-online.target
4-
ConditionPathExists=!/boot/firmware/gitops-bootstrap.done
54

65
[Service]
76
Type=oneshot
8-
EnvironmentFile=/boot/firmware/gitops-bootstrap.env
7+
EnvironmentFile=/boot/firmware/gitops.env
98
ExecStartPre=/bin/sleep 60
10-
ExecStartPre=/boot/firmware/gitops-install-and-configure-ansible.sh
11-
ExecStart=/boot/firmware/gitops-run-ansible-playbook-and-reboot.sh
9+
ExecStartPre=/usr/local/bin/gitops-preparation.sh
10+
ExecStart=/usr/local/bin/gitops-bootstrap.sh
1211
RemainAfterExit=true
1312

1413
[Install]

scripts/files/gitops-bootstrap.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
set -e -E -u -C -o pipefail
3+
4+
if [[ -f "/boot/firmware/gitops-bootstrap.done" ]]; then
5+
echo "GitOps bootstrap already completed. Exiting."
6+
exit 0
7+
fi
8+
9+
# shellcheck source=/dev/null
10+
source "/boot/firmware/gitops.env"
11+
12+
# shellcheck source=/dev/null
13+
source "/usr/local/bin/gitops-utils.sh"
14+
15+
checkout_repository
16+
install_roles
17+
install_collections
18+
run_ansible_playbook "bootstrap.yml"
19+
20+
echo "Create marker file"
21+
touch "/boot/firmware/gitops-bootstrap.done"
22+
23+
echo "Reboot system"
24+
reboot

scripts/files/gitops-deployment.sh

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
set -e -E -u -C -o pipefail
3+
4+
exec 1> >(logger --tag "$(basename "$0")") 2>&1
5+
6+
# shellcheck source=/dev/null
7+
source "/boot/firmware/gitops.env"
8+
9+
# shellcheck source=/dev/null
10+
source "/usr/local/bin/gitops-utils.sh"
11+
12+
checkout_repository
13+
install_roles
14+
install_collections
15+
run_ansible_playbook "site.yml"

scripts/files/gitops-install-and-configure-ansible.sh

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
set -e -E -u -C -o pipefail
3+
4+
if [[ -f "/boot/firmware/gitops-preparation.done" ]]; then
5+
echo "GitOps preparation already completed. Exiting."
6+
exit 0
7+
fi
8+
9+
echo "Update package information"
10+
apt-get update
11+
12+
echo "Install Python pip"
13+
apt-get --yes install python3-pip
14+
15+
echo "Install Git"
16+
apt-get --yes install git
17+
18+
echo "Install Ansible"
19+
pip3 install \
20+
--disable-pip-version-check \
21+
--break-system-packages \
22+
--root-user-action=ignore \
23+
ansible
24+
25+
echo "Create Ansible configuration directory"
26+
mkdir --parent --verbose /etc/ansible
27+
28+
echo "Create Ansible configuration file"
29+
tee "/etc/ansible/ansible.cfg" <<EOT
30+
[defaults]
31+
collections_path = /etc/ansible/collections
32+
interpreter_python = auto_silent
33+
nocows = true
34+
roles_path = /etc/ansible/roles
35+
vault_password_file = /etc/ansible/.vault_pass.txt
36+
verbosity = 1
37+
38+
[diff]
39+
always = true
40+
EOT
41+
42+
echo "Create Ansible inventory file"
43+
tee "/etc/ansible/hosts.yml" <<EOT
44+
${ANSIBLE_HOSTGROUP}:
45+
hosts:
46+
${ANSIBLE_HOSTNAME}:
47+
ansible_connection: local
48+
ansible_host: 127.0.0.1
49+
EOT
50+
51+
echo "Create Ansible Vault password file"
52+
echo "${ANSIBLE_VAULT_PASSWORD}" >/etc/ansible/.vault_pass.txt
53+
54+
echo "Create marker file"
55+
touch "/boot/firmware/gitops-preparation.done"

0 commit comments

Comments
 (0)