<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: devchile</title>
    <description>The latest articles on DEV Community by devchile (@devchile).</description>
    <link>https://dev.to/devchile</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F94432%2Fbe64c621-e702-4d8b-ad77-520a41b7c8c2.png</url>
      <title>DEV Community: devchile</title>
      <link>https://dev.to/devchile</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devchile"/>
    <language>en</language>
    <item>
      <title>Deploying masonite 2 project with Nginx and Gunicorn</title>
      <dc:creator>devchile</dc:creator>
      <pubDate>Mon, 29 Jul 2019 05:26:03 +0000</pubDate>
      <link>https://dev.to/devchile/deploying-masonite-2-project-with-nginx-and-gunicorn-3pnj</link>
      <guid>https://dev.to/devchile/deploying-masonite-2-project-with-nginx-and-gunicorn-3pnj</guid>
      <description>&lt;p&gt;&lt;a href="https://docs.masoniteproject.com/" rel="noopener noreferrer"&gt;Masonite&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;It brings you a useful utility called &lt;code&gt;craft&lt;/code&gt; command that make much easy and faster to create your models/controllers/authentication/middlewares classes and so on.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements used for this guide
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.debian.org/distrib/" rel="noopener noreferrer"&gt;Debian Buster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.masoniteproject.com/" rel="noopener noreferrer"&gt;Masonite 2.2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python 3.7&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gunicorn.org/" rel="noopener noreferrer"&gt;Gunicorn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing your web app
&lt;/h2&gt;

&lt;p&gt;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 &lt;a href="https://dev.to/masonite/masonite-framework-tutorial-series-part-1-140e"&gt;this very well explained tutorial&lt;/a&gt; for installation process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;craft new demoapp
cd demoapp

# Create the virtual env with python3
python3 -m venv venv
source venv/bin/activate
craft install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make a new &lt;em&gt;demoapp&lt;/em&gt; 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 &lt;code&gt;requirements.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In this last step (on my machine using Debian Sid) it prints some errors with Debian version of python wheels installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed building wheel for masonite
Failed building wheel for masonite-validation
Failed building wheel for masonite-dot
Failed building wheel for pyyaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# activate virtualenv if is deactivated
source venv/bin/activate
pip install wheel
craft install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install nginx &amp;amp; gunicorn
&lt;/h2&gt;

&lt;p&gt;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.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# We need nginx and gunicorn3 for python3
sudo aptitude install nginx gunicorn3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Masonite brings out of the box a &lt;code&gt;wsgi.py&lt;/code&gt; file that you can use to execute our application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gunicorn3 wsgi:application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gunicorn defaults settings will allow to access to local machine only. If you want to access from other device you can use &lt;code&gt;-b&lt;/code&gt; option.&lt;/p&gt;

&lt;h1&gt;
  
  
  Nginx and Gunicorn Configuration
&lt;/h1&gt;

&lt;p&gt;After install nginx we will configure Gunicorn to run as a service on systemd, so this will allow us to control with &lt;code&gt;systemctl&lt;/code&gt; command and run after system reboot.&lt;/p&gt;

&lt;p&gt;This will be the &lt;code&gt;/etc/nginx/sites-avalaible/default&lt;/code&gt; file, the path to the project is &lt;code&gt;/home/admin/webapps/demoapp&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the Nginx config file is edited we need to check the syntax is ok:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the Gunicorn service:&lt;br&gt;
&lt;code&gt;/etc/systemd/system/gunicorn.service&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[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

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ~/logs/
sudo chown admin.www-data ~/logs/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;/etc/systemd/system/gunicorn.socket&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.socket

[Install]
WantedBy=sockets.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now almost everything is in place, we need to reload our services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl daemon-reload

# start gunicorn
sudo systemctl start gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To check if gunicorn service is working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally restart nginx to work with our deployed application&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And ta-dah!&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxtifrzeg42wayq0aoodl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxtifrzeg42wayq0aoodl.png" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;If you like beautiful code, try Masonite.&lt;/p&gt;

</description>
      <category>masonite</category>
      <category>gunicorn</category>
      <category>nginx</category>
      <category>python</category>
    </item>
  </channel>
</rss>
