How to Move your Websites from Vercel to a VM

How to Move your Websites from Vercel to a VM

Photo by AltumCode / Unsplash

Why move away from Vercel?

1) Usage-based pricing. Higher-traffic, higher bill.2) Vendor lock-in. The more you build, the harder it is to migrate away from it.3) Limited value. Vercel's auto-scaling is unnecessary and we can implement its auto-deploy ourself.

Step 1: Setup a VM on Digital Ocean (called a "droplet")

For the purposes of this guide:- Set the OS to Debian 12- Choose Premium AMD $7/mo- Add a new ssh key (follow the instructions provided)- Make the hostname "main-vm"

Step 2: Easy Access to Your VM

1) Navigate to your droplet on your DigitalOcean dashboard2) Click "Add a Reserved IP"3) Copy the Reserved IP4) Run the following line in your terminal:bash

echo "mainvm() { ssh root@RESERVED_IP }" >> ~/.zshrc && source ~/.zshrc && mainvm

Step 3: Create a new user on your VM

You're gonna want to do this for every website you will be hosting on this VM (you can host pretty much as many as you want)1) In your terminalbash

mainvm
adduser NEW_USERNAME && usermod -aG sudo NEW_USERNAME && su NEW_USERNAME 
sudo visudo

3) append the following line to the end of the file:NEW_USERNAME ALL=(ALL) NOPASSWD: ALL

Step 4: Set up nginx

1) Follow this great guide from DigitalOcean to set up Nginx: https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-debian-112) Follow this also great guide from DigitalOcean to set up SSL:https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-debian-11

^^ Notes on the first guide

1) Make sure to install ufw, allow OpenSSH, and do sudo ufw enable2) Skip the beginning of Step 5, start at the part in the attached image3) Replace the location block in your nginx config with this:

location / {
    proxy_pass http://localhost:LISTENING_PORT;
}

^^ Notes on the second guide

1) Point your domain's @ A record and it's www A record to your new VM's reserved IP address before starting the second guide. FYI this will result in downtime.

Step 5: Set up systemd, npm, and add ssh key

1) Navigate to your back to your terminal where you are sshed into your VMbash

sudo apt install npm -y
sudo nano /lib/systemd/system/PROJECT_NAME.service

4) Use the following gist to create the systemd service file: https://gist.github.com/edverma/e063698013edfeca7d073f0bd7c03119bash

sudo systemctl enable PROJECT_NAME.service && sudo nano ~/.env

7) Paste the following into the .env file

HOST=0.0.0.0
PORT=LISTENING_PORT

Step 6: Create a new SSH key

1) Follow this great guide from GitHub to create a new SSH key for your user on your VM: https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent2) Run the following in your terminal:bash

cat .ssh/id_ed25519.pub >> .ssh/authorized_keys

Step 7: Set up Autodeploy from GitHub

1) Navigate to the settings page of your project's GitHub repository2) Navigate to "Actions" under "Secrets and Variables"- HOST: your vm's reserved ip- USERNAME: the username you set up- SSH_PRIVATE_KEY: the private ssh key you just set up- SSH_PASSPHRASE: the password for the ssh key you set up3) Use the following gist to create an action in your codebase in a file .github/workflows/deploy.yml: https://gist.github.com/edverma/d6802106ee554b09c8945d93e66c42cc

Step 8: Sweet sweet victory

Now you can press that juicy delete button on this associated vercel project.Host as many websites as you want on your new VM, just make sure the LISTENING_PORT, USERNAME, and PROJECT_NAME variables don't collide.If you want to use Hetzner, @d4m1n made a great guide here for that: https://x.com/d4m1n/status/1826989595361222887