Compare commits

...
11 Commits
72 changed files with 1253 additions and 123 deletions
+2
View File
@@ -1,3 +1,5 @@
hosts
proxmox.*
.vscode
.vault_pass
logs
+5 -1
View File
@@ -1,3 +1,7 @@
[defaults]
host_key_checking = False
roles_path = ./roles:/etc/ansible/roles
roles_path = ./roles:/etc/ansible/roles
group_vars = ./group_vars
[ssh_connection]
ssh_args = -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
+18
View File
@@ -0,0 +1,18 @@
- hosts: all
become: true
user: admin
tasks:
- name: Verify if system is Debian
debug:
msg: "This playbook is running on a Debian system."
when: ansible_facts['os_family'] == "Debian"
- name: Stop playbook if system is not Debian
fail:
msg: "This playbook only supports Debian."
when: ansible_facts['os_family'] != "Debian"
- name: Include Bootstrap role
import_role:
name: bootstrap
when: ansible_facts['os_family'] == "Debian"
+35
View File
@@ -0,0 +1,35 @@
FROM debian:trixie-slim
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Berlin
ENV ANSIBLE_VERSION=2.20.6
ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN apt update && apt install -y --no-install-recommends \
nano \
git \
wget \
unzip \
curl \
python3-pip \
tzdata \
openssh-client \
iputils-ping \
&& rm -rf /var/lib/apt/lists/*
RUN mkdir -p /etc/ssh/ssh_config.d \
&& printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > /etc/ssh/ssh_config.d/99-no-hostkey-check.conf
RUN pip3 install --no-cache-dir --upgrade \
ansible-core~=${ANSIBLE_VERSION}
RUN mkdir -p /root/.bashrc.d
COPY ansible-functs.sh /root/.bashrc.d/ansible-functs.sh
RUN chmod +x /root/.bashrc.d/ansible-functs.sh \
&& printf '\n[ -f /root/.bashrc.d/ansible-functs.sh ] && . /root/.bashrc.d/ansible-functs.sh\n' >> /root/.bashrc
COPY requirements.yml /ansible/requirements.yml
RUN ansible-galaxy collection install -r /ansible/requirements.yml
WORKDIR /ansible
CMD ["ansible-playbook", "--version"]
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
# Useful bashrc functions for ansible in docker
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias ap='ansible-playbook'
alias ag='ansible-galaxy'
alias av='ansible-vault'
+7
View File
@@ -0,0 +1,7 @@
collections:
- name: ansible.posix
version: 2.2.0
- name: community.general
version: 13.0.1
- name: community.docker
version: 5.2.0
Executable
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
defaultimage="ansible:deb13"
export ANSIBLE_HOST_KEY_CHECKING=False
export ANSIBLE_SSH_ARGS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
export ANSIBLE_CONFIG=./ansible.cfg
# Ermittle den nächsten freien Container-Namen
base_name="ansible"
network_name="ansible-dualstack"
counter=1
while docker ps -a --format '{{.Names}}' | grep -q "^${base_name}-${counter}$"; do
counter=$((counter + 1))
done
container_name="${base_name}-${counter}"
if docker network inspect "$network_name" >/dev/null 2>&1; then
network_ipv6_enabled=$(docker network inspect -f '{{.EnableIPv6}}' "$network_name" 2>/dev/null)
if [ "$network_ipv6_enabled" != "true" ]; then
echo "Docker-Netzwerk '$network_name' existiert bereits ohne IPv6-Unterstuetzung." >&2
echo "Bitte Netzwerk entfernen oder einen anderen Netzwerknamen verwenden." >&2
exit 1
fi
else
if ! docker network create --driver bridge --ipv6 "$network_name" >/dev/null; then
echo "Docker-Netzwerk '$network_name' mit IPv6 konnte nicht erstellt werden." >&2
echo "Pruefe, ob Docker IPv6 fuer benutzerdefinierte Bridge-Netze unterstuetzt." >&2
exit 1
fi
fi
docker run --rm -dit \
--name "$container_name" \
--hostname "$container_name" \
--network "$network_name" \
-e ANSIBLE_HOST_KEY_CHECKING=False \
-e ANSIBLE_SSH_ARGS='-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null' \
-e ANSIBLE_CONFIG=./ansible.cfg \
-v "$(pwd):/ansible" \
-v ansible_ssh_keys:/root/.ssh \
-w /ansible \
$defaultimage \
"/bin/bash"
docker exec "$container_name" sh -lc "mkdir -p /root/.ssh && chmod 700 /root/.ssh && printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > /root/.ssh/config && chmod 600 /root/.ssh/config"
container_ipv4=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{if .IPAddress}}{{.IPAddress}}{{end}}{{end}}' "$container_name" 2>/dev/null)
container_ipv6=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{if .GlobalIPv6Address}}{{.GlobalIPv6Address}}{{end}}{{end}}' "$container_name" 2>/dev/null)
container_os=$(docker exec "$container_name" sh -c 'grep PRETTY_NAME /etc/os-release 2>/dev/null | cut -d= -f2 | tr -d "\"" 2>/dev/null')
echo "-----------------------------------"
echo "Container Name : $container_name"
echo "Container IPv4 : ${container_ipv4:-n/a}"
echo "Container IPv6 : ${container_ipv6:-n/a}"
echo "Container OS : ${container_os:-n/a}"
echo "-----------------------------------"
docker attach "$container_name"
+37
View File
@@ -0,0 +1,37 @@
debian:
hosts:
rp:
ansible_host: 192.168.212.50
bitwarden:
ansible_host: 192.168.212.20
pdf:
ansible_host: 192.168.212.65
mailcow:
ansible_host: 192.168.212.70
plex:
ansible_host: 192.168.212.62
cloud:
ansible_host: 192.168.212.60
romm:
ansible_host: 192.168.212.64
gitea:
ansible_host: 192.168.212.30
ssh_service_name: ssh
ipam:
ansible_host: 192.168.212.56
ssh_service_name: ssh
teamspeck6:
ansible_host: 192.168.212.75
wiki:
ansible_host: 192.168.212.55
patchmon:
ansible_host: 192.168.212.80
einstein-dns:
ansible_host: 192.168.212.53
proxmox:
hosts:
dmc12:
ansible_host: 192.168.212.10
pbs:
ansible_host: 192.168.212.11
+10
View File
@@ -0,0 +1,10 @@
debian:
hosts:
healthcheck:
ansible_host: 2a01:4f8:1c1e:62dd::1
netbird:
ansible_host: 2a01:4f8:1c1c:8c8::1
teleport:
ansible_host: 2a01:4f8:1c19:c7d::1
podcast-linkstack:
ansible_host: 2a01:4f8:c17:de13::1
+8
View File
@@ -0,0 +1,8 @@
# Standardwerte, die überschrieben werden können
os_update_auto_upgrade: true
os_also_update_mirror: false
os_update_mirrors:
# Role needs two mirros to use for the sources.list.j2 Template
- "http://deb.debian.org/debian" # Enter a main mirror here (not security)
- "http://security.debian.org/debian-security" # Enter a security mirror here
os_update_version_codename: "trixie" # KEEP UNTOUCHED!! | Used for jinja2 Template fill in as it determines the current codename of system where ansible is run on
+11
View File
@@ -0,0 +1,11 @@
---
# SSH authorized keys for admin user
# Format: key and optional comment
admin_authorized_keys:
- key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/XwF0Na+YH7lRqGtwEcyIMVGTQZetNDrC9sZ8ofjC5 niklas@Linkman-PC"
comment: "Niklas - Linkman-PC"
- key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA+EvtGavPlXfv7b00jSYsXX2+IEsqFWupEs6Rzf5z9q root@ansible"
comment: "Generic Ansible Key"
# Admin user password (hashed with SHA-512)
admin_password: "$6$NmIxM3ZbJDsbC1E6$BO8ag1ZyBqbhELjk0ppKV0CLnYXhHDp9oZc.jmkc62N9hjwbXihF1FmvsYgMKKINVcwaE73u2dRO8pnE6yEGH/"
+1
View File
@@ -0,0 +1 @@
monitoring_zabbix_passive_servers: ["10.13.37.1"]
+20
View File
@@ -0,0 +1,20 @@
home:
children:
debian:
hosts:
rp:
ansible_host: 10.13.37.11
paperless:
ansible_host: 10.13.37.30
homeassistant:
ansible_host: 10.13.37.15
teleport-jumper:
ansible_host: 10.13.37.50
idris-dns:
ansible_host: 10.13.37.53
it-tools:
ansible_host: 10.13.37.16
proxmox:
hosts:
tardis:
ansible_host: 10.13.37.5
+18
View File
@@ -0,0 +1,18 @@
- hosts: all
user: admin
become: true
tasks:
- name: Verify if system is Debian
debug:
msg: "This playbook is running on a Debian system."
when: ansible_facts['os_family'] == "Debian"
- name: Stop playbook if system is not Debian
fail:
msg: "This playbook only supports Debian."
when: ansible_facts['os_family'] != "Debian"
- name: Include Docker setup role
import_role:
name: docker
when: ansible_facts['os_family'] == "Debian"
+1
View File
@@ -2,5 +2,6 @@
# vars:
# good_keys: "{{ lookup('env', 'good_keys') | from_json }}"
# bad_keys: "{{ lookup('env', 'bad_keys') | from_json }}"
user: admin
roles:
- role: manage-ssh-keys
+18
View File
@@ -0,0 +1,18 @@
- hosts: all
user: admin
become: true
tasks:
- name: Verify if system is Debian
debug:
msg: "This playbook is running on a Debian system."
when: ansible_facts['os_family'] == "Debian"
- name: Stop playbook if system is not Debian
fail:
msg: "This playbook only supports Debian."
when: ansible_facts['os_family'] != "Debian"
- name: Include monitoring role
import_role:
name: monitoring
when: ansible_facts['os_family'] == "Debian"
+9 -3
View File
@@ -1,17 +1,23 @@
- hosts: all
user: admin
become: true
tasks:
- name: Verify if system is Debian
debug:
msg: "This playbook is running on a Debian system."
when: ansible_os_family == "Debian"
when: ansible_facts['os_family'] == "Debian"
- name: Stop playbook if system is not Debian
fail:
msg: "This playbook only supports Debian."
when: ansible_os_family != "Debian"
when: ansible_facts['os_family'] != "Debian"
- name: Include OS update role
include_role:
name: os-updates
when: ansible_os_family == "Debian"
when: ansible_facts['os_family'] == "Debian"
- name: Include healthcheck role (post-update quality gate)
include_role:
name: healthcheck
when: ansible_facts['os_family'] == "Debian"
+18
View File
@@ -0,0 +1,18 @@
- hosts: all
user: admin
become: true
tasks:
- name: Verify if system is Debian
debug:
msg: "This playbook is running on a Debian system."
when: ansible_facts['os_family'] == "Debian"
- name: Stop playbook if system is not Debian
fail:
msg: "This playbook only supports Debian."
when: ansible_facts['os_family'] != "Debian"
- name: Include hawser role
import_role:
name: hawser
when: ansible_facts['os_family'] == "Debian"
+13
View File
@@ -0,0 +1,13 @@
---
# SSH authorized keys for admin user
# Format: key and optional comment
admin_authorized_keys:
- key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/XwF0Na+YH7lRqGtwEcyIMVGTQZetNDrC9sZ8ofjC5 niklas@Linkman-PC"
comment: "Niklas - Linkman-PC"
- key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINPHSP1qvaoJDwMtka6UV9aOw24cKHBOa2Eyx7JBmhEg dennis@DESKTOP-V99ARL9"
comment: "Dennis - DESKTOP-V99ARL9"
- key: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA+EvtGavPlXfv7b00jSYsXX2+IEsqFWupEs6Rzf5z9q root@ansible"
comment: "Generic Ansible Key"
# Admin user password (hashed with SHA-512)
admin_password: "$6$NmIxM3ZbJDsbC1E6$BO8ag1ZyBqbhELjk0ppKV0CLnYXhHDp9oZc.jmkc62N9hjwbXihF1FmvsYgMKKINVcwaE73u2dRO8pnE6yEGH/"
+11
View File
@@ -0,0 +1,11 @@
---
- name: Restart sshd
service:
name: "{{ ssh_service_name | default('sshd') }}"
state: restarted
remote_user: admin
- name: Reload keyboard layout
shell: setupcon
ignore_errors: yes
remote_user: admin
+17
View File
@@ -0,0 +1,17 @@
---
- name: Create .ssh directory for admin user
file:
path: /home/admin/.ssh
state: directory
owner: admin
group: admin
mode: '0700'
- name: Deploy authorized SSH keys for admin user
template:
src: authorized_keys.j2
dest: /home/admin/.ssh/authorized_keys
owner: admin
group: admin
mode: '0600'
when: admin_authorized_keys is defined and admin_authorized_keys | length > 0
+10
View File
@@ -0,0 +1,10 @@
---
- name: Configure SSH daemon
template:
src: sshd.conf.j2
dest: /etc/ssh/sshd_config
owner: root
group: root
mode: '0600'
validate: /usr/sbin/sshd -T -f %s
notify: Restart sshd
@@ -0,0 +1,9 @@
---
- name: Configure swappiness to reduce swap usage
become: yes
ansible.posix.sysctl:
name: vm.swappiness
value: 10
state: present
reload: yes
when: ansible_facts['virtualization_type'] != "lxc"
+15 -5
View File
@@ -6,10 +6,20 @@
shell: /bin/bash
createhome: yes
state: present
password: "{{ admin_password }}"
password_lock: no
- name: Create sudoers.d directory if not exists
file:
path: /etc/sudoers.d
state: directory
mode: '0755'
- name: Set sudo privileges for admin user
lineinfile:
path: /etc/sudoers.d/10-admin
line: "admin ALL=(ALL) NOPASSWD:ALL"
validate: 'visudo -cf %s'
state: present
template:
src: sudoers-admin.j2
dest: /etc/sudoers.d/10-admin
owner: root
group: root
mode: '0440'
validate: 'visudo -cf %s'
@@ -0,0 +1,19 @@
---
- name: Install basic packages
ansible.builtin.apt:
name:
- fastfetch
- htop
- curl
- wget
- git
- sudo
- console-setup
- qemu-guest-agent
- cron
- net-tools
- tcpdump
- locales-all
update_cache: yes
install_recommends: no
state: present
+13
View File
@@ -0,0 +1,13 @@
---
- name: Remove openssh-client if ssh package is installed
package:
name: ssh
state: absent
- name: Install OpenSSH server
ansible.builtin.apt:
name:
- openssh-server
- openssh-client
update_cache: yes
state: present
-6
View File
@@ -1,6 +0,0 @@
---
- name: Install sudo
apt:
name: sudo
state: present
become: yes
+32
View File
@@ -0,0 +1,32 @@
---
- import_tasks: install-basicpackages.yml
- import_tasks: create-admin-user.yml
- import_tasks: set-motd.yml
tags: motd
- import_tasks: set-keyboardlayout.yml
- import_tasks: install-openssh.yml
tags: ssh
- import_tasks: configure-ssh.yml
tags: ssh
- import_tasks: add-ssh-keys.yml
tags: ssh
- import_tasks: setup-bashrc.yml
tags: bashrc
- import_tasks: configure-sysctl.yml
tags: sysctl
- import_role:
name: docker
when: not skip_docker | default(false)
- import_role:
name: monitoring
when: not skip_monitoring | default(false)
@@ -0,0 +1,9 @@
---
- name: Set keyboard layout to QWERTZ
template:
src: keyboard.j2
dest: /etc/default/keyboard
owner: root
group: root
mode: '0644'
notify: Reload keyboard layout
+19
View File
@@ -0,0 +1,19 @@
- name: Set MOTD to display fastfetch on login
copy:
content: |
#!/bin/bash
# Managed by Ansible - Do not edit manually
if [[ -z "${FASTFETCH_MOTD_SHOWN:-}" && -z "${SUDO_USER:-}" ]]; then
fastfetch -s os:kernel:uptime:packages:shell:disk:cpu:memory:localip:colors
export FASTFETCH_MOTD_SHOWN=1
fi
dest: /etc/profile.d/motd.sh
owner: root
group: root
mode: '0755'
- name: Remove default MOTD file if it exists
file:
path: /etc/motd
state: absent
+46
View File
@@ -0,0 +1,46 @@
---
- name: Get all regular users from /etc/passwd (including root)
shell: |
getent passwd | awk -F: '($3 >= 1000 && $3 < 65534 && $7 !~ /nologin|false/) || $3 == 0 {print $1":"$6}'
register: system_users
changed_when: false
- name: Create user list with home directories
set_fact:
user_list: "{{ system_users.stdout_lines | map('split', ':') | list }}"
- name: Ensure .bashrc exists for all users
file:
path: "{{ item[1] }}/.bashrc"
state: touch
owner: "{{ item[0] }}"
mode: '0644'
modification_time: preserve
access_time: preserve
loop: "{{ user_list }}"
when: item[1] is defined and item[1] != ""
- name: Add useful aliases to .bashrc
blockinfile:
path: "{{ item[1] }}/.bashrc"
marker: "# {mark} ANSIBLE MANAGED ALIASES"
block: |
# Useful Aliases
alias ll='ls -la'
alias la='ls -A'
alias l='ls -CF'
alias ..='cd ..'
alias ...='cd ../..'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
# Additional useful shortcuts
alias df='df -h'
alias du='du -h'
alias free='free -h'
owner: "{{ item[0] }}"
mode: '0644'
create: no
loop: "{{ user_list }}"
when: item[1] is defined and item[1] != ""
@@ -0,0 +1,8 @@
# {{ ansible_managed }}
# This file is managed by Ansible. Do not edit it manually.
{% for key_entry in admin_authorized_keys %}
{% if key_entry.comment is defined %}
# {{ key_entry.comment }}
{% endif %}
{{ key_entry.key }}
{% endfor %}
+8
View File
@@ -0,0 +1,8 @@
# {{ ansible_managed }}
# This file is managed by Ansible. Do not edit it manually.
XKBMODEL="pc105"
XKBLAYOUT="de"
XKBVARIANT=""
XKBOPTIONS=""
BACKSPACE="guess"
+42
View File
@@ -0,0 +1,42 @@
# {{ ansible_managed }}
# This file is managed by Ansible. Do not edit it manually.
# This is the ssh server system-wide configuration file.
# See sshd_config(5) for more information.
Port 22
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::
# HostKeys
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# Authentication
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
PermitEmptyPasswords no
AuthenticationMethods publickey
MaxAuthTries 3
# SFTP
Subsystem sftp /usr/lib/openssh/sftp-server
# Security
X11Forwarding no
PermitTunnel no
AllowAgentForwarding no
AllowTcpForwarding yes
PermitOpen any
ClientAliveInterval 300
ClientAliveCountMax 2
Compression no
UseDNS no
# Logging
SyslogFacility AUTH
LogLevel VERBOSE
# Accept locale-related environment variables
AcceptEnv LANG LC_*
@@ -0,0 +1,5 @@
# Sudoers configuration for admin user
# {{ ansible_managed }}
# This file is managed by Ansible. Do not edit it manually.
admin ALL=(ALL) NOPASSWD:ALL
+8
View File
@@ -0,0 +1,8 @@
docker_mirror: https://download.docker.com/linux/debian
os_version_codename: "{{ ansible_lsb.codename }}"
docker_packages:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-buildx-plugin
- docker-compose-plugin
+17
View File
@@ -0,0 +1,17 @@
---
- name: Restart Docker
ansible.builtin.systemd:
name: docker
state: restarted
daemon_reload: yes
- name: Reload Docker
ansible.builtin.systemd:
name: docker
state: reloaded
- name: Start Docker
ansible.builtin.systemd:
name: docker
state: started
enabled: yes
+40
View File
@@ -0,0 +1,40 @@
---
- name: Update apt cache
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: Install required packages
ansible.builtin.apt:
name:
- ca-certificates
- curl
state: present
- name: Create keyrings directory
ansible.builtin.file:
path: /etc/apt/keyrings
state: directory
mode: '0755'
- name: Download Docker GPG key
ansible.builtin.get_url:
url: "{{ docker_mirror }}/gpg"
dest: /etc/apt/keyrings/docker.asc
mode: '0644'
- name: Add Docker repository
ansible.builtin.template:
src: sources.list.j2
dest: /etc/apt/sources.list.d/docker.sources
mode: '0644'
- name: Update apt cache after adding repository
ansible.builtin.apt:
update_cache: yes
- name: Install Docker packages
ansible.builtin.apt:
name: "{{ docker_packages }}"
state: present
notify: Start Docker
+2
View File
@@ -0,0 +1,2 @@
- name: Include Docker installation tasks
ansible.builtin.include_tasks: install-docker.yml
+7
View File
@@ -0,0 +1,7 @@
# {{ ansible_managed }}
# Package sources for Docker for Codename {{ os_version_codename }}. This file is generated by Ansible using the docker role.
Types: deb
URIs: {{ docker_mirror }}
Suites: {{ os_version_codename }}
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
+15
View File
@@ -0,0 +1,15 @@
# Name des Docker Compose Projekts
hawser_project_name: hawser
# Verzeichnis, in dem die Compose-Datei auf den Zielsystemen liegt
hawser_compose_dir: /opt/hawser
# Freigegebener Port des Hawser-Agents
hawser_port: "2376"
# Name des externen Docker Volumes für die Stack-Dateien
hawser_stacks_volume: hawser_stacks
# ALLOW_INSECURE_NO_AUTH=true erlaubt Standard-Mode ohne Token auf nicht-loopback Adressen.
# Nur setzen, wenn das Netzwerk durch andere Maßnahmen abgesichert ist.
hawser_allow_insecure_no_auth: true
+2
View File
@@ -0,0 +1,2 @@
---
# Keine Handler erforderlich docker compose up -d ersetzt laufende Container eigenständig
+2
View File
@@ -0,0 +1,2 @@
- name: Update Hawser Docker stack
ansible.builtin.import_tasks: update-stack.yml
+31
View File
@@ -0,0 +1,31 @@
- name: Gather Docker host information
community.docker.docker_host_info:
register: hawser_docker_info
ignore_errors: true
- name: Check if Hawser compose file is present
ansible.builtin.stat:
path: "{{ hawser_compose_dir }}/docker-compose.yml"
register: hawser_compose_file
when: hawser_docker_info is not failed
- name: Deploy Hawser compose file from template
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ hawser_compose_dir }}/docker-compose.yml"
owner: root
group: root
mode: "0640"
when:
- hawser_docker_info is not failed
- hawser_compose_file.stat.exists
- name: Pull latest images and recreate Hawser stack
community.docker.docker_compose_v2:
project_src: "{{ hawser_compose_dir }}"
project_name: "{{ hawser_project_name }}"
state: present
pull: always
when:
- hawser_docker_info is not failed
- hawser_compose_file.stat.exists
@@ -0,0 +1,17 @@
services:
hawser:
container_name: hawser
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- {{ hawser_stacks_volume }}:/data/stacks
ports:
- "{{ hawser_port }}:2376"
environment:
- ALLOW_INSECURE_NO_AUTH={{ hawser_allow_insecure_no_auth | string | lower }}
image: ghcr.io/finsys/hawser:latest
restart: always
volumes:
{{ hawser_stacks_volume }}:
external: true
name: {{ hawser_stacks_volume }}
+11
View File
@@ -0,0 +1,11 @@
# Post-update health check (quality gate) defaults.
# The role verifies that every Docker container is running after an OS update
# and records the result in the same update log used by the os-updates role.
healthcheck_logging_enabled: "{{ os_update_logging_enabled | default(true) }}"
healthcheck_log_dir: "{{ os_update_log_dir | default('/ansible/logs') }}"
healthcheck_log_inventory: "{{ inventory_file | basename | splitext | first }}"
healthcheck_log_file: "{{ healthcheck_log_dir }}/{{ healthcheck_log_inventory }}/{{ ansible_facts['hostname'] }}/update.log"
# When true, the role fails the playbook if any container is not running.
healthcheck_fail_on_unhealthy: false
+85
View File
@@ -0,0 +1,85 @@
# Post-update health check (quality gate).
# Detects whether Docker is installed and, if so, verifies that every
# container is in the running state. Results are appended to the update
# log as a "quality_gate" section, tied to the current update run via the
# os-updates preflight start timestamp.
- name: Healthcheck - Detect Docker binary
ansible.builtin.command: which docker
register: healthcheck_docker_bin
changed_when: false
failed_when: false
- name: Healthcheck - Record Docker presence
ansible.builtin.set_fact:
healthcheck_docker_installed: "{{ healthcheck_docker_bin.rc == 0 }}"
- name: Healthcheck - List all container names
ansible.builtin.command: "docker ps -a --format {{ '{{' }}.Names{{ '}}' }}"
register: healthcheck_all_containers
changed_when: false
when: healthcheck_docker_installed | bool
- name: Healthcheck - List running container names
ansible.builtin.command: "docker ps --filter status=running --format {{ '{{' }}.Names{{ '}}' }}"
register: healthcheck_running_containers
changed_when: false
when: healthcheck_docker_installed | bool
- name: Healthcheck - Evaluate container health
ansible.builtin.set_fact:
healthcheck_total_containers: "{{ healthcheck_all_containers.stdout_lines | length }}"
healthcheck_running_count: "{{ healthcheck_running_containers.stdout_lines | length }}"
healthcheck_non_running_containers: "{{ (healthcheck_all_containers.stdout_lines | difference(healthcheck_running_containers.stdout_lines)) | list }}"
when: healthcheck_docker_installed | bool
- name: Healthcheck - Determine overall result
ansible.builtin.set_fact:
healthcheck_all_running: "{{ (healthcheck_non_running_containers | length) == 0 }}"
healthcheck_passed: "{{ (healthcheck_non_running_containers | length) == 0 }}"
when: healthcheck_docker_installed | bool
- name: Healthcheck - Default result when Docker is not installed
ansible.builtin.set_fact:
healthcheck_total_containers: 0
healthcheck_running_count: 0
healthcheck_non_running_containers: []
healthcheck_all_running: true
healthcheck_passed: true
when: not (healthcheck_docker_installed | bool)
- name: Healthcheck - Ensure log directory exists
ansible.builtin.file:
path: "{{ healthcheck_log_file | dirname }}"
state: directory
delegate_to: localhost
when: healthcheck_logging_enabled | bool
- name: Healthcheck - Write quality gate section to update log
ansible.builtin.blockinfile:
path: "{{ healthcheck_log_file }}"
create: yes
marker: "# {mark} ANSIBLE-HEALTHCHECK"
block: |
quality_gate:
docker_installed: {{ healthcheck_docker_installed }}
total_containers: {{ healthcheck_total_containers }}
running_containers: {{ healthcheck_running_count }}
all_running: {{ healthcheck_all_running }}
non_running_containers:
{% for c in healthcheck_non_running_containers %}
- {{ c }}
{% endfor %}
healthcheck_passed: {{ healthcheck_passed }}
delegate_to: localhost
when: healthcheck_logging_enabled | bool
- name: Healthcheck - Fail when containers are unhealthy (quality gate)
ansible.builtin.fail:
msg: >-
Quality gate failed: the following containers are not running:
{{ healthcheck_non_running_containers | join(', ') }}
when:
- healthcheck_fail_on_unhealthy | bool
- healthcheck_docker_installed | bool
- not (healthcheck_all_running | bool)
+2 -3
View File
@@ -1,12 +1,11 @@
---
ssh_user: "root"
authorized_keys_file: >-
{{ "/root/.ssh/authorized_keys" if ssh_user == "root" else "/home/{{ ssh_user }}/.ssh/authorized_keys" }}
ssh_user: "admin"
# Liste der erwünschten (Good) Keys
good_keys:
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL/XwF0Na+YH7lRqGtwEcyIMVGTQZetNDrC9sZ8ofjC5 niklas@Linkman-PC"
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINPHSP1qvaoJDwMtka6UV9aOw24cKHBOa2Eyx7JBmhEg dennis@DESKTOP-V99ARL9"
- "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA+EvtGavPlXfv7b00jSYsXX2+IEsqFWupEs6Rzf5z9q root@ansible"
# Liste der unerwünschten (Bad) Keys
bad_keys:
+2 -2
View File
@@ -5,8 +5,8 @@
- name: Füge Good Keys hinzu
import_tasks: add-goodkeys.yml
when: good_keys
when: good_keys.defined and good_keys | length > 0
- name: Entferne Bad Keys
import_tasks: remove-badkeys.yml
when: bad_keys
when: bad_keys.defined and bad_keys | length > 0
@@ -1,8 +1,8 @@
---
- name: Stelle sicher, dass das .ssh-Verzeichnis existiert
- name: Prüfe das .ssh-Verzeichnis des eingeloggten Users
file:
path: "{{ authorized_keys_file | dirname }}"
path: "{{ ansible_env.HOME }}/.ssh"
state: directory
owner: "{{ ssh_user }}"
group: "{{ ssh_user }}"
owner: "{{ ansible_user_id }}"
group: "{{ ansible_user_gid | default(ansible_user_id) }}"
mode: '0700'
+15
View File
@@ -0,0 +1,15 @@
monitoring_zabbix_version: "7.0"
monitoring_zabbix_release_package: "zabbix-release_latest_{{ monitoring_zabbix_version }}+debian{{ ansible_distribution_major_version }}_all.deb"
monitoring_zabbix_release_url: "https://repo.zabbix.com/zabbix/{{ monitoring_zabbix_version }}/debian/pool/main/z/zabbix-release/{{ monitoring_zabbix_release_package }}"
monitoring_zabbix_release_path: "/tmp/{{ monitoring_zabbix_release_package }}"
monitoring_zabbix_agent_package: zabbix-agent2
monitoring_zabbix_agent_service: zabbix-agent2
monitoring_zabbix_config_file: /etc/zabbix/zabbix_agent2.conf
monitoring_zabbix_agent_user: zabbix
monitoring_zabbix_passive_servers: ["192.168.212.1"]
monitoring_zabbix_active_servers: ""
monitoring_zabbix_listen_port: 10050
monitoring_zabbix_docker_group: docker
monitoring_zabbix_docker_socket_path: /var/run/docker.sock
monitoring_zabbix_docker_plugin_config_file: /etc/zabbix/zabbix_agent2.d/plugins.d/docker.conf
monitoring_zabbix_docker_endpoint: "unix://{{ monitoring_zabbix_docker_socket_path }}"
+6
View File
@@ -0,0 +1,6 @@
---
- name: Restart Zabbix Agent
ansible.builtin.systemd:
name: "{{ monitoring_zabbix_agent_service }}"
state: restarted
daemon_reload: yes
@@ -0,0 +1,9 @@
---
- name: Configure Zabbix agent
ansible.builtin.template:
src: zabbix_agent2.conf.j2
dest: "{{ monitoring_zabbix_config_file }}"
owner: root
group: root
mode: '0644'
notify: Restart Zabbix Agent
@@ -0,0 +1,47 @@
---
- name: Gather Docker group entries
ansible.builtin.getent:
database: group
key: "{{ monitoring_zabbix_docker_group }}"
failed_when: false
- name: Check whether Docker socket exists
ansible.builtin.stat:
path: "{{ monitoring_zabbix_docker_socket_path }}"
register: monitoring_docker_socket
- name: Ensure Zabbix agent can access Docker socket
ansible.builtin.user:
name: "{{ monitoring_zabbix_agent_user }}"
groups: "{{ monitoring_zabbix_docker_group }}"
append: yes
when:
- monitoring_docker_socket.stat.exists
- monitoring_zabbix_docker_group in (ansible_facts.getent_group | default({}))
notify: Restart Zabbix Agent
- name: Ensure Docker plugin configuration directory exists
ansible.builtin.file:
path: "{{ monitoring_zabbix_docker_plugin_config_file | dirname }}"
state: directory
owner: root
group: root
mode: '0755'
when: monitoring_docker_socket.stat.exists
- name: Configure Docker plugin endpoint
ansible.builtin.template:
src: docker.conf.j2
dest: "{{ monitoring_zabbix_docker_plugin_config_file }}"
owner: root
group: root
mode: '0644'
when: monitoring_docker_socket.stat.exists
notify: Restart Zabbix Agent
- name: Remove Docker plugin configuration when Docker socket is absent
ansible.builtin.file:
path: "{{ monitoring_zabbix_docker_plugin_config_file }}"
state: absent
when: not monitoring_docker_socket.stat.exists
notify: Restart Zabbix Agent
+11
View File
@@ -0,0 +1,11 @@
---
- name: Install Zabbix agent package
ansible.builtin.apt:
name: "{{ monitoring_zabbix_agent_package }}"
state: present
- name: Ensure Zabbix agent service is enabled and started
ansible.builtin.systemd:
name: "{{ monitoring_zabbix_agent_service }}"
state: started
enabled: yes
@@ -0,0 +1,22 @@
---
- name: Install repository prerequisites
ansible.builtin.apt:
name:
- ca-certificates
state: present
update_cache: yes
cache_valid_time: 3600
- name: Download Zabbix release package
ansible.builtin.get_url:
url: "{{ monitoring_zabbix_release_url }}"
dest: "{{ monitoring_zabbix_release_path }}"
mode: '0644'
- name: Install Zabbix release package
ansible.builtin.apt:
deb: "{{ monitoring_zabbix_release_path }}"
- name: Update apt cache after Zabbix repository setup
ansible.builtin.apt:
update_cache: yes
+14
View File
@@ -0,0 +1,14 @@
- import_tasks: validate.yml
tags: monitoring
- import_tasks: install-repository.yml
tags: monitoring
- import_tasks: install-agent.yml
tags: monitoring
- import_tasks: configure-docker.yml
tags: monitoring
- import_tasks: configure-agent.yml
tags: monitoring
+11
View File
@@ -0,0 +1,11 @@
---
- name: Stop playbook if system is not Debian
ansible.builtin.fail:
msg: "This role only supports Debian."
when: ansible_facts['os_family'] != "Debian"
- name: Ensure Zabbix passive servers are defined
ansible.builtin.assert:
that:
- monitoring_zabbix_passive_servers | length > 0
fail_msg: "Set monitoring_zabbix_passive_servers to the IPs, CIDRs or DNS names allowed to query the agent."
@@ -0,0 +1,2 @@
# {{ ansible_managed }}
Plugins.Docker.Endpoint={{ monitoring_zabbix_docker_endpoint }}
@@ -0,0 +1,11 @@
# {{ ansible_managed }}
PidFile=/run/zabbix/zabbix_agent2.pid
LogFile=/var/log/zabbix/zabbix_agent2.log
LogFileSize=0
Server={{ monitoring_zabbix_passive_servers | join(',') }}
{% if monitoring_zabbix_active_servers | length > 0 %}
ServerActive={{ monitoring_zabbix_active_servers | join(',') }}
{% endif %}
HostnameItem=system.hostname
ListenPort={{ monitoring_zabbix_listen_port }}
Include=/etc/zabbix/zabbix_agent2.d/*.conf
+12 -2
View File
@@ -1,9 +1,19 @@
# Standardwerte, die überschrieben werden können
os_update_auto_upgrade: true
os_also_update_mirror: false
# Logging of OS update runs (preflight package count/list, updated packages, duration)
os_update_logging_enabled: true
os_update_log_dir: /ansible/logs
os_update_log_inventory: "{{ inventory_file | basename | splitext | first }}"
os_update_log_file: "{{ os_update_log_dir }}/{{ os_update_log_inventory }}/{{ ansible_facts['hostname'] }}/update.log"
os_update_mirrors:
# Role needs two mirros to use for the sources.list.j2 Template
- "http://deb.debian.org/debian" # Enter a main mirror here (not security)
- "http://security.debian.org/debian-security" # Enter a security mirror here
os_update_major_version: false # Can either be true or false | To toggle if systems need to be upgraded to newer codename
os_update_version_codename: "{{ ansible_distribution_release }}" # KEEP UNTOUCHED!! | Used for jinja2 Template fill in as it determines the current codename of system where ansible is run on
os_update_version_codename: "{{ ansible_facts['distribution_release'] }}" # KEEP UNTOUCHED!! | Used for jinja2 Template fill in as it determines the current codename of system where ansible is run on
os_update_debian_codenames:
# Only these suites are considered Debian codenames and will be rewritten in sources.list.d
- trixie
- bookworm
- bullseye
+3 -6
View File
@@ -3,9 +3,6 @@
clean: yes
autoclean: yes
- name: Reboot system
command: /sbin/reboot
async: 1
poll: 0
ignore_errors: true
when: reboot_required.stdout == "yes"
- name: apt autoremove
apt:
autoremove: yes
@@ -0,0 +1,46 @@
# Postflight logging: which packages were updated and how long it took.
# Run logging steps only when os_update_logging_enabled is true.
- name: Logging - Record end epoch
command: date +%s
register: os_update_log_end_ts
changed_when: false
when: os_update_logging_enabled | bool
- name: Logging - Compute upgrade duration
set_fact:
os_update_duration_seconds: "{{ (os_update_log_end_ts.stdout | int) - (os_update_log_start_ts.stdout | int) }}"
when: os_update_logging_enabled | bool
- name: Logging - Ensure log directory exists
file:
path: "{{ os_update_log_file | dirname }}"
state: directory
delegate_to: localhost
when: os_update_logging_enabled | bool
- name: Logging - Write update log entry
blockinfile:
path: "{{ os_update_log_file }}"
create: yes
marker: "# {mark} ANSIBLE-OS-UPDATE"
block: |
host: {{ ansible_facts['hostname'] }}
started: {{ os_update_log_start_iso.stdout }}
duration_seconds: {{ os_update_duration_seconds }}
upgradable_packages_count: {{ os_update_upgradable_count }}
upgrade_changed: {{ os_update_upgrade_result.changed | default(false) }}
upgrade_failed: {{ os_update_upgrade_result.failed | default(false) }}
upgradable_packages:
{% for ver in os_update_upgradable_versions %}
- {{ ver.split()[0] }} ({{ ver.split()[1] }} -> {{ ver.split()[2] }})
{% endfor %}
reboot_required: {{ os_update_reboot_required }}
reboot_reason: {{ os_update_reboot_reason }}
reboot_triggered: {{ os_update_reboot_triggered }}
reboot_started: {{ os_update_reboot_start_iso }}
reboot_downtime_seconds: {{ os_update_reboot_downtime_seconds }}
kernel_before: {{ os_update_running_kernel.stdout | default('n/a') }}
kernel_after: {{ os_update_running_kernel_after }}
delegate_to: localhost
when: os_update_logging_enabled | bool
@@ -0,0 +1,48 @@
# Preflight logging: how many and which packages need to be updated.
# Run logging steps only when os_update_logging_enabled is true.
- name: Logging - Refresh apt cache for accurate preflight
apt:
update_cache: yes
changed_when: false
when: os_update_logging_enabled | bool
- name: Logging - Record start epoch
command: date +%s
register: os_update_log_start_ts
changed_when: false
when: os_update_logging_enabled | bool
- name: Logging - Record start ISO time
command: date -Iseconds
register: os_update_log_start_iso
changed_when: false
when: os_update_logging_enabled | bool
- name: Preflight - Gather upgradable packages
command: apt list --upgradable
register: os_update_upgradable
changed_when: false
when: os_update_logging_enabled | bool
- name: Preflight - Build list of upgradable package names, versions and count
set_fact:
os_update_upgradable_names: >-
{{
os_update_upgradable.stdout_lines
| select('search', '\[upgradable')
| map('regex_replace', '^([^/]+)/.*$', '\1')
| list
}}
os_update_upgradable_versions: >-
{{
os_update_upgradable.stdout_lines
| select('search', '\[upgradable')
| map('regex_replace', '^([^/]+)/\S+\s+(\S+)\s+\S+\s+\[upgradable from: (\S+)\]$', '\1 \3 \2')
| list
}}
os_update_upgradable_count: >-
{{
(os_update_upgradable.stdout_lines | select('search', '\[upgradable') | list | length) | int
}}
when: os_update_logging_enabled | bool
-5
View File
@@ -3,10 +3,5 @@
include_tasks: update_mirrors.yml
ignore_errors: true
- name: Upgrade to new major version if enabled
when: os_update_major_version
include_tasks: update_major_version.yml
ignore_errors: true
- name: Upgrade all packages
include_tasks: upgrade_packages.yml
+83
View File
@@ -0,0 +1,83 @@
# Reboot decision and execution.
# Determines whether a reboot is needed because a new kernel was installed,
# performs the reboot asynchronously, waits for the host to come back, and
# records timing facts for the update log.
- name: Gather running kernel
command: uname -r
register: os_update_running_kernel
changed_when: false
when: ansible_facts['virtualization_type'] != 'lxc'
- name: Gather latest installed kernel
shell: |
dpkg -l | grep -E '^ii' | grep 'linux-image-[0-9]' | awk '{print $2}' | sort | tail -n 1
register: os_update_latest_kernel
changed_when: false
failed_when: false
when: ansible_facts['virtualization_type'] != 'lxc'
- name: Determine reboot decision
set_fact:
os_update_reboot_required: true
os_update_reboot_reason: "new kernel installed ({{ os_update_running_kernel.stdout }} -> {{ os_update_latest_kernel.stdout | regex_replace('^linux-image-', '') }})"
when:
- ansible_facts['virtualization_type'] != 'lxc'
- os_update_latest_kernel.stdout | length > 0
- os_update_running_kernel.stdout not in os_update_latest_kernel.stdout
- name: Default reboot decision to false
set_fact:
os_update_reboot_required: "{{ os_update_reboot_required | default(false) }}"
os_update_reboot_reason: "{{ os_update_reboot_reason | default('none') }}"
- name: Default reboot timing facts
set_fact:
os_update_reboot_triggered: false
os_update_reboot_start_iso: "n/a"
os_update_reboot_downtime_seconds: 0
os_update_running_kernel_after: "{{ os_update_running_kernel.stdout | default('n/a') }}"
- block:
- name: Reboot - Record start time
command: date -Iseconds
register: os_update_reboot_start_iso_raw
changed_when: false
- name: Reboot - Record start epoch
command: date +%s
register: os_update_reboot_start_ts
changed_when: false
- name: Reboot - Reboot system
command: /sbin/reboot
async: 1
poll: 0
ignore_errors: true
- name: Reboot - Wait for host to come back online
wait_for_connection:
delay: 10
timeout: 600
register: os_update_reboot_wait
- name: Reboot - Record end epoch
command: date +%s
register: os_update_reboot_end_ts
changed_when: false
- name: Reboot - Compute downtime
set_fact:
os_update_reboot_downtime_seconds: "{{ (os_update_reboot_end_ts.stdout | int) - (os_update_reboot_start_ts.stdout | int) }}"
- name: Reboot - Gather running kernel after reboot
command: uname -r
register: os_update_running_kernel_after_raw
changed_when: false
- name: Reboot - Record reboot facts
set_fact:
os_update_reboot_triggered: true
os_update_reboot_start_iso: "{{ os_update_reboot_start_iso_raw.stdout }}"
os_update_running_kernel_after: "{{ os_update_running_kernel_after_raw.stdout }}"
when: os_update_reboot_required | bool
@@ -1,44 +0,0 @@
- name: Backup existing sources in /etc/apt
copy:
src: "{{ item }}"
dest: "{{ item }}.bak"
remote_src: yes
loop: "{{ lookup('ansible.builtin.fileglob', '/etc/apt/sources.list.d/*.list') + ['/etc/apt/sources.list'] }}"
when: item | file
- name: Update sources.list for new major version
template:
src: sources.list.j2
dest: /etc/apt/sources.list
vars:
os_update_version_codename: "{{ new_version_codename }}" # Variable gets passed by main.yml task
- name: Update additional repositories in /etc/apt/sources.list.d (deb822 format)
replace:
path: "{{ item }}"
regexp: '^(Suites:.*\s)({{ os_update_version_codename }})(\s|$)'
replace: '\1{{ new_version_codename }}\3'
loop: "{{ lookup('ansible.builtin.fileglob', '/etc/apt/sources.list.d/*.sources') }}"
when: item | file
ignore_errors: true
- name: Update additional repositories in /etc/apt/sources.list.d (old format fallback)
lineinfile:
path: "{{ item }}"
regexp: '^(deb .* )({{ os_update_version_codename }})'
replace: '\1{{ new_version_codename }}'
loop: "{{ lookup('ansible.builtin.fileglob', '/etc/apt/sources.list.d/*.list') }}"
when: item | file
ignore_errors: true
- name: Update apt cache
apt:
update_cache: yes
- name: Perform distribution upgrade
apt:
upgrade: yes
allow_unauthenticated: yes
notify:
- Reboot system
- apt cleanup
+50 -4
View File
@@ -1,20 +1,66 @@
- name: Run last dist upgrade before changing codename
apt:
update_cache: yes
upgrade: dist
when: ansible_facts['distribution_release'] != os_update_version_codename
- name: Backup existing sources.list
copy:
src: /etc/apt/sources.list
dest: /etc/apt/sources.list.bak
remote_src: yes
force: yes
ignore_errors: true
when: ansible_facts['distribution_version'] is version('13', '<=') # Only apply under Debian 13 and newer
- name: Remove existing debian.sources file from LXC image
- name: Remove existing sources.list to avoid conflicts with new deb822 format
file:
path: /etc/apt/sources.list.d/debian.sources
path: /etc/apt/sources.list
state: absent
when: ansible_facts['distribution_version'] is version('13', '>=') # Only apply for Debian 13 and newer
- name: Update sources.list with new mirrors
- name: Update sources.list.d with new mirrors
template:
src: sources.list-deb822.j2
dest: /etc/apt/sources.list.d/debian.sources
when: ansible_facts['distribution_version'] is version('13', '>=') # Only apply for Debian 13 and newer
register: cache_update_needed
- name: Update sources.list with new mirrors for older Debian versions
template:
src: sources.list.j2
dest: /etc/apt/sources.list
when: ansible_facts['distribution_version'] is version('13', '<') # Only apply for Debian versions older than 13
register: cache_update_needed
- name: Find sources list fragments
find:
paths: /etc/apt/sources.list.d
patterns: "*.list,*.sources"
file_type: file
register: apt_sources_list_fragments
- name: Align suite codenames in sources.list.d for .list files
replace:
path: "{{ item.path }}"
backup: yes
regexp: '^(deb(?:-src)?\s+(?:\[[^\]]+\]\s+)?\S+\s+)({{ os_update_debian_codenames | join("|") }})(-[^\s]+)?(\s+.+)$'
replace: '\1{{ os_update_version_codename }}\3\4'
loop: "{{ apt_sources_list_fragments.files }}"
when: (item.path | regex_search('\.list$')) is not none
register: cache_update_needed
- name: Align suite codenames in sources.list.d for .sources files
replace:
path: "{{ item.path }}"
backup: yes
regexp: '^(Suites:\s+)({{ os_update_debian_codenames | join("|") }})(-[^\s]+)?(.*)$'
replace: '\1{{ os_update_version_codename }}\3\4'
loop: "{{ apt_sources_list_fragments.files }}"
when: (item.path | regex_search('\.sources$')) is not none
register: cache_update_needed
- name: Update apt cache
apt:
update_cache: yes
update_cache: yes
when: cache_update_needed is changed
+10 -20
View File
@@ -1,27 +1,17 @@
- name: Run preflight logging
include_tasks: logging_preflight.yml
- name: Upgrade all installed packages
apt:
upgrade: full
update_cache: yes
notify:
register: os_update_upgrade_result
notify:
- apt cleanup
- apt autoremove
- name: Check if a kernel update is available
shell: |
dpkg -l | grep -E '^ii' | grep 'linux-image-[0-9]' | awk '{print $2}' | sort | tail -n 1
register: latest_kernel
when: ansible_virtualization_type != 'lxc'
- name: Run reboot decision and reboot if required
include_tasks: reboot.yml
- name: Check if running kernel matches the latest installed kernel
shell: |
echo "{{ latest_kernel.stdout }}" | grep -c $(uname -r)
register: kernel_match
changed_when: false
ignore_errors: true
when: ansible_virtualization_type != 'lxc'
- name: Mark reboot required if a new kernel is installed
set_fact:
reboot_required: "yes"
when:
- ansible_virtualization_type != 'lxc'
- kernel_match.stdout == "0"
- name: Run postflight logging
include_tasks: logging_postflight.yml
@@ -0,0 +1,26 @@
# {{ ansible_managed }}
# Package sources for Debian {{ os_update_version_codename }}. This file is generated by Ansible using the os-updates role.
# Using deb822 format for sources.list as it is the new standard in Debian 13 and newer. This file is placed in /etc/apt/sources.list.d/debian.sources to avoid conflicts with older sources.list files and to allow coexistence during transition.
Types: deb
URIs: {{ os_update_mirrors[0] }}
Suites: {{ os_update_version_codename }}
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: {{ os_update_mirrors[0] }}
Suites: {{ os_update_version_codename }}-updates
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: {{ os_update_mirrors[0] }}
Suites: {{ os_update_version_codename }}-backports
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb
URIs: {{ os_update_mirrors[1] }}
Suites: {{ os_update_version_codename }}-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
+6 -18
View File
@@ -1,20 +1,8 @@
# {{ ansible_managed }}
Types: deb
URIs: {{ os_update_mirrors[0] }}
Suites: {{ os_update_version_codename }}
Components: main contrib non-free non-free-firmware
# {{ ansible_managed }} | This file is managed by Ansible. Do not edit it manually.
# Package sources for Debian {{ os_update_version_codename }}. This file is generated by Ansible using the os-updates role.
Types: deb
URIs: {{ os_update_mirrors[0] }}
Suites: {{ os_update_version_codename }}-updates
Components: main contrib non-free non-free-firmware
deb {{ os_update_mirrors[0] }} {{ os_update_version_codename }} main contrib non-free non-free-firmware
deb {{ os_update_mirrors[0] }} {{ os_update_version_codename }}-updates main contrib non-free non-free-firmware
deb {{ os_update_mirrors[0] }} {{ os_update_version_codename }}-backports main contrib non-free non-free-firmware
Types: deb
URIs: {{ os_update_mirrors[0] }}
Suites: {{ os_update_version_codename }}-backports
Components: main contrib non-free non-free-firmware
Types: deb
URIs: {{ os_update_mirrors[1] }}
Suites: {{ os_update_version_codename }}-security
Components: main contrib non-free non-free-firmware
deb {{ os_update_mirrors[1] }} {{ os_update_version_codename }}-security main contrib non-free non-free-firmware
+9
View File
@@ -0,0 +1,9 @@
$ANSIBLE_VAULT;1.1;AES256
34323331303232653139313063663566323064373330346237653366363965303235376230396534
3364383031333064336239653661313066383534626565320a666433333038303938333163363030
65623133356566313263616564626166396635343863353065646538343333383066333839666239
3739643861393534360a353837636662303065623735373063313937633731636338643631623435
65613634316432373837393638636165326231616563353765376533313336373165313436353566
65346536316533343966323531333866626162363837653762383265366632323330646665643635
62653238353738613937393632336132646364633962646637353331613061363564346234333439
63356431373962343737