Update playbooks/nextcloud-upgrade.yml
This commit is contained in:
+129
-86
@@ -1,21 +1,32 @@
|
|||||||
- name: Resilient Nextcloud upgrade on Rocky Linux
|
- name: Resilient & Environment-Aware Nextcloud Upgrade
|
||||||
hosts: all
|
hosts: all
|
||||||
become: yes
|
become: yes
|
||||||
vars:
|
|
||||||
# --- Configuration Variables ---
|
|
||||||
nextcloud_dir: /var/www/nextcloud
|
|
||||||
web_user: apache
|
|
||||||
php_cli: /usr/bin/php
|
|
||||||
service_name: httpd
|
|
||||||
|
|
||||||
# --- Environment for occ commands ---
|
# ----------------------------------------------------------------------
|
||||||
# This avoids setting TMPDIR on every single task
|
# ⚠️ REQUIRED USER VARIABLES
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# YOU MUST EDIT THESE 3 VARIABLES TO MATCH YOUR SERVER
|
||||||
|
vars:
|
||||||
|
# 1. The full path to your Nextcloud installation
|
||||||
|
nextcloud_dir: /var/www/nextcloud
|
||||||
|
|
||||||
|
# 2. The *exact* PHP CLI binary your Nextcloud uses
|
||||||
|
# (e.g., /usr/bin/php, /usr/bin/php8.1, /opt/remi/php81/root/bin/php)
|
||||||
|
php_cli_path: /usr/bin/php
|
||||||
|
|
||||||
|
# 3. The service name for your webserver or PHP-FPM
|
||||||
|
# (e.g., httpd, apache2, nginx, php8.1-fpm)
|
||||||
|
web_service_name: httpd
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# INTERNAL PLAYBOOK VARIABLES
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
vars:
|
||||||
|
# Environment for all occ commands
|
||||||
occ_env:
|
occ_env:
|
||||||
TMPDIR: /tmp
|
TMPDIR: /tmp
|
||||||
|
|
||||||
# --- Core Apps ---
|
# Core apps to NOT disable during upgrade
|
||||||
# Add any app you consider "core" and do NOT want to disable.
|
|
||||||
# user_ldap is a good example if you use it for auth.
|
|
||||||
core_apps:
|
core_apps:
|
||||||
- activity
|
- activity
|
||||||
- twofactor_nextcloud_notification
|
- twofactor_nextcloud_notification
|
||||||
@@ -34,91 +45,123 @@
|
|||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
|
|
||||||
- name: Reminder - ensure backups exist
|
# ----------------------------------------------------------------------
|
||||||
|
# 🛡️ STAGE 1: PREFLIGHT CHECKS & FACT GATHERING
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
- name: 1.1 - Validate 'nextcloud_dir'
|
||||||
|
stat:
|
||||||
|
path: "{{ nextcloud_dir }}/config/config.php"
|
||||||
|
register: config_stat
|
||||||
|
|
||||||
|
- name: 1.2 - Fail if 'config.php' not found
|
||||||
|
fail:
|
||||||
|
msg: |
|
||||||
|
'config.php' not found at '{{ nextcloud_dir }}/config/config.php'.
|
||||||
|
Please correct the 'nextcloud_dir' variable in the playbook.
|
||||||
|
when: not config_stat.stat.exists
|
||||||
|
|
||||||
|
- name: 1.3 - 🧠 DISCOVER 'nc_web_user' from 'config.php' owner
|
||||||
|
set_fact:
|
||||||
|
nc_web_user: "{{ config_stat.stat.owner }}"
|
||||||
|
|
||||||
|
- name: 1.4 - Display discovered file owner
|
||||||
debug:
|
debug:
|
||||||
msg: "⚠️ CRITICAL: Ensure you have valid DB + data directory backups BEFORE PROCEEDING!"
|
msg: "Discovered Nextcloud web user: {{ nc_web_user }}"
|
||||||
|
|
||||||
- name: Pause playbook for 10 seconds to allow backup cancellation
|
- name: 1.5 - Validate 'php_cli_path'
|
||||||
pause:
|
stat:
|
||||||
seconds: 10
|
path: "{{ php_cli_path }}"
|
||||||
prompt: "Press Ctrl+C and then 'A' to abort if you do not have backups."
|
register: php_stat
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
- name: 1.6 - Fail if 'php_cli_path' is not an executable file
|
||||||
# Step 1: Check current version
|
fail:
|
||||||
# ----------------------------------------------------------------------
|
msg: |
|
||||||
- name: Get current Nextcloud version
|
'php_cli_path' ('{{ php_cli_path }}') does not exist or is not executable.
|
||||||
command: "{{ php_cli }} occ status"
|
Please correct the 'php_cli_path' variable.
|
||||||
|
when: not php_stat.stat.exists or not php_stat.stat.isexe
|
||||||
|
|
||||||
|
- name: 1.7 - Validate 'web_service_name'
|
||||||
|
service_facts:
|
||||||
|
|
||||||
|
- name: 1.8 - Fail if 'web_service_name' is not a known service
|
||||||
|
fail:
|
||||||
|
msg: |
|
||||||
|
'web_service_name' ('{{ web_service_name }}') is not a valid service on this host.
|
||||||
|
Please correct the 'web_service_name' variable.
|
||||||
|
when: "web_service_name not in ansible_facts.services"
|
||||||
|
|
||||||
|
- name: 1.9 - Get current NC status (and check if installed)
|
||||||
|
command: "{{ php_cli_path }} occ status"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
register: occ_status
|
register: occ_status
|
||||||
changed_when: false
|
changed_when: false
|
||||||
failed_when: "'installed: true' not in occ_status.stdout"
|
failed_when: "'installed: true' not in occ_status.stdout"
|
||||||
|
|
||||||
- name: Parse and show current version
|
- name: 1.10 - Parse and show current version
|
||||||
set_fact:
|
set_fact:
|
||||||
current_version: "{{ occ_status.stdout | regex_search('versionstring: (.*)', '\\1') | first | default('unknown') }}"
|
current_version: "{{ occ_status.stdout | regex_search('versionstring: (.*)', '\\1') | first | default('unknown') }}"
|
||||||
when: occ_status.stdout is defined
|
when: occ_status.stdout is defined
|
||||||
|
|
||||||
- name: Show current version
|
- name: 1.11 - Show current version
|
||||||
debug:
|
debug:
|
||||||
msg: "Current Nextcloud version: {{ current_version }}"
|
msg: "Current Nextcloud version: {{ current_version }}"
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Step 2: Disable 3rd party apps
|
# 🔄 STAGE 2: PRE-UPGRADE PREPARATION
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
- name: Get list of installed apps
|
- name: 2.1 - Backup Reminder
|
||||||
command: "{{ php_cli }} occ app:list"
|
debug:
|
||||||
|
msg: "⚠️ CRITICAL: Ensure you have valid DB + data directory backups BEFORE PROCEEDING!"
|
||||||
|
|
||||||
|
- name: 2.2 - Pause playbook for 10 seconds to allow cancellation
|
||||||
|
pause:
|
||||||
|
seconds: 10
|
||||||
|
prompt: "Press Ctrl+C and then 'A' to abort if you do not have backups."
|
||||||
|
|
||||||
|
- name: 2.3 - Get list of installed apps
|
||||||
|
command: "{{ php_cli_path }} occ app:list"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
register: app_list
|
register: app_list
|
||||||
changed_when: false
|
changed_when: false
|
||||||
|
|
||||||
- name: Disable all non-core 3rd party apps
|
- name: 2.4 - Disable all non-core 3rd party apps
|
||||||
command: "{{ php_cli }} occ app:disable {{ item }}"
|
command: "{{ php_cli_path }} occ app:disable {{ item }}"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
loop: "{{ app_list.stdout_lines | select('match', '^[ ]*-[ ](.*):[ ]enabled$') | map('regex_replace', '^[ ]*-[ ](.*):[ ]enabled$', '\\1') | list }}"
|
loop: "{{ app_list.stdout_lines | select('match', '^[ ]*-[ ](.*):[ ]enabled$') | map('regex_replace', '^[ ]*-[ ](.*):[ ]enabled$', '\\1') | list }}"
|
||||||
register: app_disable_result
|
register: app_disable_result
|
||||||
when: item not in core_apps
|
when: item not in core_apps
|
||||||
ignore_errors: yes # Don't fail if an app can't be disabled
|
ignore_errors: yes # Don't fail if an app can't be disabled
|
||||||
|
|
||||||
- name: Save list of successfully disabled apps for re-enabling
|
- name: 2.5 - Save list of successfully disabled apps
|
||||||
set_fact:
|
set_fact:
|
||||||
disabled_apps: "{{ app_disable_result.results | selectattr('changed', 'defined') | selectattr('changed') | map(attribute='item') | list }}"
|
disabled_apps: "{{ app_disable_result.results | selectattr('changed', 'defined') | selectattr('changed') | map(attribute='item') | list }}"
|
||||||
when: app_disable_result is defined and app_disable_result.results is defined
|
when: app_disable_result is defined and app_disable_result.results is defined
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Step 3: Begin Upgrade Transaction Block
|
# 🚀 STAGE 3: TRANSACTIONAL UPGRADE BLOCK
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
- name: Perform Nextcloud Upgrade (Transactional)
|
- name: 3.0 - Perform Nextcloud Upgrade (Transactional)
|
||||||
block:
|
block:
|
||||||
|
|
||||||
- name: Check if maintenance mode is already active
|
- name: 3.1 - Enable maintenance mode
|
||||||
command: "{{ php_cli }} occ maintenance:mode"
|
command: "{{ php_cli_path }} occ maintenance:mode --on"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
register: maint_status
|
|
||||||
changed_when: false
|
|
||||||
failed_when: false # Don't fail, just check output
|
|
||||||
|
|
||||||
- name: Enable maintenance mode
|
|
||||||
command: "{{ php_cli }} occ maintenance:mode --on"
|
|
||||||
args:
|
|
||||||
chdir: "{{ nextcloud_dir }}"
|
|
||||||
become_user: "{{ web_user }}"
|
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
when: "'maintenance mode is not active' in maint_status.stdout"
|
|
||||||
|
|
||||||
- name: Run Nextcloud CLI updater (with retry logic)
|
- name: 3.2 - Run Nextcloud CLI updater (with retry logic)
|
||||||
command: "{{ php_cli }} updater/updater.phar --no-interaction"
|
command: "{{ php_cli_path }} updater/updater.phar --no-interaction"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
register: updater_result
|
register: updater_result
|
||||||
until:
|
until:
|
||||||
@@ -126,93 +169,93 @@
|
|||||||
- "'Update successful' in updater_result.stdout or 'Nextcloud is already latest version' in updater_result.stdout"
|
- "'Update successful' in updater_result.stdout or 'Nextcloud is already latest version' in updater_result.stdout"
|
||||||
retries: 3
|
retries: 3
|
||||||
delay: 10
|
delay: 10
|
||||||
# This is the final failure check for the updater itself
|
|
||||||
failed_when:
|
failed_when:
|
||||||
- updater_result.rc != 0
|
- updater_result.rc != 0
|
||||||
- "'Nextcloud is already latest version' not in updater_result.stdout"
|
- "'Nextcloud is already latest version' not in updater_result.stdout"
|
||||||
|
|
||||||
- name: Run occ upgrade
|
- name: 3.3 - Run occ upgrade (This is the most critical step)
|
||||||
command: "{{ php_cli }} occ upgrade"
|
command: "{{ php_cli_path }} occ upgrade"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
# CRITICAL: Do NOT ignore errors here. This is the main failure point.
|
# CRITICAL: Do NOT ignore errors here. If this fails, we must stop.
|
||||||
|
|
||||||
- name: Add missing indices (optional cleanup)
|
- name: 3.4 - Run optional cleanup commands
|
||||||
command: "{{ php_cli }} occ db:add-missing-indices"
|
command: "{{ item }}"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
ignore_errors: yes
|
loop:
|
||||||
|
- "{{ php_cli_path }} occ db:add-missing-indices"
|
||||||
|
- "{{ php_cli_path }} occ db:convert-filecache-bigint --no-interaction"
|
||||||
|
ignore_errors: yes # These are optional, so we ignore failures
|
||||||
|
|
||||||
- name: Convert filecache bigint fields (optional cleanup)
|
- name: 3.5 - Disable maintenance mode (SUCCESS)
|
||||||
command: "{{ php_cli }} occ db:convert-filecache-bigint --no-interaction"
|
command: "{{ php_cli_path }} occ maintenance:mode --off"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
|
||||||
ignore_errors: yes
|
|
||||||
|
|
||||||
- name: Disable maintenance mode (SUCCESS)
|
|
||||||
command: "{{ php_cli }} occ maintenance:mode --off"
|
|
||||||
args:
|
|
||||||
chdir: "{{ nextcloud_dir }}"
|
|
||||||
become_user: "{{ web_user }}"
|
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
|
|
||||||
- name: Re-enable previously disabled 3rd party apps
|
- name: 3.6 - Re-enable previously disabled 3rd party apps
|
||||||
command: "{{ php_cli }} occ app:enable {{ item }}"
|
command: "{{ php_cli_path }} occ app:enable {{ item }}"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
loop: "{{ disabled_apps | default([]) }}"
|
loop: "{{ disabled_apps | default([]) }}"
|
||||||
when: disabled_apps is defined and disabled_apps | length > 0
|
when: disabled_apps is defined and disabled_apps | length > 0
|
||||||
ignore_errors: yes # Don't let a single app fail the whole restart
|
ignore_errors: yes # Don't let a single app fail the whole restart
|
||||||
|
|
||||||
- name: Restart web service
|
- name: 3.7 - Restart web service
|
||||||
service:
|
service:
|
||||||
name: "{{ service_name }}"
|
name: "{{ web_service_name }}"
|
||||||
state: restarted
|
state: restarted
|
||||||
|
|
||||||
- name: Check new Nextcloud version
|
- name: 3.8 - Verify new version
|
||||||
command: "{{ php_cli }} occ status"
|
command: "{{ php_cli_path }} occ status"
|
||||||
args:
|
args:
|
||||||
chdir: "{{ nextcloud_dir }}"
|
chdir: "{{ nextcloud_dir }}"
|
||||||
become_user: "{{ web_user }}"
|
become_user: "{{ nc_web_user }}"
|
||||||
environment: "{{ occ_env }}"
|
environment: "{{ occ_env }}"
|
||||||
register: occ_status_after
|
register: occ_status_after
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
- name: Display new version info
|
- name: 3.9 - Display new version info
|
||||||
debug:
|
debug:
|
||||||
var: occ_status_after.stdout
|
var: occ_status_after.stdout
|
||||||
|
|
||||||
- name: ✅ Upgrade Complete
|
- name: 3.10 - ✅ Upgrade Complete
|
||||||
debug:
|
debug:
|
||||||
msg: "Nextcloud successfully upgraded!"
|
msg: "Nextcloud successfully upgraded!"
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Step 4: Rescue Block (This ONLY runs if the 'block' above fails)
|
# 🆘 STAGE 4: RESCUE BLOCK (This ONLY runs if STAGE 3 fails)
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
rescue:
|
rescue:
|
||||||
|
|
||||||
- name: ❌ UPGRADE FAILED - REPORTING
|
- name: ❌ UPGRADE FAILED - REPORTING
|
||||||
debug:
|
debug:
|
||||||
msg: |
|
msg: |
|
||||||
!!!!!!!!!! UPGRADE FAILED !!!!!!!!!!
|
!!!!!!!!!! CRITICAL UPGRADE FAILURE !!!!!!!!!!
|
||||||
|
|
||||||
|
The playbook has failed during the upgrade block.
|
||||||
The server is being LEFT IN MAINTENANCE MODE for manual inspection.
|
The server is being LEFT IN MAINTENANCE MODE for manual inspection.
|
||||||
|
|
||||||
Host: {{ inventory_hostname }}
|
Host: {{ inventory_hostname }}
|
||||||
|
Discovered Web User: {{ nc_web_user }}
|
||||||
|
|
||||||
Please SSH to the host and check logs to fix manually.
|
Please SSH to the host and check logs to fix manually.
|
||||||
|
|
||||||
Logs to check:
|
Logs to check:
|
||||||
- {{ nextcloud_dir }}/data/updater.log
|
- {{ nextcloud_dir }}/data/updater.log
|
||||||
- {{ nextcloud_dir }}/data/nextcloud.log
|
- {{ nextcloud_dir }}/data/nextcloud.log
|
||||||
|
|
||||||
Run '{{ php_cli }} occ maintenance:mode --off' manually when fixed.
|
Once fixed, run this command manually as the web user:
|
||||||
|
'{{ php_cli_path }} occ maintenance:mode --off'
|
||||||
|
|
||||||
- name: Fail the playbook run
|
- name: 4.1 - Fail the playbook run
|
||||||
fail:
|
fail:
|
||||||
msg: "Nextcloud upgrade failed. Host is in maintenance mode."
|
msg: "Nextcloud upgrade failed. Host is in maintenance mode."
|
||||||
Reference in New Issue
Block a user