DEV Community

Cover image for Deploy your own production-grade file server on a VPS for free in just a few steps
boiler_agents
boiler_agents

Posted on

Deploy your own production-grade file server on a VPS for free in just a few steps

Deploy Your Own Production-Grade File Server on a Free VPS (Step-by-Step Guide)

By following this blog, you will:

  • Deploy a Spring Boot file-server boilerplate on a free VPS
  • Secure it with nginx and Let’s Encrypt
  • Run it either natively with systemd or inside Docker.
  • Test everything with the included Postman collection.

Who this post is for

  • Developers who want a lightweight, self-hosted file server (uploads, streaming, metadata, and delete).
  • Anyone looking to experiment with free-tier VPS hosting.
  • Readers comfortable with basic Linux commands, SSH, and Git.

What you will need (prerequisites)

Note: Free VPS plans vary in limits. Always monitor your provider’s dashboard for billing and read their documentation.


Quick architecture (what we’ll set up)

  1. Spring Boot app listening on port 8000.
  2. Either:
    • Managed by systemd (native deployment).
    • Or inside a Docker container.
  3. nginx as reverse proxy with TLS (via Let’s Encrypt).
  4. Files stored on server disk (or optionally object storage for durability).

Step 1: Prepare the boilerplate locally on your machine

  • Download file-upload-api boilerplate and extract.
  • Open the extracted folder with your IDE (Eclipse, VS Code, Netbeans, etc.).
  • Update file src/main/resources/application.properties as per your requirements:
# Server Configuration
spring.application.name=springboot-file-upload-api
server.port=8000

# File Configuration
spring.servlet.multipart.max-file-size=50MB
spring.servlet.multipart.max-request-size=50MB

# Change this path to where you want files to be stored
upload.path=/opt/fileserver/uploads
Enter fullscreen mode Exit fullscreen mode
  • Run the project and test with the included Postman collection.
  • Build the JAR:
 ./mvnw clean package -DskipTests
Enter fullscreen mode Exit fullscreen mode

or

 ./gradlew bootJar
Enter fullscreen mode Exit fullscreen mode

The JAR will be located at target/file-server-0.1.0.jar.


Step 2: Pick a free VPS

  • Oracle Cloud Always Free → compute instances with enough resources for small apps.
  • AWS / Google Cloud Free → great for experimentation, but watch usage.

For this guide, we will assume a Ubuntu 22.04 VPS. Steps are similar for other distros.


Step 3: Connect to your VPS

ssh ubuntu@YOUR_VM_IP
Enter fullscreen mode Exit fullscreen mode

Update the system and install base tools:

sudo apt update && sudo apt upgrade -y
sudo apt install -y nginx certbot python3-certbot-nginx ufw \
    apt-transport-https ca-certificates curl software-properties-common
Enter fullscreen mode Exit fullscreen mode

Option A: Native Deployment (systemd)

Install Java 21

sudo apt install -y openjdk-21-jdk
Enter fullscreen mode Exit fullscreen mode

Create a directory for the app

sudo mkdir -p /opt/fileserver
Enter fullscreen mode Exit fullscreen mode

Upload JAR from local machine

scp target/file-server-0.1.0.jar ubuntu@YOUR_VM_IP:/opt/fileserver/app.jar
Enter fullscreen mode Exit fullscreen mode

Create systemd service

/etc/systemd/system/fileserver.service:

[Unit]
Description=File Server Spring Boot App
After=network.target

[Service]
User=ubuntu
WorkingDirectory=/opt/fileserver
ExecStart=/usr/bin/java -jar /opt/fileserver/app.jar --spring.profiles.active=prod
SuccessExitStatus=143
Restart=always
RestartSec=10
Environment=JAVA_OPTS=-Xms256m -Xmx512m

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable fileserver
sudo systemctl start fileserver
sudo journalctl -u fileserver -f
Enter fullscreen mode Exit fullscreen mode

Option B: Docker Deployment

With Docker, you don’t need Java installed on VPS.

Install Docker

# Add Docker repo
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo tee /usr/share/keyrings/docker-archive-keyring.gpg > /dev/null

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker $USER
Enter fullscreen mode Exit fullscreen mode

⚠️ Log out and back in (or run newgrp docker) to use Docker without sudo.

Test Docker:

docker run hello-world
Enter fullscreen mode Exit fullscreen mode

Upload JAR

scp target/file-server-0.1.0.jar ubuntu@YOUR_VM_IP:/opt/fileserver/app.jar
Enter fullscreen mode Exit fullscreen mode

Create Dockerfile in /opt/fileserver

FROM eclipse-temurin:21-jdk-alpine
WORKDIR /app
COPY app.jar app.jar
EXPOSE 8000
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
Enter fullscreen mode Exit fullscreen mode

Build & run container

cd /opt/fileserver
docker build -t fileserver:latest .
docker run -d --name fileserver \
  -p 8000:8000 \
  -v /opt/fileserver/storage:/data \
  fileserver:latest
Enter fullscreen mode Exit fullscreen mode

Check logs:

docker logs -f fileserver
Enter fullscreen mode Exit fullscreen mode

Step 4: Configure nginx as a reverse proxy

Create /etc/nginx/sites-available/fileserver:

server {
    listen 80;
    server_name fileserver.example.com;

    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
Enter fullscreen mode Exit fullscreen mode

Enable and reload:

sudo ln -s /etc/nginx/sites-available/fileserver /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

Step 5: Enable HTTPS with Let’s Encrypt

sudo certbot --nginx -d fileserver.example.com
Enter fullscreen mode Exit fullscreen mode

Check renewal is active:

systemctl status certbot.timer
Enter fullscreen mode Exit fullscreen mode

Step 6: Setup firewall (UFW)

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'   # 80 + 443
sudo ufw enable
sudo ufw status
Enter fullscreen mode Exit fullscreen mode

Production considerations & tips

  • Object storage: You can connect to S3 or your provider’s storage by making some tweaks.
  • Monitoring: Use journalctl, docker logs, or monitoring tools for monitoring.
  • Backups: Schedule snapshots or rsync offsite backups.
  • nginx upload size: Already set to 50M above. You can adjust as needed.

Done 🎉

You now have a production-grade file server running on a free VPS, accessible over HTTPS, and easily testable with the included Postman collection.

👉 Grab the boilerplate here: Spring Boot File-Server Boilerplate

Top comments (0)