8 Non-PHP Web Application Hosting

The previous chapters mostly focused on deployment of simple multi-page PHP applications. While PHP is still arguably one of the most popular programming languages for web applications programs written in Python and NodeJS are gaining momentum at a very accelerated rate and although books that teach out you about NodeJS/Espress and Python/Flask, they tend to cover it from a programming point of view rather than a deployment point of view.

One very fundamental difference between PHP programs and most other back end programming languages has to do with the “longevity” of the program. Most multi-page applications run for a very short amount of time and simply go away after the page has been rendered. If you think about desktop programs, you know that programs start and run for a very long time until the user wants to close them. A big advantage of this type of program is that the loading happens just one time and the user can then get different features from menu items. The overhead of loading the program into memory happens just one time.

8.1 Services

The first thing that we need to cover when writing a “long running” program is that the program needs to be running in the background all the time. When we talked about PHP applications in an earlier chapter, apache was responsible for loading the program and asking it to be run. We could write small programs in any language that we want and have the web server software launch the application for each page load but instead we will write the application in a way where it runs all the time.

To have something running in Linux in the background requires that we create a service. In the case of Ubuntu Linux we are talking about.

8.2 Reverse Proxies and Web Applications

Although a web application could listen directly on port 80/443 and serve up requests directly, most systems would be deployed instead with a regular web server configured as a reverse proxy to the application.

(put an image of an application with a reverse proxy here).

There are several things that you can gain by using a reverse proxy in front of a web application. * You can easily set up a site that responds with “under maintenance” for any time that your application is not running. * You can have the front end web server handle requests for static content such as HTML files, CSS files, and images. Web servers, especially nginx, have been written to handle static content very quickly. * It makes it easier to load balance your application if you need to scale it up. * The web server can deal with the SSL connection so that your application doesn’t have to worry about things like certificates and keys.

8.3 Python Based Applications

Let’s write a small dynamic application written in Python to find out what things we will need to deal with to deploy such a site. We will make this very simple, we will have some basic message including the current time displayed to the user along with a CSS file and an image file.

An important thing to note about web applications (other than PHP) is that they don’t have to be kept in a specific folder. We will create the application in the folder /usr/local/src/pythonapp. Here is the program that I put together:

from flask import Flask
import time
import datetime


app = Flask("demonstration")

@app.route("/")
def main_page():
        dt = datetime.datetime.fromtimestamp(time.time())
        return f"""
<html>
<head>
</head>
<body>
<h1>The Time</h1>
<img src="/images/clock.jpg">
The current time is {dt}.
</body>
</html>
"""

app.run()

The only route that I have created is just for the “/” URI. When a browser asks for this resource a simply HTML body is sent back but we have written the response to give back the current time on the server. I also included a small picture of a clock found from the images folder. The Flask library does have the ability to serve up static files like images and JS files and I would normally configure this to make development a bit easier but this time I wanted to leave it out so that we could demonstrate the configuration of nginx.

This application can be run from the command prompt but instead, I have created the following service file in /etc/systemd/system/pyclock.service:

[Unit]
Description=Clock Application in Python

Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /usr/local/src/pythonapp/test.py
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

and I have started it using systemctl start pyclock.

The next order of business is to configure a reverse proxy in nginx to pass all requests to the pyclock application with the exception of the /images folder which we will serve up directly by nginx:

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/pyclock;
        index index.html index.htm index.nginx-debian.html;
        server_name _;
        location / {
                proxy_pass http://localhost:5000;
        }
        location /images {
                try_files $uri $uri/ =404;
        }
}

What is going to happen with this configuration is that all requests into the server (with the exception of things that start with /images) will be forwarded to port 5000 on local host. Remember that this “forwarding” doesn’t mean redirection, it means that nginx will ask the Python application for the output and send it back to the client. The client only knows that nginx responded but doesn’t know it was actually sent to another place. Everything that starts with /images will instead be handled directly by nginx.

So why split things into 2 pieces and why not just let the Python application handle everything? Remember that nginx was developed to serve static files extremely quickly so we are giving the static files to nginx and we are sending all of the dynamic content to the python application. If we wanted to implement HTTPS on this server we just need to configure nginx to use the certificates the same way that we have always worked and allow the dynamic content to be sent to the Python application over the HTTP channel. We would probably also use the firewall at this point to block access to port 5000 from all outside access.

8.3.1 Gunicorn Application Server

TODO: Need to put some stuff here about green unicorn.

8.4 Node Based Applications

8.5 Java Based Applications