Why Oracle Cloud Free Tier?
Oracle Cloud's free tier is genuinely the best free cloud offering in 2025. Unlike AWS or GCP free tiers that expire after 12 months, OCI's Always Free resources never expire. For a Laravel SaaS with moderate traffic, you can run a full production stack at zero cost — forever.
| Cloud | Free Compute | Free RAM | Expires? | Storage |
|---|---|---|---|---|
| Oracle OCI | 4 OCPU (ARM) | 24 GB | ✓ Never | 200 GB |
| AWS Free Tier | 1 vCPU (t2.micro) | 1 GB | ✗ 12 months | 30 GB |
| GCP Free Tier | 1 vCPU (e2-micro) | 1 GB | ✓ Never | 30 GB |
| Azure Free | 1 vCPU (B1S) | 1 GB | ✗ 12 months | 32 GB |
Ubuntu 22.04 VM → PHP 8.3 + Nginx → Laravel app → MySQL 8 → Let's Encrypt SSL → OCI firewall rules → auto-deploy with Git. Full production stack, $0/month forever.
Step 1 — Create OCI Instance
Sign up at cloud.oracle.com (free, no credit card required for Always Free resources). Then create your compute instance:
.key file. You'll need it for SSH access. Keep it safe — you cannot re-download it.Step 2 — Server Setup
SSH into your instance using the private key. The public IP is shown on the instance details page.
# Set key permissions (required on Linux/Mac) chmod 400 ~/Downloads/your-key.key # SSH into instance (ubuntu is default user for Ubuntu images) ssh -i ~/Downloads/your-key.key ubuntu@YOUR_PUBLIC_IP # First — update everything sudo apt update && sudo apt upgrade -y
Install PHP 8.3 + Extensions
# Add Ondrej PHP PPA (most up-to-date PHP packages) sudo add-apt-repository ppa:ondrej/php -y sudo apt update # Install PHP 8.3 + all Laravel required extensions sudo apt install -y \ php8.3 \ php8.3-fpm \ php8.3-cli \ php8.3-mbstring \ php8.3-xml \ php8.3-curl \ php8.3-mysql \ php8.3-zip \ php8.3-bcmath \ php8.3-tokenizer \ php8.3-gd \ php8.3-redis \ unzip git # Verify php -v # PHP 8.3.x (cli) ... # Install Composer globally curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer composer --version
Step 3 — Nginx Setup
sudo apt install nginx -y sudo systemctl enable nginx sudo systemctl start nginx
Create the Nginx server block for your Laravel app:
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/laravel/public;
index index.php index.html;
# Laravel SPA / API — all requests to index.php
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# Block access to .env and hidden files
location ~ /\.(?!well-known).* {
deny all;
}
# Static asset caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
client_max_body_size 50M;
error_log /var/log/nginx/laravel-error.log;
access_log /var/log/nginx/laravel-access.log;
}
# Enable site
# sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
# sudo nginx -t && sudo systemctl reload nginx
# Enable site, remove default, reload sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/ sudo rm -f /etc/nginx/sites-enabled/default sudo nginx -t # must show: syntax is ok sudo systemctl reload nginx
Step 4 — MySQL 8 Setup
sudo apt install mysql-server -y sudo systemctl enable mysql # Run security wizard — set root password, remove test DB sudo mysql_secure_installation # Create Laravel database and user sudo mysql -u root -p -- Inside MySQL shell: CREATE DATABASE laravel_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'StrongPassword123!'; GRANT ALL PRIVILEGES ON laravel_db.* TO 'laravel_user'@'localhost'; FLUSH PRIVILEGES; EXIT;
Never open MySQL port 3306 to the internet in OCI Security List. MySQL should only be accessible on localhost. Use SSH tunnels for remote DB management tools like TablePlus or DBeaver.
Step 5 — Deploy Laravel App
# Create web directory and clone your project sudo mkdir -p /var/www/laravel sudo chown ubuntu:ubuntu /var/www/laravel cd /var/www/laravel git clone https://github.com/youruser/your-laravel-app.git . # Install dependencies (no dev packages on production) composer install --optimize-autoloader --no-dev # Copy and configure environment cp .env.example .env nano .env # ── Inside .env, set these: ───────────────── APP_ENV=production APP_DEBUG=false APP_URL=https://yourdomain.com DB_DATABASE=laravel_db DB_USERNAME=laravel_user DB_PASSWORD=StrongPassword123! # ──────────────────────────────────────────── # Generate app key, run migrations, cache config php artisan key:generate php artisan migrate --force php artisan config:cache php artisan route:cache php artisan view:cache # Set correct permissions sudo chown -R www-data:www-data /var/www/laravel sudo chmod -R 755 /var/www/laravel sudo chmod -R 775 /var/www/laravel/storage sudo chmod -R 775 /var/www/laravel/bootstrap/cache
Step 6 — SSL with Let's Encrypt
Free SSL certificate via Certbot. Auto-renews every 90 days — set it and forget it.
# Install Certbot + Nginx plugin sudo apt install certbot python3-certbot-nginx -y # Request certificate (auto-configures Nginx for HTTPS) sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com # Certbot will ask for email, agree to TOS # It auto-modifies your Nginx config to add: # listen 443 ssl; # ssl_certificate / ssl_certificate_key paths # HTTPS redirect from port 80 # Test auto-renewal sudo certbot renew --dry-run # Auto-renew cron (already added by Certbot, verify): sudo systemctl status certbot.timer
Visit https://yourdomain.com — you should see the green padlock. Test SSL quality at ssllabs.com/ssltest — aim for A or A+ rating.
Step 7 — OCI Firewall & Security Rules
OCI has two layers of firewall: the OCI Security List (cloud level) and Ubuntu UFW (OS level). Both must allow traffic.
OCI Security List (VCN)
Go to OCI Console → Networking → Virtual Cloud Networks → your VCN → Security Lists → Default Security List. Add these Ingress Rules:
| Port | Protocol | Source | Purpose |
|---|---|---|---|
| 22 | TCP | Your IP only | SSH Access |
| 80 | TCP | 0.0.0.0/0 | HTTP (Certbot) |
| 443 | TCP | 0.0.0.0/0 | HTTPS |
| 3306 | TCP | ❌ Never open | MySQL — localhost only |
Ubuntu UFW Firewall
# Configure UFW — whitelist only what's needed sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw allow 22/tcp # SSH sudo ufw allow 80/tcp # HTTP sudo ufw allow 443/tcp # HTTPS # Enable — type 'y' when prompted sudo ufw enable sudo ufw status verbose
Step 8 — Auto Deploy with Git Hook
Manual deploy every time is tedious. Set up a Git post-receive hook so git push automatically deploys to production:
# Create deploy script
nano /var/www/laravel/deploy.sh
#!/bin/bash set -e APP_DIR="/var/www/laravel" echo "🚀 Starting deployment..." cd $APP_DIR # Pull latest code git pull origin main # Install/update dependencies composer install --optimize-autoloader --no-dev --quiet # Run migrations (safe with --force in CI) php artisan migrate --force # Clear & rebuild all caches php artisan optimize:clear php artisan config:cache php artisan route:cache php artisan view:cache # Reset permissions sudo chown -R www-data:www-data $APP_DIR/storage sudo chown -R www-data:www-data $APP_DIR/bootstrap/cache # Restart PHP-FPM gracefully sudo systemctl reload php8.3-fpm echo "✅ Deployment complete!"
chmod +x /var/www/laravel/deploy.sh # Test deploy manually first bash /var/www/laravel/deploy.sh # Add sudo rule so deploy.sh can reload php-fpm without password echo "ubuntu ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload php8.3-fpm" | sudo tee /etc/sudoers.d/laravel-deploy
What you've built: A production Laravel stack on OCI Always Free — Ubuntu 22.04 + PHP 8.3 + Nginx + MySQL 8 + Let's Encrypt SSL + UFW firewall + automated deploy script. Total monthly cost: $0.00.
Next steps to harden: Set up MySQL automated backups to OCI Object Storage, configure Laravel queue workers with Supervisor, add Redis for caching and session management, and set up Fail2ban to block SSH brute force attempts.
OCI Certified tip: The free ARM instances (VM.Standard.A1.Flex) are ideal for Laravel. PHP 8.3 + PHP-FPM performs extremely well on ARM — I've seen 3–4x better requests/second vs t2.micro on AWS at similar CPU.