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
- Install pythonenv as root at the OS level (I am using Ubuntu)
- #apt install python3-venv
- Change to user who will be running the API service
- Create a folder for your project and Start venv
- mkdir helloworld
- cd helloworld
- python3 -m venv helloworld_env
$ source helloworld_env/bin/activate
Pip install flask flask_restful gunicorn
Create Linux service with gunicorn
- As root
- Create service file for our own systemd service
- #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
- 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
- Now enable your service
systemctl enable {your_service}
- Create Nginx reverse proxy
- Install nginx as root: # apt-get install nginx
- Clean up the default web page
- # rm /etc/nginx/sites-enabled/default
- 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;
}
}
- 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
Ben Tuma
Over 20 years of experience in the Information Technology field. I love technology and seeing how it changes and impacts peoples lives for the better. I have healthy appetite for innovation and problem solving.
I am sharing my knowledge and challenges in hopes to help others as we constantly face ever changes problems in IT and technology.