diff --git a/playbooks/debian.yml b/playbooks/debian.yml index bbf97bb..1180f9d 100644 --- a/playbooks/debian.yml +++ b/playbooks/debian.yml @@ -15,4 +15,4 @@ - name: Configure virtual machine import_role: name: debian-qemu - when: ansible_virtualization_type == 'kvm' + when: ansible_virtualization_role == 'guest' and ansible_virtualization_type == 'kvm' diff --git a/playbooks/new-machine-id.yml b/playbooks/new-machine-id.yml new file mode 100644 index 0000000..f61bfdf --- /dev/null +++ b/playbooks/new-machine-id.yml @@ -0,0 +1,22 @@ +- name: Change machine-id in Debian + hosts: all + gather_facts: no + become: yes + tasks: + - name: Remove files with old machine-id + file: + path: "{{ item }}" + state: absent + loop: + - /etc/machine-id + - /var/lib/dbus/machine-id + + - name: Ensure a new UUID is generated for /etc/machine-id + command: + cmd: dbus-uuidgen --ensure=/etc/machine-id + + - name: Create symbolic link for /var/lib/dbus/machine-id + file: + src: /etc/machine-id + dest: /var/lib/dbus/machine-id + state: link diff --git a/roles/debian-base/tasks/main.yml b/roles/debian-base/tasks/main.yml index bbdc17a..dcd5f94 100644 --- a/roles/debian-base/tasks/main.yml +++ b/roles/debian-base/tasks/main.yml @@ -32,5 +32,3 @@ tags: bacula - import_tasks: vn-repo.yml tags: vn-repo -- import_tasks: grub_startup.yml - tags: grub_startup diff --git a/roles/debian-base/tasks/relayhost.yml b/roles/debian-base/tasks/relayhost.yml index dc04fe1..f912812 100644 --- a/roles/debian-base/tasks/relayhost.yml +++ b/roles/debian-base/tasks/relayhost.yml @@ -1,29 +1,33 @@ -- name: Install exim packages - apt: - name: exim4 - state: present -- name: Prepare exim configuration - blockinfile: - path: /etc/exim4/update-exim4.conf.conf - marker_begin: '--- BEGIN VN ---' - marker_end: '--- END VN ---' - marker: "# {mark}" - block: | - dc_eximconfig_configtype='satellite' - dc_other_hostnames='{{ ansible_fqdn }}' - dc_local_interfaces='127.0.0.1' - dc_readhost='{{ ansible_fqdn }}' - dc_smarthost='{{ smtp_server }}' - dc_hide_mailname='true' - state: present - create: yes - mode: u=rw,g=r,o=r - notify: update exim configuration - register: exim_config -- name: Force execution of handlers immediately - meta: flush_handlers -- name: Sending mail to verify relay host configuration works - shell: > - sleep 2; echo "If you see this message, relayhost on {{ ansible_fqdn }} has been configured correctly." \ - | mailx -s "Relayhost test for {{ ansible_fqdn }}" "{{ sysadmin_mail }}" - when: exim_config.changed +- name: Getting service facts to check for postfix + service_facts: +- when: "'postfix.service' not in ansible_facts.services" + block: + - name: Install exim packages + apt: + name: exim4 + state: present + - name: Prepare exim configuration + blockinfile: + path: /etc/exim4/update-exim4.conf.conf + marker_begin: '--- BEGIN VN ---' + marker_end: '--- END VN ---' + marker: "# {mark}" + block: | + dc_eximconfig_configtype='satellite' + dc_other_hostnames='{{ ansible_fqdn }}' + dc_local_interfaces='127.0.0.1' + dc_readhost='{{ ansible_fqdn }}' + dc_smarthost='{{ smtp_server }}' + dc_hide_mailname='true' + state: present + create: yes + mode: u=rw,g=r,o=r + notify: update exim configuration + register: exim_config + - name: Force execution of handlers immediately + meta: flush_handlers + - name: Sending mail to verify relay host configuration works + shell: > + sleep 2; echo "If you see this message, relayhost on {{ ansible_fqdn }} has been configured correctly." \ + | mailx -s "Relayhost test for {{ ansible_fqdn }}" "{{ sysadmin_mail }}" + when: exim_config.changed diff --git a/roles/debian-base/tasks/root.yml b/roles/debian-base/tasks/root.yml index eccf51d..9f3d548 100644 --- a/roles/debian-base/tasks/root.yml +++ b/roles/debian-base/tasks/root.yml @@ -26,7 +26,7 @@ lookup(passbolt, inventory_hostname_short, username='root', password=root_password, - uri='ssh://'+hostname_fqdn + uri='ssh://'+hostname_fqdn+'/' ) }} environment: diff --git a/roles/debian-base/tasks/timesync.yml b/roles/debian-base/tasks/timesync.yml index 57974cf..57d45df 100644 --- a/roles/debian-base/tasks/timesync.yml +++ b/roles/debian-base/tasks/timesync.yml @@ -1,23 +1,28 @@ -- name: Ensure directory for timesyncd custom configuration exists - file: - path: /etc/systemd/timesyncd.conf.d/ - state: directory - owner: root - group: root - mode: u=rwx,g=rx,o=rx -- name: Configure NTP settings in /etc/systemd/timesyncd.conf.d/vn-ntp.conf - copy: - dest: /etc/systemd/timesyncd.conf.d/vn-ntp.conf - content: | - [Time] - NTP={{ time_server }} - FallbackNTP={{ time_server_spain }} - owner: root - group: root - mode: u=rw,g=r,o=r - notify: restart systemd-timesyncd -- name: Ensure systemd-timesyncd service is enabled and started - service: - name: systemd-timesyncd - enabled: yes - state: started +- name: Getting service facts to check for timesyncd + service_facts: +- when: "'systemd-timesyncd.service' in ansible_facts.services" + block: + - name: Ensure directory for timesyncd custom configuration exists + file: + path: /etc/systemd/timesyncd.conf.d/ + state: directory + owner: root + group: root + mode: u=rwx,g=rx,o=rx + - name: Configure timesyncd service + copy: + dest: /etc/systemd/timesyncd.conf.d/vn-ntp.conf + content: | + [Time] + NTP={{ time_server }} + FallbackNTP={{ time_server_spain }} + owner: root + group: root + mode: u=rw,g=r,o=r + notify: restart systemd-timesyncd + - name: Ensure timesyncd service is enabled and started + when: "ansible_facts.services['systemd-timesyncd.service'].status == 'enabled'" + service: + name: systemd-timesyncd + enabled: yes + state: started diff --git a/roles/debian-host/tasks/apparmor.yml b/roles/debian-host/tasks/apparmor.yml index a239254..887d95f 100644 --- a/roles/debian-host/tasks/apparmor.yml +++ b/roles/debian-host/tasks/apparmor.yml @@ -1,12 +1,16 @@ -- name: Stop AppArmor - systemd: - name: apparmor - state: stopped -- name: Disable AppArmor service - systemd: - name: apparmor - enabled: no -- name: Mask AppArmor service - systemd: - name: apparmor - masked: yes \ No newline at end of file +- name: Getting service facts to check for apparmor + service_facts: +- when: "'apparmor.service' in ansible_facts.services" + block: + - name: Stop AppArmor + systemd: + name: apparmor + state: stopped + - name: Disable AppArmor service + systemd: + name: apparmor + enabled: no + - name: Mask AppArmor service + systemd: + name: apparmor + masked: yes \ No newline at end of file diff --git a/roles/debian-qemu/handlers/main.yml b/roles/debian-qemu/handlers/main.yml index 0079561..0bca163 100644 --- a/roles/debian-qemu/handlers/main.yml +++ b/roles/debian-qemu/handlers/main.yml @@ -1,7 +1,3 @@ -- name: restart-nslcd - service: - name: nslcd - state: restarted - name: restart-autofs service: name: autofs diff --git a/roles/debian-qemu/tasks/autofs.yml b/roles/debian-qemu/tasks/autofs.yml index b6688cf..cc7815a 100644 --- a/roles/debian-qemu/tasks/autofs.yml +++ b/roles/debian-qemu/tasks/autofs.yml @@ -11,7 +11,6 @@ lineinfile: path: /etc/nsswitch.conf line: "automount: files" - notify: restart-nslcd - name: Add file homes.autofs configured to autofs template: src: homes.autofs diff --git a/roles/debian-base/tasks/grub_startup.yml b/roles/debian-qemu/tasks/grub_startup.yml similarity index 100% rename from roles/debian-base/tasks/grub_startup.yml rename to roles/debian-qemu/tasks/grub_startup.yml diff --git a/roles/debian-qemu/tasks/main.yml b/roles/debian-qemu/tasks/main.yml index bcb11ce..1b49a8d 100644 --- a/roles/debian-qemu/tasks/main.yml +++ b/roles/debian-qemu/tasks/main.yml @@ -6,3 +6,5 @@ tags: autofs - import_tasks: blacklist.yml tags: blacklist +- import_tasks: grub_startup.yml + tags: grub_startup diff --git a/scripts/backup_pve.sh b/scripts/backup_pve.sh new file mode 100644 index 0000000..326058a --- /dev/null +++ b/scripts/backup_pve.sh @@ -0,0 +1,148 @@ +#!/bin/bash +# Script to automate Proxmox PVE node backups to a PBS machine. +# +# Author: Xavi Lleó +# Copyright (c) 2025 Verdnatura S.L. All rights reserved. +# Version: 1.0.3 +# ¿Juan Wants add GPL License? +# +# A configuration file is required in the user's home directory who runs this command. +# The file should be sourced using CONFIG_FILE before execution. +# +# Example of a configuration file: +# +# Default values +# USER_API="root@pam!api" +# USER="root@pam" +# IP_PBS="192.168.1.250" +# POOL="backup-pool" +# BACKUP_ITEMS="etc-pve.pxar:/etc/pve,interfaces.pxar:/etc/network" +# LOG_FILE="/var/log/proxmox-backup-node-pve.log" +# KEY_FILE="mykeyfile.key" #In case you want encrypted backups +# PBS_PASSWORD='mypass or api token' +# PBS_FINGERPRINT='b0:69:24:75:f0:92:a2:72:37:7c:c1:cb:0d:ba:8e:14:EE:XX:AA:MM:PP:LL:EE:e4:2b:07:02:18:86:9a:df:45' +# +# If you prefer to use switches in a one-liner, refer to the help section (--help) for available options. +# Remember to add the port after the IP address when using an API user for authentication. +# Example: IP_PBS="192.168.1.250:8007" + + +CONFIG_FILE="$HOME/.backup_config.conf" + +# https://pbs.proxmox.com/docs/backup-client.html#environment-variables +export PBS_PASSWORD +export PBS_FINGERPRINT + +if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" +else + echo "Error: Configuration file not found at $CONFIG_FILE" + exit 1 +fi + +show_help() { + echo "Usage: $0 [options]" + echo + echo "Options:" + echo " --standard Perform a standard backup." + echo " --encrypt Perform an encrypted backup (requires a key file)." + echo " --ip Repository IP address (overrides configuration)." + echo " --pool Name of the backup pool (overrides configuration)." + echo " --items List of backup items in 'name1:source1,name2:source2' format." + echo " --user-api Specify user API credentials for backup." + echo " --user Specify user credentials for backup." + echo " --help Show this help." + exit 0 +} + +exit_from_repo() { + proxmox-backup-client logout --repository "$REPOSITORY" 2>>"$LOG_FILE" && echo "$(date '+%Y-%m-%d %H:%M:%S') - Logged out from repository $REPOSITORY" | tee -a "$LOG_FILE" +} + +# Check if PBS_PASSWORD and PBS_FINGERPRINT are set +if [ -z "$PBS_PASSWORD" ] || [ -z "$PBS_FINGERPRINT" ]; then + echo "Error: PBS_PASSWORD or PBS_FINGERPRINT is not set." + exit 1 +fi + +while [[ $# -gt 0 ]]; do + case "$1" in + --standard) + MODE="standard" + ;; + --encrypt) + MODE="encrypt" + ;; + --ip) + IP_PBS="$2" + shift + ;; + --pool) + POOL="$2" + shift + ;; + --items) + BACKUP_ITEMS="$2" + shift + ;; + --user-api) + USER_API="$2" + shift + ;; + --user) + USER="$2" + shift + ;; + --help) + show_help + ;; + *) + echo "Error: Unrecognized option '$1'" + show_help + ;; + esac + shift +done + +if [ -z "$MODE" ]; then + echo "You must specify --standard or --encrypt." + show_help +fi + +if [ -n "$USER_API" ]; then + REPOSITORY="$USER_API@$IP_PBS:$POOL" +else + REPOSITORY="$USER@$IP_PBS:$POOL" +fi + +echo "$(date '+%Y-%m-%d %H:%M:%S') - Starting backup to repository $REPOSITORY" | tee -a "$LOG_FILE" +for item in $(echo "$BACKUP_ITEMS" | tr ',' '\n'); do + BACKUP_NAME=$(echo "$item" | cut -d':' -f1) + TARGET_DIR=$(echo "$item" | cut -d':' -f2) + + if [ "$MODE" == "encrypt" ]; then + if [ ! -f "$KEY_FILE" ]; then + echo "The key file $KEY_FILE does not exist." | tee -a "$LOG_FILE" + exit 1 + fi + + proxmox-backup-client backup "$BACKUP_NAME:$TARGET_DIR" --repository "$REPOSITORY" --crypt-mode encrypt --keyfile "$KEY_FILE" --backup-type 'host' 2>>"$LOG_FILE" + else + proxmox-backup-client backup "$BACKUP_NAME:$TARGET_DIR" --repository "$REPOSITORY" --backup-type 'host' 2>>"$LOG_FILE" + fi + + if [ $? -ne 0 ]; then + echo "Backup failed for $BACKUP_NAME" | tee -a "$LOG_FILE" + exit 1 + fi + sleep 5 +done + +if [ $? -eq 0 ]; then + exit_from_repo + echo -e "$(date '+%Y-%m-%d %H:%M:%S') - Backup completed successfully. You can check the log at $LOG_FILE\n" | tee -a "$LOG_FILE" +else + exit_from_repo + echo -e "$(date '+%Y-%m-%d %H:%M:%S') - Error during backup. You can check the log at $LOG_FILE\n" | tee -a "$LOG_FILE" + exit 1 +fi