Recently I came across a scenario where I didn’t have the right infrastructure for my automation framework and I didn’t want to accept this limitation and end it there. I decided to make my own path by building my own API server. This is something I had never done before, but the goal of this was simple: keep it simple and lightweight and an easy way to trigger my code. I needed to make it easy enough to access it via an API call from service now to make the script calls or commands to the program. 

Since our code set is based on Python I began reviewing different modules and platforms that would allow an API interface.

What I ended up with after my research was Flask, Gunicorn (Green Unicorn), and NGINX.

So the framework is pretty simple
Python + Flask = Backed API framework and scripts
Gunicorn = The bridge from the backend Flask framework to a production ready web interface
Nginx = The frontend web server handling the requests, reverse proxy and handling the encryption  

For our example we will make a basic API program called helloworld

So our steps will be the following 

  1. Install pythonenv as root at the OS level (I am using Ubuntu) 
    1. #apt install python3-venv 
    2. Change to user who will be running the API service
    3. Create a folder for your project and Start venv 
    4. mkdir helloworld 
    5. cd helloworld 
    6. python3 -m venv helloworld_env 

$ source helloworld_env/bin/activate 

Pip install flask flask_restful gunicorn 

 

Create Linux service with gunicorn 

  1. As root
  2. Create service file for our own systemd service
  3. #vi  /lib/systemd/system/helloworld-API.service and add the following contents 

[Unit]
Description=hello world api
After=network.target
After=systemd-user-sessions.service
After=network-online.target

[Service]
User=root
Type=simple
ExecStart=/home/{your_user}/helloworld/start.sh
TimeoutSec=30
Restart=on-failure
RestartSec=15
StartLimitInterval=350
StartLimitBurst=10

[Install]
WantedBy=multi-user.target

 

  1. As the user create the start script 

#!/bin/bash 

echo Starting Flask example app. 

cd /home/gvm 

source ai-test/bin/activate 

gunicorn -w 2 -b 127.0.0.1:5080 app:app 

 

  1. Now enable your service  

systemctl enable {your_service}
 

  1. Create Nginx reverse proxy 
  1. Install nginx as root: # apt-get install nginx 
  1. Clean up the default web page 
  1. # rm /etc/nginx/sites-enabled/default 
  1. vi /etc/nginx/sites-enabled/reverse-proxy.conf 

Add the following contents: 

server {

listen 6080;

listen [::]:6080;

server_name _;

access_log /var/log/nginx/reverse-access.log;

error_log /var/log/nginx/reverse-error.log;

 

location / {

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header HOST $http_host;

proxy_pass http://127.0.0.1:5080;

proxy_redirect off;

}

}

 

  1. Lets add encryption with an SSL cert 

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/selfsigned.key -out /etc/ssl/certs/selfsigned.crt 

openssl dhparam -out /etc/nginx/dhparam.pem 4096 

 

server {
    listen 6080;
    listen [::]:6080;
    server_name {server_fqdn};

    return 302 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    ssl_certificate /etc/ssl/certs/selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/selfsigned.key;

    ssl_dhparam /etc/nginx/dhparam.pem;
    location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header HOST $http_host;
                proxy_pass http://127.0.0.1:8080;
                proxy_redirect off;
    }
}

 

Reference articles
https://medium.com/@thishantha17/build-a-simple-python-rest-api-with-apache2-gunicorn-and-flask-on-ubuntu-18-04-c9d47639139b
 

https://dev.to/chand1012/how-to-host-a-flask-server-with-gunicorn-and-https-942