Home | About | Blog | Connect with me
Published On: Oct 04 2025
Written By: Krishnan Sethuraman
Category: Infrastructure

I recently started building AI applications for my startup and had to host a Flask application on my Ubuntu 18.04 server (yes I need to upgrade). This was my first Python application so I had to do a little bit of digging around to find out what was the best way to deploy and host a Flask application.
Unfortunately a Flask application cannot be deployed and hosted like a Laravel application. An Apache module called WSGI is required.
Flask does not have a strict folder structure like Laravel. This is both a positive and negative aspect. For the experienced developers it is convenient as they can design their own folder structure. But for the new ones like me it can be very confusing.
So I have developed my own folder structure for my applications. I have committed this scaffolding to a Github repo.
The entry point for my application is run.py. I have provided the run.py content below.
# run.py
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run(port=5001, debug=True)
Each feature will act as an independent module. So feature1 will have its own folder and inside it will be its own routes.py and models.py files. The library or helper functions will be inside the utils folder. This will keep the source code a bit more manageable. Though I am not a big fan of this and might move towards Django, but for now it makes things manageable.
diagram for file structure
As we will be using wsgi to host our application we must create a wsgi.py file on our Linux server with the following contents. The run.py is the entry point on localhost whereas wsgi.py is for the production environment.
# wsgi.py
import sys
import os
from app import create_app # adjust if your factory is different
sys.path.insert(0, os.path.dirname(__file__))
application = create_app()
I used Jenkins to deploy the aplication. However I was unable to automate the build process. So for now I have restricted to checking out the source code from the master branch and then deploying it to the server with scp. The Jenkins does nothing more (I will figure out to automate this fully). I have provided my Jenkinsfile below.
//Jenkinsfile
pipeline {
agent any
environment {
REMOTE_HOST = credentials('SERVER_IP')
REMOTE_USER = credentials('SERVER_JENKINS_USER')
REMOTE_PASSWORD = credentials('SERVER_JENKINS_PASSWORD')
REMOTE_DESTINATION = credentials('APPLICATION_PATH')
}
stages {
stage('Deploy Files') {
steps {
script {
sh "sshpass -p ${REMOTE_PASSWORD} scp -r ${WORKSPACE}/* ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DESTINATION}"
}
}
}
stage('Clean Workspace') {
steps {
cleanWs()
}
}
}
}
I use Apache as my preferred web server as I understand Apache better than nginx.
The first step is to deploy the source code from the repository to the server which we have achieved above. Once the latest source code is deployed the next step is to login into the server and run the following commands.
The first step would be to ensure all all prerequisites are met on the server. You can refer the following steps to setup the same. We have to enable certain modules in Apache.
$ sudo apt update
$ sudo apt install python3-pip python3-venv libapache2-mod-wsgi-py3 -y
$ sudo a2enmod wsgi
$ sudo systemctl restart apache2
$ sudo a2enmod proxy
$ sudo a2enmod proxy_http
$ sudo systemctl restart apache2
With the code deployed and server configured we run the following commands to complete the build. Before doing so just ensure that the requirements.txt has gunicorn added to it. Gunicorn is mandatory to host Flask application on Ubuntu. It's the easiest, reliable and robust way to host a Flask application in production.
$ cd /var/www/flask-application
$ python3.11 -m venv venv
$ source venv/bin/activate
$ pip install --upgrade pip
$ pip install -r requirements.txt
The Flask application is now ready to be fired up.
The popular opinion here is to use something like supervisor to run the application. But I always prefer the build systemd in Linux.
So I created systemd service to run the application forever.
# /etc/systemd/system/flask-app.service
Add the following content to the flask-app.service and save it.
[Unit]
Description=Gunicorn instance to serve flask API
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/flask-application
Environment="PATH=/var/www/flask-application/venv/bin"
ExecStart=/var/www/flask-application/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:application
[Install]
WantedBy=multi-user.target
Now enable the systemd service.
# systemctl daemon-reload
# systemctl start flask-app
# systemctl enable flask-app
By now we should have the Flask application up and running. We can test the same by checking the status of the systemd service.
# systemctl status flask-app
Please note that for every deployment restarting the systemd service is mandatory. Else the systemd service will not recognize the new code changes. Running pip install is not mandatory unless there are new packages aka modules added to the requirements.txt file.
# systemctl restart flask-app
Once the Flask application is up and running the next step is to create a virtual host in Apache so that we can access are application at a domain name like flask-app.example.com.
# cp 000-default.conf flask-app.example.com.conf
In side the file add the following content and save and close the file.
<VirtualHost *:80>
ServerName flask-app.example.com
# Ensure Apache proxies requests
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
ErrorLog ${APACHE_LOG_DIR}/flask-app_error.log
CustomLog ${APACHE_LOG_DIR}/flask-app_access.log combined
</VirtualHost>
Finally enable the new virtual host and restart Apache server.
# a2ensite flask-app.example.com.conf
# systemctl restart apache2
You should now be able to open up your flask application at flask-app.example.com, assuming the DNS record has been created.
Founder & CTO of Geedesk. Passionate about building software from scratch, launching SaaS products, and helping teams deliver enterprise-grade solutions.
Like what you are reading?
Discover more similar articles sent to your email
Subscribe to my newsletter