Deploying masonite 2 project with Nginx and Gunicorn
Tags: masonite, gunicorn, nginx, python
Published: 2019-07-29 05:26:03

---
title: Deploying masonite 2 project with Nginx and Gunicorn
published: true
description: Deploy masonite 2 project with Nginx and Gunicorn
tags: masonite,gunicorn,nginx,python
---

[Masonite](https://docs.masoniteproject.com/) is an incredible developer friendly framework to develop modern web applications with python. With a lot of out of the box functionality with an extremely extendable architecture. On my own experience, it helps you a lot to build your applications with a beautiful code.

It brings you a useful utility called `craft` command that make much easy and faster to create your models/controllers/authentication/middlewares classes and so on.

Craft command brings built in a web server designed to run on development environment your web application. While this makes development comfortable, this web server is not designed to deploy on production.

On this guide i will try to explain how to configure and deploy your Masonite app on a virtual private server such as AWS or DigitalOcean.

## Requirements used for this guide

* [Debian Buster](https://www.debian.org/distrib/)
* [Masonite 2.2](https://docs.masoniteproject.com/)
* Python 3.7
* Nginx
* [Gunicorn](https://gunicorn.org/)

## Installing your web app

To start, i will make a new Masonite project. I'm gonna skip the install step because is no the goal of this guide, but you can use [this very well explained tutorial](https://dev.to/masonite/masonite-framework-tutorial-series-part-1-140e) for installation process.

```
craft new demoapp
cd demoapp

# Create the virtual env with python3
python3 -m venv venv
source venv/bin/activate
craft install
```

This will make a new *demoapp* folder with the crafted application, then it will create the virtual env and activate it and to finish it will install the requirements described in the `requirements.txt` file.

In this last step (on my machine using Debian Sid) it prints some errors with Debian version of python wheels installed:

```
Failed building wheel for masonite
Failed building wheel for masonite-validation
Failed building wheel for masonite-dot
Failed building wheel for pyyaml
```
but craft command creates the application key and all is working without problems, but if it makes you noise, my suggested workaround is to install in the virtual env the wheels with pip:
```
# activate virtualenv if is deactivated
source venv/bin/activate
pip install wheel
craft install
```
## Install nginx & gunicorn

In debian you can use apt, apt-get or aptitude to install packages. We will need to install nginx web server and configure it to make a proxy reverse to gunicorn.

```
# We need nginx and gunicorn3 for python3
sudo aptitude install nginx gunicorn3
```

Gunicorn is a Python WSGI HTTP Server for UNIX. Is recommended to use Gunicorn behind an HTTP proxy server (as Nginx in this case).

Masonite brings out of the box a `wsgi.py` file that you can use to execute our application:
```
gunicorn3 wsgi:application
```

Gunicorn defaults settings will allow to access to local machine only. If you want to access from other device you can use `-b` option.

# Nginx and Gunicorn Configuration

After install nginx we will configure Gunicorn to run as a service on systemd, so this will allow us to control with `systemctl` command and run after system reboot.

This will be the `/etc/nginx/sites-avalaible/default` file, the path to the project is `/home/admin/webapps/demoapp`
```
server {
	server_name demoapp.io;

	location = /favicon.ico { access_log off; log_not_found off; }
	location /public/ {
		root /home/admin/webapps/demoapp/storage;
	}
	location /static/ {
		root /home/admin/webapps/demoapp/storage;
	}
	location /uploads/ {
		root /home/admin/webapps/demoapp/storage;
	}
	location /compiled/ {
		root /home/admin/webapps/demoapp/storage;
	}

	access_log /var/log/nginx/access.log;

	location / {
		include proxy_params;
		proxy_set_header Host $host;
		proxy_pass http://unix:/run/gunicorn.socket;
	}
}

```
Now the Nginx config file is edited we need to check the syntax is ok:
```
sudo nginx -t

# Output
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```


Create the Gunicorn service:
`/etc/systemd/system/gunicorn.service`
```
[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
PIDFile=/run/gunicorn/pid
User=admin
Group=www-data
RuntimeDirectory=gunicorn
WorkingDirectory=/home/admin/webapps/demoapp
ExecStart=/usr/bin/gunicorn3 --pid /run/gunicorn/pid\
          --workers 3\
          --bind unix:/run/gunicorn.socket wsgi\
          --error-logfile /home/admin/logs/error.log\
          --access-logfile /home/admin/logs/access.log\
          --log-level debug\
          --timeout 320
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

```

This service file execute `gunicorn3` command using the pid-file (on `/run/gunicorn/pid`) and make a connection thought a socket file located on `/run/gunicorn.socket`, it saves logs on `/home/admin/logs/` directory so it will need permissions:

```
mkdir ~/logs/
sudo chown admin.www-data ~/logs/
```

Create `/etc/systemd/system/gunicorn.socket` file:
```
[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.socket

[Install]
WantedBy=sockets.target
```

Now almost everything is in place, we need to reload our services:
```
sudo systemctl daemon-reload

# start gunicorn
sudo systemctl start gunicorn
```

To check if gunicorn service is working:
```
sudo systemctl status gunicorn

# Output
● gunicorn.service - gunicorn daemon
   Loaded: loaded (/etc/systemd/system/gunicorn.service; disabled)
   Active: active (running) since Wed 2019-07-29 21:05:07 UTC; 49s ago
 Main PID: 10154 (gunicorn)
   CGroup: /system.slice/gunicorn.service
           ├─10154 /home/admin/webapps/demoapp/venv/bin/python3 /home/admin/webapps/demoapp/venv/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.socket wsgi:application
           ├─10157 /home/admin/webapps/demoapp/venv/bin/python3 /home/admin/webapps/demoapp/venv/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.socket wsgi:application
           ├─10158 /home/admin/webapps/demoapp/venv/bin/python3 /home/admin/webapps/demoapp/venv/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.socket wsgi:application
           └─10159 /home/admin/webapps/demoapp/venv/bin/python3 /home/admin/webapps/demoapp/venv/bin/gunicorn --workers 3 --bind unix:/run/gunicorn.socket wsgi:application

Dec 21 21:05:07 debian-512mb-nyc3-01 systemd[1]: Started gunicorn daemon.
```

Finally restart nginx to work with our deployed application
```
sudo systemctl restart nginx
```

And ta-dah!
![](https://thepracticaldev.s3.amazonaws.com/i/4ppfqdyegqrtkdsezpbn.png)

## Conclusions

If you like beautiful code, try Masonite.