
Gold unicorn for Python Flask Apps
Normally you can serve a Python Flask app using Gunicorn like this:
gunicorn -b 0.0.0.0:8080 app:app
This binds all network traffic (0.0.0.0) on port 8080 to app.py program’s app object. First one is the file name (without py extension) and second one is the app object inside the Python code.
Normally you can serve a Python Flask app using Gunicorn like this:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Here is a common structure of a flask app:
Using Gunicorn with Pm2
With pm2 usage of gunicorn is slightly more complicated.
pm2 start "gunicorn -b 0.0.0.0:8080" app:app
Or giving the app a name for monitoring purposes like below.
pm2 --name=PythonApp start "gunicorn -b 0.0.0.0:8080" app:app
The difference between using 0.0.0.0 and localhost as the bind address in the Gunicorn command can affect the accessibility of the server.
When you use gunicorn -b 0.0.0.0:8000 app:app, Gunicorn binds to all network interfaces, allowing connections from any IP address, including external IP addresses. This makes your server accessible from both the local machine and other machines on the network.
However, when you use gunicorn -b localhost:8000 app:app, Gunicorn only binds to the loopback interface, also known as 127.0.0.1. This means that the server is only accessible from the local machine itself. Connections from other machines on the network or external IP addresses will be blocked.
Add Ingress Rule to allow Inbound Traffic
You should configure the server to allow Inbound traffic for specific port you’d like to use such as 8000, 8080, 80, 81, 3000, 5000 etc.
Port 80 is the universally accepted HTTP port and browsers automatically look for port 80 when a root domain URL or IP is accessed.
You need to open the port to listening under VCN (Virtual Cloud Networks) > Subnet > Default Security List for vcn-xyz > Add Ingress Rules

Listing Post Listening Activity
lsof -i -P -n
You can use lsof to show a list of files being served and filter it to internet files only and force it to show the ports instead of app names.
-i: Filters the output to show only Internet-related open files (network connections).
-P: Prevents the conversion of port numbers to service names.
-n: Skips the conversion of IP addresses to hostnames.
Alternatively, you can use netstat to do something similar:
netstat -tln # Show only listening TCP ports
netstat -uln # Show only listening UDP ports
If you don’t see your desired port here. First place to look is the firewall rules.
Additionally, you will want to allow your cloud instance or server to accept inbound traffic from those ports if you want to achieve access from other machines to the specific port.
A good test for this is to use curl command.
If
curl localhost:8080
works from inside ssh but you still can’t access 8080 through public ip that means inbound traffic is not being allowed.
Serving Flask App Using Gunicorn via Pm2
Even a classier way to serve Flask app is to generate a configuration JS file and instruct Pm2 to use gunicorn to serve the Flask app.
File can be created as below:
module.exports = {
apps: [
{
name: 'Flaskmyapp',
script: 'gunicorn',
args: 'app:app -b 0.0.0.0:5000',
interpreter: 'python',
interpreter_args: '-u',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
FLASK_APP: 'app.py',
FLASK_ENV: 'production',
},
},
],
};
Nginx Reverse Proxy
It’s common to reverse proxy with Nginx to specific ports. You can instruct Nginx to Reverse Proxy multiple ports, especially other than port 80, like this:
server {
listen 80;
server_name servername;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 81;
server_name servername;
location / {
proxy_pass http://localhost: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;
}
}
In this example port 80 on public IP will forward to port 3000 while port 81 on public IP forwards to port 5000.