├── .gitattributes ├── .gitignore ├── README.md ├── gunicorn_start ├── main.py ├── nginx-fastapi-app ├── requirements-dev.txt ├── requirements.txt └── supervisor-fast-api.conf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .venv/ 2 | .DS_Store 3 | __pycache__/* 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fastapi-nginx-gunicorn 2 | 3 | Deploying a FastAPI web app to a Virtual Private Server (VPS) is tricky. If you're not familiar with technologies such as NGINX or Gunicorn, it can easily overwhelm you. Check out [this tutorial](https://dylancastillo.co/fastapi-nginx-gunicorn/) so you won't have to spend as much time on your first deployment as I did. 4 | -------------------------------------------------------------------------------- /gunicorn_start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | NAME=fastapi-app 4 | DIR=/home/fastapi-user/fastapi-nginx-gunicorn 5 | USER=fastapi-user 6 | GROUP=fastapi-user 7 | WORKERS=3 8 | WORKER_CLASS=uvicorn.workers.UvicornWorker 9 | VENV=$DIR/.venv/bin/activate 10 | BIND=unix:$DIR/run/gunicorn.sock 11 | LOG_LEVEL=error 12 | 13 | cd $DIR 14 | source $VENV 15 | 16 | exec gunicorn main:app \ 17 | --name $NAME \ 18 | --workers $WORKERS \ 19 | --worker-class $WORKER_CLASS \ 20 | --user=$USER \ 21 | --group=$GROUP \ 22 | --bind=$BIND \ 23 | --log-level=$LOG_LEVEL \ 24 | --log-file=- 25 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # Create hello world FastAPI app 2 | from fastapi import FastAPI 3 | 4 | app = FastAPI() 5 | 6 | 7 | @app.get("/") 8 | def read_root(): 9 | return {"message": "It's working!"} 10 | -------------------------------------------------------------------------------- /nginx-fastapi-app: -------------------------------------------------------------------------------- 1 | upstream app_server { 2 | server unix:/home/fastapi-user/fastapi-nginx-gunicorn/run/gunicorn.sock fail_timeout=0; 3 | } 4 | 5 | server { 6 | listen 80; 7 | 8 | # add here the ip address of your server 9 | # or a domain pointing to that ip (like example.com or www.example.com) 10 | server_name XXXX; 11 | 12 | keepalive_timeout 5; 13 | client_max_body_size 4G; 14 | 15 | access_log /home/fastapi-user/fastapi-nginx-gunicorn/logs/nginx-access.log; 16 | error_log /home/fastapi-user/fastapi-nginx-gunicorn/logs/nginx-error.log; 17 | 18 | location / { 19 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 20 | proxy_set_header Host $http_host; 21 | proxy_redirect off; 22 | 23 | if (!-f $request_filename) { 24 | proxy_pass http://app_server; 25 | break; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | flake8==6.0.0 2 | black==22.12.0 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi==0.89.1 2 | gunicorn==20.1.0 3 | uvicorn[standard]==0.20.0 4 | -------------------------------------------------------------------------------- /supervisor-fast-api.conf: -------------------------------------------------------------------------------- 1 | [program:fastapi-app] 2 | command=/home/fastapi-user/fastapi-nginx-gunicorn/gunicorn_start 3 | user=fastapi-user 4 | autostart=true 5 | autorestart=true 6 | redirect_stderr=true 7 | stdout_logfile=/home/fastapi-user/fastapi-nginx-gunicorn/logs/gunicorn-error.log 8 | --------------------------------------------------------------------------------