🎓 Guided Learning Project — This is a continuation of my vprofile-local on-premises project. Having manually provisioned and configured the full stack on a local machine using Vagrant and VirtualBox, the next step in the learning journey was to migrate the same infrastructure to AWS — replicating every service in the cloud without changing a single line of application code. Both projects were completed as guided walkthroughs following the course by hkhcoder.
💡 Why lift & shift? Before optimising for the cloud, it's important to understand how to move an existing workload as-is. This project builds that foundation — mapping each on-prem VM directly to an AWS equivalent — before exploring more cloud-native approaches.
A re-hosting (lift & shift) migration of the VProfile multi-tier Java web application from a local Vagrant/VirtualBox environment to AWS. The on-premises services are mapped 1-to-1 to equivalent AWS infrastructure with no code changes.
User/Browser
│
▼
[ Route 53 ] ← DNS
│
▼
[ Application Load Balancer ] ← HTTPS Termination (replaces Nginx)
│
▼
[ EC2: Tomcat (Auto Scaling Group) ] ← Application Server
│
├──► [ EC2: Memcache ] ← DB Caching (replaces Memcache VM)
├──► [ EC2: RabbitMQ ] ← Message Broker (replaces RabbitMQ VM)
└──► [ EC2: MySQL ] ← Relational DB (replaces MySQL VM)
| On-Prem | AWS Equivalent | Notes |
|---|---|---|
| Nginx VM | Application Load Balancer | HTTPS, SSL termination |
| Tomcat VM | EC2 (Auto Scaling Group) | Same AMI, same config |
| MySQL VM | EC2 (or RDS) | MariaDB on EC2 |
| Memcache VM | EC2 | ElastiCache optional upgrade |
| RabbitMQ VM | EC2 | Amazon MQ optional upgrade |
| Vagrant hostmanager | Route 53 Private Hosted Zone | Internal DNS |
- AWS Account with IAM user and programmatic access
- AWS CLI configured locally
- Key pair created in your target AWS region
- Basic understanding of EC2, Security Groups, and ALB
Three security groups are required:
| Type | Protocol | Port | Source |
|---|---|---|---|
| HTTPS | TCP | 443 | 0.0.0.0/0 |
| HTTP | TCP | 80 | 0.0.0.0/0 |
| Type | Protocol | Port | Source |
|---|---|---|---|
| Custom TCP | TCP | 8080 | vprofile-elb-sg |
| SSH | TCP | 22 | My IP |
| Type | Protocol | Port | Source |
|---|---|---|---|
| MySQL/Aurora | TCP | 3306 | vprofile-app-sg |
| Custom TCP | TCP | 11211 | vprofile-app-sg |
| Custom TCP | TCP | 5672 | vprofile-app-sg |
| All Traffic | All | All | vprofile-backend-sg (self-referencing) |
All backend instances (MySQL, Memcache, RabbitMQ) use the same base AMI (Amazon Linux 2 / CentOS) and are launched in the vprofile-backend-sg security group.
Launch an instance and run:
dnf update -y
dnf install epel-release git mariadb-server -y
systemctl start mariadb && systemctl enable mariadb
mysql_secure_installation # root password: admin123
# Create DB and user
mysql -u root -padmin123 <<EOF
CREATE DATABASE accounts;
GRANT ALL PRIVILEGES ON accounts.* TO 'admin'@'%' IDENTIFIED BY 'admin123';
FLUSH PRIVILEGES;
EOF
# Import schema
cd /tmp
git clone -b local https://github.com/hkhcoder/vprofile-project.git
mysql -u root -padmin123 accounts < vprofile-project/src/main/resources/db_backup.sql
systemctl restart mariadbdnf install epel-release memcached -y
systemctl start memcached && systemctl enable memcached
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/sysconfig/memcached
systemctl restart memcacheddnf install epel-release wget -y
dnf -y install centos-release-rabbitmq-38
dnf --enablerepo=centos-rabbitmq-38 -y install rabbitmq-server
systemctl enable --now rabbitmq-server
rabbitmqctl add_user test test
rabbitmqctl set_user_tags test administrator
rabbitmqctl set_permissions -p / test ".*" ".*" ".*"
systemctl restart rabbitmq-serverCreate a Private Hosted Zone (e.g., vprofile.internal) in Route 53 and add the following A records pointing to the private IPs of your backend EC2s:
| Record | Points to |
|---|---|
db01.vprofile.internal |
MySQL EC2 private IP |
mc01.vprofile.internal |
Memcache EC2 private IP |
rmq01.vprofile.internal |
RabbitMQ EC2 private IP |
This replaces the /etc/hosts entries managed by Vagrant's hostmanager plugin in the on-premises setup.
Point backend hostnames at your Route 53 DNS names:
jdbc.url=jdbc:mysql://db01.vprofile.internal:3306/accounts
memcached.active.host=mc01.vprofile.internal
rabbitmq.address=rmq01.vprofile.internalcd vprofile-project
export MAVEN_OPTS="-Xmx512m"
mvn install# Upload from local machine
aws s3 cp target/vprofile-v2.war s3://YOUR_BUCKET/vprofile-v2.war
# On the Tomcat EC2
aws s3 cp s3://YOUR_BUCKET/vprofile-v2.war /tmp/vprofile-v2.war
systemctl stop tomcat
rm -rf /usr/local/tomcat/webapps/ROOT*
cp /tmp/vprofile-v2.war /usr/local/tomcat/webapps/ROOT.war
chown tomcat.tomcat /usr/local/tomcat/webapps -R
systemctl start tomcat- Create a Target Group pointing to the Tomcat EC2 on port
8080, health check path:/login - Create an Application Load Balancer in
vprofile-elb-sg - Add an HTTPS listener (port 443) with an SSL certificate from ACM
- Forward traffic to the target group
Create a public A record or CNAME in your domain pointing to the ALB DNS name:
vprofile.yourdomain.com → ALB DNS Name
Navigate to:
https://vprofile.yourdomain.com
or via the ALB DNS name directly. You should see the VProfile login page.
| Aspect | On-Premises (Vagrant) | AWS (Lift & Shift) |
|---|---|---|
| Compute | VirtualBox VMs | EC2 Instances |
| DNS | /etc/hosts via vagrant-hostmanager |
Route 53 Private Hosted Zone |
| Load Balancer | Nginx reverse proxy | Application Load Balancer |
| SSL | Manual / none | ACM Certificate |
| Storage | Local disk | EBS |
| Artifact delivery | Local Maven build | S3 |
| Scalability | Manual | Auto Scaling Groups |
.
├── src/
│ └── main/
│ └── resources/
│ ├── application.properties ← update with AWS DNS names
│ └── db_backup.sql
├── userdata/ ← EC2 user data scripts (optional)
│ ├── mysql.sh
│ ├── memcache.sh
│ ├── rabbitmq.sh
│ └── tomcat.sh
└── README.md
To avoid ongoing charges, terminate resources in this order:
- Delete the Load Balancer and Target Group
- Terminate all EC2 instances
- Delete the S3 bucket contents and bucket
- Delete Route 53 hosted zones
- Release any Elastic IPs
- Lift & shift cloud migration strategy (re-hosting)
- EC2 instance provisioning and configuration
- Security group design for multi-tier architecture
- Application Load Balancer with SSL termination via ACM
- Private DNS with Route 53 hosted zones
- S3 for artifact storage and delivery
- IAM roles for EC2-to-S3 access