Super Java Host
  1. Home
  2. Guides
  3. Deploy Spring Boot to a VPS

Deploy a Spring Boot application to a VPS

From an empty Ubuntu server to your Spring Boot JAR on your own domain with HTTPS, using systemd and Nginx.

The plan

The application listens on 127.0.0.1:8080 and runs as a systemd service under its own user. Nginx accepts the public traffic on ports 80 and 443 and passes it on. A firewall allows only SSH, HTTP and HTTPS. Point your domain's A record at the server IP before you start.

1. Update the server and install Java

sudo apt update && sudo apt -y upgrade
sudo apt install -y openjdk-21-jdk-headless nginx ufw
java -version

2. Open only the ports you need

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

Allow SSH before enabling the firewall, or you will lock yourself out.

3. Build the JAR and copy it

On your computer:

./mvnw -DskipTests package          # or: ./gradlew bootJar
scp target/myapp-0.0.1.jar user@your-server:/tmp/app.jar

On the server, create a user and a folder:

sudo useradd --system --home-dir /opt/app --shell /usr/sbin/nologin app
sudo mkdir -p /opt/app
sudo install -o app -g app -m 0640 /tmp/app.jar /opt/app/app.jar

4. Configuration outside the JAR

Keep passwords and environment-specific settings out of the JAR. Spring Boot reads environment variables, so use a protected file:

sudo tee /etc/app.env >/dev/null <<'EOF'
SERVER_ADDRESS=127.0.0.1
SERVER_PORT=8080
SERVER_FORWARD_HEADERS_STRATEGY=native
# SPRING_DATASOURCE_URL=jdbc:postgresql://127.0.0.1:5432/mydb
# SPRING_DATASOURCE_USERNAME=myuser
# SPRING_DATASOURCE_PASSWORD=change-me
EOF
sudo chown root:app /etc/app.env && sudo chmod 0640 /etc/app.env

SERVER_FORWARD_HEADERS_STRATEGY=native makes Spring trust the X-Forwarded-* headers from Nginx, so generated links use https.

5. systemd service

sudo tee /etc/systemd/system/app.service >/dev/null <<'EOF'
[Unit]
Description=Spring Boot application
After=network.target

[Service]
User=app
Group=app
WorkingDirectory=/opt/app
EnvironmentFile=/etc/app.env
ExecStart=/usr/bin/java -Xms256m -Xmx768m -XX:+ExitOnOutOfMemoryError -jar /opt/app/app.jar
SuccessExitStatus=143
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now app
sudo journalctl -u app -f

The heap in this example fits a 2 GB server. Use the JVM heap calculator for other sizes. Test locally: curl -I http://127.0.0.1:8080/.

6. Nginx

sudo tee /etc/nginx/sites-available/app >/dev/null <<'EOF'
server {
    listen 80;
    server_name example.com www.example.com;

    client_max_body_size 20m;

    location / {
        proxy_pass http://127.0.0.1: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;
        proxy_read_timeout 60s;
    }
}
EOF
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/app
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx

Replace example.com with your domain.

7. Free SSL certificate

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com --redirect -m you@example.com --agree-tos
sudo systemctl list-timers | grep certbot

Certbot edits the Nginx file to add the certificate and the redirect, and installs a timer that renews it.

8. Deploy a new version

scp target/myapp.jar user@your-server:/tmp/app.jar
ssh user@your-server 'sudo install -o app -g app -m 0640 /tmp/app.jar /opt/app/app.jar && sudo systemctl restart app'

That is the whole manual route. On a Spring Boot hosting plan all of it, plus a deploy-app command for step 8, is done for you from €15.30 per month.

Last updated October 29, 2026.

Your own Java server, billed monthly

Plans from €15.30 a month. Set up for you, or run for you.