These steps are intended to be run the first time a development or production copy of this application is setup.
- Open a Command Prompt / Terminal / Shell, either:
- On your local computer / localhost
- Or, if you develop on a remote server then SSH into the remote machine.
- Execute the following commands:
- (Optional) For Production or Remote Servers Only
sudo useradd usernamehere -s /bin/bash && passwd usernamehere
sudo mkdir /home/usernamehere/public_html && chown -Rf usernamehere:groupnamehere /home/usernamehere/public_html
- (Optional) Install Git on your operating system, assuming you don't already have it installed:
- RedHat / CentOS / Fedora:
sudo update yum
&&sudo yum install git
- Ubuntu / Debian:
sudo apt-get update
&&sudo apt-get install git
- Mac:
sudo brew install git
- RedHat / CentOS / Fedora:
cd
to change the directory to where you want the git repository / application to be downloaded- Clone the GitHub repository, or your fork
- Using the SSH protocol:
git clone git@github.com:codeforgreenville/upstate_tech_cal_service.git
- Or, using the HTTPS protcol:
git clone https://github.com/codeforgreenville/upstate_tech_cal_service.git
- Using the SSH protocol:
cd upstate_tech_cal_service
- Install Pipenv - Verify the installation with
pipenv --version
, the output should look something like:pipenv, version 2021.5.29
- In the project directory, run
pipenv install
This installs dependencies listed in the project's Pipfile and creates a virtualenv for the project. - You can verify the env has been created by checking for it at
~/.local/share/virtualenvs/
- To install a new package, you can use
pipenv install <package-name>
- To activate the subshell, use
pipenv shell
- For more help with available Pipenv commands, use
pipenv -h
- (Optional) For Production or Remote Servers Only
- Create a local config.ini file, if one does not exist.
cp config.ini.example config.ini && nano config.ini
- Fill in the placeholder values in your config.ini with the real values for the following,
nano config.ini
- Register your own Eventbrite token
- Flask secret can be any long random string
- (No longer needed) Version 3 of the Meetup.com API requires an Oauth Key. However, as of Oct 2019, we're using only public GET API endpoints that require not authentication. It's not necessary to register a Meetup.com API key unless/until the app needs access to an authenticated endpoint, at which point the key could be added to the config file
- Create a local logging_config.ini file
cp logging_config.ini.example logging_config.ini
mkdir logs
- Test with gunicorn WSGI Server on a localhost port
- Run the following to generate / update the
all_meetups.json
file in your application directory. - cd ~/upstate_tech_cal_service && pipenv shell && python update_cal_data.py && exit
- Start a "localhost" web server:
gunicorn --bind 0.0.0.0:8000 app:app
- Visit the localhost application in your web browser, and see if it works:
http://localhost:8000/api/gtc?tags=1'
- Run the following to generate / update the
- (Optional) On Remote or Production Servers - Setup a cronjob to generate the all_meetings.json, for example, at :35 after every hour
crontab -e -u usernamehere
35 * * * * source $HOME/.bashrc; cd ~/upstate_tech_cal_service && pipenv shell && python update_cal_data.py && exit
- (Optional) Configure hosting via a real Web Server, like Apache or Nginx
- Setup gunicorn as a systemd daemon. Change "apache" to "nginx" in this file if you're using Nginx, and update the USERNAME and virtualenvs path to match your path.
sudo nano /etc/systemd/system/gunicorn.service
-
[Unit] Description=Gunicorn instance to serve cal_service After=network.target [Service] User=root Group=apache WorkingDirectory=/home/eventapi/upstate_tech_cal_service Environment="PATH=/home/USERNAME/.local/share/virtualenvs/upstate_tech_cal_service-########/bin" ExecStart=/home/USERNAME/.local/share/virtualenvs/upstate_tech_cal_service-########/bin/gunicorn --workers 3 --log-file /var/log/gunicorn.log --log-level error --bind unix:/var/run/cal_service.sock -m 007 app:app [Install] WantedBy=multi-user.target
- Save and reload the new systemd daemon "unit file" using
sudo systemctl daemon-reload
- To make any future edits to the gunicorn systemd unit file, use
systemctl edit --full gunicorn.service
and be sure to reload usingsudo systemctl daemon-reload
- Start the Gunicorn systemd daemon using
systemctl restart gunicorn
- Verify it's running by using
systemctl status gunicorn
and check that /var/run/cal_service.sock exists. You can also use a tool likehtop
to see there are 3 active/worker gunicorn threads
- Configure an Nginx or Apache to "talk" to the gunicorn via the respective "proxy" directive(s)
- Apache Example
<VirtualHost *:443> UseCanonicalName On ServerName events.openupstate.org DocumentRoot /home/eventapi/public_html DirectoryIndex index.html ErrorLog /var/log/httpd/events.openupstate.org_error_log CustomLog /var/log/httpd/events.openupstate.org_access_log combined ProxyPass /api/ unix:/var/run/cal_service.sock|http://events.openupstate.org/api/ <Directory /home/eventapi/public_html> Options -Indexes +IncludesNOEXEC +SymLinksifOwnerMatch +ExecCGI allow from all AllowOverride None Include /home/eventapi/public_html/.htaccess </Directory> # HSTS to force browsers to always ask for https Header always set Strict-Transport-Security "max-age=31536000;" SSLCertificateFile /etc/letsencrypt/live/events.openupstate.org/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/events.openupstate.org/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf # Enable Gzip Compression AddOutputFilterByType DEFLATE application/json+ld application/json text/css text/html application/x-javascript application/javascript text/javascript </VirtualHost>
- Nginx Virtual Host Example - modified from Boban, and not tested
server { server_tokens off; listen 443 ssl; server_name events.openupstate.org; ssl_certificate /etc/letsencrypt/live/events.openupstate.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/events.openupstate.org/privkey.pem; access_log /var/log/nginx/access.myserver.log; error_log /var/log/nginx/error.myserver.log; # Enable Gzip Compression gzip on; gzip_types application/json+ld application/json text/css text/html application/x-javascript application/javascript text/javascript; location /api { include proxy_params; proxy_pass http://unix:/var/run/cal_service.sock; } }
- Apache Example
- Create a Gunicorn log file for the web server and the web server user may need permissions to write to it,
sudo touch /var/log/gunicorn.log && chown apache:apache /var/log/gunicorn.log && chmod g+w /var/log/gunicorn.log
- Setup gunicorn as a systemd daemon. Change "apache" to "nginx" in this file if you're using Nginx, and update the USERNAME and virtualenvs path to match your path.
- https://djangodeployment.com/2016/11/30/how-to-setup-apache-with-gunicorn/
- predis/predis#277
- https://axilleas.me/en/blog/2013/selinux-policy-for-nginx-and-gitlab-unix-socket-in-fedora-19/
- https://stackoverflow.com/q/36527427
- http://vicch.github.io/pkb/programming/book/servers_for_hackers.html
- http://dev.prodigi.us/post/python-gunicorn-apache-simple-and-performant-method-deploy-your-django-projects/
- https://www.vioan.eu/blog/2016/10/10/deploy-your-flask-python-app-on-ubuntu-with-apache-gunicorn-and-systemd/
- https://www.digitalocean.com/community/tutorials/how-to-serve-flask-applications-with-gunicorn-and-nginx-on-centos-7
- https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04
- https://pipenv.pypa.io/en/latest/install/