Koha Tier Migration Guide
Comprehensive guide for migrating Koha between tiers with step-by-step backup, export, and import procedures.
Complete guide for safely migrating your Koha installation between tiers (Free → Basic → Standard → Enterprise) with detailed backup and data migration procedures.
⚠️ Read before proceeding
This guide describes a process that can cause data loss or extended downtime if steps are missed or executed out of order.
Before you start:
- Back up your data and verify the backup is complete and restorable.
- Test the full process on a non-production environment before touching your live library.
- Schedule a maintenance window and notify users if this affects a production system.
Not confident? KohaSupport can guide you through migrations and upgrades. Contact us for professional assistance →
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)
↓
Free Tier (ARM64 - better performance)
↓
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
# - Reduced 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
- ✓ Reduced downtime (high availability design)
- ✓ 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: [email protected]
- Subject: “Migration Planning - [Your Library]”
- Include: Current tier, target tier, record count
During Migration
Emergency support:
- Email: [email protected]
- 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
- Reduced-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 Free Tier (Single-server)
- Deploy Standard Tier
- Deploy Enterprise Tier
Last Updated: December 2025
Next Steps
More in AWS & Deployment
Was this article helpful?