Contao is a Symfony-based, Composer-managed CMS, which means every update touches three things at once: the composer.json/composer.lock package definitions, the PHP framework code, and the database schema. Rushing an upgrade on a live site is the fastest way to trigger a blank screen, a broken database migration, or a plugin conflict that takes your site offline. This guide walks you through a repeatable, low-risk process: create a full snapshot, clone your site to a staging area, run the update through the Contao Manager, apply database migrations safely, and finally automate ongoing backups with cron on Hostiso.

Our stack (LiteSpeed Enterprise, PHP 8.2/8.3/8.4, MariaDB 10.11, Redis object caching on NVMe) handles Contao 5 comfortably, but the discipline below matters regardless of hardware.

Understand the Contao Update Model Before You Touch Anything

Contao 4.13 and Contao 5 use the public/ folder as the document root and are fully Composer-driven. A few rules save you from disaster:

  • Never skip major versions. You must reach the latest minor of your current major before jumping up. For example, a 4.10.x install must first go to 4.13.x before moving to Contao 5 (docs.contao.org).
  • Every update — even a bugfix — may ship template changes and database migrations. Custom templates in templates/ need re-checking after major jumps.
  • Contao 5 dropped automatic detection of the legacy web/ folder, so rename it to public/ (or set public-dir in composer.json) before upgrading (docs.contao.org).

Step 1: Take a Full Snapshot (Files + Database)

Before running any package update, the Contao team explicitly recommends backing up composer.json, composer.lock, and the database (docs.contao.org). Do both the file-level and database-level snapshot from your control panel.

Back up files

DirectAdmin (Evolution):

  • Go to Account Manager → File Manager.
  • Navigate to your Contao project root (the folder that contains composer.json and public/).
  • Select all files, click Compress, and save the archive outside the web root or download it locally.

cPanel (Jupiter):

  • Open Files → File Manager.
  • Browse to the Contao project root, select everything, and click Compress to create a .tar.gz archive, then download it.

Back up the database

DirectAdmin (Evolution):

  • Go to Account Manager → MySQL Management, select your Contao database, and use the Download / export option to save a full SQL dump.

cPanel (Jupiter):

  • Open Databases → phpMyAdmin, select your Contao database, click Export, choose Quick → SQL, and download the file.
Contao also ships a native backup command. From SSH in your project root you can run php vendor/bin/contao-console contao:backup:create to generate a compressed SQL backup in var/backups (docs.contao.org). We automate this later.

Step 2: Build a Staging Clone to Test the Upgrade

Never test upgrades on production. Create an isolated copy under a subdomain such as staging.yourdomain.com.

Create the staging directory and copy files

DirectAdmin (Evolution):

  • Create the subdomain under Account Manager → Domains (or the Subdomains section).
  • Use File Manager to copy your entire project into the new subdomain directory. For Contao 5, point the subdomain document root to .../staging/current/public if you use rolling releases, otherwise to the project's public/ folder.

cPanel (Jupiter):

  • Create the subdomain under Domains → Domains and set its document root to the staging public/ folder.
  • Copy the files with File Manager, or use the built-in Copy feature.

Create and import a staging database

DirectAdmin: Under Account Manager → MySQL Management, create a new database + user (e.g. site_staging), then import your production SQL dump into it.

cPanel: Use Databases → MySQL Databases to create the database and user, assign privileges, then import the dump through phpMyAdmin.

Update the staging .env.local file (or DATABASE_URL) so the clone points to the staging database — never the live one. Confirm the staging site loads before proceeding.

Step 3: Run the Update on Staging via Contao Manager

Log into the Contao Manager on your staging clone (typically staging.yourdomain.com/contao-manager.phar.php). The Manager handles Composer for you, which avoids the memory limits that often kill a raw composer update on shared hosting (docs.contao.org).

  1. For a bugfix release, simply click Update Packages.
  2. For a minor version bump, click the cogwheel icon next to "Contao Open Source CMS", enter the target version, then click Update Packages followed by Apply changes.
  3. Watch the process log via the details icon. The update can take several minutes.

If you are on Cloud VPS with SSH access, you can alternatively run vendor/bin/dep deploy with Deployer for rolling symlink releases and near-zero downtime, in which case the vHost document root should point to current/public (docs.contao.org).

Step 4: Apply Database Migrations Safely

After packages update, the database schema is often out of date. Open the Contao Install Tool (or run migrations from the Contao Manager) and review the proposed SQL changes. Apply only the changes Contao suggests, then close the tool (docs.contao.org).

Via SSH the equivalent commands are:

php vendor/bin/contao-console contao:migrate --dry-run
php vendor/bin/contao-console contao:migrate

Always run the --dry-run first to preview changes. On our LiteSpeed + Redis stack, clear the object cache after migrating so stale entries don't linger:

php vendor/bin/contao-console cache:clear
php vendor/bin/contao-console cache:warmup

Test the staging front end and back end thoroughly: article rendering, forms, custom modules, and any commercial extensions. If an extension isn't unlocked for the new version, evaluate whether a newer major exists or whether you can drop it (docs.contao.org).

Step 5: Promote the Tested Update to Production

Once staging is verified, repeat the exact steps on production during a low-traffic window. Because you already know the migration path and extension outcomes, the live run is predictable. Put Contao into maintenance mode (Back End → System Maintenance) during the short migration window to prevent writes while the schema changes, then disable it once the site is confirmed healthy.

If you hit a white screen or 500 error after promotion, the cause is usually a leftover cache, a PHP version mismatch, or a failed migration — similar troubleshooting logic applies across Symfony-style apps, as covered in our Laravel 500 error guide.

Step 6: Automate Ongoing Backups with Cron

Contao's native backup command is cron-friendly and self-managing — it cleans up old backups based on your retention policy (docs.contao.org). Schedule a daily backup at 23:10.

DirectAdmin (Evolution):

  • Go to Advanced Features → Cron Jobs.
  • Add a new job with minute 10, hour 23, and the command below (adjust the path and PHP binary to match your account).

cPanel (Jupiter):

  • Open Advanced → Cron Jobs.
  • Under Add New Cron Job, set the schedule to 10 23 * * * and paste the command.
10 23 * * * /usr/local/bin/php /home/USER/domains/yourdomain.com/vendor/bin/contao-console contao:backup:create

Confirm the correct PHP path in Extra Features → Select PHP Version (DirectAdmin) or Software → Select PHP Version (cPanel) so the CLI runs on PHP 8.2+.

Tune the retention policy

Edit config/config.yaml in your project to control how many backups are kept and which tables to skip:

contao:
  backup:
    ignore_tables: ['tl_crawl_queue', 'tl_log', 'tl_search', 'tl_search_index', 'tl_search_term']
    keep_max: 5
    keep_intervals: ['1D', '7D', '14D', '1M']

These defaults keep the newest backup plus the oldest per interval, capped at five total (docs.contao.org). Keep keep_max at least one greater than the number of intervals. Backups land in var/backups — periodically pull those off-server for true disaster recovery.

FAQs

Can I run the whole update over SSH instead of the Contao Manager?

Yes, with composer update followed by contao:migrate. However, on shared environments a raw composer update can exceed memory or CPU limits and leave the install half-finished. The Contao Manager (or Deployer on a VPS) is the safer route for constrained accounts.

Do I need to clear Redis and OPcache after upgrading?

Yes. After migrations, run cache:clear and cache:warmup, and if OPcache aggressively caches your PHP files, reload the site or restart the PHP handler so the new code is picked up. Stale caches are the most common cause of "the update ran but nothing changed".

How do I restore if an upgrade fails?

Restore your file archive through File Manager, re-import the pre-update SQL dump via phpMyAdmin (cPanel) or MySQL Management (DirectAdmin), and if you used the native command you can restore the latest backup with php vendor/bin/contao-console contao:backup:restore. Because you tested on staging first, production restores should be rare.