Anasayfa / Software / Deploying a Flask Web App on a Linux VPS: A Step‑by‑Step Guide

Deploying a Flask Web App on a Linux VPS: A Step‑by‑Step Guide

Flask server

Running a Flask application on a remote Linux VPS can feel like a daunting task, especially when you’re juggling code, security, and performance. This guide walks you through every essential step— from a fresh server to a production‑ready, SSL‑secured site— using real commands and practical tips. By the end, you’ll have a solid, maintainable deployment that you can replicate for future projects.

What You’ll Need

  • A Linux VPS (Ubuntu 22.04 LTS is used in examples)
  • Root or sudo access via SSH
  • A domain name pointing to your VPS IP
  • Git installed on the server
  • Python 3.10+ and pip
  • Virtualenv (or venv) for isolated dependencies
  • Gunicorn – a WSGI HTTP server for Python
  • Nginx – a reverse proxy and static file server
  • UFW or another firewall
  • Certbot (optional, for free SSL certificates)

Step 1: Secure the Server and Update Packages

Log in to your VPS with SSH. Replace user and your_ip with your own values.

ssh user@your_ip

Once connected, run the standard update and upgrade sequence. This ensures you start from a clean, patched base.

sudo apt update && sudo apt upgrade -y

Enable the uncomplicated firewall (UFW) and allow only the ports you’ll need: SSH (22), HTTP (80), and HTTPS (443).

sudo ufw allow OpenSSH
sudo ufw allow http
sudo ufw allow https
sudo ufw enable

Confirm the status:

sudo ufw status

At this point your server is up‑to‑date and protected from unwanted traffic.

Step 2: Install Required Software

Install the core packages: Git, Python, pip, virtualenv, Nginx, and build tools.

sudo apt install -y git python3-pip python3-venv nginx build-essential

Verify the installations:

git --version
python3 --version
pip3 --version
nginx -v

If you plan to use a database later (PostgreSQL, MySQL), install it now, but it’s not required for a basic Flask app.

Step 3: Clone Your Flask Project and Set Up a Virtual Environment

Navigate to a directory where you keep your web projects, then clone the repository. Adjust the URL to match your own Git source.

mkdir -p ~/apps && cd ~/apps
git clone https://github.com/yourusername/your-flask-app.git
cd your-flask-app

Create a virtual environment inside the project folder and activate it.

python3 -m venv venv
source venv/bin/activate

Install your application’s dependencies. Most Flask projects include a requirements.txt file.

pip install -r requirements.txt

Test the app locally to ensure it runs before moving on.

export FLASK_APP=app.py
flask run --host=0.0.0.0

You should see the “Running on http://0.0.0.0:5000/” message. Open a browser and point to http://your_ip:5000 to confirm the app works.

Step 4: Configure Gunicorn as a Systemd Service

Gunicorn will serve your Flask app in production. First, install it inside the virtual environment if it isn’t already listed in requirements.txt.

pip install gunicorn

Create a systemd service file so the OS can manage Gunicorn automatically. Use sudo nano (or your preferred editor) to create the file.

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

Paste the following content, replacing placeholders with your actual paths and usernames. Note that we avoid double quotes to keep JSON parsing simple.

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

[Service]
User=your_user
Group=www-data
WorkingDirectory=/home/your_user/apps/your-flask-app
Environment="PATH=/home/your_user/apps/your-flask-app/venv/bin"
ExecStart=/home/your_user/apps/your-flask-app/venv/bin/gunicorn --workers 3 --bind unix:yourflaskapp.sock wsgi:app

[Install]
WantedBy=multi-user.target

Save and exit. Then reload systemd, start the service, and enable it at boot.

sudo systemctl daemon-reload
sudo systemctl start yourflaskapp
sudo systemctl enable yourflaskapp

Check the status to ensure there are no errors:

sudo systemctl status yourflaskapp

If everything looks good, Gunicorn is now listening on a Unix socket named yourflaskapp.sock.

Step 5: Set Up Nginx as a Reverse Proxy

Nginx will forward external HTTP/HTTPS requests to the Gunicorn socket and also serve static files directly. Create a new server block for your domain.

sudo nano /etc/nginx/sites-available/yourdomain.com

Insert the following configuration, again avoiding double quotes:

server {
listen 80;
server_name yourdomain.com www.yourdomain.com;

location / {
include proxy_params;
proxy_pass http://unix:/home/your_user/apps/your-flask-app/yourflaskapp.sock;
}

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

Enable the site and test the Nginx configuration.

sudo ln -s /etc/nginx/sites-available/yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t

If the test passes, reload Nginx.

sudo systemctl reload nginx

Now visiting http://yourdomain.com should display your Flask app, routed through Nginx.

Step 6: Secure the Site with Let’s Encrypt SSL

HTTPS is a must for any public web service. Install Certbot and obtain a free certificate.

sudo apt install -y certbot python3-certbot-nginx

Run the interactive command; it will automatically edit your Nginx config to redirect HTTP to HTTPS.

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Follow the prompts, choose to redirect all traffic to HTTPS, and let Certbot handle renewal.

Verify renewal works:

sudo certbot renew --dry-run

With a valid certificate in place, your Flask app is now served securely over the internet.

Common Mistakes to Avoid

1. Forgetting to activate the virtual environment before installing dependencies leads to system‑wide packages and version conflicts.
2. Mismatched file permissions on the Gunicorn socket can cause Nginx to return 502 errors. Ensure the socket is owned by the www-data group or adjust the User/Group lines in the systemd file.
3. Hard‑coding absolute paths in the service file makes migration harder. Use variables like $HOME when possible.
4. Skipping firewall rules for HTTP/HTTPS will block legitimate traffic.
5. Not testing the app locally before adding Gunicorn/Nginx can waste time debugging configuration issues instead of code bugs.

Tips and Tricks

• Use gunicorn --daemon only for quick testing; rely on systemd for production management.
• Store environment variables (e.g., secret keys) in a .env file and load them with python-dotenv instead of hard‑coding them.
• Enable log rotation for both Gunicorn and Nginx to prevent disk‑space exhaustion.
• If your app serves large static assets, consider adding a CDN or enabling Nginx caching directives.
• Regularly run sudo apt update && sudo apt upgrade -y on the VPS to keep security patches current.

Frequently Asked Questions

Can I use Apache instead of Nginx?

Yes, Apache can proxy to Gunicorn via mod_proxy, but Nginx is lighter, handles concurrent connections better, and is the de‑facto standard for Python deployments.

Do I need to restart Gunicorn after every code change?

When you modify Python code, restart the systemd service so Gunicorn reloads the updated modules: sudo systemctl restart yourflaskapp. For zero‑downtime reloads, you can use sudo systemctl reload yourflaskapp if your service file supports it.

What if I want to run multiple Flask apps on the same VPS?

Create separate systemd services and Unix sockets for each app, then configure distinct Nginx server blocks (or subdomains) that point to the corresponding sockets. Keep each app in its own directory with its own virtual environment.

Conclusion

Deploying a Flask web app on a Linux VPS involves a clear sequence: secure the server, install dependencies, isolate your code with a virtual environment, serve it via Gunicorn, and expose it safely through Nginx with SSL. By following the steps above and watching out for common pitfalls, you’ll have a robust, production‑ready deployment that can scale as your project grows. Happy coding, and enjoy the satisfaction of seeing your Flask app live on the web!

Photo by Zarak Khan on Unsplash

Etiketlendi: