Migrating from Legacy Installation to Docker - wiso-forschungslabor/hroot-documentation GitHub Wiki
This guide details the complete migration path for upgrading an existing, older hroot installation (v2.x / v3.x installed directly on bare-metal with Apache/Nginx, Phusion Passenger/Puma, RVM, and legacy settings in config/environments/production.rb) to the modern, containerized hroot v4.0+ Docker architecture.
Before migrating, choose the Docker deployment flavor that best matches your laboratory's infrastructure:
| Feature / Criterion | Option A: Precompiled Docker Image (Recommended) | Option B: Self-Compiled Docker Build (Source Code) |
|---|---|---|
| Best For | Standard production deployments, university labs wanting zero maintenance overhead. | Custom forks, laboratories with local code modifications, or air-gapped environments. |
| Image Source | Pulled pre-built from GitHub Container Registry (ghcr.io). |
Compiled locally on the server from cloned Git repository. |
| Server CPU / RAM Needed | Minimal (No compilation needed on server). | Moderate (Server builds Ruby gems & precompiles assets). |
| Setup Speed | Instant (Seconds to pull & start). | 5–10 minutes (Initial image build time). |
| In-App 1-Click Updates |
Full Support via Admin UI (/admin/options/check). |
Manual / CLI updates (git pull && docker compose up -d --build). |
| Registry Authentication | Requires one-time docker login ghcr.io (for private repos). |
No registry login needed (builds locally). |
| Dedicated Guide | Docker (precompiled) | Docker (self-compiled) |
| Area | Legacy hroot (v2.x / v3.x) | Modern hroot (v4.0+) |
|---|---|---|
| Runtime & Hosting | Direct on Linux host (Apache + Passenger, Puma, RVM) | Docker & Docker Compose (isolated containers) |
| Configuration | Hardcoded in config/environments/production.rb & database.yml
|
Central .env environment variables or Web Setup Wizard
|
| Secrets & Keys | Hardcoded in files or secrets.yml
|
Auto-generated SECRET_KEY_BASE & VAPID keys |
| Background Tasks | Host crontab via manual whenever --update-crontab
|
Automated cron container in Docker Compose |
| Ruby Version | Legacy Ruby 2.7 / 3.0 / 3.2 via RVM | Ruby 3.3 / 4.0 managed automatically inside container |
| Update Process | Manual 10-step CLI procedure on host OS |
1-Click Auto-Update or docker compose pull
|
Before starting the migration, ensure you have:
- Root or
sudoaccess to your server. - Sufficient disk space for database dumps and Docker images (~5–10 GB recommended).
- Scheduled maintenance window for your research laboratory.
- If using Option A (Precompiled Image) with a private repository: A GitHub Personal Access Token (PAT) with
read:packagespermission.
-
Export the Legacy MySQL Database:
mysqldump -u <db_user> -p --single-transaction --routines --triggers <db_name> > ~/hroot_legacy_backup_$(date +%Y%m%d_%H%M).sql
-
Back Up Uploaded Files (Participant Documents, Attachments):
cp -r /path/to/old/hroot/public/uploads ~/hroot_uploads_backup
To prevent background tasks from executing twice or ports (80/443/3000) colliding with Docker:
-
Clear Legacy Host Crontab:
cd /path/to/old/hroot RAILS_ENV=production bundle exec whenever --clear-crontab
-
Stop and Disable Old Web Services:
-
If using Apache / Passenger:
sudo systemctl stop apache2 sudo systemctl disable apache2
-
If using NGINX / Puma / Systemd service:
sudo systemctl stop hroot nginx sudo systemctl disable hroot nginx
-
If using Apache / Passenger:
On your Ubuntu/Debian server:
sudo apt update
sudo apt install docker.io docker-compose-v2 -y
sudo usermod -aG docker $USER
# Log out and back in to apply group changes(Note: docker.io installs the underlying Docker daemon/engine, while docker-compose-v2 installs the modern docker compose CLI orchestration plugin).
-
Clone the modern hroot repository:
git clone https://github.com/wiso-forschungslabor/hroot.git /srv/hroot cd /srv/hroot(If using a custom fork:
git clone https://github.com/<your-account>/hroot.git /srv/hroot)[!NOTE] Why clone the repository when using precompiled Docker images?
Cloning the repository provides the required orchestration configuration files (docker-compose.yml, initialization scriptbin/init-env,.env.example, and directory structure for persistent volume mounts likeuploads/).
When choosing Option A (Precompiled Images), you will not compile any code on your server — Docker Compose directly pulls the pre-built image fromghcr.io. -
Initialize Environment Configuration:
chmod +x bin/init-env ./bin/init-env
This automatically generates secure random keys for
SECRET_KEY_BASE, WebPushVAPIDkeypairs, and internal database passwords. -
Extract Configuration to
.env: Open/path/to/old/hroot/config/environments/production.rband configure your laboratory settings in/srv/hroot/.env:Old Setting in production.rbNew Variable in .envExample config.action_mailer.default_url_options = { host: '...' }APP_DOMAINAPP_DOMAIN=hroot.uni-hamburg.deconfig.action_mailer.smtp_settings = { address: '...' }SMTP_ADDRESSSMTP_ADDRESS=mail.uni-hamburg.deconfig.action_mailer.smtp_settings = { port: ... }SMTP_PORTSMTP_PORT=587config.action_mailer.smtp_settings = { user_name: '...' }SMTP_USER_NAMESMTP_USER_NAME=hroot-mailerconfig.action_mailer.smtp_settings = { password: '...' }SMTP_PASSWORDSMTP_PASSWORD=secretHROOT_SETTINGS[:contact_email]CONTACT_EMAIL[email protected]HROOT_SETTINGS[:sender_email]SENDER_EMAIL[email protected]HROOT_SETTINGS[:log_email]LOG_EMAIL[email protected] -
Choose Your Target Database Architecture:
[!TIP] Architecture Recommendation:
- Option A (External Database Server): If your university or IT department operates a dedicated MySQL/MariaDB database cluster with central backup strategies and high availability, keeping an external database server is the recommended enterprise choice for security and ease of disaster recovery.
-
Option B (Internal Docker MySQL Container): If you want a self-contained all-in-one server with minimal administration overhead, Docker's internal MySQL container (
DATABASE_HOST=db) manages everything in one place.
Use this scenario if you want Docker to manage the database locally on the server (whether your old database was on the host or on an external server):
- Start only the MySQL database container:
docker compose up -d db
- Wait 10 seconds for MySQL initialization, then import your legacy database dump:
docker compose exec -T db mysql -u root -p${MYSQL_ROOT_PASSWORD:-rootpassword} ${DATABASE_NAME:-hroot_production} < ~/hroot_legacy_backup_*.sql
Use this scenario if your existing database remains on a central external database server:
- Set
DATABASE_HOST,DATABASE_USERNAME,DATABASE_PASSWORD, andDATABASE_NAMEin.envto point to your external database server. - No import command is required into Docker — HROOT will connect directly to your existing database during container launch and apply schema migrations in Step 7.
- Verify that your database user permissions permit running migrations (
ALTER TABLE,CREATE TABLE,ADD COLUMN).
Copy the legacy uploads folder (participant documents, attachments) into the new Docker storage volume directory:
cp -r ~/hroot_uploads_backup/* /srv/hroot/uploads/Choose your deployment mode:
- Authenticate with GitHub Container Registry (one-time if using private repo/packages):
docker login ghcr.io -u <your-github-username>
- Start the services:
docker compose up -d
- Build and launch containers locally:
docker compose up -d --build
You can finalize the migration using either the In-Browser Setup Wizard or the CLI:
- Open your browser at
https://<APP_DOMAIN>/setup(orhttp://localhost:3000/setup). - Unlock the wizard using your
HROOT_SETUP_TOKEN(defined in.env). - Select „Upgrade from v3.x to v4.0 (Existing Database)“ in the Setup Type selector at the top.
- Under the Banking-Admin tab:
- If your legacy database does not have a user with the new
banking_adminrole, choose „Promote an existing administrator to Banking-Admin“ from the dropdown list.
- If your legacy database does not have a user with the new
- In the sidebar under Database Status & Schema:
- Click „Test Connection“ — HROOT verifies connectivity, detects your legacy user records, and counts pending v4 migrations.
- Verify under Database & Secrets that your database connection preset (Internal Docker DB vs. External MySQL Server) is configured.
- Click „Run v4 Upgrade & Complete Setup“ — HROOT automatically applies all v4 schema migrations safely (
db:migrate) without altering any participant or experiment data, promotes your administrator account, and completes setup.
Run the schema migrations manually via Docker Compose:
docker compose exec web bin/rails db:migrate-
Verify Services & Cron Container:
Confirm that background tasks (invitation queue, digest emails, IMAP bounce handlers) are operating normally.
docker compose ps docker compose logs -f cron
- Sign in with an existing administrator account.
- Check Admin
$\rightarrow$ Options$\rightarrow$ System Check & Updates (/admin/options/check) to verify environment status. - Create a test experiment session to verify participant booking, email confirmations, and calendar synchronization.