Physical Address:
A34-Köshe, 17-Üi,
Astana, Qazaqstan
Physical Address:
A34-Köshe, 17-Üi,
Astana, Qazaqstan
In this easy-to-follow tutorial, we’ll guide you through deploying a Flask web app using Nginx on an LXC Container. This container is smoothly running on ProxMox, with Ubuntu 23.04 as the chosen LXC version. We’ve opted for LXC because of its lightweight nature and its impressive capability to serve our web app efficiently, even with limited server resources.
1. Create a new LXC container on the ProxMox, and use Ubuntu 23.04 Standard for the container version.
2. As soon as the LXC is up and running, we need to add new user:
adduser myuser
usermod -aG sudo myuser
3. Update the system, then install python3-pip and python3-venv
sudo apt update
sudo apt upgrade
sudo apt install python3-pip
apt install python3-venv
4. create a python virtual environment, and activate it:
python3 -m venv ~/env/myuser
source ~/env/myuser/bin/activate
5. Install Gunicorn
pip install gunicorn
6. At this point I assume your Flask Web App is already created and ready to be deployed on the LXC server. Either use git clone or upload the code into server directly. Then install all dependencies of Flask web app from requirements.txt (pip3 install -r requirements.txt)
Another option, you can create a python file name as flask.py and add simple codes below:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Hello, Flask!"
7. Run the Flask web app and double check if it’s running.
python flask.py
and you may see similar results as below:
* Serving Flask app 'flask'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://localhost:5555
Press CTRL+C to quit
8. Create a gunicorn web server gateway interface file- wsgi.py and put below code:
from flask import app
if __name__ == '__main__':
app.run()
9. We need a system service to serve the Gunicorn without manual interaction, idea is to make sure the web app is automatically up and running each time the server powers up. Create a flaskapp.service file and save it with below codes:
sudo nano /etc/systemd/system/flaskapp.service
[Unit]
Description=Guniron instance to serve Flask web app
After=network.target
[Service]
User=myuser
Group=www-data
WorkingDirectory=/home/myuser/FlaskWebAppDirectory
Environment="PATH=/home/myuser/env/myuser/bin"
ExecStart=/home/myuser/env/myuser/bin/gunicorn -w 4 wsgi:app
Restart=always
[Install]
WantedBy=multi-user.target
Note: The -w
option at ExecStart specifies the number of processes to run; a starting value could be CPU * 2
. The default is only 1 worker, which is probably not what you want for the default worker type. For more please check out Flask Official documentation here
10. Enable auto start, start and check status:
sudo systemctl daemon-reload
sudo systemctl start flaskapp
sudo systemctl enable flaskapp
sudo systemctl status flaskapp
* flaskapp.service - Guniron instance to serve Flask web app
Loaded: loaded (/etc/systemd/system/flaskapp.service; enabled; preset: enabled)
Active: active (running) since Wed 2024-01-24 05:36:29 UTC; 6min ago
Main PID: 1114 (gunicorn)
Tasks: 5 (limit: 38254)
Memory: 209.5M
CPU: 1.316s
CGroup: /system.slice/flaskapp.service
|-1114 /home/myuser/env/myuser/bin/python3 /home/myuser/env/myuser/bin/gunicorn -w 4 wsgi:app
|-1115 /home/myuser/env/myuser/bin/python3 /home/myuser/env/myuser/bin/gunicorn -w 4 wsgi:app
|-1116 /home/myuser/env/myuser/bin/python3 /home/myuser/env/myuser/bin/gunicorn -w 4 wsgi:app
|-1117 /home/myuser/env/myuser/bin/python3 /home/myuser/env/myuser/bin/gunicorn -w 4 wsgi:app
`-1118 /home/myuser/env/myuser/bin/python3 /home/myuser/env/myuser/bin/gunicorn -w 4 wsgi:app
Jan 24 05:36:29 FlaskApp systemd[1]: Started flaskapp.service - Guniron instance to serve Flask web app.
Jan 24 05:36:29 FlaskApp gunicorn[1114]: [2024-01-24 05:36:29 +0000] [1114] [INFO] Starting gunicorn 21.2.0
Jan 24 05:36:29 FlaskApp gunicorn[1114]: [2024-01-24 05:36:29 +0000] [1114] [INFO] Listening at: http://127.0.0.1:8000 (1114)
Jan 24 05:36:29 FlaskApp gunicorn[1114]: [2024-01-24 05:36:29 +0000] [1114] [INFO] Using worker: sync
Jan 24 05:36:29 FlaskApp gunicorn[1115]: [2024-01-24 05:36:29 +0000] [1115] [INFO] Booting worker with pid: 1115
Jan 24 05:36:29 FlaskApp gunicorn[1116]: [2024-01-24 05:36:29 +0000] [1116] [INFO] Booting worker with pid: 1116
Jan 24 05:36:29 FlaskApp gunicorn[1117]: [2024-01-24 05:36:29 +0000] [1117] [INFO] Booting worker with pid: 1117
Jan 24 05:36:29 FlaskApp gunicorn[1118]: [2024-01-24 05:36:29 +0000] [1118] [INFO] Booting worker with pid: 1118
11. Install Nginx:
sudo apt install nginx
12. Add Flask Web App config file on Nginx:
sudo nano /etc/nginx/sites-enabled/flask
server {
listen 80;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
13. Unlink Nginx Default site then check the syntax:
sudo unlink /etc/nginx/sites-enabled/default
sudo nginx -t
Here is the output if test is successful:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Reload Nginx
sudo nginx -s reload
At this point our Flask Web app is up and running via Nginx
14. Finally, we need to update the firewall rules on the server, remove unnecessary ports that allowed, check the firewall status:
sudo ufw allow "Nginx Full"
sudo ufw delete allow <port-number>
sudo ufw status
Result:
Status: active
To Action From
-- ------ ----
Nginx Full ALLOW Anywhere
Nginx Full (v6) ALLOW Anywhere (v6)
Note: Please make sure you have added firewall rule for ssh port 22, otherwise you will lose remote connection:
sudo ufw allow 22