DEV Community

Cover image for Step-by-Step Deployment Guide for Spring Boot Services on Ubuntu Server with CI/CD & Reverse Proxy
Om Patil
Om Patil

Posted on

Step-by-Step Deployment Guide for Spring Boot Services on Ubuntu Server with CI/CD & Reverse Proxy

🧭 Overview
In this guide, I’ll walk you through a complete deployment pipeline for Spring Boot services using GitHub Actions, Ubuntu servers, and Nginx. We'll deploy two environmentsβ€”Dev and Prodβ€”on separate servers and configure:

βœ… Systemd-based service management
βœ… Auto-start on reboot
βœ… Reverse proxy with Nginx
βœ… CI/CD using GitHub Actions
βœ… Branch-based deployment:
β†’ Push to dev β†’ Deploys to Dev server
β†’ Push to main β†’ Deploys to Prod server

      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚ Static IP  β”‚
      β”‚ your-ip    β”‚
      β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
           β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”
    β”‚  Reverse    β”‚
    β”‚   Proxy     β”‚
    β”‚   (Nginx)   β”‚
    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
  β”Œβ”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”
  β”‚              β”‚
Enter fullscreen mode Exit fullscreen mode

β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
β”‚ Dev Serverβ”‚ β”‚ Prod Serverβ”‚
β”‚your-ip β”‚ β”‚ your-ip |
β”‚ Port 8081 β”‚ β”‚ Port 8082 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ”§ 1. Initial Server Setup
βœ… Install Java 21
sudo apt update && sudo apt upgrade -y
sudo apt install openjdk-21-jdk -y
java -version

πŸ“ Create App Directory
mkdir ~/apps
cd ~/apps

πŸ“¦ 2. Deploy Spring Boot Applications
Upload your JARs to respective servers:

scp dev-app.jar ubuntu@your-ip:/home/ubuntu/apps/
scp prod-app.jar ubuntu@your-ip:/home/ubuntu/apps/

βš™οΈ 3. Create systemd Services
Use environment variables for better flexibility.

πŸ”‘ Create Environment Files
On Dev Server:
echo "SERVER_PORT=8081" > /home/ubuntu/apps/dev.env

On Prod Server:
echo "SERVER_PORT=8082" > /home/ubuntu/apps/prod.env

πŸ§ͺ Dev Service: /etc/systemd/system/dev-app.service
[Unit]
Description=Spring Boot Dev Application
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/apps
EnvironmentFile=/home/ubuntu/apps/dev.env
ExecStart=/usr/bin/java -jar /home/ubuntu/apps/dev-app.jar --server.port=${SERVER_PORT}
SuccessExitStatus=143
Restart=always
RestartSec=5
StandardOutput=file:/home/ubuntu/apps/dev-output.log
StandardError=file:/home/ubuntu/apps/dev-error.log

[Install]
WantedBy=multi-user.target
Repeat similarly for prod-app.service with prod.env.

▢️ 4. Enable and Start Services
sudo systemctl daemon-reload
sudo systemctl enable dev-app # On Dev Server
sudo systemctl enable prod-app # On Prod Server

sudo systemctl start dev-app
sudo systemctl start prod-app

βœ… 5. Verify Deployment
Check status:
systemctl status dev-app
systemctl status prod-app

Test API:
curl http://:8081/endpoint
curl http://:8082/endpoint

πŸ”„ 6. CI/CD: Auto-Deploy with GitHub Actions
Create workflow files for each branch.

Example: .github/workflows/deploy-dev.yml
on:
push:
branches: [dev]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Copy JAR to Dev Server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.DEV_HOST }}
username: ubuntu
key: ${{ secrets.SSH_KEY }}
source: target/dev-app.jar
target: /home/ubuntu/apps/dev-app.jar

  - name: Restart Dev App
    uses: appleboy/ssh-action@master
    with:
      host: ${{ secrets.DEV_HOST }}
      username: ubuntu
      key: ${{ secrets.SSH_KEY }}
      script: sudo systemctl restart dev-app
Enter fullscreen mode Exit fullscreen mode

Repeat similarly for main branch β†’ Prod server.

πŸ“œ 7. Logging with Rotation
Logs are stored at:

/home/ubuntu/apps/dev-output.log

/home/ubuntu/apps/prod-output.log

πŸ“¦ Add Log Rotation
Create /etc/logrotate.d/dev-app:

/home/ubuntu/apps/dev-output.log {
daily
rotate 7
compress
missingok
notifempty
copytruncate
}
Repeat for prod-output.log.

πŸ›‘οΈ 8. Security Best Practices
Enable UFW firewall:

sudo ufw allow 22
sudo ufw allow 80
sudo ufw allow 8081
sudo ufw allow 8082
sudo ufw enable
Disable root SSH login

Keep servers updated regularly

Use GitHub Secrets for all sensitive credentials

🌐 9. Optional: Reverse Proxy with Nginx
Install Nginx on your reverse proxy server:

sudo apt install nginx -y

Create config: /etc/nginx/sites-available/reverse-proxy
server {
listen 80;
server_name your-ip;

location /dev/ {
    proxy_pass http://your-ip:8081/;
    proxy_set_header Host $host;
}

location /prod/ {
    proxy_pass http://your-ip:8082/;
    proxy_set_header Host $host;
}
Enter fullscreen mode Exit fullscreen mode

}

Enable and restart:
sudo ln -s /etc/nginx/sites-available/reverse-proxy /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

Test:
http://your-ip/dev/hello β†’ Dev
http://your-ip/prod/hello β†’ Prod

🧠 Pro Tips for Production
Health Check : Use /actuator/health endpoint and restart if it fails
Monitoring : Use htop, glances, or Prometheus + Grafana
Docker (Optional) : Containerize apps to simplify deployment
Secrets : Always use .env files or GitHub Secrets
Recovery : Keep previous .jar backups or use versioned deployment folders

🏁 Conclusion
With this setup, you’ve built a complete, secure, and automated deployment pipeline for Spring Boot services:

Branch-based CI/CD deployment

Nginx reverse proxy with clean routing

Auto-restarting apps

Centralized logging with rotation

Optional Docker support for scaling later

πŸ“’ If this helped you, give a ❀️ or comment below!
Follow me for more hands-on guides in DevOps, Linux, and Java πŸš€

Top comments (0)