Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8aea5f0077 | |||
| d78a3d9133 | |||
| 29b1e5eb02 | |||
| c0e96f2543 | |||
| 7104111ac4 | |||
| 56a93411de | |||
| c5217c1a0f | |||
| b693daec8b | |||
| 2523ab8a28 | |||
| f5c6d28095 | |||
| 601954fe7c |
@@ -1,26 +0,0 @@
|
|||||||
- name: All Arch hosts up-to-date
|
|
||||||
hosts: arch
|
|
||||||
tasks:
|
|
||||||
- name: Get current Python minor version
|
|
||||||
ansible.builtin.shell:
|
|
||||||
cmd: python --version | grep -Po '\d+\.\d+'
|
|
||||||
register: orig_python
|
|
||||||
- name: Full repository upgrade
|
|
||||||
become: true
|
|
||||||
community.general.pacman:
|
|
||||||
update_cache: true
|
|
||||||
upgrade: true
|
|
||||||
- name: Get new Python minor version
|
|
||||||
ansible.builtin.shell:
|
|
||||||
cmd: python --version | grep -Po '\d+\.\d+'
|
|
||||||
register: new_python
|
|
||||||
- name: AUR upgrade
|
|
||||||
aur:
|
|
||||||
use: pikaur
|
|
||||||
upgrade: true
|
|
||||||
aur_only: true
|
|
||||||
- import_tasks: ../tasks/aur_rebuild.yml
|
|
||||||
vars:
|
|
||||||
package_pattern: python
|
|
||||||
when:
|
|
||||||
- new_python.stdout is version(orig_python.stdout, '>', version_type='strict')
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
- name: Create test script to determine if reboot is necessary
|
|
||||||
hosts: all
|
|
||||||
tasks:
|
|
||||||
- name: Create ~/bin if it doesn't already exist
|
|
||||||
ansible.builtin.shell:
|
|
||||||
cmd: mkdir ~/bin
|
|
||||||
args:
|
|
||||||
creates: ~/bin/
|
|
||||||
- name: Build needs_reboot
|
|
||||||
ansible.builtin.shell:
|
|
||||||
cmd: |
|
|
||||||
print '#!/usr/bin/env zsh' > needs_reboot
|
|
||||||
source ~/.zsh_functions
|
|
||||||
declare -f kernel_func >> needs_reboot
|
|
||||||
perl -pi -e 'if (/OK/) { $_ = "false\n" }' needs_reboot
|
|
||||||
perl -pi -e 'if (/needs reboot/) { $_ = "true\n" }' needs_reboot
|
|
||||||
printf "\n\n\nkernel_func\n" >> needs_reboot
|
|
||||||
chmod +x needs_reboot
|
|
||||||
args:
|
|
||||||
creates: needs_reboot
|
|
||||||
executable: /usr/bin/zsh
|
|
||||||
chdir: ~/bin/
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
- name: All Debian hosts up-to-date
|
|
||||||
hosts: debian
|
|
||||||
tasks:
|
|
||||||
- name: Full system upgrade
|
|
||||||
become: true
|
|
||||||
ansible.builtin.apt:
|
|
||||||
#executable: /usr/bin/pikaur
|
|
||||||
update_cache: true
|
|
||||||
name: "*"
|
|
||||||
state: latest
|
|
||||||
#upgrade: true
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
kernel_func () {
|
|
||||||
machine_id=$(cat /etc/machine-id)
|
|
||||||
current_kernel=$(uname -r)
|
|
||||||
current_ucode=$(awk -F'[[:space:]]*:[[:space:]]*' '/microcode/ {print $2}' /proc/cpuinfo | uniq)
|
|
||||||
[[ -f /run/next_kernel ]] && next_kernel="$(sudo cat /run/next_kernel)"
|
|
||||||
next_ucode=$(iucode_tool -lqS /lib/firmware/intel-ucode/ | grep -Po 'rev 0x\d+' | tr -d '[rev ]' | tail -1)
|
|
||||||
if [[ "${current_kernel}" == ${next_kernel} ]] && [[ "${current_ucode}" == ${next_ucode} ]] || [[ -z "${next_kernel}" ]]
|
|
||||||
then
|
|
||||||
print -P "[%F{#00ff00}OK%f]"
|
|
||||||
else
|
|
||||||
print -P "[%F{yellow}needs reboot%f]"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
- name: Stop mollyguard if active
|
|
||||||
ansible.builtin.script: stop_mollyguard
|
|
||||||
register: mg
|
|
||||||
- name: Determine if a reboot is necessary
|
|
||||||
ansible.builtin.command:
|
|
||||||
cmd: ~/bin/needs_reboot
|
|
||||||
register: needs_reboot
|
|
||||||
- name: Conditionally reboot
|
|
||||||
ansible.builtin.reboot:
|
|
||||||
when:
|
|
||||||
- inventory_hostname not in group['controller']
|
|
||||||
- mgc succeeded
|
|
||||||
- needs_reboot succeeded
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
- name: AUR upgrade
|
||||||
|
aur:
|
||||||
|
use: pikaur
|
||||||
|
upgrade: true
|
||||||
|
aur_only: true
|
||||||
|
|
||||||
|
- name: Rebuild AUR Python packages if version changed
|
||||||
|
ansible.builtin.import_tasks: aur_rebuild.yaml
|
||||||
|
check_mode: false
|
||||||
|
vars:
|
||||||
|
package_pattern: python
|
||||||
|
when: new_python is version(orig_python, '>', version_type='strict')
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
- name: Get original Python version
|
||||||
|
ansible.builtin.include_tasks: python_check.yaml
|
||||||
|
vars:
|
||||||
|
target_var: orig_python
|
||||||
|
|
||||||
|
- name: Perform official repository updates
|
||||||
|
ansible.builtin.import_tasks: repo_upgrade.yaml
|
||||||
|
|
||||||
|
- name: Get new Python version
|
||||||
|
ansible.builtin.include_tasks: python_check.yaml
|
||||||
|
vars:
|
||||||
|
target_var: new_python
|
||||||
|
|
||||||
|
- name: Perform AUR updates and rebuilds
|
||||||
|
ansible.builtin.import_tasks: aur_upgrade.yaml
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
- name: Run Python version command
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: python --version | grep -Po '\d+\.\d+'
|
||||||
|
register: _temp_python_version
|
||||||
|
changed_when: false
|
||||||
|
check_mode: false
|
||||||
|
|
||||||
|
- name: Assign version to dynamic variable
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
"{{ target_var }}": "{{ _temp_python_version.stdout }}"
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- name: Full repository upgrade
|
||||||
|
become: true
|
||||||
|
community.general.pacman:
|
||||||
|
update_cache: true
|
||||||
|
upgrade: true
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- name: Full system upgrade
|
||||||
|
become: true
|
||||||
|
ansible.builtin.apt:
|
||||||
|
update_cache: true
|
||||||
|
upgrade: full
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
- name: Perform official repository updates
|
||||||
|
ansible.builtin.import_tasks: apt_upgrade.yaml
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Pull latest images and update Docker Compose stacks
|
||||||
|
become: true
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
pull: always
|
||||||
|
build: always
|
||||||
|
loop: "{{ docker_compose_dirs | default([]) }}"
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
- name: Tear down Mailcow and main Docker stack(s) (LIFO)
|
||||||
|
become: true
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ item }}"
|
||||||
|
state: absent
|
||||||
|
# Drops Mailcow first, THEN loops through your main stacks
|
||||||
|
loop: "{{ [mailcow_dir | default('/data/mailcow')] + (docker_compose_dirs | default([])) }}"
|
||||||
|
listen: Restart main Docker stack
|
||||||
|
|
||||||
|
- name: Bring main Docker stack(s) and Mailcow back up (FIFO)
|
||||||
|
become: true
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
# Brings your main stacks up first (recreating the network), THEN Mailcow
|
||||||
|
loop: "{{ (docker_compose_dirs | default([])) + [mailcow_dir | default('/data/mailcow')] }}"
|
||||||
|
listen: Restart main Docker stack
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
- name: Execute unattended Mailcow update
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: ./update.sh --force
|
||||||
|
chdir: "{{ mailcow_dir | default('/data/mailcow') }}"
|
||||||
|
register: mailcow_first_pass
|
||||||
|
# Exit code 2 means "modules updated, run me again". Anything else is a real failure.
|
||||||
|
failed_when: mailcow_first_pass.rc not in [0, 2]
|
||||||
|
changed_when:
|
||||||
|
- mailcow_first_pass.rc == 0
|
||||||
|
- "'Updated code is available' in mailcow_first_pass.stdout or 'Pulling' in mailcow_first_pass.stdout or 'Upgrading' in mailcow_first_pass.stdout"
|
||||||
|
notify: Restart main Docker stack
|
||||||
|
|
||||||
|
- name: Re-run unattended Mailcow update (if modules changed)
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: ./update.sh --force
|
||||||
|
chdir: "{{ mailcow_dir | default('/data/mailcow') }}"
|
||||||
|
# Only trigger this second pass if the first pass threw the specific restart code
|
||||||
|
when: mailcow_first_pass.rc == 2
|
||||||
|
register: mailcow_second_pass
|
||||||
|
changed_when:
|
||||||
|
- "'Updated code is available' in mailcow_second_pass.stdout or 'Pulling' in mailcow_second_pass.stdout or 'Upgrading' in mailcow_second_pass.stdout"
|
||||||
|
notify: Restart main Docker stack
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
# Exit code 0 = Reboot required
|
||||||
|
# Exit code 1 = System is up to date / No reboot needed
|
||||||
|
|
||||||
|
# 1. Branch based on detected distro
|
||||||
|
if [[ -f /etc/os-release ]]; then
|
||||||
|
source /etc/os-release
|
||||||
|
else
|
||||||
|
echo "Cannot determine OS."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# DEBIAN LOGIC
|
||||||
|
# ==========================================
|
||||||
|
if [[ "$ID" == "debian" || "$ID_LIKE" == *"debian"* ]]; then
|
||||||
|
# Debian automatically creates this file when a kernel, microcode,
|
||||||
|
# or core library update requires a reboot.
|
||||||
|
if [[ -f /var/run/reboot-required ]]; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# ARCH LINUX LOGIC
|
||||||
|
# ==========================================
|
||||||
|
elif [[ "$ID" == "arch" || "$ID_LIKE" == *"arch"* ]]; then
|
||||||
|
|
||||||
|
# --- KERNEL CHECK ---
|
||||||
|
# Get the currently running kernel version
|
||||||
|
current_kernel=$(uname -r)
|
||||||
|
|
||||||
|
# Determine the installed kernel package based on the running kernel's name
|
||||||
|
# e.g., "6.1.60-1-lts" -> "linux-lts", "6.5.9-arch1-1" -> "linux"
|
||||||
|
if [[ "$current_kernel" == *"-lts" ]]; then
|
||||||
|
kernel_pkg="linux-lts"
|
||||||
|
elif [[ "$current_kernel" == *"-zen" ]]; then
|
||||||
|
kernel_pkg="linux-zen"
|
||||||
|
elif [[ "$current_kernel" == *"-hardened" ]]; then
|
||||||
|
kernel_pkg="linux-hardened"
|
||||||
|
else
|
||||||
|
kernel_pkg="linux"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get the installed version from pacman.
|
||||||
|
# Note: pacman uses periods (6.5.9.arch1-1) while uname uses dashes (6.5.9-arch1-1).
|
||||||
|
# We strip the package name and format it to match `uname -r` for a clean comparison.
|
||||||
|
installed_kernel=$(pacman -Q "$kernel_pkg" | awk '{print $2}' | sed 's/\./-/g' | sed 's/-\([^-]*\)$/.\1/')
|
||||||
|
|
||||||
|
# In some UKI setups or specific Arch versions, the sed replacement above might not
|
||||||
|
# perfectly match `uname -r` format. A bulletproof fallback is checking if the
|
||||||
|
# modules directory for the currently running kernel has been removed by a pacman update.
|
||||||
|
if [[ ! -d "/usr/lib/modules/$current_kernel" ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- MICROCODE CHECK ---
|
||||||
|
# Check CPU vendor to determine which microcode package to look for
|
||||||
|
vendor=$(grep -m 1 'vendor_id' /proc/cpuinfo | awk '{print $3}')
|
||||||
|
if [[ "$vendor" == "GenuineIntel" ]]; then
|
||||||
|
ucode_pkg="intel-ucode"
|
||||||
|
elif [[ "$vendor" == "AuthenticAMD" ]]; then
|
||||||
|
ucode_pkg="amd-ucode"
|
||||||
|
else
|
||||||
|
ucode_pkg=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$ucode_pkg" ]]; then
|
||||||
|
# Check if the microcode package was updated recently by looking at the
|
||||||
|
# build date of the installed package vs the boot time of the system.
|
||||||
|
|
||||||
|
# Get system boot time in seconds since epoch
|
||||||
|
boot_time=$(awk '{print int($1)}' /proc/uptime)
|
||||||
|
boot_epoch=$(( $(date +%s) - boot_time ))
|
||||||
|
|
||||||
|
# Get the install time of the microcode package
|
||||||
|
ucode_install_epoch=$(expac '%time' "$ucode_pkg" 2>/dev/null || echo 0)
|
||||||
|
|
||||||
|
# If the microcode was installed AFTER the system booted, reboot needed
|
||||||
|
if (( ucode_install_epoch > boot_epoch )); then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If we made it this far, neither kernel nor microcode triggered a reboot
|
||||||
|
exit 1
|
||||||
|
|
||||||
|
else
|
||||||
|
# Fallback for unsupported OS
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
- name: Temporarily stop Mollyguard to allow reboot
|
||||||
|
become: true
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: mollyguard.service
|
||||||
|
state: stopped
|
||||||
|
listen: Reboot system
|
||||||
|
|
||||||
|
- name: Execute System Reboot
|
||||||
|
become: true
|
||||||
|
ansible.builtin.reboot:
|
||||||
|
msg: "Reboot initiated by Ansible"
|
||||||
|
reboot_timeout: 600
|
||||||
|
listen: Reboot system
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
- name: Check if kernel or microcode update requires reboot
|
||||||
|
ansible.builtin.script: check_reboot.zsh # Your script placed in files/
|
||||||
|
register: reboot_check
|
||||||
|
# Prevent Ansible from failing if the script returns false (exit code 1)
|
||||||
|
failed_when: false
|
||||||
|
# Trigger the handler ONLY if the script returns true (exit code 0)
|
||||||
|
changed_when: reboot_check.rc == 0
|
||||||
|
# Forces this specific task to run during a dry run
|
||||||
|
check_mode: false
|
||||||
|
notify: Reboot system
|
||||||
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if systemctl is-active mollyguard; then
|
|
||||||
systemctl stop mollyguard
|
|
||||||
fi
|
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
- name: Establish systemd-creds for use with multiple services
|
||||||
|
hosts: arch debian
|
||||||
|
become: true
|
||||||
|
|
||||||
|
vars_prompt:
|
||||||
|
- name: passphrase
|
||||||
|
prompt: "Enter password manager passphrase"
|
||||||
|
private: true
|
||||||
|
confirm: true
|
||||||
|
- name: creds_var
|
||||||
|
prompt: "Enter the environment variable where systemd will store the credential PATH"
|
||||||
|
private: false
|
||||||
|
- name: creds_name
|
||||||
|
prompt: "Enter the credential name"
|
||||||
|
private: false
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create shared systemd runtime override directory
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: mkdir /etc/systemd/system/shared.d
|
||||||
|
creates: /etc/systemd/system/shared.d
|
||||||
|
- name: Create override
|
||||||
|
ansible.builtin.shell:
|
||||||
|
cmd: |
|
||||||
|
printf {{ passphrase }} | (echo "[Service]"; systemd-creds encrypt --name={{ creds_name }} --pretty - -) >> /etc/systemd/system/shared.d/00-systemd-creds.conf
|
||||||
|
printf "Environment=%s=%%d/%s\n" {{ creds_var }} {{ creds_name }} >> /etc/systemd/system/shared.d/00-systemd-creds.conf
|
||||||
|
#creates: /etc/systemd/system/shared.d/00-systemd-creds.conf
|
||||||
Reference in New Issue
Block a user