Learn how to migrate web servers using AWS Application Migration Service (MGN). This comprehensive guide covers MGN agent installation, continuous replication, test cutover, and production migration with minimal downtime.
In this comprehensive guide, we’ll use AWS Application Migration Service (MGN) to perform a “lift-and-shift” migration of the source web server from the on-premises VPC to the target AWS environment. MGN performs continuous, block-level replication and allows for seamless cutover with minimal downtime, making it the ideal solution for production-grade server migrations.
Estimated Time: 90-120 minutes (including initial sync time)
Region: ap-south-1 (Mumbai)
Difficulty: Intermediate
AWS Application Migration Service (MGN) is the modern approach to server migration, offering:
⚠️ Resources that will incur charges:
Estimated MGN Cost: ~$1-2 per day during active replication
💡 Cost Tip: MGN initial setup and replication is free for the first 90 days (2,160 hours) of source server usage. After that, it’s $0.01188/hour per source server.
┌─────────────────────────────────────────────────────────────────┐
│ Source Server (on-prem-vpc) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ EC2: on-prem-web-server │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ MGN Agent (installed) │ │ │
│ │ │ - Captures disk blocks continuously │ │ │
│ │ │ - Encrypts data │ │ │
│ │ │ - Sends to MGN staging area │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ Continuous Replication (encrypted)
▼
┌─────────────────────────────────────────────────────────────────┐
│ MGN Staging Area (automatically created in target account) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Replication Server (t3.small) │ │
│ │ - Receives replicated data │ │
│ │ - Stores in staging EBS volumes │ │
│ │ - Keeps continuous point-in-time copies │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ When you trigger Cutover
▼
┌─────────────────────────────────────────────────────────────────┐
│ Target Environment (aws-target-vpc) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ New Migrated EC2 Instance │ │
│ │ - Exact copy of source server │ │
│ │ - Launched in target subnet │ │
│ │ - All data and applications intact │ │
│ │ - Ready to serve traffic │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
1. MGN Agent: Lightweight software installed on the source server that performs block-level replication 2. Replication Server: Temporary EC2 instance (t3.small) automatically created by MGN to receive replicated data 3. Staging EBS Volumes: Temporary storage holding the replicated data 4. Initial Sync: First-time full replication of the source disk (can take 30-90 minutes depending on size) 5. Continuous Replication: Ongoing capture of disk changes (keeps target up-to-date) 6. Test Cutover: Optional test to verify the migrated server works correctly 7. Cutover: Final launch of the production migrated instance in the target environment
If this is your first time using MGN in this region:
MGN needs certain IAM roles. These are typically auto-created:
The MGN agent needs an IAM role to authenticate and send replication data. This is more secure than using access keys.
MGN-Agent-RoleIAM role for MGN agent replicationMGN-Agent-Role{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
When you create an IAM role for EC2, AWS automatically creates an instance profile with the same name. Let’s verify it exists:
MGN-Agent-RoleMGN-Agent-Role is automatically created and ready to use📝 IMPORTANT: The instance profile ARN will be:
arn:aws:iam::935398764279:instance-profile/MGN-Agent-Role⚠️ Security Note: This approach is more secure than using access keys as the credentials are automatically managed by AWS and don’t need to be stored manually.
You’ll see commands similar to this (yours will be specific to your region):
wget -O ./aws-replication-installer-init https://aws-application-migration-service-ap-south-1.s3.ap-south-1.amazonaws.com/latest/linux/aws-replication-installer-init
sudo chmod +x aws-replication-installer-init
sudo ./aws-replication-installer-init --region ap-south-1
📝 Keep this browser tab open - you’ll need these commands
ssh -i on-prem-web-key.pem ec2-user@YOUR_SOURCE_PUBLIC_IP
On the source server, run the correct commands:
# Download the MGN agent installer (binary executable)
wget -O ./aws-replication-installer-init https://aws-application-migration-service-ap-south-1.s3.ap-south-1.amazonaws.com/latest/linux/aws-replication-installer-init
# Make it executable and run the installer
sudo chmod +x aws-replication-installer-init
sudo ./aws-replication-installer-init --region ap-south-1
Before running the installer, we need to attach the IAM role to the source instance:
The installer will automatically detect the region from the command line parameter and prompt you for disk selection:
1. Disk Selection:
Choose the disks you want to replicate. Your disks are: /dev/xvda,/dev/nvme0n1
To replicate some of the disks, type the path of the disks, separated with a comma (for example, /dev/sda,/dev/sdb). To replicate all disks, press Enter:
Response: Press Enter to replicate all disks (recommended)
2. The installer will then:
Note: The installer automatically uses the IAM role attached to the instance for authentication, so no manual credential entry is needed.
The installer will:
Expected output:
Installing AWS Replication Agent...
Creating snapshot...
Installing MGN agent...
Agent installed successfully.
Initial sync started.
This process takes 5-10 minutes.
⚠️ Do not close the SSH session during installation
# Check if the agent is running
sudo systemctl status aws-replication-agent
# Expected output: "active (running)"
# Check agent logs (optional)
sudo tail -f /var/log/aws-replication-agent.log
✅ If the status is “active (running)”, the agent is successfully installed!
| Server Name | Status | Data Replication Status | Migration Lifecycle |
|---|---|---|---|
| 10.0.1.x | Initializing | Initial Sync | Not Ready |
Click on the server to see detailed information:
The Data replication status will progress through these stages:
☕ This is a good time for a break! Initial sync typically takes 30-90 minutes depending on:
The Migration lifecycle status will change to:
✅ Once it says “Ready for testing”, you can proceed to the next step
Before we launch the migrated server, we need to configure where and how it should launch in the target environment.
General launch settings:
Network settings:
IAM instance profile:
Tenancy:
License:
Right sizing:
You can specify scripts to run after the instance launches:
Post-launch script (optional):
#!/bin/bash
# Restart web server after migration
systemctl restart httpd
# Log migration timestamp
echo "Server migrated on $(date)" >> /var/log/migration.log
Migration Hub provides a central dashboard to track all your migrations.
Legacy-to-Cloud-MigrationMigration of on-premises web server and database to AWSBefore doing the final cutover, it’s best practice to test the migration.
This takes 5-10 minutes
mgn-test-i-xxxxxxxxxOption A: Using Bastion Host (if you created one in Phase 2)
# SSH to bastion host first
ssh -i on-prem-web-key.pem ec2-user@BASTION_PUBLIC_IP
# Then SSH to the test instance from bastion
ssh ec2-user@10.1.11.x
Option B: Using Systems Manager Session Manager (Recommended)
Option C: Temporarily add public IP for testing
http://ELASTIC_IPOnce connected to the test instance:
# Check if Apache is running
sudo systemctl status httpd
# Check web content
curl http://localhost
# Check if it can connect to source database (it should still point to source)
psql --host=YOUR_SOURCE_RDS_ENDPOINT --port=5432 --username=postgres --dbname=legacydb -c "SELECT COUNT(*) FROM users;"
# Check network configuration
ip addr show
ip route
Expected results:
⚠️ Important: Test instances remain running and incur costs. We’ll clean them up after cutover.
Now that testing is successful, let’s do the final production cutover.
Before cutting over, ensure:
This takes 5-10 minutes
mgn-cutover- followed by original instance IDFor clarity, let’s rename it:
migrated-web-serverEnvironment, Value: ProductionMigratedFrom, Value: on-prem-vpcMigrationDate, Value: 2025-10-17Use one of the methods from Step 7.4 (Bastion, Session Manager, or temporary Elastic IP).
# Check Apache status
sudo systemctl status httpd
# If not running, start it
sudo systemctl start httpd
sudo systemctl enable httpd
# Check if web server responds
curl http://localhost
# Verify Python CGI application
curl http://localhost/cgi-bin/db_app.py
# Check PostgreSQL client
psql --version
The application is still pointing to the source database (which is correct until we migrate the database in Phase 4):
# Test connection to source database
psql --host=YOUR_SOURCE_RDS_ENDPOINT --port=5432 --username=postgres --dbname=legacydb -c "SELECT * FROM users;"
# This should still work and show your 4 users
⚠️ Don’t do this yet - wait until Phase 4 (DMS) is complete
After you complete the database migration in Phase 4, you’ll update the application to point to the new database:
sudo sed -i 's|YOUR_SOURCE_RDS_ENDPOINT|YOUR_TARGET_RDS_ENDPOINT|g' /var/www/cgi-bin/db_app.py
sudo systemctl restart httpd
For a production setup, you’d put the migrated server behind an ALB for high availability.
migrated-web-tg/migrated-web-servermigrated-app-albmigrated-web-tgmigrated-app-alb-xxxxxxxxx.ap-south-1.elb.amazonaws.comWait 2-3 minutes for health checks to pass, then:
# Test from your local machine
curl http://YOUR_ALB_DNS_NAME
# Or open in browser
http://YOUR_ALB_DNS_NAME
✅ You should see your application served through the ALB!
Before finalizing:
finalize to confirm💰 After finalization, you stop paying for replication infrastructure!
migrated-web-serverIf you have a domain:
Create a migration report documenting:
📝 Important IDs for Phase 4 and Cleanup:
| Resource | Value | Notes |
|---|---|---|
| Migrated Instance ID | i-xxxxxxxxx | In target VPC |
| Migrated Instance Private IP | 10.1.11.x | In target-app-subnet-1a |
| Target Group ARN | arn:aws:… | (if created) |
| ALB DNS Name | xxx.ap-south-1.elb.amazonaws.com | (if created) |
| MGN Agent IAM Role | MGN-Agent-Role | Can be deleted after finalization |
Solution:
python3 --versionsudo cat /var/log/aws-replication-agent.log/opt/aws/mgn and reinstallSolution:
iostat -x 1Solution:
Solution:
Solution:
sudo systemctl status httpd/var/log/httpd/error_log✅ Phase 3 Complete!
Your web server has been successfully migrated from the on-premises environment to the target AWS VPC using MGN!
What you’ve accomplished:
Current state:
Proceed to Phase 4: Migrate the database using AWS Database Migration Service (DMS)
# Check MGN agent status
sudo systemctl status aws-replication-agent
# View MGN agent logs
sudo tail -f /var/log/aws-replication-agent.log
# Restart MGN agent (if needed)
sudo systemctl restart aws-replication-agent
# Connect to migrated instance via Session Manager
# (Do this from AWS Console → Systems Manager → Session Manager)
# Test application on migrated server
curl http://localhost
curl http://localhost/cgi-bin/db_app.py
# Check Apache logs
sudo tail -f /var/log/httpd/access_log
sudo tail -f /var/log/httpd/error_log
In this comprehensive guide, we’ve successfully migrated a production web server using AWS Application Migration Service (MGN), demonstrating the power of modern cloud migration tools. This hands-on approach provides essential experience with enterprise-grade server migration strategies.
What we’ve accomplished:
Key Learning Outcomes:
This server migration is now complete and ready for the final phase of our migration journey, where we’ll migrate the database using AWS Database Migration Service (DMS).
This is Part 3 of a comprehensive AWS migration series. Here is the Part 4, where we’ll migrate the database using AWS Database Migration Service (DMS).