Updating an existing installation - wiso-forschungslabor/hroot-documentation GitHub Wiki

Updating an Existing Installation

This guide covers all update workflows for hroot, ranging from seamless One-Click In-App updates to manual bare-metal command-line upgrades.

Important

Safety First: Before performing any update or schema migration, always ensure a full database backup (mysqldump) and a copy of your uploaded files (uploads/) exist.


Table of Contents


Update Methods Comparison Matrix

The table below explains what actions are required across the four different update methods:

Step / Action 1. In-App Auto-Update 2. Docker Precompiled Image 3. Docker Source Build 4. Manual Bare-Metal Update
Trigger Mechanism Admin Web UI button docker compose pull docker compose up -d --build Manual shell commands
Safety DB Snapshot Automated (Pre-update dump) Manual command Manual command Manual command
bundle install Pre-packaged in Image (0s) Pre-packaged in Image (0s) Automated in Docker build stage Manual bundle install
assets:precompile Pre-compiled in Image (0s) Pre-compiled in Image (0s) Automated in Docker build stage Manual rake assets:precompile
Database Migrations Automated in isolated container Automated via container entrypoint Executed via bin/rails db:migrate Manual rake db:migrate
Background Cronjobs Automated (cron container) Automated (cron container) Automated (cron container) Manual whenever --update-crontab
Web Server Restart Automated (Zero-downtime reload) Automated container restart Automated container restart touch tmp/restart.txt / systemd
Health Check & Rollback Automated 5-stage rollback Manual container rollback Manual git rollback Manual database & code restore

1. In-App One-Click Auto-Update (Admin UI)

Best for: Production installations using standard Docker deployment (ghcr.io image).

Administrators can check for updates and trigger upgrades directly within the web interface without opening a server terminal:

  1. Sign in as a Banking Administrator.
  2. Navigate to Admin $\rightarrow$ Options $\rightarrow$ System Check & Updates (/admin/options/check).
  3. The system compares your installed Git commit against the latest release on GitHub:
    • System is up to date: No action required.
    • Update Available: Displays the new version, commit message, and changes.
  4. Click Update System Now to trigger the automated 5-stage update pipeline:
    • Stage 1 (Database Snapshot): A safety dump of your MySQL database is saved to tmp/backups/.
    • Stage 2 (Image Download): The new Docker image layer is downloaded from ghcr.io in background.
    • Stage 3 (Schema Migration): Database migrations (db:migrate) execute safely inside an isolated container.
    • Stage 4 (Health Check): The new application container starts and polls readiness for up to 180 seconds.
    • Stage 5 (Automatic Rollback): If any error occurs or the health check fails, the previous image and database state are restored automatically.

Tip

Security & Rootless Docker: When running under Rootless Docker, the updater container communicates with the user-space Docker socket without root privileges, combining convenient In-App updates with strict host-level isolation. On standard Docker engines, ensure deployment commands are executed via sudo docker compose instead of adding users to the docker group.
Migrating an existing setup? See Migrating an Existing Docker Installation to Rootless Docker for a quick 3-minute guide.


2. Docker Update with Precompiled Image (docker compose pull)

Best for: Production Docker setups managed via command line or automated server cronjobs.

  1. Create a quick database backup:
    docker compose exec db mysqldump -u hroot -p${DATABASE_PASSWORD} ${DATABASE_NAME:-hroot_production} > backup_pre_update_$(date +%F).sql
  2. Pull the latest precompiled Docker image from ghcr.io:
    docker compose pull
  3. Restart containers with the updated image:
    docker compose up -d
    The container entrypoint automatically executes db:prepare to apply any new database schema migrations.
  4. Verify container logs:
    docker compose logs -f web cron

3. Docker Update with Source Code Build (docker compose up -d --build)

Best for: Laboratories running custom code modifications, forks, or self-compiled deployments.

  1. Create a database backup:
    docker compose exec db mysqldump -u hroot -p${DATABASE_PASSWORD} ${DATABASE_NAME:-hroot_production} > backup_pre_update_$(date +%F).sql
  2. Pull latest source code updates:
    git pull origin master  # or your customized branch / tag
  3. Check for new environment variables:
    diff -u .env .env.example
  4. Rebuild the Docker image and restart services:
    docker compose up -d --build
    Docker compiles new Ruby gems and precompiles frontend assets during the multi-stage build process.
  5. Run database migrations:
    docker compose exec web bin/rails db:migrate
  6. Verify operation:
    docker compose logs -f web cron

4. Manual Bare-Metal Update (Legacy CLI)

Best for: Legacy servers without Docker (running directly on Ubuntu with native Ruby, rbenv, Passenger/Puma, and MySQL).

Follow these steps sequentially:

  1. Create a full database backup:
    mysqldump -u <db_user> -p <db_name> > backup_pre_update_$(date +%F).sql
  2. (Optional) Enable Maintenance Page:
    RAILS_ENV=production bundle exec rake rack:turnout:down[reason="Scheduled Maintenance Update"]
  3. Pull latest source code:
    git pull origin master
  4. Check environment variables:
    diff -u .env .env.example
  5. Check Ruby version:
    Ensure your active Ruby matches .ruby-version (e.g. 4.0.6):
    ruby -v
    # If an upgrade is required: rbenv install 4.0.6 && rbenv global 4.0.6
  6. Install / Update Ruby Gems:
    bundle install
  7. Run Database Migrations:
    RAILS_ENV=production bin/rails db:migrate
  8. Recompile Frontend Assets:
    RAILS_ENV=production bin/rails assets:clobber
    RAILS_ENV=production bin/rails assets:precompile
  9. Update Background Jobs in Crontab (whenever):
    RAILS_ENV=production bundle exec whenever --update-crontab
  10. Restart the Web Server:
    • Phusion Passenger:
      touch tmp/restart.txt
    • Systemd / Puma / NGINX / Apache:
      sudo systemctl restart hroot nginx   # or apache2
  11. Disable Maintenance Page:
    RAILS_ENV=production bundle exec rake rack:turnout:up

5. Major Version Migration: Upgrading from Legacy hroot (v3.x) to v4.0

If your laboratory is upgrading from an older major version of hroot (v2.x / v3.x with hardcoded settings in production.rb, database.yml, RVM, and bare-metal Apache/Passenger), choose one of the following two dedicated upgrade paths:

Path A: Migrate from Legacy Bare-Metal to Modern Docker v4.0 (Recommended)

Switch your installation to containerized Docker deployment for 1-click updates, isolated dependencies, and zero maintenance overhead.

Path B: Upgrade Legacy Bare-Metal to Bare-Metal v4.0 (Native Non-Docker)

Keep your installation running directly on the Linux host with system Ruby, rbenv, Passenger/Puma, and MySQL, while upgrading the codebase to v4.0 and migrating configuration into .env.


6. Merging Upstream Updates & Building Images for Custom Forks

If your laboratory or institution maintains a custom fork of hroot (e.g. https://github.com/<your-account>/hroot):

Caution

Strict Privacy & Licensing Notice: Any Docker images built from your fork on GitHub Container Registry (ghcr.io) MUST remain Private (Private Packages). Making the container image public makes the underlying source code accessible to the public, which constitutes a violation of the software license / terms of use. Ensure in your GitHub Package Settings that the image visibility is set to Private.


Step 1: Merge Upstream Updates into Your Fork

To pull in updates published to the official wiso-forschungslabor/hroot repository:

  1. Commit any local custom changes:
    git status
    git add . && git commit -m "Save local customizations"
  2. Add upstream repository as a remote (one-time setup):
    git remote add upstream https://github.com/wiso-forschungslabor/hroot.git
  3. Fetch and merge latest upstream releases:
    git fetch upstream
    git merge upstream/master
  4. Push the merged changes to your fork:
    git push origin master  # or your customized branch

Step 2: Build the Docker Image in Your Fork

You can build and publish your customized Docker image to ghcr.io/<your-account>/hroot using GitHub Actions:

  1. Enable GitHub Actions in your Fork (one-time setup):
    • Go to your forked repository on GitHub $\rightarrow$ Actions tab.
    • Click "I understand my workflows, go ahead and enable them" if prompted.
  2. Trigger the Docker Build:
    • Option A (Via Git Tag): Create and push a version tag matching v*:
      git tag v4.1.0-myCustomVersion
      git push origin v4.1.0-myCustomVerision
    • Option B (Manual UI Trigger): Go to GitHub $\rightarrow$ Actions $\rightarrow$ select "Build and Publish Docker Image" $\rightarrow$ click Run workflow $\rightarrow$ select your branch and click Run workflow.

GitHub Actions will automatically build the image and push it to ghcr.io/<your-account>/hroot.


Step 3: Configure HROOT to Use Your Fork Image & Update Routine

To allow your server and the built-in In-App One-Click Update Routine (or docker compose pull) to track your custom fork (one-time-setup, after that, the system will automatically use that fork & Branch to check for updates):

  1. Configure your server's .env file:

    # Point Docker Compose to your fork's image
    HROOT_IMAGE=ghcr.io/<your-account>/hroot:latest
    
    # Point the In-App Update Checker to your GitHub repository and branch
    UPDATE_GITHUB_REPO=<your-account>/hroot
    UPDATE_BRANCH=master  # or your tracking branch
  2. Authenticate Docker with GitHub Container Registry (for Private Packages): Since your fork's image is private, log in with a GitHub Personal Access Token (PAT with read:packages scope):

    echo $GITHUB_PAT | docker login ghcr.io -u <your-github-username> --password-stdin
  3. Deploy or Update:

    • Via Web UI: Go to Admin $\rightarrow$ Options $\rightarrow$ System Check & Updates and click Update System Now.
    • Via Terminal: Run:
      docker compose pull && docker compose up -d

7. Changing the Update Path (Switching from Upstream to Custom Fork or Branch)

If your installation previously pulled updates from the official upstream repository (ghcr.io/wiso-forschungslabor/hroot:latest / wiso-forschungslabor/hroot on master) and you now want to switch to a custom fork (or switch between different branches such as master $\leftrightarrow$ staging), follow this step-by-step migration procedure.

Why Switch the Update Path?

  • Your laboratory created a custom fork (e.g. https://github.com/<your-account>/hroot) to implement institutional customizations, custom themes, or specialized integrations.
  • You built your own Docker images via GitHub Actions and want your running server (and the In-App Update button) to follow your fork's release cycle instead of the official upstream repository.
  • You want to test a pre-release branch (e.g., feature/custom-auth or staging) before rolling it out to production.

Step-by-Step Procedure to Change the Update Path

Step 1: Ensure Your Fork Image is Built & Host is Authenticated

  1. In your GitHub fork repository, ensure the Docker build workflow has executed successfully (via GitHub Actions) and pushed an image to ghcr.io/<your-account>/hroot:<tag>.
  2. Confirm the package visibility in GitHub is set to Private (mandatory per license).
  3. On your production server host, ensure Docker is authenticated with GitHub Container Registry using a Personal Access Token (PAT) with read:packages permissions:
    echo "<YOUR_GITHUB_PAT>" | docker login ghcr.io -u <YOUR_GITHUB_USERNAME> --password-stdin

Step 2: Update Server Configuration (.env)

Open .env in the root of your hroot deployment on the server and adjust the update path variables:

# 1. Target Docker image repository and tag
HROOT_IMAGE=ghcr.io/<your-account>/hroot:latest

# 2. GitHub repository checked for new commits & version comparison
UPDATE_GITHUB_REPO=<your-account>/hroot

# 3. Branch tracked for updates (e.g. master, staging, or custom branch)
UPDATE_BRANCH=master

Note

  • HROOT_IMAGE: Tells docker-compose.yml which container image to download and run for the web and cron services.
  • UPDATE_GITHUB_REPO and UPDATE_BRANCH: Tell the in-app version checker (/admin/options/check) which GitHub repository and branch API to query when checking if a newer commit is available.

Step 3: Create a Pre-Switch Safety Database Backup

Before transitioning to the new image, always create an explicit database backup:

docker compose exec db mysqldump -u hroot -p${DATABASE_PASSWORD} ${DATABASE_NAME:-hroot_production} > backup_pre_switch_$(date +%F).sql

Step 4: Pull New Image and Recreate Services

Execute the transition by pulling the newly configured image and restarting the stack:

# 1. Pull the new image from your fork
docker compose pull

# 2. Recreate containers with the new image and reloaded .env configuration
docker compose up -d

Tip

On container startup, the entrypoint script automatically runs bin/rails db:prepare (db:migrate), applying any new database migrations introduced in your custom fork.

Step 5: Verify the Switched Update Path in the Admin UI

  1. Sign in as a Banking Administrator.
  2. Go to Admin $\rightarrow$ Options $\rightarrow$ System Check & Updates (/admin/options/check).
  3. Verify that:
    • The GitHub Repository now links to https://github.com/<your-account>/hroot.
    • The Tracked Branch shows your configured branch (master).
    • The Commit Comparison compares your running container against the latest commit in your custom fork.

Switching Back to Upstream or Between Branches

To switch back to the official upstream repository or to a different branch at any time:

  1. Edit .env to restore:
    HROOT_IMAGE=ghcr.io/wiso-forschungslabor/hroot:latest
    UPDATE_GITHUB_REPO=wiso-forschungslabor/hroot
    UPDATE_BRANCH=master
  2. Run docker compose pull && docker compose up -d.
  3. Check /admin/options/check to confirm the upstream update path is active again.
⚠️ **GitHub.com Fallback** ⚠️