Skip to content
setup servers (Nginx, Gunicorn) πŸ¦„ on macOS 🍎 for Python 🐍
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
static
.editorconfig
.gitignore
Makefile
README.md
myproject.py
requirements.txt
wsgi.py

README.md

OVERVIEW

  • what: setup servers (Nginx, Gunicorn) πŸ¦„ on macOS 🍎 for Python 🐍
  • why: most guides show setup on a Linux server (which makes sense) but macoS is useful for learning and for local dev

WHAT WE'LL DO

                +---------------+
                |    Nginx      |
                |               |
                |               |
                +---------------+
                       X
                       X
                       X
                       X
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        X                            X
        X                            X
        X                            X
+----------------+                   X
|    gunicorn    |                   X
|                |                   X
|                |             +----------------+
+----------------+             |    static      |
        X                      |    assets      |
        X                      |                |
+----------------+             +----------------+
|    Flask       |
|                |
|                |
+----------------+

THINGS WE'LL USE

  • packages from Homebrew: nginx and httpie
  • Python 3
  • Makefile for our commands (to understand what all the commands do, just run make help)
  • Flask for the webserver (our gunicorn and Nginx config should hold true for any WSGI server -> if you try this with Django, Pyramid, et al. and run into a problem, just open an issue and we'll figure it out!)

STEP 1: NGINX ➑️ STATIC ASSETS

                +---------------+
                |    Nginx      |
                |               |
                |               |
                +---------------+
                       X
                       X
                       X
                       X
                       XXXXXXXXXXXXXXX
                                     X
                                     X
                                     X
                                     X
                                     X
                                     X
                               +----------------+
                               |    static      |
                               |    assets      |
                               |                |
                               +----------------+

  • download Nginx using Homebrew: brew install nginx
  • start Nginx: make ng-serve
  • hit Nginx: make ng-hit to hit our Nginx server, which will return its default welcome page
$ make ng-hit

http http://127.0.0.1:8080
HTTP/1.1 200 OK
# other output
<h1>Welcome to nginx!</h1>
  • next, go update the Nginx configuration file (/etc/nginx/nginx.conf) to point at our repo's static assets
- location / {
+ location /static {
-   root   html;
+   root   path/to/your/nginx-wsgi;
-   index  index.html index.htm;
+   index  my-asset.html;
}
  • reload Nginx so it knows about our updated config: make ng-up
  • hit Nginx at the static route to validate it's serving our bespoke HTML πŸ˜„: make ng-static
$ make ng-static

http http://127.0.0.1:8080/static/
HTTP/1.1 200 OK
# other output
<h1>Nginx is serving my-asset.html!</h1>

STEP 2: GUNICORN ➑️ FLASK

+----------------+                   
|    gunicorn    |                   
|                |                   
|                |             
+----------------+             
        X                      
        X                      
+----------------+             
|    Flask       |
|                |
|                |
+----------------+
$ make flask-hit

http http://127.0.0.1:5000
<h1>Flask running!</h1>
  • start gunicorn: make guni-serve
  • hit gunicorn on port 8000 to validate that it passes the request to Flask on port 5000: make guni-hit
$ make guni-hit

http http://127.0.0.1:8000
<h1>Flask running!</h1>

STEP 3: NGINX ➑️ GUNICORN

                +---------------+
                |    Nginx      |
                |               |
                |               |
                +---------------+
                       X
                       X
                       X
                       X
        XXXXXXXXXXXXXXXXX
        X                            
        X                            
        X                            
+----------------+                   
|    gunicorn    |                   
|                |                   
|                |             
+----------------+             
  • update the Nginx conf again, this time to pass requests to gunicorn
+ location / {
+     proxy_pass http://127.0.0.1:8000;
+ }
  • reload Nginx so it knows about our updated config: make ng-up
  • hit Nginx: make ng-hit -> this time, instead of the default Nginx page, we'll see that the request passes from Nginx to gunicorn and finally to Flask
$ make ng-hit

http http://127.0.0.1:8080
HTTP/1.1 200 OK
# other output
<h1>Flask running!</h1>

Now, everything is wired together:

                +---------------+
                |    Nginx      |
                |               |
                |               |
                +---------------+
                       X
                       X
                       X
                       X
        XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        X                            X
        X                            X
        X                            X
+----------------+                   X
|    gunicorn    |                   X
|                |                   X
|                |             +----------------+
+----------------+             |    static      |
        X                      |    assets      |
        X                      |                |
+----------------+             +----------------+
|    Flask       |
|                |
|                |
+----------------+

This guide is just to get you up-and-running. For more explanation, here are some articles that helped me:

You can’t perform that action at this time.