I have been creating a web page for my wife. It is a booking site for her business and is written in a combination of jquery, HTML, CSS, CouchDB, and python.
For the python side of the house I am using Flask. This micro-framework works well for me and allowed me more freedom than I saw reading about Django.
It has taken some time, but the app works well. It can retrieve bookings from CouchDB, display them in a calendar, and accept new bookings from a form on the same page. Jquery handles the calendar display, as well as the AJAX call to populate it. Flask handles the data collection from Couch, the data, and the writing of new data to Couch. For cleanliness, two repositories are used for bookings: one for confirmed bookings and one for requests that have not been reviewed. Another repository provides a client list, but is not accessible from the website.
Then came the fun part. To serve a website with Flask, the internal web server is insufficient. You need additional tools. In my case, NGINX and uWSGI. uWSGI provides an intermediary between Flask and NGINX. NGINX provides a reverse proxy, handling the requests to serve the website.
To make the three elements talk, you need to configure them. A good starter guide is found here. However, your mileage may vary. Mine did.
Configuration is not the same as in the article for my systems. I found the same thing worked in an AWS EC2 instance as worked on a local Vagrant Debian Stretch instance.
So, referencing the starter guide, here are my deltas.
[uwsgi]
module = wsgi #This is the name of the file to be run to start the application. In the example it is wsgi.py, less the suffix.
master = true
processes = 5
socket = myproject.sock #The name is irrelevant. This is just what the socket will be called. Because it has no path, it will be created in the same directory as this ini file.
chmod-socket = 660 #permissions for the above socket once created
vacuum = true
die-on-term = true
For the python side of the house I am using Flask. This micro-framework works well for me and allowed me more freedom than I saw reading about Django.
It has taken some time, but the app works well. It can retrieve bookings from CouchDB, display them in a calendar, and accept new bookings from a form on the same page. Jquery handles the calendar display, as well as the AJAX call to populate it. Flask handles the data collection from Couch, the data, and the writing of new data to Couch. For cleanliness, two repositories are used for bookings: one for confirmed bookings and one for requests that have not been reviewed. Another repository provides a client list, but is not accessible from the website.
Then came the fun part. To serve a website with Flask, the internal web server is insufficient. You need additional tools. In my case, NGINX and uWSGI. uWSGI provides an intermediary between Flask and NGINX. NGINX provides a reverse proxy, handling the requests to serve the website.
To make the three elements talk, you need to configure them. A good starter guide is found here. However, your mileage may vary. Mine did.
Configuration is not the same as in the article for my systems. I found the same thing worked in an AWS EC2 instance as worked on a local Vagrant Debian Stretch instance.
So, referencing the starter guide, here are my deltas.
myproject.ini
My file ended up being the same as the one in the document, but I have added some explanations to the item below:
[uwsgi]
module = wsgi #This is the name of the file to be run to start the application. In the example it is wsgi.py, less the suffix.
master = true
processes = 5
socket = myproject.sock #The name is irrelevant. This is just what the socket will be called. Because it has no path, it will be created in the same directory as this ini file.
chmod-socket = 660 #permissions for the above socket once created
vacuum = true
die-on-term = true
Upstart script
This is how I made a raspberry pi SD card unbootable. Upstart is not the standard system process manager for Debian (or Ubuntu, apparently). Casually installing it will delete Systemd, the default. I would not recommend doing this unless you know what you're doing, in which case you probably wouldn't be taking my advice anyway.
I wrote a systemd service rather than upstart config. There are translation tables between the two to help.
To make the equivalent systemd file, you'll need to sudo vi /lib/systemd/system/<name_of_choice>.service to make a service file and open it for editing.
If you don't like vi, substitute editor of choice.
The file I made looks like:
[Unit]
Description=Whatever you want to write
After=syslog.target
[Service]
User=<user to run uwsgi>
Environment="PATH=/path/to/your/apps/virtualenv/bin" #The quotes and PATH were needed here
WorkingDirectory=/path/to/your/ini #Do not include the filename in this path
ExecStart=/path/to/your/apps/virtualenv/bin/uwsgi --ini /path/to/your/ini/<filename.ini> #No relative paths here. Uses the virtualenv uwsgi to open the ini file.
Restart=always
[Install]
WantedBy=multi-user.target #This is runlevel3. WantedBy ensure it starts at this runlevel.
Final item
This was the most annoying part and betrays my relative newness to Linux. Nginx could not do anything with the socket. Without the socket, it can't talk to uWSGI. Without talking, my app is not going to be served.
I resolve this with a poor approach, but it worked. I edited /etc/nginx/nginx.conf.
For good practice, when editing this kind of file, it's worth doing something like cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup.
The above command will make a copy of the unedited file, allowing you to recover from catastrophic mistakes.
All I did to this file was edit the very first line from:
user www-data
...to:
user <my user>
Then everything worked. That being said, the better approach would be to work out why www-data was prevented from handling the socket, but I chose not to die on that hill today. My app works inside a vagrant box and on AWS.
This post was just to highlight the variations this user experienced. I regard the linked guide very highly and would recommend it for starting out. Aside from the above items, everything else worked fine.
Comments
Post a Comment