The Ultimate Indie Hacker Guide to Zero-Spend Infrastructure
If you are an indie hacker or developer building side projects, the $20/month hosting fee per project adds up fast. AWS, GCP, and DigitalOcean all want your credit card. But Oracle Cloud quietly offers the best "Always Free" tier in the industry.
What you get for exactly $0.00:
- 4 ARM Ampere A1 Compute instances
- 24 GB of RAM
- 200 GB of Block Storage
- 10 TB of Outbound Data Transfer
- 2 AMD Micro Compute instances
This guide will show you how to provision the server, configure the notoriously complex Virtual Cloud Network (VCN), install Docker, set up Traefik as a reverse proxy, and deploy your first app with automated HTTPS—all in under 30 minutes.
Step 1: Provisioning the ARM Ampere A1 Instance
- Sign up for an Oracle Cloud account (you will need a credit card for verification, but you will not be charged if you stay within the Always Free tier).
- Go to Compute > Instances and click Create Instance.
- Name your instance (e.g.,
zero-spend-box-01). - In the Image and Shape section:
- Click Edit.
- Change the image to Ubuntu 22.04.
- Change the shape to Ampere > VM.Standard.A1.Flex.
- Max out the sliders to 4 OCPUs and 24 GB of memory (assuming this is your only instance).
- In the Networking section, ensure it assigns a public IPv4 address.
- Add SSH keys: Paste your public SSH key or generate a new one. Do not skip this or you will be locked out.
- Under Boot volume, leave it at the default (or scale up to 200GB if you wish).
- Click Create and wait for the instance state to turn "Running." Note down the Public IP address.
Step 2: Conquering the Oracle VCN (Ingress/Egress Rules)
By default, Oracle's firewall blocks almost everything. Even if you open ports in ufw on Ubuntu, the cloud-level Virtual Cloud Network (VCN) will still block incoming traffic to ports 80 and 443.
- On your instance details page, click on your Subnet (e.g.,
subnet-xxxx). - Click on the Security List (e.g.,
Default Security List for vcn-xxxx). - Click Add Ingress Rules.
- Add the following rule for HTTP:
-
Source CIDR:
0.0.0.0/0 - IP Protocol: TCP
-
Destination Port Range:
80
-
Source CIDR:
- Click Add Ingress Rules again.
- Add the following rule for HTTPS:
-
Source CIDR:
0.0.0.0/0 - IP Protocol: TCP
-
Destination Port Range:
443
-
Source CIDR:
- (Optional) If you plan to expose other ports (like a database admin panel), add them here, but be careful with
0.0.0.0/0.
Now, SSH into your instance:
ssh ubuntu@YOUR_PUBLIC_IP
We must also open the ports on the local Ubuntu iptables/ufw:
# Oracle uses iptables by default on Ubuntu images
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 443 -j ACCEPT
sudo netfilter-persistent save
Step 3: Installing Docker and Docker Compose
We will run everything in containers to keep the server clean and easily reproducible.
# Update packages
sudo apt update && sudo apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add your user to the Docker group
sudo usermod -aG docker $USER
# Log out and log back in for changes to take effect
exit
Reconnect via SSH. Verify Docker is running:
docker ps
Step 4: Setting up Traefik Reverse Proxy
Traefik is a modern reverse proxy that automatically discovers Docker containers and requests Let's Encrypt SSL certificates for them.
- Create a directory for Traefik:
mkdir -p ~/traefik/data
cd ~/traefik
- Create an empty file for the Let's Encrypt certificates:
touch data/acme.json
chmod 600 data/acme.json
- Create the
docker-compose.ymlfile:
version: '3.8'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/acme.json:/acme.json
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.myresolver.acme.tlschallenge=true"
- "--certificatesresolvers.myresolver.acme.email=YOUR_EMAIL@EXAMPLE.COM"
- "--certificatesresolvers.myresolver.acme.storage=/acme.json"
# Global HTTP to HTTPS redirect
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
networks:
proxy:
external: true
Note: Replace YOUR_EMAIL@EXAMPLE.COM with your actual email address.
- Create the external network and start Traefik:
docker network create proxy
docker compose up -d
Step 5: Deploying Your First App
Let's deploy a simple "Hello World" Nginx container to prove everything works, including automatic SSL.
- Point a DNS A record (e.g.,
app.yourdomain.com) to your Oracle instance's Public IP address. - Wait a few minutes for DNS to propagate.
- Create a new directory for your app:
cd ~
mkdir my-app
cd my-app
- Create a
docker-compose.ymlfor your app:
version: '3.8'
services:
web:
image: nginx:alpine
container_name: my-app-web
restart: unless-stopped
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(\`app.yourdomain.com\`)"
- "traefik.http.routers.myapp.entrypoints=websecure"
- "traefik.http.routers.myapp.tls.certresolver=myresolver"
networks:
proxy:
external: true
Note: Replace app.yourdomain.com with your actual domain.
- Launch the app:
docker compose up -d
- Open
https://app.yourdomain.comin your browser. You should see the standard Nginx welcome page, fully secured with a valid HTTPS certificate!
Conclusion
You now have a production-ready, 24GB RAM, 4-core server running entirely for free. With Docker and Traefik, deploying a new MVP is as simple as creating a docker-compose.yml file, updating the Host label, and running docker compose up -d.
If you found this guide helpful and want more zero-spend architecture tips, subscribe to my newsletter where I share deep dives into building profitable indie projects without burning venture capital.
Happy building!
Top comments (0)