Automating Manual Nextcloud Upgrades – closingtags </>
Automation Homelab Security Server

Automating Manual Nextcloud Upgrades

The #Nextcloud upgrade process never works for me and I always end up having to walk through the manual upgrade process step-by-step. After yet another failed update, I decided it was time to #automate the process using #ansible.

I know it’s been a long time since I’ve posted here but I have a good reason, I swear. I’ve been busy on another big project for the past several months that I hope to announce soon.

But until then, let’s talk about what a pain it has been for me to upgrade Nextcloud.

What is Nextcloud?

Nextcloud is an open source cloud solution. It allows users to sync files to a central location that can then be accessed from computers or mobile devices anywhere. Along with file sync functionality, it also provides a calendar, contacts, task management, and various other features like video chat that can be included through apps installed on the system. Think of it like a Google or Microsoft account but instead of being run on Big Tech’s Cloud©, it can be run on a computer in your home.

But why?

The advantages of running one’s own Nextcloud instance are plentiful. One reason is to have access to a nearly unlimited amount of storage data. The roughly 11TB of capacity at my disposal dwarfs the free tier limit of 15GB allotted from Google Drive. I could pay Google for more storage space but then I would always be beholden to their terms and conditions, which means I could be locked out of my account at any point and lose access to my data. With Nextcloud, I control my data.

homelab noun

A collection of computers used for learning about about system administration that typically pushes the operator to insanity or poverty.

Nothing is free

But it’s not all fun and games. For instance, having my own Nextcloud instance means that I have to operate and maintain the server that powers it. That means applying updates to the underlying server as well as the Nextcloud server software. And while Nextcloud itself is consistent and reliable, the included update process is not. For me, it frequently fails when performing updates via the provided administrative web interface. This may not be the case for others (I suspect it has something to do with my installation or configuration) but it so reliably fails me, that I’ve completely given up on using the web updater and instead prefer to upgrade the server software manually. This process is involved and time consuming. To get an idea of how to upgrade Nextcloud manually, see this list of steps I have to take each time I want to apply an update:

Nextcloud Manual Upgrade

  1. SSH into the server
  2. Navigate to Nextcloud directory:
    cd /var/www/
  3. Download next release:
  4. Unpack release to /var/www/nextcloud/:
    tar -xjf nextcloud...tar.bz2
  5. Stop web server:
    service nginx stop
  6. Disable background jobs by commenting out last line cron job:
    crontab -u www-data -e
  7. Backup old Nextcloud installation by moving it:
    mv /var/www/current-nextcloud-install/ /var/www/old-nextcloud-install/
  8. Move new release into current installation directory:
    mv /var/www/nextcloud/ /var/www/current-nextcloud-install/
  9. Copy old installation configuration:
    cp /var/www/old-nextcloud-install/config/config.php /var/www/current-nextcloud-install/config/config.php
  10. Copy old apps to new installation:
    cp -r /var/www/old-nextcloud-install/apps/ /var/www/current-nextcloud-install/

    I’ve previously used this handy command to see which apps are in need of being installed:
    diff -q /var/www/old-nextcloud-install/apps/ /var/www/current-nextcloud-install/apps/ | grep "Only in"

  11. Fix ownership of the application:
    chown -R www-data:www-data /var/www/current-nextcloud-install/
  12. Fix directory permissions:
    find /var/www/current-nextcloud-install/ -type d -exec chmod 750 {} \;
  13. Fix file permissions:
    find /var/www/current-nextcloud-install/ -type f -exec chmod 640 {} \;
  14. Restart the web server:
    service nginx start
  15. Run Nextcloud upgrade script as www-data user:
    sudo -u www-data php /var/www/current-nextcloud-install/occ upgrade
  16. Re-enable background jobs in cron by uncommenting last line:
    crontab -u www-data -e

Whew! While none of these steps are particularly difficult on their own, they become a pain when combined. Especially since Nextcloud doesn’t support skipping versions. If your installation falls behind by a couple version, prepare to do this multiple times before you’re caught up 😩.

Automation to the Rescue

Over the years of operating my homelab, I’ve learned many things. The most important takeaway is that maintaining server infrastructure manually is a colossal waste of time. If you have to do something more than once, it should be automated.

XKCD comic about automation. At the top, it reads "I spend a lof of time on this task. I should write a program automating it!" followed by line graphs outlining theory and reality. Theory shows automation saving time while reality depicts the ongoing development and neverending struggle of maintaining the automation program.

Because Nextcloud is updated so frequently, I decided to automate it all with Ansible! I’ve written about automation with Ansible before so if you’re unfamiliar, check out my other posts. I could always go back to trying to update Nextcloud via the web interface but at this point, I’ve lost all hope it will ever succeed. Instead, I’ve taken the manual upgrade steps and put them into an Ansible role. If you’re want thee. If you have to do something more than once, it should be automated. code, I’ve updated my Ansible Proxmox Automation repository on GitHub. That repository contains the full playbook (books/update-nextcloud.yml), which performs a backup of the container before beginning the upgrade; as well as the role (roles/nextcloud/tasks/main.yml) which runs through the manual upgrade steps. If you don’t like GitHub, I’ve provided a generalized role that achieves the same results as the manual upgrade steps below:

Note! The playbook that calls this role must include a vars_prompt to accept the URL for the archive to download. Otherwise, you’d have to change the playbook each time.

- name: Unpack remote release file to /var/www/nextcloud/
    remote_src: true
    src: '{{ release }}'
    dest: /var/www/

- name: Stop webserver
   name: nginx
   state: stopped

- name: Remove cron
    name: cloudcron
    user: www-data
    state: absent

- name: Move old install
    src: /var/www/current/
    dest: /var/www/old/
    remote_src: true
    follow: true

- name: Remove old install folder
    path: /var/www/current/
    state: absent

- name: Move new install
    src: /var/www/nextcloud/
    dest: /var/www/current/
    remote_src: true

- name: Copy config from old install to new
    src: /var/www/old/config/config.php
    dest: /var/www/current/config/config.php
    remote_src: true

- name: Copy apps from old install to new
    src: /var/www/old/apps/
    dest: /var/www/current/apps/
    remote_src: true

- name: Fix ownership
    path: /var/www/current/
    owner: www-data
    group: www-data
    recurse: yes
    state: directory
    follow: false

- name: Fix directory permissions
  command: find /var/www/current/ -type d -exec chmod 750 {} \;

- name: Fix file permissions
  command: find /var/www/current/ -type f -exec chmod 640 {} \;

- name: Start webserver
    name: nginx
    state: started

- name: Run nextcloud upgrade CLI
  command: sudo -u www-data php /var/www/current/occ upgrade

- name: Add cron
    name: cloudcron
    user: www-data
    job: 'php -f /var/www/current/cron.php'
    minute: '*/5'
    state: present

For all you other homelabbers out there, I hope this saves you some time so you can get back to tinkering and enjoy yourself instead of beating your head against the wall.

Some issues I’ve encountered

  • Symlinks – I used to symlink my data directory but apparently Nextcloud hasn’t allowed that since many versions before I was doing it. Its easy enough to get around this by specifying the data/ directory within the Nextcloud configuration file.
  • Broken installation after upgrade – I’ve had a few installations that are broken after upgrading where not even the occ command line interface will run. In my experience, this is due to apps being copied over. Removing the apps/ directory, copying in the fresh version from the archive, and continuing the upgrade has typically resolved this issue.
  • PHP – Newer versions of Nextcloud (26+)require newer versions of PHP (8.0+). This role does not account for that.

By Dylan Hildenbrand

Author and full stack web developer experienced with #PHP, #SvelteKit, #JS, #NodeJS, #Linux, #WordPress, and #Ansible. Check out my book at!

Do you like these posts? Consider sponsoring me on GitHub!

Dylan Hildenbrand smiling at the camera. I have tossled, brown hair, rounded glasses, a well-trimmed and short beard. I have light complexion and am wearing a dark sweater with a white t-shirt underneath.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.