How to Host a Website in Oracle Cloud Free Tier

edited March 28 in Technical

This post is originally published on blog

Oracle Cloud is a cloud computing service offered by Oracle Corporation.
Oracle Cloud has a generous free tier that offers two "always free" virtual machine (VM) instances with the following specification:

  • KVM virtualization
  • 1/8 CPU cores (AMD EPYC 7551)
  • 1GB memory
  • 45GB disk storage
  • 1 IPv4 address, no IPv6
  • 48Mbps Internet bandwidth

I signed up for Oracle Cloud, so that I can have some more free computing resources to play with.
The sign-up procedure requires a credit card for identity confirmation purpose, but the credit card will not be charged.
During sign-up, there's a choice of home region, which determines the location of VM instances; once selected, it cannot be changed in the future.

A common use case for a virtual machine is to host a website.
Due to the firewalls, hosting a website on Oracle Cloud needs a few more steps.
Here's exactly how to deploy a website in a Oracle Cloud Free Tier VM instance.

Create a VM Instance

Each Oracle Cloud account is eligible for two Always Free VM instances.
To create a VM, sign in to the Oracle Cloud console, in "Quick Actions" section click Create a VM instance.

Oracle Cloud console - Quick Actions

This takes us to the "Create Compute Instance" page.

In "Configure placement and hardware" section, change the "image" to Canonical Ubuntu 20.04.
Do not select the "Canonical Ubuntu 20.04 Minimal" option.

Create Compute Instance - Configure placement and hardware

In "Configure network" section, select Create new virtual cloud network, and keep other options at their default values.

Create Compute Instance - Configure networking

In "Add SSH keys" section, select Paste public keys, and paste your SSH public key in the text box below.
If you do not have a SSH public key, follow this guide to generate one.

Finally, click the Create button to create the compute VM instance.
Within a few seconds, you should see the "Instance Details" page.

Instance Details

You can now SSH into the VM instance using the public IP address and username displayed in the "Instance Access" section.
This is also a good time to add a DNS record toward the public IP address, so that we can activate HTTPS later.

DNS record

Configure Ingress Rules

Oracle Cloud has a strict firewall that, by default, only allows SSH access.
In order to host a website, it is necessary to configure the firewall so that it allows HTTP traffic.

To access the firewall configuration page, click the "subnet" name in "Primary VNIC" section of "Instance Details" page.
Then, on "Subnet Details" page, click "Default Security List for …" in "Security Lists" section.
Click Add Ingress Rules button, and enter these two rules:

  • Allow HTTP/1.1 and HTTP/2

    • stateless: disabled
    • source CIDR:
    • IP protocol: TCP
    • destination port range: 80,443
  • Allow HTTP/3

    • stateless: disabled
    • source CIDR:
    • IP protocol: UDP
    • destination port range: 443

After that, you should see the following ingress rules in the table:

Virtual Cloud Networks - Ingress Rules

Install HTTP Server

With the firewall rules in place, we are ready to install an HTTP server.
In this guide, I'm installing Caddy HTTP server along with PHP-FPM.
They can be installed from Caddy package repository and ondrej/php PPA respectively.

echo "deb [trusted=yes] /" | sudo tee -a /etc/apt/sources.list.d/caddy-fury.list
sudo add-apt-repository ppa:ondrej/php
sudo apt install caddy php8.0-fpm

Before we can start the HTTP server, there's one more firewall to configure: the local iptables.
Oracle Cloud not only has an external firewall at subnet level, but also blocks traffic in iptables INPUT chain.
We can setup a systemd service to insert iptables rules before Caddy starts:

sudoedit /etc/systemd/system/caddy-iptables.service
  (paste the caddy-iptables.service content)

sudo systemctl daemon-reload
sudo systemctl enable caddy-iptables
sudo systemctl start caddy-iptables

The systemd unit file caddy-iptables.service should have the following content:

Description=Firewall rules for Caddy

ExecStartPre=+/usr/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT
ExecStartPre=+/usr/sbin/iptables -I INPUT -p tcp --dport 443 -j ACCEPT
ExecStartPre=+/usr/sbin/iptables -I INPUT -p udp --dport 443 -j ACCEPT
ExecStopPost=+/usr/sbin/iptables -D INPUT -p tcp --dport 80 -j ACCEPT
ExecStopPost=+/usr/sbin/iptables -D INPUT -p tcp --dport 443 -j ACCEPT
ExecStopPost=+/usr/sbin/iptables -D INPUT -p udp --dport 443 -j ACCEPT


Upload your website content, and make sure the www-data group can access them.
In this example, I'll create two simple files:

sudo mkdir -p /var/www/html
echo '<h1>hello</h1>' | sudo tee /var/www/html/index.html
echo '<?php phpinfo(); ?>' | sudo tee /var/www/html/phpinfo.php

Edit the Caddyfile (/etc/caddy/Caddyfile), paste the following:
(change the domain name and root directory as appropriate)

} {
  root * /var/www/html
  php_fastcgi unix//run/php/php8.0-fpm.sock

  header {
    Strict-Transport-Security max-age=2592000
    X-Frame-Options SAMEORIGIN
    X-Content-Type-Options nosniff
    Referrer-Policy no-referrer-when-downgrade

Finally, restart the webserver for the settings to take effect:

sudo systemctl restart caddy
sudo systemctl restart php8.0-fpm

Test the Website

To confirm everything is working, we can visit the index page and the PHP script in the browser.

Then, we execute the curl command line tool (on a different machine) to confirm the HTTP-to-HTTPS redirect is working properly, and the website works over HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3.

$ curl --http1.0 -I
HTTP/1.0 308 Permanent Redirect
Connection: close
Server: Caddy
Date: Fri, 25 Dec 2020 20:17:10 GMT

$ curl --http1.1 -I
HTTP/1.1 308 Permanent Redirect
Connection: close
Server: Caddy
Date: Fri, 25 Dec 2020 20:17:14 GMT

$ curl --http1.1 -I
HTTP/1.1 200 OK
Accept-Ranges: bytes
Alt-Svc: h3-29=":443"; ma=2592000
Content-Length: 15
Content-Type: text/html; charset=utf-8
Etag: "qlwrw5f"
Last-Modified: Fri, 25 Dec 2020 18:40:53 GMT
Referrer-Policy: no-referrer-when-downgrade
Server: Caddy
Strict-Transport-Security: max-age=2592000
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Date: Fri, 25 Dec 2020 20:17:18 GMT

$ curl --http2 -I
HTTP/2 200
accept-ranges: bytes
alt-svc: h3-29=":443"; ma=2592000
content-type: text/html; charset=utf-8
etag: "qlwrw5f"
last-modified: Fri, 25 Dec 2020 18:40:53 GMT
referrer-policy: no-referrer-when-downgrade
server: Caddy
strict-transport-security: max-age=2592000
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
content-length: 15
date: Fri, 25 Dec 2020 20:17:23 GMT

$ docker run -it --rm ymuski/curl-http3 curl --http3 -I
HTTP/3 200
referrer-policy: no-referrer-when-downgrade
strict-transport-security: max-age=2592000
x-content-type-options: nosniff
etag: "qlwrw5f"
last-modified: Fri, 25 Dec 2020 18:40:53 GMT
accept-ranges: bytes
x-frame-options: SAMEORIGIN
alt-svc: h3-29=":443"; ma=2592000
content-type: text/html; charset=utf-8
content-length: 15
server: Caddy

Finally, we use SSL Server Test to verify that TLS certificates and crypto are configured securely, and use Security Headers to check that HTTP Strict Transport Security is setup correctly.


This article explains how to deploy a website in a VM instance on Oracle Cloud Free Tier.
It involves the following steps:

  1. Create an always free compute VM instance.
  2. Add ingress rules in Virtual Cloud Network subnet.
  3. Install Caddy HTTP server and PHP.
  4. Configure local iptables firewall.
  5. Test the website installation.

I have five ≥1GB, ≤$16/year KVM servers. Are you jealous?


  • Just be sure to have a backup & plan B. They fucked over a bunch of people by killing trials unexpectedly

  • vyasvyas OGContent Writer

    Nicely done.
    You should add the minimum amount of push-ups required to make everything work well

    Thanked by (1)Asim
  • A great article as always!

    Definitely will try to sign up for their free plan :smiley:

  • @havoc said:
    Just be sure to have a backup & plan B. They fucked over a bunch of people by killing trials unexpectedly

    i received marketing calls from oracle regard the service and whatnot. sound nice enough and dont think they would really kills the trials without any notice...
    plus, one of my premium 32gb instance had not been reclaimed after 2 months overdue of trial...still running..of course i no longer do anything serious on it...
    and free instance works too, do have website on it
    the account come with 20gb free s3 compatible s3 storage, mounted it up with rclone and works like magic.

  • Not_OlesNot_Oles Hosting ProviderContent Writer

    @yoursunny Wow! Your tutorials are so well written! Always a pleasure to read because of how well written they are, regardless of whether I am relatively more or less interested in the content.

    @yoursunny said: 48Mbps Internet bandwidth

    The screenshot seems to say "Network Bandwidth (Gbps): 0.48"

    Are people using Oracle Cloud any better protected from "surprise billing" than people using, say, Amazon Web Services or Google Cloud Platform?

    Tom, not Oles. Happy New York City guy visiting in Mexico!
    Purveyor of Fast-as-Metal LXC and KVM VPSes!

  • @yoursunny said: 48Mbps Internet bandwidth

    @Not_Oles said:
    The screenshot seems to say "Network Bandwidth (Gbps): 0.48"

    The port is 480Mbps, but you can only get to this speed within the data center.
    Internet bandwidth is 48Mbps.

    YABS in Tokyo

    iperf3 Network Speed Tests (IPv4):
    Provider        | Location (Link)           | Send Speed      | Recv Speed     
                    |                           |                 |                
    Clouvider       | London, UK (10G)          | 44.8 Mbits/sec  | 44.9 Mbits/sec      | Paris, FR (10G)           | 44.6 Mbits/sec  | 45.4 Mbits/sec 
    WorldStream     | The Netherlands (10G)     | 43.8 Mbits/sec  | 44.6 Mbits/sec 
    Wifx            | Zurich, CH (10G)          | 42.4 Mbits/sec  | 40.8 Mbits/sec 
    Biznet          | Jakarta, Indonesia (1G)   | 48.2 Mbits/sec  | 40.7 Mbits/sec 
    Clouvider       | NYC, NY, US (10G)         | 46.6 Mbits/sec  | 45.8 Mbits/sec 
    Velocity Online | Tallahassee, FL, US (10G) | 45.1 Mbits/sec  | 45.7 Mbits/sec 
    Clouvider       | Los Angeles, CA, US (10G) | busy            | busy           
    Iveloz Telecom  | Sao Paulo, BR (2G)        | busy            | busy    

    48Mbps is enough for small websites.
    If you have a large website, you can afford a larger instance with SR-IOV ports.

    Thanked by (3)Not_Oles ferri Asim

    I have five ≥1GB, ≤$16/year KVM servers. Are you jealous?

Sign In or Register to comment.