How to Set Up a Powerful, Free Forever Server on Oracle Cloud (Caddy Edition)
Earlier in 2025, I signed up for Oracle’s “Free Forever” cloud offer. It was, and still is, one of the most generous free tiers available, especially for developers and hobbyists. I wrote a blog post to document my setup, and today I’m updating it with a more modern, simpler stack and more tips for anyone starting out.
The goal remains the same: to combine all the “Always Free” resources into a single, powerful virtual private server (VPS) that you can use for your projects without ever paying a dime. This guide is my personal reference for setting it up again, and I hope it helps you too.
Oracle Cloud’s Always Free tier offers an incredibly generous free VPS that’s perfect for hosting websites, APIs, and side projects. This comprehensive guide combines the simplicity of Caddy with robust security practices to create a production-ready server.
Table of Contents
-
What You Actually Get: The “Always Free” Powerhouse
-
Why Caddy Over NGINX?
-
Step 1: Sign Up and Create the Instance
Sign Up for the Offer
-
Select Your Home Region
-
Create a VM Instance
-
Configure the Instance
-
Create the Instance
-
Step 2A: Networking Configuration (Critical)
-
Step 2B: Setup a Static Public IP Address
Access the Oracle Cloud Console
-
Navigate to Networking → Public IPs
-
Create a Reserved Public IP
-
Detach the Ephemeral IP
-
Attach the Reserved IP
-
Step 3: Connect to Your Server via SSH
Prepare Your SSH Key
-
Connect to the Server
-
Step 4: Understanding Users and Creating Your Own Account
Default Users on Your Oracle Ubuntu VM
-
Why Create Another User Account?
-
Create Your Own User Account
-
Set Up SSH Keys for Your New User (Optional but Recommended)
-
Quick User Switching
-
Step 5: Essential Server Security
-
Step 6: Install and Configure UFW Firewall
Connect via Instance Console (Recommended)
-
Install and Configure UFW
-
Enable UFW
-
If You Get Locked Out
-
Optional: Allow Other Ports
-
Step 7: Install Caddy Web Server
Install Caddy
-
Configure Caddy
-
Reload Caddy
-
Verify Caddy is Working
-
Step 8: Configure Your DNS
At Your Domain Registrar
- Step 9: Final Verification
Troubleshooting
- Step 10: Add Block Volume for Additional Storage (Optional)
Understanding Oracle’s Storage Allocation
-
Why Use a Separate Block Volume?
-
Adding and Mounting a Block Volume
-
Step 11: Create a Custom Image (Backup)
Stop the VM (Recommended)
-
Create the Custom Image
-
Start the VM Again
-
How to Use the Custom Image
-
Additional Useful Tools
Install tmux
-
Install curl and wget
-
Python Environment Setup (Optional)
-
What’s Next? Ideas for Your Server
Host a Website or Web App
-
Run Docker Containers
-
Host a Minecraft Server
-
Media Server
-
Connect to Oracle Autonomous Database
-
Host a Development Environment
-
Preventing Instance Reclamation
-
Best Practices Summary
-
Caddy Configuration Examples
Multiple Sites with Subdomains
-
With Custom Headers and Compression
-
With Rate Limiting
-
Conclusion
What You Actually Get: The “Always Free” Powerhouse
First, let’s be clear about how generous this offer is. When you consolidate the main resources for a single server, this is what you get, for free, forever:
| Component / Purpose | “Always Free” Allocation | How It Benefits Your Server |
|---|---|---|
| Server CPU & RAM | 4 ARM OCPUs & 24 GB RAM | This is the core of your machine. It’s powerful enough to run multiple apps, a game server, or a complex web service. |
| Primary Storage | 200 GB Block Storage (Total) | Your server’s “hard drive.” This is the combined total of boot volumes and block volumes. Typically: 50 GB boot + 150 GB block volume. |
| Database | 2 Autonomous Databases | You get two dedicated, fully-managed Oracle databases. Offloading your database work to these frees up your server’s CPU and RAM. |
| Networking | 1 Load Balancer & 10 TB/month Data Transfer | A stable public entry point for your services and a massive amount of free bandwidth. |
Why Caddy Over NGINX?
While NGINX is powerful and widely used, Caddy offers several advantages:
-
Automatic HTTPS: Caddy automatically obtains and renews SSL/TLS certificates from Let’s Encrypt
-
Simpler Configuration: Caddy’s configuration syntax is more intuitive and easier to read
-
Modern Defaults: Caddy comes with secure defaults out of the box
-
No Plugin Required: Unlike NGINX, you don’t need additional plugins for automatic SSL
Step 1: Sign Up and Create the Instance
Sign Up for the Offer
Go to the Oracle Cloud Free Tier page and sign up. You will need a credit card for verification, but you won’t be charged as long as you only use “Always Free” eligible resources.
Select Your Home Region
Choose your region carefully. All your “Always Free” resources must be in this single region. In my case, I selected Phoenix, as it is one of the big regions closer to Mexico. I had the bad experience in another Oracle VM setup of selecting Querétaro, México, but since it is new and doesn’t have as much resources as other regions, I couldn’t install any server under the free eligible offer.
Create a VM Instance
From the OCI console dashboard, click “Create a VM instance”

Configure the Instance
Shape Configuration:
-
Name: Give your server a descriptive name, like vps-main or my-cloud-server
-
Placement: Leave as is
-
Image and Shape: This is the most important part
Click “Edit”
-
Click “Change Image” and select Ubuntu (the latest LTS version – currently 24.04)
-
Click “Change Shape”
-
Select “Ampere” under “Shape series”
-
Choose the VM.Standard.A1.Flex shape
-
Drag the OCPU slider to 4 and the Memory slider to 24
-
This uses up your entire free ARM allocation for maximum power
-
Click “Select shape”







Boot Volume:
-
The default boot volume size is 50 GB (minimum: 47 GB)
-
You can increase it up to 200 GB, but this uses your entire free storage allocation
-
Important: The 200 GB free tier limit applies to the combined total of boot volumes AND block volumes
-
Recommended approach: Keep the default 50 GB boot volume, then add a 150 GB block volume later for flexibility

SSH Keys:
-
Download and securely store the private key. Losing it means losing access to the VM
-
The private key file on your local machine must have permissions 600 or 400
-
Use a dedicated key for this server

Create the Instance
After all these steps, click “Create” to launch the VM. It will take a minute or two to provision. Once it’s “Running” (green), note down its Public IP Address.

Step 2A: Networking Configuration (Critical)
- Security List: This is absolutely critical. Oracle Cloud has a built-in firewall that must be configured
Create a new Security List (or modify the default)
- Add Ingress Rules BEFORE launching the instance:
Rule 1 (SSH):
Source: 0.0.0.0/0
-
IP Protocol: TCP
-
Destination Port Range: 22
-
Stateless: No
-
Rule 2 (HTTP):
Source: 0.0.0.0/0
-
IP Protocol: TCP
-
Destination Port Range: 80
-
Stateless: No
-
Rule 3 (HTTPS):
Source: 0.0.0.0/0
-
IP Protocol: TCP
-
Destination Port Range: 443
-
Stateless: No
Important: Without these rules, the VM will be unreachable, even if UFW is configured correctly later. This is the single biggest source of problems for new users.



Step 2B: Setup a Static Public IP Address
When you create a VM, it usually gets an ephemeral public IP that can change if you stop/start the VM. A reserved public IP stays assigned to your account until you release it.

Access the Oracle Cloud Console
Log in to your Oracle Cloud Infrastructure (OCI) console.
Navigate to Networking → Public IPs
In the OCI menu, go to Networking → IP Management → Reserved Public IPs
Create a Reserved Public IP
-
Click the Reserve Public IP Address button
-
Fill in the details:
Create in Compartment: Select the same compartment where your VM is located
-
Name: Give it a descriptive name (e.g., my-server-reserved-ip)
-
IP Address Source: Choose Oracle (Recommended)
-
IP Address Assignment: Choose Reserve a public IPv4 address
-
Click Reserve Public IP Address
Detach the Ephemeral IP
-
Go to your VM instance details: Compute → Instances → Click your VM
-
Under Resources, click Attached VNICs
-
Click on the name of your VNIC
-
Under Resources, click IPv4 Addresses
-
Click the three dots menu (…) next to the ephemeral IP address
-
Select Edit
-
Change Public IP Type to No Public IP
-
Click Update
Attach the Reserved IP
-
Stay on the same IPv4 Addresses page for your VNIC
-
Click “Assign Public IPv4 Address” (or click the three dots on the Private IP Address and hit “Edit”)
-
Choose Reserved Public IP
-
Select the reserved IP you created from the dropdown
-
Click Assign or Update
Step 3: Connect to Your Server via SSH
You’ll use an SSH client to connect. If you’re on Windows, you can use PowerShell, WSL, Git Bash or PuTTY. On macOS or Linux, use your terminal.
Prepare Your SSH Key
If you’re using WSL on Windows, first copy the key to your WSL instance:
# Copy from Windows downloads to WSLcp /mnt/c/Users/your_username/Downloads/ssh-key-file.key ~/.ssh/my-server.key
# Set the correct permissions (mandatory for security)chmod 400 ~/.ssh/my-server.key
If you’re on macOS or Linux, just move the key to ~/.ssh/ and set permissions:
# Move the key to SSH directorymv ~/Downloads/ssh-key-file.key ~/.ssh/my-server.key
# Set the correct permissionschmod 400 ~/.ssh/my-server.keyConnect to the Server
# Replace the IP with your server's public IPssh -i ~/.ssh/my-server.key ubuntu@YOUR_SERVER_IPType yes when prompted to trust the host. You are now logged into your new server!
Note: The default username for Ubuntu instances is ubuntu
Step 4: Understanding Users and Creating Your Own Account
Default Users on Your Oracle Ubuntu VM
When Oracle creates your Ubuntu VM, it automatically sets up these user accounts:
-
root: The superuser account with full system privileges (SSH login disabled for security)
-
ubuntu: The default user account you use to connect via SSH
Important Security Note:
-
Neither root nor ubuntu have passwords set by default
-
Oracle Cloud uses SSH key-based authentication only – password login is disabled
-
The ubuntu user has passwordless sudo access (can run admin commands without a password)
-
You authenticate using the SSH private key you downloaded during VM creation
Why Create Another User Account?
While you can use the ubuntu account for everything, creating your own user account is recommended for:
-
Emergency Console Access: If you get locked out of SSH, you can use the Oracle Instance Console to login with a password-based account
-
Best Practice: Separate your personal administration from the default system account
-
Multiple Administrators: Give access to other people without sharing your SSH key
-
Better Audit Trail: Track who performed which actions on the server
Create Your Own User Account
# Create a new user (replace 'username' with your desired username)sudo adduser username
# This will prompt you to:# 1. Set a password (important for Oracle Console access!)# 2. Enter optional user information (you can skip these)
# Add the user to the sudo group (for administrative privileges)sudo usermod -aG sudo username
# Add the user to the adm group (for log access)sudo usermod -aG adm usernameSet Up SSH Keys for Your New User (Optional but Recommended)
If you want to login directly as your new user via SSH:
# Switch to the new usersu - username
# Create SSH directorymkdir -p ~/.sshchmod 700 ~/.ssh
# Copy the authorized keys from ubuntu usersudo cp /home/ubuntu/.ssh/authorized_keys ~/.ssh/sudo chown username:username ~/.ssh/authorized_keyschmod 600 ~/.ssh/authorized_keysNow you can connect directly:
ssh -i ~/.ssh/my-server.key username@YOUR_SERVER_IPQuick User Switching
You can switch between users without logging out:
# Switch to your user accountsu - username
# Switch back to ubuntu (if needed)su - ubuntu
# Return to previous userexitStep 5: Essential Server Security
Before installing anything, let’s update the system and prepare for security configuration.
# Update package list and upgrade installed packagessudo apt update && sudo apt upgrade -yThis ensures all your system packages are up to date with the latest security patches.
Step 6: Install and Configure UFW Firewall
UFW (Uncomplicated Firewall) is a simple firewall to manage access rules by ports. This provides an additional layer of security on top of Oracle’s cloud firewall.
CRITICAL WARNING: Before enabling UFW, you MUST allow SSH connections, or you will lock yourself out of the server!
Connect via Instance Console (Recommended)
To prevent accidental lockout, connect to your VM from the Oracle Instance Console:
It will ask for the username and password that we created in the step earlier. We can’t use root or ubuntu users because they are passwordless. Accessing the server from Cloud Shell should be done only for emergencies when for some reason we get locked out from accessing it via SSH, that’s why it is very important to setup another user

-
Go to your instance details in OCI Console
-
Click “Launch Cloud Shell Connection”
-
This opens a terminal at the bottom
-
Switch to the ubuntu user:
sudo su - ubuntuVerify you’re using the correct user:
whoamiInstall and Configure UFW
# Update and install UFWsudo apt updatesudo apt upgrade -ysudo apt install ufw -y
# CRITICAL: Allow SSH first to prevent lockoutsudo ufw allow 22/tcp
# Allow HTTP and HTTPS for web trafficsudo ufw allow 80/tcpsudo ufw allow 443/tcp
# Check the rules before enablingsudo ufw show addedEnable UFW
After verifying the rules look correct:
# Enable the firewallsudo ufw enable
# Verify the statussudo ufw statusYou should see output showing UFW is active with ports 22, 80, and 443 allowed.

If You Get Locked Out
If you can’t connect via SSH after enabling UFW, connect via Oracle Instance Console and run:
sudo ufw disableThen carefully review and re-add your firewall rules.
Optional: Allow Other Ports
If you need to allow other ports for specific applications:
# MySQL/MariaDBsudo ufw allow 3306/tcp
# PostgreSQLsudo ufw allow 5432/tcp
# Custom application portsudo ufw allow 8080/tcpBest Practice: Only allow ports that are absolutely necessary. The fewer ports you have open, the more secure your server is.
Step 7: Install Caddy Web Server
This is where we replace NGINX and Certbot with a much simpler solution. Caddy automatically provisions and renews free SSL certificates from Let’s Encrypt.
Install Caddy
We’ll add Caddy’s official repository to ensure we get updates:
# Install prerequisitessudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
# Add Caddy's GPG keycurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
# Add Caddy's repositorycurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
# Update and install Caddysudo apt updatesudo apt install caddy
# Verify Caddy is runningsudo systemctl status caddyConfigure Caddy
Caddy is configured with a simple file called Caddyfile. Let’s create a basic configuration.
# Open the Caddyfile with a text editorsudo nano /etc/caddy/CaddyfileDelete all the default content and replace it with this:
your-domain.com { respond "Hello from my new Oracle server!"}Important: Replace your-domain.com with the actual domain name you will point to this server.
Save the file and exit (Ctrl+X, then Y, then Enter).
Reload Caddy
To apply the new configuration:
sudo systemctl reload caddyVerify Caddy is Working
Check the status:
sudo systemctl status caddyYou should see that Caddy is “active (running)”.
Step 8: Configure Your DNS
Now, point your domain name to the server’s IP address.
At Your Domain Registrar
-
Go to your domain registrar (Namecheap, GoDaddy, Cloudflare, etc.)
-
Find the DNS management section for your domain
-
Create an “A” record:
Host/Name: @ (for the root domain your-domain.com) or www (for www.your-domain.com)
-
Value/Points to: Your server’s Public IP Address
-
TTL (Time to Live): Set to the lowest possible value or leave as default
-
Save the record
DNS changes can take anywhere from a few minutes to a few hours to propagate. You can check propagation at whatsmydns.net.
Step 9: Final Verification
Once your DNS has updated, open a web browser and navigate to https://your-domain.com.
You should see:
-
Your message: “Hello from my new Oracle server!”
-
A padlock icon in the address bar (indicating HTTPS is working)
-
Caddy has automatically handled the entire HTTPS process for you!
Troubleshooting
If you don’t see your site:
-
Check DNS Propagation: Use whatsmydns.net to verify DNS has propagated
-
Check Firewalls: Verify ports 80 and 443 are open in both UFW and Oracle Cloud security list
-
Check Caddy Configuration:# View Caddy logs sudo journalctl -u caddy -n 50 # Test from within the VM curl http://localhost/
-
Verify Domain in Caddyfile: Make sure the domain in /etc/caddy/Caddyfile matches exactly
Step 10: Add Block Volume for Additional Storage (Optional)
Since we used the default 50 GB boot volume during instance creation, you have 150 GB of free storage remaining in your Always Free allocation.
Understanding Oracle’s Storage Allocation
Oracle’s Always Free tier provides 200 GB total of block storage, which includes:
-
Boot volumes: The primary disk where your OS is installed (minimum 47 GB, default 50 GB)
-
Block volumes: Additional storage you can attach to instances
You have two options:
-
Single large boot volume: 200 GB boot volume (uses entire allocation, less flexible)
-
Boot + Block volumes: 50 GB boot + 150 GB block volume (recommended for flexibility)
Why Use a Separate Block Volume?
-
Flexibility: You can detach and attach block volumes to different instances
-
Data persistence: Keep your data separate from the OS
-
Better organization: Use boot volume for OS/apps, block volume for data
-
Easier backups: Back up data volume separately from system volume
Adding and Mounting a Block Volume
For detailed instructions on creating, attaching, and properly mounting a block volume with systemd (for automatic mounting on boot), see this dedicated guide:
Adding and Mounting a Block Volume in Ubuntu with systemd
The guide covers:
-
Creating and attaching a block volume in Oracle Cloud
-
Formatting the volume with ext4
-
Setting up systemd mount units (more reliable than fstab)
-
Proper permissions and ownership configuration
-
Troubleshooting common issues
Step 11: Create a Custom Image (Backup)
Before installing additional software, create a backup image of your VM. This allows you to quickly restore or create new VMs if something goes wrong.
Stop the VM (Recommended)
It’s strongly recommended to stop the VM before creating a custom image to ensure filesystem consistency:
-
In OCI Console, go to your instance details
-
Click “Stop” and wait for it to completely stop
Create the Custom Image
-
On the instance details page, click “More Actions” → “Create Custom Image”
-
Give it a descriptive name (e.g., my-server-caddy-baseline-2025-11-01)
-
Choose your compartment
-
Click “Create Custom Image”
The process will take some time depending on your boot volume size.
Start the VM Again
After the image is created, start your VM:
-
Click “Start” on the instance details page
-
Wait for it to reach “Running” state
-
Reconnect via SSH
How to Use the Custom Image
To create a new VM from your custom image:
-
Go to Compute → Custom Images
-
Find your image and click it
-
Click “Create Instance”
-
Complete the instance creation as normal
Additional Useful Tools
Install tmux
tmux allows you to manage multiple terminal sessions and keep processes running even after you disconnect:
# Install tmuxsudo apt updatesudo apt install tmux -yBasic tmux commands:
| Action | Command |
|---|---|
| Start a new session | tmux |
| Create a named session | tmux new -s session_name |
| Detach from session | Ctrl + B then D |
| List active sessions | tmux ls |
| Reattach to session | tmux attach -t session_name |
| Close session from within | exit |
Install curl and wget
Essential tools for downloading files and making HTTP requests:
sudo apt updatesudo apt install curl wget -yPython Environment Setup (Optional)
If you plan to run Python applications:
# Install pip3sudo apt install python3-pip -y
# Install pipx (for isolated Python tools)sudo apt install pipxpipx ensurepath
# Install uv (modern Python package manager)pipx install uv
# Verify installation (close and reopen terminal first)uv --versionWhat’s Next? Ideas for Your Server
You now have a powerful, secure, and free ARM server. Here are some great ideas for what to do with it:
Host a Website or Web App
Caddy can easily:
-
Run a static site using the file_server directive
-
Act as a reverse proxy for applications written in Node.js, Python, Go, or PHP
Example Caddyfile for a static site:
your-domain.com { root * /var/www/your-site file_server}Example Caddyfile for a reverse proxy:
app.your-domain.com { reverse_proxy localhost:3000}Run Docker Containers
Install Docker and manage multiple applications in containers:
sudo apt install docker.io docker-compose -ysudo usermod -aG docker $USERImportant: Use Docker images built for the linux/arm64 architecture. Many official images on Docker Hub are multi-arch and will work seamlessly.
Host a Minecraft Server
The standard Java version of the Minecraft server runs perfectly on ARM:
sudo apt install default-jre -yThen download and run the Minecraft server JAR file.
Media Server
Set up Plex or Jellyfin. Both have official, native builds for ARM64:
-
Jellyfin ARM64 Installation
-
Plex Media Server
Connect to Oracle Autonomous Database
Install your application stack on the server and use the free Oracle database as your backend for amazing performance, freeing up your server’s resources.
Host a Development Environment
Set up:
-
Git server (Gitea or GitLab)
-
CI/CD pipelines
-
Code-server (VS Code in the browser)
-
JupyterHub for data science work
Preventing Instance Reclamation
Important: Oracle may reclaim “idle” Always Free instances. An instance is idle if it has very low CPU, memory, or network usage for 7 days.
To prevent this:
-
Run a web server that gets occasional traffic (which you’ve done!)
-
Set up a simple cron job that performs periodic tasks
-
Run a lightweight monitoring service
-
Keep Docker containers running
Simply having Caddy running and serving your website should be sufficient to avoid the idle classification.
Best Practices Summary
-
Always use SSH keys, never password authentication
-
Configure both firewalls: Oracle Cloud Security List AND UFW
-
Create regular backups using Custom Images
-
Keep the system updated: Run sudo apt update && sudo apt upgrade regularly
-
Use tmux for long-running processes
-
Monitor logs: sudo journalctl -u caddy for Caddy logs
-
Use subdomain for applications: Keep your main domain for your main site
-
Test in staging first: Use your custom image to spin up test VMs for experimentation
-
Document your setup: Keep notes of what you’ve installed and configured
-
Set up monitoring: Consider installing monitoring tools like Netdata or Prometheus
Caddy Configuration Examples
Multiple Sites with Subdomains
your-domain.com { root * /var/www/main-site file_server}
blog.your-domain.com { root * /var/www/blog file_server}
api.your-domain.com { reverse_proxy localhost:8080}With Custom Headers and Compression
your-domain.com { encode gzip
header { # Enable HSTS Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" # Security headers X-Content-Type-Options "nosniff" X-Frame-Options "DENY" Referrer-Policy "strict-origin-when-cross-origin" }
root * /var/www/your-site file_server}With Rate Limiting
your-domain.com { rate_limit { zone dynamic { key {remote_host} events 100 window 1m } }
reverse_proxy localhost:3000}Conclusion
You now have a production-ready, secure, and powerful free server running on Oracle Cloud with Caddy handling automatic HTTPS. This setup combines:
-
Security: UFW firewall + Oracle Cloud Security Lists + automatic HTTPS
-
Simplicity: Caddy’s easy configuration
-
Power: 4 ARM cores and 24GB RAM
-
Reliability: Custom image backups
-
Scalability: Ready for multiple applications and domains
Enjoy your free forever server! 🚀
Additional Resources:
-
Oracle Cloud Free Tier Documentation
-
Caddy Documentation
-
Ubuntu Server Guide
-
UFW Documentation