Docs / Migration Guides / Migrate from AWS EC2 to VPS

Migrate from AWS EC2 to VPS

By Admin · Mar 15, 2026 · Updated Apr 23, 2026 · 279 views · 4 min read

Why Migrate from AWS EC2?

AWS EC2 costs can escalate quickly, especially with data transfer charges, EBS storage, and associated services like RDS, ElastiCache, and ALB. A self-managed VPS can provide equivalent or better performance at a fraction of the cost. This guide covers a systematic migration from EC2 to a VPS.

Cost Comparison

A typical t3.medium EC2 instance (2 vCPU, 4GB RAM) costs approximately $30-40/month before adding EBS, bandwidth, and other AWS services. An equivalent VPS typically costs $10-20/month with generous bandwidth included. For many workloads, the savings are 60-80%.

Pre-Migration Assessment

  • Inventory all AWS services in use (EC2, RDS, S3, SES, CloudFront, Route 53)
  • Document security groups and network ACLs
  • List all environment variables and secrets
  • Map dependencies between services
  • Identify AWS-specific services that need alternatives

AWS Service Alternatives

AWS ServiceSelf-Hosted Alternative
RDSMySQL/PostgreSQL installed directly
ElastiCacheRedis installed directly
S3MinIO or Backblaze B2
SESPostal, Postfix, or external SMTP (Postmark/Resend)
CloudFrontCloudflare (free tier)
Route 53Cloudflare DNS (free)
ALBNginx reverse proxy
CloudWatchPrometheus + Grafana

Step 1: Prepare the VPS

# Provision a VPS with matching or better specs
# Install the same OS version as your EC2 instance

# Install required software
sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx mysql-server redis-server \
    php8.3-fpm php8.3-mysql php8.3-redis php8.3-curl \
    certbot python3-certbot-nginx ufw fail2ban

# Configure firewall
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

# Harden SSH
sudo sed -i "s/PermitRootLogin yes/PermitRootLogin no/" /etc/ssh/sshd_config
sudo systemctl restart sshd

Step 2: Migrate the Database

# From RDS or EC2 MySQL:
# On EC2/RDS, export the database
mysqldump -h rds-endpoint.amazonaws.com -u admin -p \
    --single-transaction --routines --triggers \
    --databases myapp_db | gzip > myapp_db.sql.gz

# Transfer to VPS
scp myapp_db.sql.gz user@vps-ip:/tmp/

# On VPS, import
zcat /tmp/myapp_db.sql.gz | mysql -u root

# Create application database user
mysql -e "CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'secure_password';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp'@'localhost';
FLUSH PRIVILEGES;"

Step 3: Transfer Application Files

# From EC2 to VPS using rsync
rsync -avz --progress -e "ssh -i ~/.ssh/ec2-key.pem" \
    ec2-user@ec2-ip:/var/www/myapp/ \
    user@vps-ip:/var/www/myapp/

# Or use scp for a one-time transfer
scp -r -i ~/.ssh/ec2-key.pem \
    ec2-user@ec2-ip:/var/www/myapp/ /var/www/myapp/

# Fix permissions
sudo chown -R www-data:www-data /var/www/myapp
sudo chmod -R 755 /var/www/myapp

Step 4: Configure Nginx

# Create Nginx virtual host
sudo tee /etc/nginx/sites-available/myapp << NGINX
server {
    listen 80;
    server_name example.com www.example.com;
    root /var/www/myapp/public;
    index index.php index.html;

    location / {
        try_files \$uri \$uri/ /index.php?\$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
        include fastcgi_params;
    }
}
NGINX

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

# Get SSL certificate
sudo certbot --nginx -d example.com -d www.example.com

Step 5: Update Application Configuration

# Update .env or configuration files
DB_HOST=localhost          # Was RDS endpoint
DB_DATABASE=myapp_db
DB_USERNAME=myapp
DB_PASSWORD=secure_password

REDIS_HOST=127.0.0.1      # Was ElastiCache endpoint

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

# Replace S3 references with MinIO or local storage
FILESYSTEM_DISK=local
# Or set up MinIO for S3-compatible local storage

Step 6: DNS Cutover

# 1. Lower DNS TTL to 300 seconds (24h before migration)
# 2. Test everything on VPS using hosts file
# 3. When ready, update DNS A record to VPS IP
# 4. Monitor for issues during propagation
# 5. Keep EC2 running for 48h as fallback

Post-Migration Checklist

  • Verify all application features work correctly
  • Set up automated backups (Restic, Borg, or similar)
  • Configure monitoring (Uptime Kuma, Prometheus)
  • Set up log rotation for Nginx and application logs
  • Terminate EC2 instances and related AWS services after confirmation period
  • Cancel or downgrade AWS account to avoid residual charges

Was this article helpful?