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)
- A copy of the Spring Boot file-server boilerplate. The repo includes a Postman collection for quick API testing.
- A (free) cloud account or VPS. Recommended free options (subject to provider limits):
- A local machine with
ssh
,scp
,java
, andmvn
orgradle
. - A domain name (optional but recommended). A domain makes HTTPS setup easier.
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)
- Spring Boot app listening on port 8000.
- Either:
- Managed by systemd (native deployment).
- Or inside a Docker container.
- nginx as reverse proxy with TLS (via Let’s Encrypt).
- 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
- Run the project and test with the included Postman collection.
- Build the JAR:
./mvnw clean package -DskipTests
or
./gradlew bootJar
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
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
Option A: Native Deployment (systemd)
Install Java 21
sudo apt install -y openjdk-21-jdk
Create a directory for the app
sudo mkdir -p /opt/fileserver
Upload JAR from local machine
scp target/file-server-0.1.0.jar ubuntu@YOUR_VM_IP:/opt/fileserver/app.jar
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
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable fileserver
sudo systemctl start fileserver
sudo journalctl -u fileserver -f
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
⚠️ Log out and back in (or run
newgrp docker
) to use Docker withoutsudo
.
Test Docker:
docker run hello-world
Upload JAR
scp target/file-server-0.1.0.jar ubuntu@YOUR_VM_IP:/opt/fileserver/app.jar
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"]
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
Check logs:
docker logs -f fileserver
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;
}
}
Enable and reload:
sudo ln -s /etc/nginx/sites-available/fileserver /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Step 5: Enable HTTPS with Let’s Encrypt
sudo certbot --nginx -d fileserver.example.com
Check renewal is active:
systemctl status certbot.timer
Step 6: Setup firewall (UFW)
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full' # 80 + 443
sudo ufw enable
sudo ufw status
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)