Complete guide for safely migrating your Koha installation between tiers (Free → Basic → Standard → Enterprise) with detailed backup and data migration procedures.
⚠️ Critical: Always test migration procedures on a non-production instance first. Never perform migrations during peak usage hours.
💼 Professional Migration Services Available: Tier migrations are complex processes that require careful planning, testing, and execution. One mistake can result in data loss or extended downtime. We strongly recommend professional assistance for production migrations. Our team has extensive experience migrating Koha instances and can ensure a smooth, zero-data-loss transition. Contact KohaSupport for professional migration services →
Before You Begin
Prerequisites
- Active AWS account with appropriate permissions
- Current Koha instance is operational
- Recent backup of current instance
- Destination tier subscription in AWS Marketplace
- At least 2 hours of scheduled downtime
- Test environment (highly recommended)
Migration Planning
Recommended Timeline:
- Week 1: Set up test environment, practice migration
- Week 2: Finalize migration plan, communicate downtime
- Week 3: Execute migration during low-traffic period
- Week 4: Monitor and optimize new deployment
Downtime Estimate:
- Free/Basic → Standard: 2-4 hours
- Standard → Enterprise: 4-6 hours
- Includes testing time
Migration Overview
Tier Migration Paths
Free Tier (x86)
↓
Basic Tier (ARM64)
↓
Standard Tier (ARM64 + S3 Backups + SSL)
↓
Enterprise Tier (ARM64 + HA + Aurora + ALB)
What Gets Migrated
Always Migrated:
- ✓ Bibliographic records (MARC)
- ✓ Item records
- ✓ Patron accounts
- ✓ Circulation history
- ✓ System preferences
- ✓ Authorized values
- ✓ Library configuration
May Need Manual Migration:
- ⚠️ Cover images (stored in filesystem)
- ⚠️ Custom reports
- ⚠️ Plugin files
- ⚠️ Custom themes
- ⚠️ SSL certificates (if using custom certificates)
Phase 1: Backup Source Instance
Step 1: Create Complete Database Backup
On source instance via EC2 Instance Connect:
Using Official Koha Backup Command (Recommended)
# Connect to source instance
# Go to EC2 Console → Connect → EC2 Instance Connect
# 1. Create backup directory for migration
sudo mkdir -p /home/ubuntu/koha-migration
cd /home/ubuntu/koha-migration
# 2. Use koha-dump to create comprehensive backup
# This creates both SQL dump and config tarball
sudo koha-dump library
# 3. Backup files will be in /var/spool/koha/library/
# Copy to migration directory
sudo cp /var/spool/koha/library/koha-library-*.sql.gz .
sudo cp /var/spool/koha/library/koha-library-*.tar.gz .
# 4. Verify backup files
ls -lh koha-library-*.sql.gz
ls -lh koha-library-*.tar.gz
# SQL file: typically 10MB - 5GB depending on your data
# TAR file: contains config, uploads, cover images
Alternative: Manual mysqldump (For Custom Backups)
# If you need a custom database backup
sudo mysqldump koha_library \
--single-transaction \
--routines \
--triggers \
--events \
--hex-blob \
--default-character-set=utf8mb4 \
> koha_database_$(date +%Y%m%d_%H%M%S).sql
# Compress backup
gzip koha_database_*.sql
ls -lh koha_database_*.sql.gz
For Standard Tier with S3 Backups
Trigger immediate backup before migration:
# Standard tier has automated S3 backups, but trigger manual backup for latest data
sudo koha-run-backups --output /var/spool/koha --days 2
# Backups are automatically uploaded to your S3 bucket
# Verify backup in S3
aws s3 ls s3://your-backup-bucket/
# Download from S3 for migration
aws s3 cp s3://your-backup-bucket/koha-library-$(date +%Y-%m-%d).sql.gz .
aws s3 cp s3://your-backup-bucket/koha-library-$(date +%Y-%m-%d).tar.gz .
💡 Tip: Standard tier automated backups run on schedule (typically daily). Trigger a manual backup before migration to ensure you have the absolute latest data.
Step 2: Export Koha Configuration
If using koha-dump (Step 1), this is already included in the .tar.gz file.
For manual exports:
# Export system preferences (optional if using koha-dump)
sudo mysqldump koha_library systempreferences \
> systempreferences_$(date +%Y%m%d).sql
# Export authorized values
sudo mysqldump koha_library authorised_values \
> authorised_values_$(date +%Y%m%d).sql
# Compress
gzip systempreferences_*.sql
gzip authorised_values_*.sql
Step 3: Backup File Uploads
If using koha-dump with –uploaded_files flag, this is included.
For comprehensive file backup:
# Use koha-dump with file upload options
sudo koha-dump --uploaded_files library
# Or manual backup:
sudo tar -czf koha_uploads_$(date +%Y%m%d).tar.gz \
/var/lib/koha/library/uploads/ \
/var/lib/koha/library/cover_images/ \
2>/dev/null || true
ls -lh koha_uploads_*.tar.gz
Step 4: Document Current Configuration
# Save current configuration details
cat > migration_config.txt << EOF
Source Instance Configuration
============================
Date: $(date)
Koha Version: $(sudo koha-shell -c "perl -MKoha -e 'print Koha::version'" library)
Database Size: $(sudo du -sh /var/lib/mysql/koha_library)
Records Count: $(sudo mysql -N -e "SELECT COUNT(*) FROM biblio" koha_library)
Items Count: $(sudo mysql -N -e "SELECT COUNT(*) FROM items" koha_library)
Patrons Count: $(sudo mysql -N -e "SELECT COUNT(*) FROM borrowers" koha_library)
EOF
cat migration_config.txt
Step 5: Upload Backups to S3
# Create temporary S3 bucket for migration
MIGRATION_BUCKET="koha-migration-$(date +%Y%m%d)-$RANDOM"
# Create bucket (choose your region)
aws s3 mb s3://$MIGRATION_BUCKET --region us-east-1
# Upload all backup files
aws s3 cp koha_database_*.sql.gz s3://$MIGRATION_BUCKET/
aws s3 cp systempreferences_*.sql.gz s3://$MIGRATION_BUCKET/
aws s3 cp authorised_values_*.sql.gz s3://$MIGRATION_BUCKET/
aws s3 cp koha_uploads_*.tar.gz s3://$MIGRATION_BUCKET/
aws s3 cp migration_config.txt s3://$MIGRATION_BUCKET/
# List uploaded files
aws s3 ls s3://$MIGRATION_BUCKET/
# Save bucket name for later
echo $MIGRATION_BUCKET > migration_bucket_name.txt
💡 Tip: Keep the source instance running until migration is complete and tested.
Phase 2: Deploy New Tier
For Standard Tier Migration
- Subscribe to Standard Tier:
- Go to AWS Marketplace
- Subscribe to Koha Standard tier
- Launch CloudFormation:
- Follow Standard Tier Deployment Guide
- Important Parameters:
InstanceType: Match or upgrade from source (e.g.,m8g.medium)EBSVolumeSize: Match or larger than sourceInstallLanguages: Same as source instanceEnableS3Backup:true(recommended)- Leave domain/SSL settings as default initially
- Wait for Deployment:
- Status:
CREATE_COMPLETE(10-15 minutes)
- Status:
For Enterprise Tier Migration
- Request ACM Certificate (if using custom domain):
- Follow Enterprise Step 0
- Wait for validation (5-60 minutes)
- Subscribe to Enterprise Tier:
- AWS Marketplace → Koha Enterprise tier
- Launch CloudFormation:
- Follow Enterprise Tier Deployment Guide
- Important Parameters:
InstanceType:m8g.mediumor largerASGMinSize:2(high availability)ASGDesiredCapacity:2DBAuroraMinACU:0.5(start small, can scale)DBAuroraMaxACU:4(adjust based on load)MultiAZ:true(recommended)
- Wait for Deployment:
- Status:
CREATE_COMPLETE(30-45 minutes)
- Status:
Phase 3: Import Data to New Instance
Step 1: Connect to New Instance
# Get new instance ID from CloudFormation Outputs
# Connect via EC2 Instance Connect
# For Enterprise: Connect to any instance in Auto Scaling Group
Step 2: Download Backups from S3
# Create working directory
mkdir -p /home/ubuntu/koha-migration
cd /home/ubuntu/koha-migration
# Get migration bucket name (from Phase 1)
MIGRATION_BUCKET="koha-migration-YYYYMMDD-XXXXX" # Replace with your bucket
# Download all backup files
aws s3 sync s3://$MIGRATION_BUCKET/ ./
# Verify downloads
ls -lh
Step 3: Prepare New Koha Instance
# Stop Koha services temporarily
sudo koha-plack --stop library
sudo koha-worker --stop library
# Backup the fresh installation (safety net)
sudo mysqldump koha_library > koha_library_fresh_install.sql
Step 4: Import Database
Choose your import method:
Method A: Using koha-restore (Recommended)
# koha-restore requires SQL dump and config tarball
# Files from koha-dump: koha-library-YYYY-MM-DD.sql.gz and koha-library-YYYY-MM-DD.tar.gz
# Note: You must koha-remove the instance first if it exists
# WARNING: This deletes the existing instance!
# sudo koha-remove library
# Restore from backups (creates fresh instance)
sudo koha-restore koha-library-*.sql.gz koha-library-*.tar.gz
# Verify import
sudo koha-mysql library -e "SELECT COUNT(*) AS 'Total Records' FROM biblio;"
sudo koha-mysql library -e "SELECT COUNT(*) AS 'Total Items' FROM items;"
sudo koha-mysql library -e "SELECT COUNT(*) AS 'Total Patrons' FROM borrowers;"
Method B: Manual Database Replace
# Decompress backup
gunzip koha-library-*.sql.gz
# Drop and recreate database (CAREFUL!)
sudo mysql -e "DROP DATABASE koha_library;"
sudo mysql -e "CREATE DATABASE koha_library CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
# Get password from koha-conf.xml
KOHA_PASS=$(sudo xmlstarlet sel -t -v 'yazgfs/config/pass' /etc/koha/sites/library/koha-conf.xml)
# Grant permissions
sudo mysql -e "DROP USER IF EXISTS 'koha_library'@'localhost';"
sudo mysql -e "CREATE USER 'koha_library'@'localhost' IDENTIFIED BY '$KOHA_PASS';"
sudo mysql -e "GRANT ALL PRIVILEGES ON koha_library.* TO 'koha_library'@'localhost';"
sudo mysql -e "FLUSH PRIVILEGES;"
# Import database
sudo mysql koha_library < koha-library-*.sql
# Verify import
sudo mysql koha_library -e "SELECT COUNT(*) AS 'Total Records' FROM biblio;"
sudo mysql koha_library -e "SELECT COUNT(*) AS 'Total Items' FROM items;"
sudo mysql koha_library -e "SELECT COUNT(*) AS 'Total Patrons' FROM borrowers;"
Method B: Selective Import (Advanced)
# Import only specific tables
sudo mysql koha_library < systempreferences_*.sql
sudo mysql koha_library < authorised_values_*.sql
# Import data tables individually
sudo mysqldump --no-create-info --skip-triggers \
koha_library biblio biblioitems items \
< koha_database_*.sql
Step 5: Import File Uploads
# Extract uploads
tar -xzf koha_uploads_*.tar.gz -C /tmp/
# Copy to new location
sudo cp -r /tmp/var/lib/koha/library/uploads/* \
/var/lib/koha/library/uploads/ 2>/dev/null || true
sudo cp -r /tmp/var/lib/koha/library/cover_images/* \
/var/lib/koha/library/cover_images/ 2>/dev/null || true
# Fix permissions
sudo chown -R library-koha:library-koha /var/lib/koha/library/uploads/
sudo chown -R library-koha:library-koha /var/lib/koha/library/cover_images/
Step 6: Update Database Configuration
For Standard/Basic Tier:
# Database is on same instance, no changes needed
echo "Database configuration verified"
For Enterprise Tier (Aurora):
# Get Aurora endpoint from CloudFormation Outputs
AURORA_ENDPOINT="your-cluster.cluster-xxxxx.us-east-1.rds.amazonaws.com"
# Update Koha configuration
sudo koha-shell library << 'EOF'
use C4::Context;
my $dbh = C4::Context->dbh;
# Configuration is handled by environment variables
EOF
# Verify connection
sudo mysql -h $AURORA_ENDPOINT -u kohaadmin -p koha_library -e "SHOW TABLES;"
Step 7: Rebuild Zebra Search Index
# Rebuild full index
sudo koha-rebuild-zebra -f -v library
# This may take 5-60 minutes depending on record count
# Progress will show on screen
Step 8: Restart Services
# Restart all Koha services
sudo koha-plack --restart library
sudo koha-worker --restart library
sudo systemctl restart apache2
# Verify services are running
sudo koha-plack --status library
sudo koha-worker --status library
sudo systemctl status apache2
Phase 4: Testing & Validation
Critical Tests Checklist
1. Basic Functionality
# Test database connection
sudo koha-mysql library -e "SELECT COUNT(*) FROM biblio;"
# Verify search index
sudo koha-shell library << 'EOF'
use C4::Search;
my ($error, $results) = SimpleSearch("ti:test");
print "Search functional\n" unless $error;
EOF
2. Staff Interface Tests
Access staff interface and verify:
- Login works with existing credentials
- Can search catalog
- Can view patron records
- Can check out items
- Can check in items
- Can view circulation history
- Reports run successfully
- System preferences are preserved
3. OPAC Tests
Access public catalog and verify:
- Search functionality works
- Bibliographic records display correctly
- Cover images appear
- Patron login works
- Account summary displays
- Holds can be placed
- Fines display correctly
4. Data Integrity Checks
# Compare record counts
echo "=== Source Instance (from migration_config.txt) ==="
grep "Records Count" migration_config.txt
grep "Items Count" migration_config.txt
grep "Patrons Count" migration_config.txt
echo "=== New Instance ==="
sudo mysql koha_library -e "
SELECT
(SELECT COUNT(*) FROM biblio) AS 'Records',
(SELECT COUNT(*) FROM items) AS 'Items',
(SELECT COUNT(*) FROM borrowers) AS 'Patrons';
"
# Should match exactly
5. Load Testing (Enterprise Only)
# Simple load test
for i in {1..10}; do
curl -I https://library.yourdomain.com/ &
done
wait
# Check all instances are healthy
# Go to EC2 Console → Target Groups → Check health status
Phase 5: Cutover & DNS Update
Preparation
- Schedule Maintenance Window:
- Notify users 48-72 hours in advance
- Choose low-traffic period (e.g., weekend evening)
- Plan for 2-4 hour window
- Create Rollback Plan:
- Keep source instance running
- Document current DNS settings
- Have source instance IP ready
DNS Update Procedure
For Standard Tier (Custom Domain)
# Get new Elastic IP from CloudFormation Outputs
NEW_ELASTIC_IP="X.X.X.X"
# Update DNS records at your provider:
# library.yourdomain.com → NEW_ELASTIC_IP (A record)
# staff.yourdomain.com → NEW_ELASTIC_IP (A record)
# Test DNS propagation
dig library.yourdomain.com +short
# Should show new IP
For Enterprise Tier (ALB)
# Get ALB DNS name from CloudFormation Outputs
ALB_DNS="koha-alb-xxxxx.us-east-1.elb.amazonaws.com"
# Update DNS records:
# library.yourdomain.com → ALB_DNS (CNAME record)
# staff.yourdomain.com → ALB_DNS (CNAME record)
# Test
dig library.yourdomain.com
# Should resolve to ALB DNS
Monitoring During Cutover
# Monitor logs in real-time
sudo tail -f /var/log/koha/library/intranet-error.log &
sudo tail -f /var/log/koha/library/opac-error.log &
sudo tail -f /var/log/apache2/error.log &
# Watch for errors during first 30 minutes
Phase 6: Post-Migration Tasks
Immediate (First Hour)
- Monitor Error Logs:
sudo grep -i error /var/log/koha/library/*.log | tail -20 sudo grep -i error /var/log/apache2/error.log | tail -20 - Test All Critical Functions:
- Circulation workflows
- Patron registration
- Reports generation
- Backup jobs (if Standard/Enterprise)
- Verify Backups:
- For Standard: Check S3 bucket for new backups
- For Enterprise: Verify Aurora automated backups
First Day
- Performance Monitoring:
- Check CloudWatch metrics
- Review instance CPU/memory usage
- Test peak-hour performance
- User Feedback:
- Monitor support tickets
- Check for user-reported issues
- Document any problems
First Week
- Fine-Tuning:
- Adjust Aurora ACU limits (Enterprise)
- Configure auto-scaling policies (Enterprise)
- Optimize system preferences
- Backup Verification:
- Test backup restoration process
- Verify S3 lifecycle policies
- Check backup retention
- Decommission Source Instance:
- Create final backup
- Stop source instance (don’t delete yet)
- Keep for 30 days as safety net
Rollback Procedures
If Migration Fails During Import
# Restore fresh installation
sudo mysql -e "DROP DATABASE koha_library;"
sudo mysql -e "CREATE DATABASE koha_library CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mysql koha_library < koha_library_fresh_install.sql
# Delete failed CloudFormation stack
aws cloudformation delete-stack --stack-name koha-new-tier
# Source instance remains untouched
If Issues Found After Cutover
- Update DNS back to source:
- Point DNS records to original instance
- Wait for propagation (5-10 minutes)
- Communicate with users:
- Send status update
- Explain temporary return to old system
- Diagnose issues:
- Review error logs
- Identify root cause
- Plan corrective action
Common Migration Issues
Database Character Set Problems
# If seeing garbled characters
sudo mysql koha_library -e "
ALTER DATABASE koha_library
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
"
# Convert tables
sudo mysql koha_library -e "
SELECT CONCAT('ALTER TABLE ', table_name, ' CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
FROM information_schema.tables
WHERE table_schema = 'koha_library';
" | sudo mysql koha_library
Search Index Not Working
# Clear and rebuild
sudo koha-rebuild-zebra -f -a -v library
# Restart Zebra
sudo systemctl restart koha-zebra-daemon
Cover Images Missing
# Verify permissions
sudo chown -R library-koha:library-koha /var/lib/koha/library/
sudo chmod -R 755 /var/lib/koha/library/uploads/
sudo chmod -R 755 /var/lib/koha/library/cover_images/
# Re-sync from S3 if needed
aws s3 sync s3://$MIGRATION_BUCKET/koha_uploads/ /var/lib/koha/library/
Tier-Specific Notes
Free → Basic Migration
- Architecture change: x86 → ARM64
- No domain changes needed
- Keep using Elastic IP
- Fastest migration (1-2 hours)
Basic → Standard Migration
- Adds S3 backup capability
- Optional: Configure custom domain
- Optional: Enable SSL
- Data migration identical to Free→Basic
Standard → Enterprise Migration
- Database moves to Aurora (significant change)
- Must configure custom domain (required)
- Must have ACM certificate
- Longest migration time (4-6 hours)
- Test extensively due to architecture differences
Enterprise Tier Upgrades (In-Place)
For Enterprise tier, upgrading to newer Koha versions is simpler:
Updating Enterprise Stack (No Migration Needed)
# 1. Update CloudFormation template parameter
# Change AMI ID to latest version in template
# 2. Create change set
aws cloudformation create-change-set \
--stack-name koha-enterprise \
--change-set-name upgrade-$(date +%Y%m%d) \
--use-previous-template \
--parameters ParameterKey=LatestAmiId,ParameterValue=ami-xxxxxxxxx
# 3. Review change set
aws cloudformation describe-change-set \
--stack-name koha-enterprise \
--change-set-name upgrade-$(date +%Y%m%d)
# 4. Execute change set
aws cloudformation execute-change-set \
--stack-name koha-enterprise \
--change-set-name upgrade-$(date +%Y%m%d)
# CloudFormation will:
# - Update Launch Template with new AMI
# - Auto Scaling Group performs rolling update
# - Launches new instances with updated AMI
# - Drains connections from old instances
# - Terminates old instances
# - Zero downtime (Enterprise HA continues serving traffic)
Enterprise Rolling Update Process:
- CloudFormation updates Launch Template
- ASG starts instance refresh
- New instance launches with updated AMI
- Health checks pass on new instance
- ALB registers new instance as healthy
- ALB drains connections from old instance
- Old instance terminates
- Process repeats for remaining instances
- No data migration needed - Aurora database remains unchanged
Advantages of Enterprise In-Place Upgrades:
- ✓ No database migration required
- ✓ Zero downtime (continuous availability)
- ✓ Automatic rollback if health checks fail
- ✓ Gradual rollout (one instance at a time)
- ✓ ALB handles traffic during upgrade
- ✓ Aurora data untouched throughout process
Best Practices
Do’s
- ✓ Test in non-production environment first
- ✓ Schedule during low-traffic periods
- ✓ Communicate with users well in advance
- ✓ Keep source instance running for 30 days
- ✓ Document every step
- ✓ Have rollback plan ready
- ✓ Verify data integrity thoroughly
Don’ts
- ✗ Don’t migrate during business hours
- ✗ Don’t delete source instance immediately
- ✗ Don’t skip testing phase
- ✗ Don’t forget to backup first
- ✗ Don’t ignore error logs
- ✗ Don’t rush the process
Getting Help
Before Migration
Schedule consultation:
- Email: support@kohasupport.com
- Subject: “Migration Planning - [Your Library]”
- Include: Current tier, target tier, record count
During Migration
Emergency support:
- Email: support@kohasupport.com
- Subject: “URGENT: Migration Issue - [Your Library]”
- Include: Error messages, screenshots, log files
Professional Migration Services
We offer fully managed migration services:
- Pre-migration assessment and planning
- Test environment setup and practice runs
- Supervised migration execution with real-time monitoring
- Post-migration optimization and performance tuning
- 30-day post-migration support and troubleshooting
- Zero-downtime migration strategies for critical systems
- Rollback planning and disaster recovery
Why use professional services:
- ✓ Eliminate risk of data loss or corruption
- ✓ Minimize downtime with expert planning
- ✓ Ensure success with experienced team
- ✓ Save time - migrations done right the first time
- ✓ Peace of mind - backed by our guarantee
Contact us for migration consultation and pricing →
Related Documentation
- Backup & Recovery Guide
- Monitoring & Maintenance
- Troubleshooting Guide
- Deploy Basic Tier
- Deploy Standard Tier
- Deploy Enterprise Tier
Last Updated: December 2025