{"id":9172,"date":"2024-08-30T14:24:09","date_gmt":"2024-08-30T14:24:09","guid":{"rendered":"https:\/\/www.webhi.com\/how-to\/?p=9172"},"modified":"2024-08-30T14:24:11","modified_gmt":"2024-08-30T14:24:11","slug":"deploying-flask-application-with-gunicorn-nginx-ubuntu","status":"publish","type":"post","link":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/","title":{"rendered":"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu"},"content":{"rendered":"\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en.jpg\" alt=\"Deploy Flask Application with Gunicorn and Nginx Ubuntu Debian\" class=\"wp-image-9189\" srcset=\"https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en.jpg 1200w, https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en-300x169.jpg 300w, https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en-1024x576.jpg 1024w, https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en-768x432.jpg 768w, https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en-150x84.jpg 150w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure>\n\n\n\n<p>Deploying a Flask application is a critical step in making your web application accessible to the world. While Flask comes with a built-in development server, it&#8217;s not suitable for production. For a robust, scalable, and production-ready setup, you\u2019ll need a combination of Gunicorn, Nginx, and Ubuntu. This guide will walk you through the process of deploying your Flask application with Gunicorn and Nginx on an Ubuntu server.<\/p>\n\n\n\n<p>Deploying Flask apps on a server might seem challenging if you&#8217;re new to backend development, but this comprehensive guide will break down each step. By the end, you&#8217;ll have a Flask application up and running on Ubuntu, served by Gunicorn and Nginx.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"understanding-the-deployment-stack-flask-gunicorn-and-nginx\"><strong>Understanding the Deployment Stack: Flask, Gunicorn, and Nginx<\/strong><\/h2>\n\n\n\n<p>Before diving into the deployment process, it\u2019s important to understand the tools we&#8217;ll be using.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"flask-the-micro-web-framework\"><strong>Flask: The Micro Web Framework<\/strong><\/h3>\n\n\n\n<p>Flask is a lightweight web framework written in Python. It&#8217;s designed to be simple, flexible, and easy to get started with, which makes it a popular choice for building web applications. However, Flask&#8217;s built-in server is not suitable for production environments because it cannot handle more than one request at a time.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"gunicorn-the-python-wsgi-http-server\"><strong>Gunicorn: The Python WSGI HTTP Server<\/strong><\/h3>\n\n\n\n<p>Gunicorn (Green Unicorn) is a Python WSGI HTTP server that serves your Flask application. It\u2019s a pre-fork worker model, which means it forks multiple worker processes to handle multiple requests simultaneously. This makes it ideal for serving Flask applications in production. Gunicorn sits between your Flask application and the web server (Nginx in this case), handling the heavy lifting of managing requests and serving responses.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"nginx-the-web-server-and-reverse-proxy\"><strong>Nginx: The Web Server and Reverse Proxy<\/strong><\/h3>\n\n\n\n<p>Nginx is a high-performance web server that also acts as a reverse proxy, load balancer, and HTTP cache. In this setup, Nginx will sit in front of Gunicorn, handling client connections and static content, and then forwarding dynamic requests to Gunicorn. This separation of concerns helps improve security, performance, and scalability.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-up-the-ubuntu-server\"><strong>Setting Up the Ubuntu Server<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"initial-server-setup\"><strong>Initial Server Setup<\/strong><\/h3>\n\n\n\n<p>First, you need access to an Ubuntu server. This could be a physical machine, a virtual machine, or a cloud instance from providers like AWS, DigitalOcean, or Google Cloud Platform.<\/p>\n\n\n\n<ol>\n<li><strong>Log in to your server:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ ssh username@your_server_ip<\/code><\/pre>\n\n\n\n<ol start=\"2\">\n<li><strong>Update your package index:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo apt update<\/code><\/pre>\n\n\n\n<ol start=\"3\">\n<li><strong>Upgrade installed packages:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo apt upgrade<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-necessary-packages\"><strong>Installing Necessary Packages<\/strong><\/h3>\n\n\n\n<p>You\u2019ll need Python, pip, and virtualenv to run your Flask application.<\/p>\n\n\n\n<ol>\n<li><strong>Install Python and pip:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo apt install python3 python3-pip<\/code><\/pre>\n\n\n\n<ol start=\"2\">\n<li><strong>Install virtualenv:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo pip3 install virtualenv<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"preparing-your-flask-application\"><strong>Preparing Your Flask Application<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"creating-a-flask-application\"><strong>Creating a Flask Application<\/strong><\/h3>\n\n\n\n<p>If you don\u2019t already have a Flask application, you can create a simple one. Here\u2019s an example:<\/p>\n\n\n\n<ol>\n<li><strong>Create a directory for your project:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ mkdir ~\/myflaskapp\n$ cd ~\/myflaskapp<\/code><\/pre>\n\n\n\n<ol start=\"2\">\n<li><strong>Create a virtual environment:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ virtualenv venv<\/code><\/pre>\n\n\n\n<ol start=\"3\">\n<li><strong>Activate the virtual environment:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ source venv\/bin\/activate<\/code><\/pre>\n\n\n\n<ol start=\"4\">\n<li><strong>Install Flask:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ pip install Flask<\/code><\/pre>\n\n\n\n<ol start=\"5\">\n<li><strong>Create a simple Flask application:<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Create a file named&nbsp;<code>app.py<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">from flask import Flask\n\napp = Flask(__name__)\n\n@app.route('\/')\ndef hello_world():\n      return 'Hello, World!'\n\nif __name__ == '__main__':\n      app.run()<\/code><\/pre>\n\n\n\n<ol start=\"6\">\n<li><strong>Test your application:<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Run the application to ensure everything works:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ python app.py<\/code><\/pre>\n\n\n\n<p>You should see output indicating that the Flask development server is running. Visit&nbsp;<code>http:\/\/your_server_ip:5000<\/code>&nbsp;in your browser, and you should see &#8220;Hello, World!&#8221;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"structuring-the-flask-application\"><strong>Structuring the Flask Application<\/strong><\/h3>\n\n\n\n<p>In a production environment, it&#8217;s good practice to structure your Flask application in a modular way. Here\u2019s a simple example of how you might structure your application:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"basic\" class=\"language-basic\">myflaskapp\/\n\u2502\n\u251c\u2500\u2500 app\/\n\u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u251c\u2500\u2500 routes.py\n\u2502   \u251c\u2500\u2500 models.py\n\u2502   \u2514\u2500\u2500 templates\/\n\u2502\n\u251c\u2500\u2500 venv\/\n\u251c\u2500\u2500 config.py\n\u251c\u2500\u2500 requirements.txt\n\u2514\u2500\u2500 wsgi.py<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"creating-a-wsgi-entry-point\"><strong>Creating a WSGI Entry Point<\/strong><\/h3>\n\n\n\n<p>Gunicorn needs a WSGI entry point to serve your Flask application. This is typically a file named&nbsp;<code>wsgi.py<\/code>:<\/p>\n\n\n\n<ol>\n<li><strong>Create the&nbsp;<code>wsgi.py<\/code>&nbsp;file:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"python\" class=\"language-python\">from app import app\n\nif __name__ == \"__main__\":\n      app.run()<\/code><\/pre>\n\n\n\n<ol start=\"2\">\n<li><strong>Install additional dependencies:<\/strong><\/li>\n<\/ol>\n\n\n\n<p>If your application has additional dependencies, list them in a&nbsp;<code>requirements.txt<\/code>&nbsp;file and install them:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ pip freeze &gt; requirements.txt\n$ pip install -r requirements.txt<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"deploying-flask-with-gunicorn\"><strong>Deploying Flask with Gunicorn<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-gunicorn\"><strong>Installing Gunicorn<\/strong><\/h3>\n\n\n\n<p>Gunicorn is a Python package, so it can be installed via pip.<\/p>\n\n\n\n<ol>\n<li><strong>Install Gunicorn:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ pip install gunicorn<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"running-gunicorn\"><strong>Running Gunicorn<\/strong><\/h3>\n\n\n\n<p>To test that Gunicorn can serve your application, run the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ gunicorn --bind 0.0.0.0:8000 wsgi:app<\/code><\/pre>\n\n\n\n<p>This command tells Gunicorn to serve your Flask application using the&nbsp;<code>wsgi.py<\/code>&nbsp;file, binding to port 8000. You should be able to access your application at&nbsp;<code>http:\/\/your_server_ip:8000<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"configuring-gunicorn-for-production\"><strong>Configuring Gunicorn for Production<\/strong><\/h3>\n\n\n\n<p>For production, you typically want to run Gunicorn with several worker processes to handle multiple requests concurrently.<\/p>\n\n\n\n<ol>\n<li><strong>Create a systemd service file for Gunicorn:<\/strong><\/li>\n<\/ol>\n\n\n\n<p>This allows you to manage Gunicorn with systemd, the init system used by Ubuntu.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo nano \/etc\/systemd\/system\/gunicorn.service<\/code><\/pre>\n\n\n\n<p>Add the following content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\"><strong>[Unit]<\/strong>\nDescription=Gunicorn instance to serve myflaskapp\nAfter=network.target\n\n<strong>[Service]<\/strong>\nUser=yourusername\nGroup=www-data\nWorkingDirectory=\/home\/yourusername\/myflaskapp\nEnvironment=\"PATH=\/home\/yourusername\/myflaskapp\/venv\/bin\"\nExecStart=\/home\/yourusername\/myflaskapp\/venv\/bin\/gunicorn --workers 3 --bind unix:myflaskapp.sock -m 007 wsgi:app\n\n<strong>[Install]<\/strong>\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<p>Replace&nbsp;<code>yourusername<\/code>&nbsp;with your actual username.<\/p>\n\n\n\n<ol start=\"2\">\n<li><strong>Start and enable the Gunicorn service:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo systemctl start gunicorn\n$ sudo systemctl enable gunicorn<\/code><\/pre>\n\n\n\n<ol start=\"3\">\n<li><strong>Check the status of the Gunicorn service:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">$ sudo systemctl status gunicorn<\/code><\/pre>\n\n\n\n<p>If everything is set up correctly, Gunicorn should be running and serving your Flask application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"setting-up-nginx\"><strong>Setting Up Nginx<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-nginx\"><strong>Installing Nginx<\/strong><\/h3>\n\n\n\n<p>If you don&#8217;t have Nginx installed, you can install it using the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo apt install nginx<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"configuring-nginx-as-a-reverse-proxy\"><strong>Configuring Nginx as a Reverse Proxy<\/strong><\/h3>\n\n\n\n<p>Nginx will act as a reverse proxy, passing requests to Gunicorn and serving static files directly.<\/p>\n\n\n\n<ol>\n<li><strong>Create a new server block:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo nano \/etc\/nginx\/sites-available\/myflaskapp<\/code><\/pre>\n\n\n\n<p>Add the following content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"nginx\" class=\"language-nginx\"><strong>server<\/strong> {\n      listen 80;\n      server_name your_domain_or_IP;\n\n      <strong>location<\/strong> \/ {\n         include proxy_params;\n         proxy_pass http:\/\/unix:\/home\/yourusername\/myflaskapp\/myflaskapp.sock;\n      }\n\n      <strong>location<\/strong> \/static\/ {\n         alias \/home\/yourusername\/myflaskapp\/app\/static\/;\n      }\n\n      error_log \/home\/yourusername\/myflaskapp\/error.log;\n      access_log \/home\/yourusername\/myflaskapp\/access.log;\n}<\/code><\/pre>\n\n\n\n<p>Replace&nbsp;<code>yourusername<\/code>&nbsp;with your actual username and&nbsp;<code>your_domain_or_IP<\/code>&nbsp;with your server&#8217;s IP address or domain name.<\/p>\n\n\n\n<ol start=\"2\">\n<li><strong>Enable the new server block:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo ln -s \/etc\/nginx\/sites-available\/myflaskapp \/etc\/nginx\/sites-enabled<\/code><\/pre>\n\n\n\n<ol start=\"3\">\n<li><strong>Test the Nginx configuration:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo nginx -t<\/code><\/pre>\n\n\n\n<p>If the test is successful, you should see output indicating that the configuration is OK.<\/p>\n\n\n\n<ol start=\"4\">\n<li><strong>Restart Nginx to apply the changes:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">$ sudo systemctl restart nginx<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"allowing-nginx-through-the-firewall\"><strong>Allowing Nginx through the Firewall<\/strong><\/h3>\n\n\n\n<p>If you\u2019re using UFW (Uncomplicated Firewall), you need to allow Nginx through the firewall.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo ufw allow 'Nginx Full'<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"securing-the-application-with-ssl\"><strong>Securing the Application with SSL<\/strong><\/h2>\n\n\n\n<p>To secure your application, you can set up SSL using Let&#8217;s Encrypt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"installing-certbot\"><strong>Installing Certbot<\/strong><\/h3>\n\n\n\n<p>Certbot is a tool to automate the process of obtaining and renewing SSL certificates.<\/p>\n\n\n\n<ol>\n<li><strong>Install Certbot and the Nginx plugin:<\/strong><\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo apt install certbot python3-certbot-nginx<\/code><\/pre>\n\n\n\n<ol start=\"2\">\n<li><strong>Obtain an SSL certificate:<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Run the following command, replacing&nbsp;<code>your_domain_or_IP<\/code>&nbsp;with your domain or IP address:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo certbot --nginx -d your_domain_or_IP<\/code><\/pre>\n\n\n\n<ol start=\"3\">\n<li><strong>Verify SSL certificate renewal:<\/strong><\/li>\n<\/ol>\n\n\n\n<p>Certbot will automatically renew your SSL certificates. You can simulate a renewal to check if it&#8217;s working:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo certbot renew --dry-run<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"monitoring-and-logging\"><strong>Monitoring and Logging<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"gunicorn-logs\"><strong>Gunicorn Logs<\/strong><\/h3>\n\n\n\n<p>Gunicorn will log its output to the systemd journal. To view the logs:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo journalctl -u gunicorn<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"nginx-logs\"><strong>Nginx Logs<\/strong><\/h3>\n\n\n\n<p>Nginx logs requests and errors to log files in&nbsp;<code>\/var\/log\/nginx\/<\/code>. You can view them with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo tail -f \/var\/log\/nginx\/access.log\n$ sudo tail -f \/var\/log\/nginx\/error.log<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"troubleshooting-common-issues\"><strong>Troubleshooting Common Issues<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"gunicorn-fails-to-start\"><strong>Gunicorn Fails to Start<\/strong><\/h3>\n\n\n\n<ul>\n<li><strong>Check the Gunicorn service status:<\/strong><\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo systemctl status gunicorn<\/code><\/pre>\n\n\n\n<p>Look for any error messages in the output.<\/p>\n\n\n\n<ul>\n<li><strong>Check Gunicorn logs:<\/strong><\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo journalctl -u gunicorn<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"nginx-fails-to-start-or-reload\"><strong>Nginx Fails to Start or Reload<\/strong><\/h3>\n\n\n\n<ul>\n<li><strong>Test Nginx configuration:<\/strong><\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo nginx -t<\/code><\/pre>\n\n\n\n<p>This command will highlight any syntax errors in your configuration files.<\/p>\n\n\n\n<ul>\n<li><strong>Check Nginx logs:<\/strong><\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ sudo tail -f \/var\/log\/nginx\/error.log<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"automating-deployment-with-a-cicd-pipeline\"><strong>Automating Deployment with a CI\/CD Pipeline<\/strong><\/h2>\n\n\n\n<p>For large or frequently updated applications, you might want to automate the deployment process using a Continuous Integration\/Continuous Deployment (CI\/CD) pipeline. This involves setting up a service like Jenkins, GitLab CI, or GitHub Actions to automatically deploy your Flask application whenever you push changes to a repository.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"setting-up-a-basic-cicd-pipeline\"><strong>Setting Up a Basic CI\/CD Pipeline<\/strong><\/h3>\n\n\n\n<ol>\n<li><strong>Choose a CI\/CD tool<\/strong>: Jenkins, GitLab CI, GitHub Actions, CircleCI, etc.<\/li>\n\n\n\n<li><strong>Configure your pipeline<\/strong>: Define your build, test, and deployment steps.<\/li>\n\n\n\n<li><strong>Integrate with your version control system<\/strong>: Automatically trigger deployments when changes are pushed to your repository.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"deploying-with-git-hooks\"><strong>Deploying with Git Hooks<\/strong><\/h3>\n\n\n\n<p>If you prefer a simpler approach, you can use Git hooks to trigger deployment scripts whenever you push changes to your server.<\/p>\n\n\n\n<ol>\n<li><strong>Create a post-receive hook on your server<\/strong>:<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ mkdir -p ~\/myflaskapp.git\/hooks\n$ nano ~\/myflaskapp.git\/hooks\/post-receive<\/code><\/pre>\n\n\n\n<p>Add the following content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">#!\/bin\/bash\ngit --work-tree=\/home\/yourusername\/myflaskapp --git-dir=\/home\/yourusername\/myflaskapp.git checkout -f\nsource \/home\/yourusername\/myflaskapp\/venv\/bin\/activate\npip install -r \/home\/yourusername\/myflaskapp\/requirements.txt\nsudo systemctl restart gunicorn<\/code><\/pre>\n\n\n\n<p>Make the hook executable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ chmod +x ~\/myflaskapp.git\/hooks\/post-receive<\/code><\/pre>\n\n\n\n<ol start=\"2\">\n<li><strong>Push updates to your server<\/strong>:<\/li>\n<\/ol>\n\n\n\n<p>From your local machine, add the remote repository:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ git remote add production ssh:\/\/username@your_server_ip\/home\/username\/myflaskapp.git<\/code><\/pre>\n\n\n\n<p>Push changes to the production server:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">$ git push production master<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"faqs\"><strong>FAQs<\/strong><\/h2>\n\n\n\n<p><strong>What is the role of Gunicorn in Flask deployment?<\/strong><\/p>\n\n\n\n<p>Gunicorn serves as the WSGI HTTP server that handles incoming requests to your Flask application. It forks multiple worker processes to manage these requests concurrently, making it a critical component in a production environment.<\/p>\n\n\n\n<p><strong>Why is Nginx used as a reverse proxy?<\/strong><\/p>\n\n\n\n<p>Nginx is used as a reverse proxy to handle client connections, manage static files, and forward dynamic requests to Gunicorn. This improves the security, performance, and scalability of your application.<\/p>\n\n\n\n<p><strong>How do I ensure that my Flask application is secure?<\/strong><\/p>\n\n\n\n<p>Securing your Flask application involves using SSL\/TLS certificates, enforcing HTTPS, setting proper permissions, and regularly updating your server and application dependencies.<\/p>\n\n\n\n<p><strong>Can I use other web servers instead of Nginx?<\/strong><\/p>\n\n\n\n<p>Yes, you can use other web servers like Apache. However, Nginx is preferred for its performance, simplicity, and ease of use as a reverse proxy.<\/p>\n\n\n\n<p><strong>What should I do if my application crashes after deployment?<\/strong><\/p>\n\n\n\n<p>Check the logs for Gunicorn and Nginx to identify the cause of the crash. Ensure that your application is correctly configured and that all dependencies are installed. Also, check for any syntax errors in your configuration files.<\/p>\n\n\n\n<p><strong>How do I scale my Flask application?<\/strong><\/p>\n\n\n\n<p>You can scale your Flask application by increasing the number of Gunicorn workers, load balancing across multiple servers, and optimizing your code and database queries.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Deploying a Flask application with Gunicorn and Nginx on Ubuntu is a powerful way to ensure your application is robust, scalable, and secure. By following the steps outlined in this guide, you can confidently deploy your Flask app in a production environment. From setting up your server and configuring your application to securing your site with SSL and troubleshooting common issues, this tutorial provides everything you need to know.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Deploying a Flask application is a critical step in making your web application accessible to the world. While Flask comes with a built-in development server, it&#8217;s not suitable for production. For a robust, scalable, and production-ready setup, you\u2019ll need a combination of Gunicorn, Nginx, and Ubuntu. This guide will walk you through the process of ..<\/p>\n<div class=\"clear-fix\"><\/div>\n<p><a href=\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\" title=\"read more...\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[188,4],"tags":[],"yoast_head":"\n<title>Deploying a Flask Application with Gunicorn and Nginx on Ubuntu - WebHi Tutorials &amp; Documentations<\/title>\n<meta name=\"description\" content=\"Learn how to deploy a Flask application with Gunicorn and Nginx on Ubuntu in this detailed, step-by-step guide.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu - WebHi Tutorials &amp; Documentations\" \/>\n<meta property=\"og:description\" content=\"Learn how to deploy a Flask application with Gunicorn and Nginx on Ubuntu in this detailed, step-by-step guide.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\" \/>\n<meta property=\"og:site_name\" content=\"WebHi Tutorials &amp; Documentations\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webhi.technology\" \/>\n<meta property=\"article:published_time\" content=\"2024-08-30T14:24:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-08-30T14:24:11+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en.jpg\" \/>\n<meta name=\"author\" content=\"webhi\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@WebHiTechnology\" \/>\n<meta name=\"twitter:site\" content=\"@WebHiTechnology\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"webhi\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"TechArticle\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\"},\"author\":{\"name\":\"webhi\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/#\/schema\/person\/b31e76e2311cdc0bb90f5e2733059a54\"},\"headline\":\"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu\",\"datePublished\":\"2024-08-30T14:24:09+00:00\",\"dateModified\":\"2024-08-30T14:24:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\"},\"wordCount\":1444,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/#organization\"},\"articleSection\":[\"CMS &amp; Web development\",\"Web servers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\",\"url\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\",\"name\":\"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu - WebHi Tutorials &amp; Documentations\",\"isPartOf\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/#website\"},\"datePublished\":\"2024-08-30T14:24:09+00:00\",\"dateModified\":\"2024-08-30T14:24:11+00:00\",\"description\":\"Learn how to deploy a Flask application with Gunicorn and Nginx on Ubuntu in this detailed, step-by-step guide.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webhi.com\/how-to\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/#website\",\"url\":\"https:\/\/www.webhi.com\/how-to\/\",\"name\":\"WebHi Tutorials &amp; Documentations\",\"description\":\"System administration and knowledge base\",\"publisher\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webhi.com\/how-to\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/#organization\",\"name\":\"WebHi Technology\",\"url\":\"https:\/\/www.webhi.com\/how-to\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webhi.com\/how-to\/gilrogre\/2022\/07\/logo.png\",\"contentUrl\":\"https:\/\/www.webhi.com\/how-to\/gilrogre\/2022\/07\/logo.png\",\"width\":288,\"height\":95,\"caption\":\"WebHi Technology\"},\"image\":{\"@id\":\"https:\/\/www.webhi.com\/how-to\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webhi.technology\",\"https:\/\/twitter.com\/WebHiTechnology\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/#\/schema\/person\/b31e76e2311cdc0bb90f5e2733059a54\",\"name\":\"webhi\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webhi.com\/how-to\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.webhi.com\/how-to\/ahuphiph\/litespeed\/avatar\/e20da107d0f4c765ead2eef88ad019d8.jpg?ver=1782424353\",\"contentUrl\":\"https:\/\/www.webhi.com\/how-to\/ahuphiph\/litespeed\/avatar\/e20da107d0f4c765ead2eef88ad019d8.jpg?ver=1782424353\",\"caption\":\"webhi\"},\"sameAs\":[\"https:\/\/www.webhi.com\/how-to\"],\"url\":\"https:\/\/www.webhi.com\/how-to\/author\/webhi\/\"}]}<\/script>\n","yoast_head_json":{"title":"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu - WebHi Tutorials &amp; Documentations","description":"Learn how to deploy a Flask application with Gunicorn and Nginx on Ubuntu in this detailed, step-by-step guide.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/","og_locale":"en_US","og_type":"article","og_title":"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu - WebHi Tutorials &amp; Documentations","og_description":"Learn how to deploy a Flask application with Gunicorn and Nginx on Ubuntu in this detailed, step-by-step guide.","og_url":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/","og_site_name":"WebHi Tutorials &amp; Documentations","article_publisher":"https:\/\/www.facebook.com\/webhi.technology","article_published_time":"2024-08-30T14:24:09+00:00","article_modified_time":"2024-08-30T14:24:11+00:00","og_image":[{"url":"https:\/\/www.webhi.com\/how-to\/gilrogre\/2024\/08\/gunicorn_flask_en.jpg"}],"author":"webhi","twitter_card":"summary_large_image","twitter_creator":"@WebHiTechnology","twitter_site":"@WebHiTechnology","twitter_misc":{"Written by":"webhi","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"TechArticle","@id":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#article","isPartOf":{"@id":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/"},"author":{"name":"webhi","@id":"https:\/\/www.webhi.com\/how-to\/#\/schema\/person\/b31e76e2311cdc0bb90f5e2733059a54"},"headline":"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu","datePublished":"2024-08-30T14:24:09+00:00","dateModified":"2024-08-30T14:24:11+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/"},"wordCount":1444,"commentCount":0,"publisher":{"@id":"https:\/\/www.webhi.com\/how-to\/#organization"},"articleSection":["CMS &amp; Web development","Web servers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/","url":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/","name":"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu - WebHi Tutorials &amp; Documentations","isPartOf":{"@id":"https:\/\/www.webhi.com\/how-to\/#website"},"datePublished":"2024-08-30T14:24:09+00:00","dateModified":"2024-08-30T14:24:11+00:00","description":"Learn how to deploy a Flask application with Gunicorn and Nginx on Ubuntu in this detailed, step-by-step guide.","breadcrumb":{"@id":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.webhi.com\/how-to\/deploying-flask-application-with-gunicorn-nginx-ubuntu\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webhi.com\/how-to\/"},{"@type":"ListItem","position":2,"name":"Deploying a Flask Application with Gunicorn and Nginx on Ubuntu"}]},{"@type":"WebSite","@id":"https:\/\/www.webhi.com\/how-to\/#website","url":"https:\/\/www.webhi.com\/how-to\/","name":"WebHi Tutorials &amp; Documentations","description":"System administration and knowledge base","publisher":{"@id":"https:\/\/www.webhi.com\/how-to\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webhi.com\/how-to\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webhi.com\/how-to\/#organization","name":"WebHi Technology","url":"https:\/\/www.webhi.com\/how-to\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webhi.com\/how-to\/#\/schema\/logo\/image\/","url":"https:\/\/www.webhi.com\/how-to\/gilrogre\/2022\/07\/logo.png","contentUrl":"https:\/\/www.webhi.com\/how-to\/gilrogre\/2022\/07\/logo.png","width":288,"height":95,"caption":"WebHi Technology"},"image":{"@id":"https:\/\/www.webhi.com\/how-to\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webhi.technology","https:\/\/twitter.com\/WebHiTechnology"]},{"@type":"Person","@id":"https:\/\/www.webhi.com\/how-to\/#\/schema\/person\/b31e76e2311cdc0bb90f5e2733059a54","name":"webhi","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webhi.com\/how-to\/#\/schema\/person\/image\/","url":"https:\/\/www.webhi.com\/how-to\/ahuphiph\/litespeed\/avatar\/e20da107d0f4c765ead2eef88ad019d8.jpg?ver=1782424353","contentUrl":"https:\/\/www.webhi.com\/how-to\/ahuphiph\/litespeed\/avatar\/e20da107d0f4c765ead2eef88ad019d8.jpg?ver=1782424353","caption":"webhi"},"sameAs":["https:\/\/www.webhi.com\/how-to"],"url":"https:\/\/www.webhi.com\/how-to\/author\/webhi\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/posts\/9172"}],"collection":[{"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/comments?post=9172"}],"version-history":[{"count":4,"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/posts\/9172\/revisions"}],"predecessor-version":[{"id":9202,"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/posts\/9172\/revisions\/9202"}],"wp:attachment":[{"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/media?parent=9172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/categories?post=9172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webhi.com\/how-to\/wp-json\/wp\/v2\/tags?post=9172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}