How do I get Flask to run on port 80?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Running a Flask app on port 80 is a deployment concern, not just a code setting. Port 80 is privileged on Linux, so direct binding often requires elevated permissions or a reverse proxy architecture. The safest production setup is Flask behind Gunicorn and Nginx, with Nginx listening on port 80.
Development Versus Production Approach
For local development, Flask built-in server is fine and usually runs on port 5000. For production, use a WSGI server such as Gunicorn and put a reverse proxy in front.
Simple Flask app:
Run with Gunicorn on internal port:
Recommended: Nginx on Port 80
Let Nginx own port 80 and forward traffic to Gunicorn. This avoids running Python as root.
Enable config and reload Nginx.
This setup also makes HTTPS termination and static file handling easier.
Alternative: Bind Directly to Port 80 with Capability
If you must bind Flask or Gunicorn directly to port 80 on Linux, assign network bind capability to Python binary. Use carefully and understand security implications.
Or bind Gunicorn directly if process permissions allow.
This is less common than reverse proxy setup and may complicate operations.
Do Not Run as Root by Default
Running app processes as root just to bind privileged ports is risky. A remote code execution bug becomes full system compromise. Prefer least privilege.
If you use systemd, run Gunicorn as a dedicated service user.
Container and Cloud Environments
In Docker and Kubernetes, applications commonly listen on non-privileged internal ports like 8080, and ingress components expose port 80 externally.
Platform networking maps external port 80 to container port 8080.
Quick Verification Checklist
After deployment, verify each layer independently so port issues are easier to isolate.
If internal check passes but external fails, focus on Nginx config and firewall rules. If both fail, inspect application startup logs and Python environment paths in your service unit.
In cloud environments, also verify security group or load balancer listener configuration, since local host checks can succeed while external traffic remains blocked.
This layered verification routine shortens incident response time and helps teams separate application bugs from infrastructure misconfiguration.
Common Pitfalls
- Using Flask development server in production.
- Binding to port 80 by running as root.
- Forgetting reverse proxy headers, causing incorrect URL scheme detection.
- Exposing Gunicorn directly to the internet without proxy buffering and limits.
- Not monitoring service restarts and health checks.
Summary
- Port 80 is privileged, so direct Flask binding needs special permissions.
- Production best practice is Gunicorn on internal port and Nginx on port 80.
- Avoid root execution and prefer least-privilege service users.
- In containers, bind app to high internal port and map externally with ingress.
- Treat port configuration as part of deployment architecture, not only app code.

