How to Deploy a Flask App on DigitalOcean: Step-by-Step Guide

How to Deploy a Flask App on DigitalOcean: Step-by-Step Guide

by | May 5, 2026 | Uncategorized | 0 comments

How to Deploy a Flask App on DigitalOcean: The Complete 2026 Walkthrough

If you have built a Python Flask application and you are ready to share it with the world, DigitalOcean remains one of the most practical and affordable hosting solutions available. Whether you are launching a side project, a REST API, or a full web application, deploying your Flask app on a DigitalOcean Droplet gives you full control over your server environment without breaking the bank.

In this guide, we will walk through every step required to deploy a Flask app on DigitalOcean, from creating your Droplet to configuring Gunicorn as your WSGI server and setting up Nginx as a reverse proxy. By the end, your Flask app will be live, secure, and production-ready.

What You Will Need Before You Start

Before diving in, make sure you have the following ready:

  • A DigitalOcean account (sign up at digitalocean.com if you do not have one)
  • A Flask application ready for deployment (either locally or in a GitHub repository)
  • A domain name (optional but recommended for production)
  • Basic familiarity with the Linux command line
  • An SSH key pair configured on your local machine

Step 1: Create a DigitalOcean Droplet

A Droplet is a virtual private server (VPS) on DigitalOcean. Here is how to create one suited for a Flask application:

  1. Log in to your DigitalOcean dashboard.
  2. Click the Create button in the top right corner and select Droplets.
  3. Choose your configuration:
Setting Recommended Choice
Image (OS) Ubuntu 24.04 LTS
Plan Basic – $6/month (1 GB RAM, 1 vCPU)
Datacenter Region Choose the one closest to your target audience
Authentication SSH Key (strongly recommended over password)

Click Create Droplet and wait a few seconds for it to spin up. Once ready, note the public IP address assigned to your Droplet.

Step 2: Connect to Your Droplet via SSH

Open a terminal on your local machine and connect:

ssh root@your_server_ip

Replace your_server_ip with the actual IP address of your Droplet.

Create a Non-Root User (Recommended)

Running everything as root is a security risk. Create a dedicated user:

adduser flaskuser
usermod -aG sudo flaskuser

Switch to the new user:

su - flaskuser

Step 3: Update the Server and Install Dependencies

Start by updating the system packages:

sudo apt update && sudo apt upgrade -y

Install Python, pip, and the essential components you will need:

sudo apt install python3 python3-pip python3-venv nginx -y

This installs:

  • Python 3 and pip for managing Python packages
  • python3-venv for creating virtual environments
  • Nginx which we will use as a reverse proxy later

Step 4: Upload or Clone Your Flask Application

You can get your Flask app onto the server in several ways. The most common approach is cloning from a Git repository:

cd /home/flaskuser
git clone https://github.com/yourusername/your-flask-app.git
cd your-flask-app

Alternatively, you can use scp to upload files from your local machine:

scp -r /path/to/your/flask-app flaskuser@your_server_ip:/home/flaskuser/

Step 5: Set Up a Python Virtual Environment

Creating a virtual environment keeps your project dependencies isolated from the system Python:

python3 -m venv venv
source venv/bin/activate

Now install your Flask app dependencies:

pip install -r requirements.txt

If you do not have a requirements.txt file yet, at minimum you will need:

pip install flask gunicorn

And then generate the file for future use:

pip freeze > requirements.txt

Step 6: Test Your Flask App Locally on the Server

Before configuring the production stack, make sure your app actually runs. Assuming your main Flask file is app.py and your Flask instance is named app:

python app.py

If it starts without errors, you are good to proceed. Press Ctrl+C to stop it.

Step 7: Configure Gunicorn as the WSGI Server

Flask’s built-in development server is not designed for production traffic. Gunicorn (Green Unicorn) is a production-grade WSGI HTTP server that handles concurrent requests efficiently.

Test Gunicorn Manually

First, make sure Gunicorn can serve your Flask app correctly:

gunicorn --bind 0.0.0.0:8000 app:app

Here, app:app means: look in the file app.py for the Flask instance named app. Adjust this based on your project structure. For example, if your file is main.py and the Flask object is application, use main:application.

Visit http://your_server_ip:8000 in your browser. If you see your app, Gunicorn is working. Stop it with Ctrl+C.

Create a Systemd Service for Gunicorn

To keep Gunicorn running in the background and auto-start on reboot, create a systemd service file:

sudo nano /etc/systemd/system/flaskapp.service

Paste the following content:

[Unit]
Description=Gunicorn instance to serve Flask app
After=network.target

[Service]
User=flaskuser
Group=www-data
WorkingDirectory=/home/flaskuser/your-flask-app
Environment="PATH=/home/flaskuser/your-flask-app/venv/bin"
ExecStart=/home/flaskuser/your-flask-app/venv/bin/gunicorn --workers 3 --bind unix:flaskapp.sock -m 007 app:app

[Install]
WantedBy=multi-user.target

Key parameters explained:

  • --workers 3 sets the number of worker processes. A common formula is (2 x number_of_cores) + 1.
  • --bind unix:flaskapp.sock creates a Unix socket file instead of binding to a TCP port. This is more secure and efficient when paired with Nginx.
  • -m 007 sets the file permissions on the socket so Nginx can access it.

Enable and start the service:

sudo systemctl start flaskapp
sudo systemctl enable flaskapp

Check the status:

sudo systemctl status flaskapp

You should see active (running). If there are errors, check the logs with:

sudo journalctl -u flaskapp

Step 8: Configure Nginx as a Reverse Proxy

Nginx will sit in front of Gunicorn, handling incoming HTTP requests, serving static files, and providing an extra layer of performance and security.

Create an Nginx Server Block

sudo nano /etc/nginx/sites-available/flaskapp

Add the following configuration:

server {
    listen 80;
    server_name your_domain_or_ip;

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/flaskuser/your-flask-app/flaskapp.sock;
    }

    location /static/ {
        alias /home/flaskuser/your-flask-app/static/;
    }
}

Replace your_domain_or_ip with your actual domain name or the Droplet IP address.

Enable the Configuration

sudo ln -s /etc/nginx/sites-available/flaskapp /etc/nginx/sites-enabled

Test the Nginx configuration for syntax errors:

sudo nginx -t

If the test passes, restart Nginx:

sudo systemctl restart nginx

Adjust the Firewall

If you are using UFW (Uncomplicated Firewall), allow Nginx traffic:

sudo ufw allow 'Nginx Full'
sudo ufw allow OpenSSH
sudo ufw enable

Now visit http://your_domain_or_ip in your browser. Your Flask app should be live.

Step 9: Secure Your App with a Free SSL Certificate

Running your app over HTTPS is essential. Let’s Encrypt provides free SSL certificates, and Certbot makes the process simple.

sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts. Certbot will automatically modify your Nginx configuration to redirect HTTP traffic to HTTPS.

Verify that auto-renewal is set up:

sudo certbot renew --dry-run

Step 10: Set Up Environment Variables (Best Practice)

Hardcoding secrets like database passwords or API keys in your source code is dangerous. Use environment variables instead.

Create a .env file in your project directory:

SECRET_KEY=your_secret_key_here
DATABASE_URL=postgresql://user:password@localhost/dbname
FLASK_ENV=production

In your Flask app, load them using python-dotenv:

pip install python-dotenv

And in your app.py:

from dotenv import load_dotenv
import os

load_dotenv()
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY')

You can also add environment variables directly into your systemd service file under the [Service] section using Environment directives.

Complete Architecture Overview

Here is what the full deployment stack looks like:

Layer Component Role
Client Browser / API consumer Sends HTTP/HTTPS requests
Web Server Nginx Reverse proxy, SSL termination, static file serving
WSGI Server Gunicorn Runs your Python Flask code with multiple workers
Application Flask Your Python web application
Infrastructure DigitalOcean Droplet Ubuntu VPS hosting everything

Troubleshooting Common Issues

Here are the most frequent problems developers run into when they deploy a Flask app on DigitalOcean, along with their solutions:

502 Bad Gateway Error

This usually means Nginx cannot communicate with Gunicorn. Check that:

  • The Gunicorn service is running: sudo systemctl status flaskapp
  • The socket file exists: ls /home/flaskuser/your-flask-app/flaskapp.sock
  • File permissions are correct on the socket and project directory

Permission Denied on the Socket

Make sure the www-data group has access. You can fix this with:

sudo chown flaskuser:www-data /home/flaskuser/your-flask-app
chmod 710 /home/flaskuser

App Works on Port 8000 But Not Through Nginx

Double-check your Nginx config file for typos in the proxy_pass path. The Unix socket path must exactly match the one in your systemd service file.

Changes to Code Are Not Reflected

After updating your Flask app code, you need to restart Gunicorn:

sudo systemctl restart flaskapp

Optional: Deploy Using Docker on DigitalOcean

If you prefer a containerized approach, you can also deploy your Flask app using Docker. This is useful for ensuring consistency between your local development environment and production.

Create a Dockerfile in your project root:

FROM python:3.12-slim

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Build and run:

docker build -t flaskapp .
docker run -d -p 8000:8000 flaskapp

Then configure Nginx to proxy to http://127.0.0.1:8000 instead of using a Unix socket.

DigitalOcean Droplet vs. App Platform: Which Should You Choose?

DigitalOcean also offers an App Platform, a managed platform-as-a-service option. Here is a quick comparison:

Feature Droplet (VPS) App Platform
Server control Full root access Managed by DigitalOcean
Setup complexity Manual configuration required Push-to-deploy from GitHub
Starting price $6/month Free tier available, then $5/month
SSL Manual (Certbot) Automatic
Best for Developers who want full control Quick deployments with minimal DevOps

For most developers who want to learn server management or need custom configurations, the Droplet approach covered in this guide is the better choice.

Performance Tips for Production Flask Apps

  • Increase Gunicorn workers based on your Droplet’s CPU cores. The formula (2 x cores) + 1 is a solid starting point.
  • Enable Gzip compression in Nginx to reduce response sizes.
  • Use a CDN like Cloudflare for static assets and global caching.
  • Monitor your server with tools like htop, DigitalOcean’s built-in monitoring, or third-party services.
  • Set up automated backups through DigitalOcean’s Droplet backup feature (small additional cost).
  • Keep your system updated regularly with sudo apt update && sudo apt upgrade.

Frequently Asked Questions

How much does it cost to deploy a Flask app on DigitalOcean?

The most affordable DigitalOcean Droplet starts at $6 per month, which includes 1 GB of RAM and 1 vCPU. This is enough to run a small to medium Flask application. You only pay for what you use, and there are no hidden fees.

Do I need Gunicorn to run Flask in production?

Yes. Flask’s built-in development server is single-threaded and not designed to handle real-world traffic. Gunicorn is a production-grade WSGI server that manages multiple worker processes, making your app significantly more reliable and performant.

Can I deploy a Flask app on DigitalOcean without a domain name?

Absolutely. You can access your app directly via the Droplet’s public IP address. However, for production use, a domain name with SSL is strongly recommended for credibility and security.

How do I update my Flask app after deployment?

SSH into your server, pull the latest code from your repository (e.g., git pull origin main), install any new dependencies, and restart the Gunicorn service with sudo systemctl restart flaskapp.

Is DigitalOcean good for hosting Python web apps?

DigitalOcean is one of the most popular choices among Python developers for hosting web applications. Its straightforward pricing, excellent documentation, and developer-friendly tools make it ideal for Flask, Django, and FastAPI projects alike.

Can I run multiple Flask apps on one Droplet?

Yes. You can create separate Gunicorn systemd services and Nginx server blocks for each application. Just make sure each app uses a unique socket file or port, and that your Droplet has enough resources to handle all of them.

How do I host a Flask app on a VPS?

The process described in this guide applies to virtually any VPS provider, not just DigitalOcean. The core steps are the same: set up the server, install Python and dependencies, configure Gunicorn as the WSGI server, and use Nginx as a reverse proxy.

Wrapping Up

Deploying a Flask app on DigitalOcean is straightforward once you understand the stack. To recap the key steps:

  1. Create a DigitalOcean Droplet with Ubuntu
  2. Set up a non-root user and install dependencies
  3. Upload your Flask app and create a virtual environment
  4. Configure Gunicorn as a systemd service
  5. Set up Nginx as a reverse proxy
  6. Secure everything with an SSL certificate

This stack (Flask + Gunicorn + Nginx on a DigitalOcean Droplet) is battle-tested, affordable, and gives you complete control over your deployment. It is the same approach used by thousands of developers and startups in production today.

If you found this guide helpful or have questions about deploying your specific Flask project, feel free to reach out. At Box Software, we help teams build and deploy reliable web applications. Visit boxsoftware.net to learn more about our services.