Skip to content

From Zero to Hero: Building Your Secure, Multi-App Website on an OCI VM

So, you have a domain name from a registrar like GoDaddy and a fresh Oracle Cloud Infrastructure (OCI) VM. What’s next? This guide will walk you through the complete, real-world process of transforming those basic components into a powerful, secure, and flexible web server capable of hosting multiple containerized applications.

We will cover everything from initial DNS setup and web server installation to advanced debugging of a multi-service application stack, based on a real-world troubleshooting journey. The key technologies we'll use are GoDaddy, OCI, Nginx, Let's Encrypt (Certbot), and Podman for containers.

Part 1: The Foundation - A Live "Coming Soon" Page

Before we deploy complex applications, we need to establish a basic web presence. This confirms our server is reachable and our domain is pointing correctly.

1. Pointing Your Domain (GoDaddy)

Your domain name needs to know the IP address of your OCI VM. This is done with an A record.

  1. Log in to your GoDaddy account and navigate to the DNS Management page for your domain (e.g., foobar.com).
  2. Crucial Tip: If you have ever used a GoDaddy service like "Website Builder," your core DNS records may be locked. You must first find and remove that connected product from your GoDaddy account to unlock DNS editing.
  3. Find the A record for your main domain (the "Name" is usually @).
  4. Edit this record and set the Value to the Public IP Address of your OCI VM.

2. Installing Nginx Web Server

We'll use Nginx, a lightweight and high-performance web server. Connect to your OCI VM (running Oracle Linux 8 in this example) via SSH and run:

# Install Nginx
sudo dnf install nginx -y

# Enable and start the Nginx service to run on boot
sudo systemctl enable --now nginx

3. Creating a Placeholder Page

  1. Create a directory for your site's files:

    sudo mkdir -p /var/www/foobar.com/html
    
  2. Create the index file:

    sudo nano /var/www/foobar.com/html/index.html
    
  3. Paste basic HTML content into the file and save it (Ctrl+X, Y, Enter).

4. Configuring Nginx

  1. Create a site-specific configuration file:

    sudo nano /etc/nginx/conf.d/foobar.com.conf
    
  2. Paste this basic server configuration. This tells Nginx to listen for traffic for foobar.com on port 80 and serve files from your new directory.

    server {
        listen 80;
        server_name foobar.com www.foobar.com;
    
        root /var/www/foobar.com/html;
        index index.html;
    
        location / {
            try_files $uri $uri/ =404;
        }
    }
    
  3. Test the configuration:

    sudo nginx -t
    

Part 2: Overcoming the First Hurdles (Firewalls & Permissions)

If you visit your domain now, you'll likely hit an error. Here’s how to debug the two most common initial blockers.

Problem 1: Connection Timeout (ERR_CONNECTION_TIMED_OUT)

This almost always means a firewall is blocking the traffic. On OCI, you have two firewalls to configure.

  1. OCI Cloud Firewall: In the OCI web console, navigate to the Security List for your VM's Virtual Cloud Network (VCN). Add an Ingress Rule to Allow TCP traffic from source 0.0.0.0/0 on Destination Port 80.
  2. VM Internal Firewall: On the VM itself, allow the HTTP service through firewalld.
    sudo firewall-cmd --permanent --add-service=http
    sudo firewall-cmd --reload
    

Problem 2: Access Denied (403 Forbidden)

Once the firewalls are open, Nginx might respond but say it's forbidden from showing the page. This is a permissions issue.

  1. Set Correct File/Directory Permissions: The nginx user needs to be able to read your website files.

    # Give nginx ownership of the files
    sudo chown -R nginx:nginx /var/www/foobar.com
    
    # Set correct permissions for directories (read/execute for others)
    sudo find /var/www/foobar.com -type d -exec chmod 755 {} \;
    
    # Set correct permissions for files (read-only for others)
    sudo find /var/www/foobar.com -type f -exec chmod 644 {} \;
    
  2. Set the SELinux Context: Oracle Linux uses SELinux, an extra security layer that is often the final blocker. You must tell it that these files are safe for a web server to access.

    sudo chcon -t httpd_sys_content_t -R /var/www/foobar.com
    

After these steps, your "Coming Soon" page should be live on http://foobar.com.


Part 3: Securing Your Site with HTTPS (Let's Encrypt & Certbot)

No modern website should run on HTTP. We'll use the free, automated service Let's Encrypt with the Certbot client to enable HTTPS.

  1. Allow HTTPS Traffic: Just as with port 80, you must open port 443 in both the OCI Security List and the VM's firewall.

    sudo firewall-cmd --permanent --add-service=https
    sudo firewall-cmd --reload
    
  2. Install Certbot on Oracle Linux: This can be tricky as certbot isn't in the default repositories. You must first enable the EPEL (Extra Packages for Enterprise Linux) repository.

    # Install the EPEL repository package
    sudo dnf install oracle-epel-release-el8 -y
    
    # Install certbot, explicitly enabling the EPEL repo
    sudo dnf --enablerepo=ol8_developer_EPEL install certbot python3-certbot-nginx -y
    
  3. Run Certbot: This command will automatically obtain a certificate for your domains and configure your Nginx file to use it.

    sudo certbot --nginx -d foobar.com -d www.foobar.com
    

    Follow the on-screen prompts. When asked about redirecting HTTP traffic to HTTPS, it is highly recommended to choose the Redirect option.

Your site is now secure and accessible at https://foobar.com.


Part 4: The Reverse Proxy - Serving Multiple Applications

Now for the advanced part: serving multiple containerized applications from the same server. Nginx will act as a reverse proxy, directing traffic to the correct backend application based on the requested subdomain.

  1. DNS for Subdomains: In GoDaddy, create CNAME records for each application (e.g., app1, app2`), pointing them to your main domain (`@`). This tells the world that `app1.foobar.com` lives at the same IP address as `foobar.com`. * **Expand Your SSL Certificate:** Re-run Certbot, adding all the new subdomains with `-d` flags. Certbot is smart enough to detect the existing certificate and will ask if you want to **Expand** it to cover the new domains. sudo certbot --nginx -d foobar.com -d www.foobar.com -d app1.foobar.com -d app2.foobar.com * **Nginx Reverse Proxy Configuration:** Create a new `.conf` file in `/etc/nginx/conf.d/` for each subdomain (e.g., `app1.conf`). Here is a clean template for `app1.conf`, proxying to a container on port `5000`: # Redirect all HTTP traffic to HTTPS for this subdomain server { listen 80; server_name app1.foobar.com; return 301 https://$host$request_uri; } # Main HTTPS server that proxies to your app server { listen 443 ssl http2; server_name app1.foobar.com; # SSL config managed by Certbot ssl_certificate /etc/letsencrypt/live/foobar.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/foobar.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Reverse Proxy Configuration location / { proxy_pass http://127.0.0.1:5000; 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; } }

* * * Part 5: Advanced Application Debugging (502 & 504 Errors) --------------------------------------------------------- With a reverse proxy in place, a new class of errors can appear. 1. **Solving Nginx `conflicting server name` Warnings** * **Problem:** `sudo nginx -t` shows warnings about duplicate server names. * **Cause:** Certbot often makes unhelpful edits to the main `/etc/nginx/nginx.conf` file, creating conflicts with the clean `.conf` files you created in `/etc/nginx/conf.d/`. * **Solution:** Replace `/etc/nginx/nginx.conf` with a clean, standard default version that does little more than `include /etc/nginx/conf.d/*.conf;`. 2. **Solving `502 Bad Gateway` Errors** * **Meaning:** Nginx tried to talk to your backend application but the **connection failed**. * **Common Cause:** SELinux is blocking the Nginx process from making outbound network connections. * **Solution:** Grant Nginx permission to connect out using an SELinux boolean. sudo setsebool -P httpd_can_network_connect 1 3. **Solving `504 Gateway Time-out` Errors** * **Meaning:** Nginx **successfully connected** to your backend, but your application took too long (default >60s) to send back a response. * **Common Cause:** The application is performing a slow task. * **Permanent Fix:** Add timeout directives to the Nginx `.conf` file for the **service that is actually slow**. # Add inside the location / { ... } block proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; * * * Part 6: Server Maintenance - Managing Podman Logs ------------------------------------------------- Voluminous logs can fill up your disk. It's important to manage them. 1. **Purging Existing Logs:** If you have a custom log path defined in your `podman run` command, you can empty it instantly with: sudo truncate -s 0 /var/log/app.log 2. **Implementing Log Rotation:** The best solution is to prevent logs from growing indefinitely. Add these options to your `podman run` command (e.g., in your CI/CD workflow file). # ... inside your podman run command ... --log-opt max-size=20m \ --log-opt rotate=5 This will limit your logs to 5 files of 20MB each. * * * Conclusion ---------- Congratulations! You have successfully navigated the entire process of setting up a secure, multi-application server. This architecture is robust, scalable, and follows modern best practices. The debugging steps outlined here are invaluable tools for any system administrator. You are now well-equipped to host and manage your own corner of the internet.