Sunday, September 22, 2019

Free Oracle Cloud: 7. Setup a web server on the Virtual Machine

This post is part of a series of blog posts on the Best and Cheapest Oracle APEX hosting: Free Oracle Cloud.

In this blog post we will configure a web server on our Compute VM Instance. This allows us to host some websites and have a custom URL for our Oracle APEX instance and applications.

Lets start with connecting to our VM:

From a Terminal connect to your Oracle Cloud VM:

ssh -i ssh_key opc@public_ip

The first thing we do, is change to the root user, as we want to install a web server it will be easier to do it with the root user. Alternatively in front of every command you can add sudo.

We logged in as the OPC user, to become the ROOT user we do:

sudo su

Although it doesn't really have anything to do with setting up a web server, I do want to share this... The first thing I always like to do on a machine, is get the system updated, so all latest software is being used. To do this, run following command:

yum update

It will take some time the first time, but after a couple of minutes you should see that all packages were updated:


So the purpose of this post was to install a web server so when we type in a certain domain, it will arrive at our machine. As web server, I typically chose between Apache and Nginx. Which one to choose is a hard one... if you search Google for "Apache vs Nginx" you can start reading ;) Since last year I started to use Nginx for all my new systems, before I always used Apache.

Following steps show how you install the Nginx web server and run it:

yum install nginx


Now we need to start the web server:

systemctl start nginx

To see if Nginx is successfully running, do:

systemctl status nginx

You should see something like:


The next thing we have to do is open the firewall on the Linux box, so incoming connections are allowed. The first line will open HTTP, the second HTTPS and then we reload the firewall:

firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

Opening the firewall on the Linux box is not enough. Oracle added some extra security layers around the VM (Compute Instance). We have to allow HTTP and HTTPS access to our machine in the Oracle Firewall too.

Click the Virtual Cloud Network link:


Click the Security Links:


And add two Ingress Rules, one for HTTP and one for HTTPS:


As Source add 0.0.0.0/0 so everything can connect to it and as destination port you specify the first time 80 (for HTTP) and the second time 443 (for HTTPS):


Once both Ingress Rules are added, your list looks like this:


Now you can navigate in a browser to your Public IP and you should see:


Now that we have a web server running and it's accessible through the IP address, we know things are working. Most of the time however you don't want to access your server through an IP address, rather you want people to use a domain name. To access my Free Oracle Cloud server for example I want to use the dgielis.com domain.

The first step to do, is in the domain provider you specify for the A record, the IP address of your Oracle Cloud VM (Compute) Instance.  I typically also setup some CNAME so any sub-domain will work too. For example I could point apex.dgielis.com to Oracle APEX Builder.


Now that the domain points to our VM, we have to make sure our web server listens to this domain and knows what to do. We will need to configure Nginx for this dgielis.com domain.

Here are the steps to do this (do this in your Terminal which is connected to your VM):

vi /etc/nginx/conf.d/dgielis.com.conf

# Add following to the file (change dgielis.com by your domain):
server {
    listen         80;
    listen         [::]:80;
    server_name    dgielis.com www.dgielis.com;
    root           /usr/share/nginx/html/dgielis.com;
    index          index.html;
    try_files $uri /index.html;
}

# Create a directory where your website resides:
mkdir /usr/share/nginx/html/dgielis.com

# Add an index.html file to the directory
# Quickest way is vi or cp an index.html in this folder
# Or develop your site locally first and when ready upload with scp
# scp -i .ssh/oraclecloud /Users/dgielis/site.zip opc@132.145.215.55:/tmp

# to test Nginx configuration
nginx -t 

# to restart Nginx
nginx -s reload

# note: in case nginx doesn't restart, kill the nginx process and try to restart again
ps -ef | grep nginx
kill ~pid~

When you go in your browser to your domain name, it should show your website!

This website runs over HTTP, but these days it's recommended to use HTTPS for your sites. Lets setup HTTPS for our website by using LetsEncrypt, a free service for SSL certificates.

First we have to install some supporting packages:

yum install certbot python2-certbot-nginx  # not necessary
yum install python27-python-pip
scl enable python27 bash
pip install certbot
pip install setuptools --upgrade
pip install certbot-nginx

Once the supporting packages are there, we can run certbot to setup the SSL certificates for our domain:

certbot --nginx

After completion of the wizard, you should see something like below:


During the Certbot wizard which configures LetsEncrypt, it asks if you want to redirect all HTTP access to HTTPS and I would answer Yes here.


Now, regardless if you use HTTP or HTTPS on dgielis.com, you will always end-up with HTTPS.
HTTPS is better for Google, better for security, so no reason not to do it :)



If we want to use our Nginx web server as reverse proxy for our APEX environment we can do that by adapting our /etc/nginx/conf.d/dgielis.com.conf file (see the location sections):

vi /etc/nginx/conf.d/dgielis.com.conf

Add following to the server:

  location /ords/ {
    proxy_pass your_apex_url/ords/;
    proxy_set_header Origin "" ;
    proxy_set_header X-Forwarded-Host $host:$server_port;
    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_connect_timeout       600;
    proxy_send_timeout          600;
    proxy_read_timeout          600;
    send_timeout                600;
  }

  location /i/ {
    proxy_pass your_apex_url/i/;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

The final configuration file looks like this:


There's one other configuration change I would suggest you do straightaway; increase the size of the max_body_size in Nginx. Add following line to nginx.conf

vi /etc/nginx/nginx.conf


Test and reload the configuration of Nginx:

nginx -t
nginx -s reload

When going in a browser to https://dgielis.com/ords/ we arrive at Oracle APEX:


There's a lot of optimisation we can do on the reverse proxy. To gain performance we can put the images folder of APEX on the Nginx server, as Nginx is super fast in transferring static files. We can add more redirects, for example that apex.dgielis.com goes to the APEX builder and app.dgielis.com goes to one of our custom APEX apps. As this post is already long, I'm not including that in here.

Once Oracle provides vanity urls, we don't need to do the above, and the URL will point directly to ATP.

Update 26-SEP-2019 (thanks Kris Rice): Note that setting the Origin would negate any CORS info that ORDS is enforcing. That could be a security issue for some people. Oracle is looking into the ability to have your ORDS running on your own Compute VM (the webserver we just setup), which would solve the issue. The vanity URLs would not have the CORS issue either.

In the next post we will use this server to add an on-premises version of APEX Office Print (AOP), so we have everything we need to export data from the database in the format we want, for example in Excel and PDF.

23 comments:

Scott said...

Awesome article - found a small typo:

scl enable paython27 bash

Should be:

scl enable python27 bash

Dimitri Gielis said...

Thanks Scott, I corrected it also in the post.

Martin Børge Nielsen said...

Thanks Dimitri ! great post.
I tried to do the same with Apache but could not get the proxy setup working.
Works great with nginx.

Brgds
Martin

Sokos said...

Awesome post Dimitri,
Quick question, where does ORDS/Rest Services reside?
Usually we have to throw the ords.war in the Application server (e.g Tomcat webapps)

Dimitri Gielis said...

ORDS is running in front of ATP and managed by Oracle.
You can't change the configuration of ORDS - you get 20 simultaneous connections (which can serve 1000s of users depending your app).

Flieger said...

Great post, Dimitri. I typically opt for Apache. Any reasons why I should switch to Nginx?

Dimitri Gielis said...

Hi Flieger,

We've both Nginx and Apache in different projects... not really a preference.

I just like to try different things for myself and Nginx became more popular in the larger world, so used that. When you read about the architecture e.g. https://www.hostingadvice.com/how-to/nginx-vs-apache/, Nginx seems better for static sites and it's used a lot as reverse proxy. But in an Oracle APEX context I don't think it makes much of a difference especially not when you use the CDN for static files.

So if Apache works for you and you know that, stick with it :)

Hope that helps,
Dimitri

Flieger said...

Thanks, Dimitri. That helps.

Souleman DEMBELE said...

thanks you Dimitri, this article is useful and very clear. it will also be a good approach to configure a load balancer. may be another point in this article series.

Jeffrey Kemp said...

Brilliant stuff, followed your instructions to the letter and it worked well.

I had one hiccup, my domain was previously pointing to a server which was already serving https; Google Chrome consistently refused to send me to the http version of the new site. I had to test it in Firefox to verify that it was working. Once the letsencrypt cert was installed, it worked fine in Chrome again.

Chimpanzee said...

Thank you so much for this. Your guides are so easy to follow because you never really assume prior knowledge of anything - you just lay it out simply, step-by-step. Really great for someone like me who is comfortable in APEX and with designing databases, but knows next to nothing when it comes to server admin. Following your guides, I've managed to set up Oracle Cloud and APEX running on my own subdomain.

Is it possible to mask the URL even further? eg https://mydomain.com/f?p=4550:1 (without the /ords) or even attaching a specific APEX application to a subdomain so myapp1.domain.com goes to one app and myapp2.domain.com goes to another app (within the same workspace)?

Lucas Souza said...

Hi, thanks for this post, this help me so much to use ATP with APEX.
BUT, now I got other problem using a NGINX with ORACLE ATP and SOCIAL LOGIN (IDCS).
I created a new application on IDCS federation service pointing to my domain configured to NGINX, but when APEX redirect to IDCS authorize page, the APEX send a wrong "redirect_uri" parameter.

The "redirect_url" is the url of APEX ATP.

My doubt is how APEX gets the value to put on redirect_uri? is the HOST HTTP variable? or is a internal parameter? and can I change this value?

thanks

Unknown said...

Hi,

Thank you so much for your precious series of posts. Even as a noob I managed to get this up and running.

Dimitri Gielis said...

Hi Chimpanzee,

You can give this a try: rewrite ^/$ /ords/f?p=101 permanent;

Hope that helps,
Dimitri

Anonymous said...

Great Post Thanks so much Dimitri.
Can you help how to setup 2 domains for apex apps?

Thanks/

Phanny said...

Great Post Thanks so much Dimitri.
Can you help how to setup 2 domains for apex apps?

Thanks/

Arturo said...
This comment has been removed by the author.
Arturo said...
This comment has been removed by the author.
Tia Barka said...

Thank you for this usefull post.
I Just added this to ninx domain config

location = / {
return 301 /ords/;
}

to redirect non /ords access.
Next step will be copy all /i resources to a local dir and avoid reverse proxy.

Jochen said...

Hi Dimitri
if i navigate to https://my-domain.com/ords/ i get an error message:

There is a problem with your environment because the Application Express files have not been loaded. Please verify that you have copied the images directory to your application server as instructed in the Installation Guide. In addition, please verify that your image prefix path is correct. Your current path is /i/19.1.0.00.15/

Should the images not already be in place by default?

thanks for help

Dimitri Gielis said...

Hi Jochen,

Yes, it should.
Did you configure NGinx to also forward /i/ ?

Dimitri

Jochen said...

Thanks for replying Dimitri.
Yes it actually did:

location /i/ {
proxy_pass https://kjflphbzcwyyi2q-dbjzzh.adb.eu-zurich-1.oraclecloudapps.com/ords/i/;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Dimitri Gielis said...

Hi Jochen,

When you go to the direct url of the Oracle Cloud, does it work for you then?
If not, best to contact Oracle.
If it does work, try to empty your cache of your browser for your domain and try again.

Hope that helps,
Dimitri