Skip to main content

From Vercel to VPS: How I’m Deploying My Smart Garbage Collection App

M
Markian MumbainTech blog
3 min read·Aug 3, 2025
TechDeployment
vincent vangoh 2
Café Terrace at Night Painting by Vincent van Gogh

For the longest time, all my app deployments lived comfortably on PaaS (Platform-as-a-Service) platforms—Vercel, Render, Heroku, and the like. They were fast, simple, and beginner-friendly. But recently, I faced a challenge that made me rethink that comfort zone.

While interviewing for a job, I was given a task: build a movie web app using the TMDB API and deploy it on your own server. Not a PaaS. A real VPS. And it had to have CI/CD too.

That one requirement made me realize something: I’d never actually deployed an app to a raw server before.

So as a test run, I decided to take one of my side projects—a smart garbage collection app—and try deploying it on a VPS. The frontend was on Vercel, the backend on Render. I wanted to move both to a single server I could manage. Here's how I did it.

Step 1: Choosing a VPS Provider

I chose DigitalOcean. Why?

I had some free credits, which made experimenting feel less risky.

I didn’t want to jump straight into AWS or GCP. That felt like skipping a step in my learning journey.

I wanted to understand what happens under the hood.

The explosion of AI tools has made this easier than ever. With some good prompts and guidance, you can learn how to set up a VPS in a day. Don’t underestimate what you can learn with the right questions.

Step 2: Backend Setup with Spring Boot

My backend is a Spring Boot app. On my local machine, I built a .jar file like this:

 mvn clean package -DskipTests

Skipping tests helps speed up the build during deployment. Once the .jar It is ready, I transfer it to the VPS:

scp target/my-app.jar root@your-vps-ip:/opt/my-app Before that, I created the folder and assigned the correct permissions:

sudo mkdir -p /opt/my-app
sudo chown $USER:$USER /opt/my-app

Step 3: Environment Variables and Systemd Service

In /opt/my-appI created a .env file with the required environment variables. Then, I set up a systemd service to ensure the app runs reliably:

sudo vim /etc/systemd/system/my-app.service
[Unit]
Description=Smart Garbage App Backend
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/opt/my-app
ExecStart=/usr/bin/java -jar my-app.jar
EnvironmentFile=/opt/my-app/.env
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target

To start the service:

sudo systemctl daemon-reload sudo systemctl enable my-app sudo systemctl start my-app sudo systemctl status my-app If everything’s working, your backend is now live

Step 4: Reverse Proxy with Nginx

To expose the backend cleanly to the internet, I added Nginx as a reverse proxy:

sudo apt install nginx Then I created a config file:

sudo vim /etc/nginx/sites-available/my-app
server {
    listen 80;
    server_name my-app.com;
    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Enable the config:

sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx Now when you visit http://my-app.com/health, you should see a response from your backend.

Step 5: Securing with HTTPS

To move from HTTP to HTTPS, I used Certbot:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d my-app.com
sudo certbot renew --dry-run

Step 6: Add a Basic Firewall

Security matters. I enabled UFW (Uncomplicated Firewall):

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Step 7: Logging

You can view logs for your Spring Boot app:

sudo journalctl -u my-app.service -f

Reviews (0)

No reviews yet. Be the first to share your thoughts!