Skip to content

Instantly share code, notes, and snippets.

@phirex
Last active January 26, 2026 00:52
Show Gist options
  • Select an option

  • Save phirex/46f5b56a45b863a2028964ae8a2bc42c to your computer and use it in GitHub Desktop.

Select an option

Save phirex/46f5b56a45b863a2028964ae8a2bc42c to your computer and use it in GitHub Desktop.
Cloud Infrastructure Setup Guide - Oracle Cloud, Cloudflare R2, Vercel (Free Tier)

Cloud Infrastructure Setup Guide

Free Tier Microservice Deployment with Oracle Cloud, Cloudflare R2, and Vercel

Author: Ori Levi & Claude

Last Updated: January 2026
Estimated Setup Time: 1-2 hours


Table of Contents

  1. Overview
  2. Prerequisites
  3. Part 1: Oracle Cloud Free Tier Setup
  4. Part 2: Cloudflare R2 Setup
  5. Part 3: Vercel Setup & Domain Purchase
  6. Part 4: Connect Everything Together
  7. Architecture Diagram
  8. Cost Summary
  9. Troubleshooting

Overview

This guide walks you through setting up a complete microservice infrastructure using free tiers of major cloud providers:

  • Oracle Cloud: Backend compute (ARM VM with 4 CPUs, 24GB RAM) + Database
  • Cloudflare R2: Object storage (S3-compatible)
  • Vercel: Frontend hosting + Domain management

All configuration is done via CLI tools for automation and reproducibility.


Prerequisites

Install Required CLI Tools

# Install Oracle Cloud CLI (OCI)
# macOS
brew install oci-cli

# Linux/Windows
curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh | bash

# Install Cloudflare Wrangler CLI
npm install -g wrangler

# Install Vercel CLI
npm install -g vercel

# Install jq for JSON parsing (optional but recommended)
brew install jq  # macOS
# or: sudo apt install jq  # Ubuntu/Debian

# Install Terraform (optional, for infrastructure as code)
brew install terraform

Generate SSH Keys (if you don't have them)

ssh-keygen -t rsa -b 4096 -C "your@email.com"
# Keys will be saved to ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub

Part 1: Oracle Cloud Free Tier Setup

1.1 Sign Up (Web Required)

  1. Go to cloud.oracle.com/free
  2. Create an account with your email
  3. Verify your identity (credit card required but won't be charged)
  4. Wait for account activation (usually instant, sometimes up to 24 hours)

Free Tier Includes:

  • 2 AMD Compute VMs (1/8 OCPU, 1GB RAM each)
  • 4 ARM Ampere A1 cores + 24GB RAM (always free) ⭐ Best value!
  • 2 Autonomous Databases (20GB each)
  • 200GB Block Storage
  • 10TB/month outbound data transfer

1.2 Configure OCI CLI

# Initial setup - creates config at ~/.oci/config
oci setup config

You'll be prompted for:

  • User OCID: Find in OCI Console β†’ Profile β†’ User Settings
  • Tenancy OCID: Find in OCI Console β†’ Profile β†’ Tenancy
  • Region: e.g., us-ashburn-1, eu-frankfurt-1, me-jeddah-1
  • Generate new API key pair?: Yes

After generation, upload the public key:

  1. Go to OCI Console β†’ Profile β†’ API Keys
  2. Click "Add API Key"
  3. Choose "Paste Public Key"
  4. Paste content of ~/.oci/oci_api_key_public.pem

1.3 Create Network Infrastructure

#!/bin/bash
# create-network.sh

# Set your compartment ID (find in OCI Console β†’ Identity β†’ Compartments)
COMPARTMENT_ID="ocid1.compartment.oc1..your_compartment_id"

# Create VCN (Virtual Cloud Network)
VCN_ID=$(oci network vcn create \
  --compartment-id "$COMPARTMENT_ID" \
  --cidr-block "10.0.0.0/16" \
  --display-name "microservice-vcn" \
  --dns-label "microservicevcn" \
  --query 'data.id' --raw-output)

echo "VCN created: $VCN_ID"

# Create Internet Gateway
IGW_ID=$(oci network internet-gateway create \
  --compartment-id "$COMPARTMENT_ID" \
  --vcn-id "$VCN_ID" \
  --is-enabled true \
  --display-name "microservice-igw" \
  --query 'data.id' --raw-output)

echo "Internet Gateway created: $IGW_ID"

# Create Route Table with internet access
RT_ID=$(oci network route-table create \
  --compartment-id "$COMPARTMENT_ID" \
  --vcn-id "$VCN_ID" \
  --route-rules '[{"cidrBlock":"0.0.0.0/0","networkEntityId":"'$IGW_ID'"}]' \
  --display-name "microservice-rt" \
  --query 'data.id' --raw-output)

echo "Route Table created: $RT_ID"

# Create Security List (firewall rules)
SL_ID=$(oci network security-list create \
  --compartment-id "$COMPARTMENT_ID" \
  --vcn-id "$VCN_ID" \
  --display-name "microservice-sl" \
  --ingress-security-rules '[
    {"protocol":"6","source":"0.0.0.0/0","tcpOptions":{"destinationPortRange":{"min":22,"max":22}}},
    {"protocol":"6","source":"0.0.0.0/0","tcpOptions":{"destinationPortRange":{"min":80,"max":80}}},
    {"protocol":"6","source":"0.0.0.0/0","tcpOptions":{"destinationPortRange":{"min":443,"max":443}}},
    {"protocol":"6","source":"0.0.0.0/0","tcpOptions":{"destinationPortRange":{"min":3000,"max":3000}}}
  ]' \
  --egress-security-rules '[{"protocol":"all","destination":"0.0.0.0/0"}]' \
  --query 'data.id' --raw-output)

echo "Security List created: $SL_ID"

# Create Subnet
SUBNET_ID=$(oci network subnet create \
  --compartment-id "$COMPARTMENT_ID" \
  --vcn-id "$VCN_ID" \
  --cidr-block "10.0.1.0/24" \
  --display-name "microservice-subnet" \
  --dns-label "microservicesub" \
  --route-table-id "$RT_ID" \
  --security-list-ids '["'$SL_ID'"]' \
  --query 'data.id' --raw-output)

echo "Subnet created: $SUBNET_ID"

# Save IDs for later use
cat > network-ids.env << EOF
VCN_ID=$VCN_ID
IGW_ID=$IGW_ID
RT_ID=$RT_ID
SL_ID=$SL_ID
SUBNET_ID=$SUBNET_ID
EOF

echo "Network IDs saved to network-ids.env"

1.4 Create ARM Compute Instance

#!/bin/bash
# create-instance.sh

source network-ids.env

COMPARTMENT_ID="ocid1.compartment.oc1..your_compartment_id"

# Get Availability Domain
AVAILABILITY_DOMAIN=$(oci iam availability-domain list \
  --compartment-id "$COMPARTMENT_ID" \
  --query 'data[0].name' --raw-output)

echo "Using Availability Domain: $AVAILABILITY_DOMAIN"

# Get latest Ubuntu 22.04 ARM image
IMAGE_ID=$(oci compute image list \
  --compartment-id "$COMPARTMENT_ID" \
  --operating-system "Canonical Ubuntu" \
  --operating-system-version "22.04" \
  --shape "VM.Standard.A1.Flex" \
  --sort-by TIMECREATED \
  --sort-order DESC \
  --query 'data[0].id' --raw-output)

echo "Using Image: $IMAGE_ID"

# Create ARM instance (4 OCPUs, 24GB RAM - free tier max)
INSTANCE_ID=$(oci compute instance launch \
  --compartment-id "$COMPARTMENT_ID" \
  --availability-domain "$AVAILABILITY_DOMAIN" \
  --shape "VM.Standard.A1.Flex" \
  --shape-config '{"ocpus": 4, "memoryInGBs": 24}' \
  --subnet-id "$SUBNET_ID" \
  --image-id "$IMAGE_ID" \
  --display-name "microservice-server" \
  --assign-public-ip true \
  --ssh-authorized-keys-file ~/.ssh/id_rsa.pub \
  --wait-for-state RUNNING \
  --query 'data.id' --raw-output)

echo "Instance created: $INSTANCE_ID"

# Get Public IP
PUBLIC_IP=$(oci compute instance list-vnics \
  --instance-id "$INSTANCE_ID" \
  --query 'data[0]."public-ip"' --raw-output)

echo "============================================"
echo "βœ… Instance ready!"
echo "Public IP: $PUBLIC_IP"
echo "SSH Command: ssh -i ~/.ssh/id_rsa ubuntu@$PUBLIC_IP"
echo "============================================"

# Save for later
echo "INSTANCE_ID=$INSTANCE_ID" >> network-ids.env
echo "PUBLIC_IP=$PUBLIC_IP" >> network-ids.env

⚠️ Note: ARM instances are in high demand. If creation fails with "Out of capacity", try:

  • Different availability domain
  • Smaller configuration (2 OCPUs, 12GB RAM)
  • Wait and retry later

1.5 Create Autonomous Database

#!/bin/bash
# create-database.sh

COMPARTMENT_ID="ocid1.compartment.oc1..your_compartment_id"
DB_NAME="microservicedb"
ADMIN_PASSWORD="YourSecurePassword123!"  # Must have: uppercase, lowercase, number, 12+ chars

# Create Autonomous Database (Always Free)
DB_ID=$(oci db autonomous-database create \
  --compartment-id "$COMPARTMENT_ID" \
  --db-name "$DB_NAME" \
  --display-name "$DB_NAME" \
  --admin-password "$ADMIN_PASSWORD" \
  --cpu-core-count 1 \
  --data-storage-size-in-tbs 1 \
  --db-workload "OLTP" \
  --is-free-tier true \
  --wait-for-state AVAILABLE \
  --query 'data.id' --raw-output)

echo "Database created: $DB_ID"

# Download connection wallet
oci db autonomous-database generate-wallet \
  --autonomous-database-id "$DB_ID" \
  --password "$ADMIN_PASSWORD" \
  --file wallet.zip

echo "Connection wallet saved to wallet.zip"

# Get connection strings
oci db autonomous-database get \
  --autonomous-database-id "$DB_ID" \
  --query 'data."connection-strings"'

1.6 Server Setup Script

After SSHing into your instance, run this setup script:

#!/bin/bash
# server-setup.sh - Run this ON the Oracle instance

set -e

echo "πŸš€ Setting up server..."

# Update system
sudo apt update && sudo apt upgrade -y

# Install essential packages
sudo apt install -y \
  docker.io \
  docker-compose \
  git \
  curl \
  wget \
  unzip \
  nginx \
  certbot \
  python3-certbot-nginx \
  build-essential

# Enable Docker
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker $USER

# Install Node.js 20 (LTS)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Verify installations
echo "Node.js version: $(node --version)"
echo "npm version: $(npm --version)"
echo "Docker version: $(docker --version)"

# Install OpenCode (AI coding assistant)
sudo npm install -g @anthropic-ai/opencode

# Alternative: Install OpenCode Go version
# curl -fsSL https://get.opencode.ai | bash

# Install PM2 for process management
sudo npm install -g pm2

# Configure firewall (iptables)
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 3000 -j ACCEPT

# Make iptables rules persistent
sudo apt install -y iptables-persistent
sudo netfilter-persistent save

# Create application directory
sudo mkdir -p /opt/microservice
sudo chown $USER:$USER /opt/microservice

echo "βœ… Server setup complete!"
echo ""
echo "Next steps:"
echo "1. Configure Nginx: sudo nano /etc/nginx/sites-available/default"
echo "2. Set up SSL: sudo certbot --nginx -d your-domain.com"
echo "3. Deploy your application to /opt/microservice"

1.7 Configure Nginx Reverse Proxy

# Create Nginx configuration
sudo tee /etc/nginx/sites-available/microservice << 'EOF'
server {
    listen 80;
    server_name api.your-domain.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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_cache_bypass $http_upgrade;
        
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}
EOF

# Enable the site
sudo ln -sf /etc/nginx/sites-available/microservice /etc/nginx/sites-enabled/

# Test and reload
sudo nginx -t && sudo systemctl reload nginx

# Get SSL certificate (after DNS is configured)
sudo certbot --nginx -d api.your-domain.com --non-interactive --agree-tos -m your@email.com

Part 2: Cloudflare R2 Setup

2.1 Sign Up (Web Required)

  1. Go to dash.cloudflare.com/sign-up
  2. Create account and verify email
  3. Add your domain (or use Cloudflare's free subdomain for testing)

Free Tier Includes:

  • 10GB storage
  • 1 million Class A operations/month (writes)
  • 10 million Class B operations/month (reads)
  • No egress fees! πŸŽ‰

2.2 Configure Wrangler CLI

# Login to Cloudflare (opens browser for OAuth)
wrangler login

# Verify login
wrangler whoami

For headless/CI environments:

# Create API token at: dash.cloudflare.com/profile/api-tokens
# Required permissions: Account.Workers R2 Storage:Edit

export CLOUDFLARE_API_TOKEN="your-api-token"
export CLOUDFLARE_ACCOUNT_ID="your-account-id"  # Find in dashboard URL or sidebar

2.3 Create R2 Bucket

#!/bin/bash
# create-r2-bucket.sh

BUCKET_NAME="microservice-storage"

# Create bucket
wrangler r2 bucket create "$BUCKET_NAME"

# List buckets to verify
wrangler r2 bucket list

# Get bucket info
wrangler r2 bucket info "$BUCKET_NAME"

2.4 Create R2 API Credentials

For S3-compatible API access (needed for your microservice):

  1. Go to Cloudflare Dashboard β†’ R2 β†’ Overview
  2. Click "Manage R2 API Tokens"
  3. Click "Create API Token"
  4. Set permissions: "Object Read & Write"
  5. Specify bucket (or all buckets)
  6. Copy the Access Key ID and Secret Access Key

Or via API:

# Create API token programmatically
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/r2/buckets/$BUCKET_NAME/tokens" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "name": "Microservice R2 Token",
    "permissions": ["object-read-write"]
  }'

2.5 Using R2 in Your Application

// Example: Node.js with AWS SDK v3
import { S3Client, PutObjectCommand, GetObjectCommand } from "@aws-sdk/client-s3";

const r2Client = new S3Client({
  region: "auto",
  endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID,
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
  },
});

// Upload file
await r2Client.send(new PutObjectCommand({
  Bucket: process.env.R2_BUCKET_NAME,
  Key: "uploads/file.pdf",
  Body: fileBuffer,
  ContentType: "application/pdf",
}));

// Download file
const response = await r2Client.send(new GetObjectCommand({
  Bucket: process.env.R2_BUCKET_NAME,
  Key: "uploads/file.pdf",
}));

Part 3: Vercel Setup & Domain Purchase

3.1 Sign Up and Login

# Login (opens browser)
vercel login

# Or login with email
vercel login your@email.com

# Or use token for CI/CD
export VERCEL_TOKEN="your-vercel-token"

3.2 Search and Buy Domain

# Check domain availability
vercel domains inspect your-domain.com

# Buy domain (requires payment method on Vercel account)
vercel domains buy your-domain.com

# Or add existing domain
vercel domains add your-domain.com

# List your domains
vercel domains ls

3.3 Deploy Project

# Navigate to your project
cd /path/to/your/frontend

# Initialize Vercel project (first time)
vercel

# Deploy to production
vercel --prod

# Link custom domain to project
vercel domains add your-domain.com --project your-project-name

3.4 Configure Environment Variables

# Add environment variables
vercel env add NEXT_PUBLIC_API_URL production
# Enter value: https://api.your-domain.com

vercel env add DATABASE_URL production
# Enter your database connection string

# List environment variables
vercel env ls

Part 4: Connect Everything Together

4.1 DNS Configuration

If your domain is on Cloudflare:

#!/bin/bash
# configure-dns.sh

DOMAIN="your-domain.com"
ORACLE_IP="your-oracle-instance-ip"

# Get Zone ID
ZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$DOMAIN" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" | jq -r '.result[0].id')

echo "Zone ID: $ZONE_ID"

# Add A record for API subdomain
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "A",
    "name": "api",
    "content": "'$ORACLE_IP'",
    "ttl": 1,
    "proxied": true
  }'

# Add CNAME for Vercel (if not using Vercel DNS)
curl -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
  -H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "type": "CNAME",
    "name": "@",
    "content": "cname.vercel-dns.com",
    "ttl": 1,
    "proxied": false
  }'

echo "DNS records configured!"

4.2 Complete Environment Variables

Create a .env.production file:

# Oracle Cloud Database
DATABASE_URL=postgresql://admin:password@your-db-host:5432/microservicedb

# Or for Oracle Autonomous DB (with wallet)
DATABASE_URL=oracle://admin:password@tcps://adb.region.oraclecloud.com:1522/dbname_tp

# Cloudflare R2
R2_ACCOUNT_ID=your-cloudflare-account-id
R2_ACCESS_KEY_ID=your-r2-access-key
R2_SECRET_ACCESS_KEY=your-r2-secret-key
R2_BUCKET_NAME=microservice-storage
R2_ENDPOINT=https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com

# URLs
FRONTEND_URL=https://your-domain.com
API_URL=https://api.your-domain.com

# OpenCode (for AI assistance on server)
ANTHROPIC_API_KEY=your-anthropic-api-key

4.3 Full Automation Script

#!/bin/bash
# full-setup.sh - Complete infrastructure setup

set -e

echo "============================================"
echo "πŸš€ Full Infrastructure Setup"
echo "============================================"

# Configuration
DOMAIN="your-domain.com"
PROJECT_NAME="my-microservice"
COMPARTMENT_ID="ocid1.compartment.oc1..xxx"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

print_status() {
    echo -e "${GREEN}βœ… $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠️  $1${NC}"
}

print_error() {
    echo -e "${RED}❌ $1${NC}"
}

# Check prerequisites
echo "Checking prerequisites..."

command -v oci >/dev/null 2>&1 || { print_error "OCI CLI not installed"; exit 1; }
command -v wrangler >/dev/null 2>&1 || { print_error "Wrangler not installed"; exit 1; }
command -v vercel >/dev/null 2>&1 || { print_error "Vercel CLI not installed"; exit 1; }

print_status "All CLI tools installed"

# Step 1: Oracle Cloud Setup
echo ""
echo "Step 1: Oracle Cloud Setup"
echo "─────────────────────────────"

# ... (Insert Oracle setup commands from sections 1.3-1.5)

print_status "Oracle Cloud infrastructure created"

# Step 2: Cloudflare R2 Setup
echo ""
echo "Step 2: Cloudflare R2 Setup"
echo "─────────────────────────────"

BUCKET_NAME="${PROJECT_NAME}-storage"
wrangler r2 bucket create "$BUCKET_NAME" 2>/dev/null || print_warning "Bucket may already exist"

print_status "R2 bucket ready: $BUCKET_NAME"

# Step 3: Vercel Setup
echo ""
echo "Step 3: Vercel Setup"
echo "─────────────────────────────"

# Deploy (assumes you're in project directory)
vercel --prod --yes 2>/dev/null || print_warning "Vercel deployment skipped"

print_status "Vercel deployment complete"

# Step 4: Generate summary
echo ""
echo "============================================"
echo "πŸŽ‰ Setup Complete!"
echo "============================================"
echo ""
echo "Resources:"
echo "  β€’ Oracle Instance: $PUBLIC_IP"
echo "  β€’ R2 Bucket: $BUCKET_NAME"
echo "  β€’ Frontend: https://$DOMAIN"
echo "  β€’ API: https://api.$DOMAIN"
echo ""
echo "Next Steps:"
echo "  1. SSH to server: ssh ubuntu@$PUBLIC_IP"
echo "  2. Run server setup script"
echo "  3. Configure DNS records"
echo "  4. Deploy your microservice code"
echo ""

Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           USERS                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              β”‚
                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Cloudflare DNS + CDN                         β”‚
β”‚           (DDoS protection, caching, SSL termination)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚                         β”‚
                   β–Ό                         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Vercel (Frontend)       β”‚   β”‚   Oracle Cloud (Backend)       β”‚
β”‚  ──────────────────────────│   β”‚  ──────────────────────────────│
β”‚  β€’ Next.js / React App     β”‚   β”‚  β€’ ARM VM (4 CPU, 24GB RAM)    β”‚
β”‚  β€’ Static assets (CDN)     β”‚   β”‚  β€’ Docker containers           β”‚
β”‚  β€’ Serverless functions    β”‚   β”‚  β€’ Nginx reverse proxy         β”‚
β”‚  β€’ Auto SSL                β”‚   β”‚  β€’ OpenCode AI assistant       β”‚
β”‚  β€’ your-domain.com         β”‚   β”‚  β€’ api.your-domain.com         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                 β”‚
                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                   β”‚                             β”‚                 β”‚
                   β–Ό                             β–Ό                 β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚    Cloudflare R2       β”‚   β”‚  Oracle Autonomous DB  β”‚   β”‚   OpenCode    β”‚
β”‚  ──────────────────────│   β”‚  ──────────────────────│   β”‚  ─────────────│
β”‚  β€’ Object storage      β”‚   β”‚  β€’ PostgreSQL/Oracle   β”‚   β”‚  β€’ AI Pair    β”‚
β”‚  β€’ S3-compatible API   β”‚   β”‚  β€’ 20GB free storage   β”‚   β”‚    Programmingβ”‚
β”‚  β€’ No egress fees      β”‚   β”‚  β€’ Auto scaling        β”‚   β”‚  β€’ Code reviewβ”‚
β”‚  β€’ Global CDN          β”‚   β”‚  β€’ Auto backups        β”‚   β”‚  β€’ Debugging  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Cost Summary

Service Free Tier Includes Paid Tier Starts
Oracle Cloud 4 ARM cores, 24GB RAM, 200GB storage, 2 DBs (20GB each), 10TB/mo egress $0 (always free tier)
Cloudflare R2 10GB storage, 1M writes, 10M reads/month, no egress fees $0.015/GB storage
Vercel 100GB bandwidth, 100GB-hours compute, automatic SSL $20/mo (Pro)
Domain N/A ~$10-20/year

Total Monthly Cost: $0-2 (just domain renewal)


Troubleshooting

Oracle Cloud Issues

Problem: "Out of capacity" error when creating ARM instance

# Solution 1: Try different availability domain
oci iam availability-domain list --compartment-id $COMPARTMENT_ID

# Solution 2: Reduce instance size
--shape-config '{"ocpus": 2, "memoryInGBs": 12}'

# Solution 3: Use automation to retry
while true; do
  oci compute instance launch ... && break
  sleep 60
done

Problem: Can't SSH to instance

# Check security list rules
oci network security-list get --security-list-id $SL_ID

# Verify public IP assigned
oci compute instance list-vnics --instance-id $INSTANCE_ID

# Check SSH key permissions
chmod 600 ~/.ssh/id_rsa

Cloudflare R2 Issues

Problem: Access denied when uploading

# Verify credentials
wrangler whoami

# Check bucket permissions
wrangler r2 bucket info $BUCKET_NAME

# Test with wrangler directly
echo "test" | wrangler r2 object put $BUCKET_NAME/test.txt

Vercel Issues

Problem: Domain not resolving

# Check DNS propagation
dig your-domain.com
nslookup your-domain.com

# Verify Vercel domain config
vercel domains inspect your-domain.com

Quick Reference Commands

# Oracle Cloud
oci compute instance list --compartment-id $COMPARTMENT_ID
oci compute instance get --instance-id $INSTANCE_ID
oci compute instance action --action STOP --instance-id $INSTANCE_ID
oci compute instance action --action START --instance-id $INSTANCE_ID

# Cloudflare R2
wrangler r2 bucket list
wrangler r2 object list $BUCKET_NAME
wrangler r2 object get $BUCKET_NAME/path/to/file
wrangler r2 object put $BUCKET_NAME/path/to/file --file ./local-file

# Vercel
vercel ls                    # List deployments
vercel logs                  # View deployment logs
vercel env ls                # List environment variables
vercel domains ls            # List domains
vercel --prod                # Deploy to production

Additional Resources


Happy deploying! πŸš€

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment