# Propel
### About
Propel allows you to deploy multiple Python/PHP/HTML apps (sites)
on a single server, run scripts and background workers.
#### - Why did I create Propel ?
The main reason, was to deploy multiple Flask apps on a single DigitalOcean VM
effortlessly. The other reason, was to make it easy to deploy applications.
---
##TLDR; Install and run Propel (simple Flask example)
1. On the server you intend to run your applications, install Propel
by running the following commands:
pip install propel
propel-setup
1. CD in the directory that contains your app, and create the following files:
-app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello Propel!"
-requirements.txt
Flask
-propel.yml
virtualenv:
name: "mysitename.com"
web:
-
name: "mysitename.com"
application: "app:app"
1. Inside of your app directory run:
propel -w
1. Now go to `http://mysitename.com`
1. Profit! (or your money back)
---
### Features
#### Deploy Python
Propel allows you deploy multiple Python sites/applications (Flask, Django)
by isolating each app into its own virtualenv, using Virtualenvwrapper, then
puts it online using Gunicon+Gevent under Supervisor, to make sure it's always up.
Then uses NGinx as proxy to access the sites.
#### - Deploy PHP/HTML
Propel is not limited to only Python app, it can deploy PHP/HTML sites too
using PHP-FPM.
#### - Script and Workers
Besides deploying sites/apps. Propel can run scripts before and after deployment.
Run other scripts individually. And background running scripts (workers) with Supervisor.
#### - Maintenance mode
Propel also has a maintenance mode that will display a maintenance page when the
website is down for maintenance or is being deployed.
#### - Packages
Propel makes use of the following packages:
- Gunicorn
- Supervisor
- Gevent
- Virtualenvwrapper
- PyYaml
- Jinja2
(They will be installed automatically, so no need to do it manually)
Requirements:
- Nginx
- php-fpm
- git (not really required, but good to have)
---
## Install & Setup
pip install propel
After installing *propel* for the first time, run the following command to setup
Supervisor conf and logs directories compatible to propel.
propel-setup
** You may need root admin
You may also need to install some other packages based on your system.
Once done, you should be good to go.
---
## How to use
**Propel** works in the current working directory (CWD). You must have the file
`propel.yml` in order for it to execute properly.
So you must `cd` into the directory that contains your `propel.yml`
Let's say my application is at: `/home/myapp.com/www`
cd /home/myapp.com/www
From there you can run the commands below:
#### propel -w | --websites
To deploy websites. It will also run scripts.before_web and scripts.after_web
propel -w
### propel -s | --scripts [name, [names ...]]
To run a custom script
propel --scripts my_script_name
Run multiple scripts
propel --scripts my_script_name another_script a_third_script
#### propel -k | --workers
To run workers in the background using Supervisor
propel --workers
### propel -x | --undeploy
To undeploy all. It will remove sites, scripts, workers, and destroy the virtualenv
propel --undeploy
### propel -m | --maintenance on|off
To activate/deactivate the site maintenance page
propel --maintenance on
propel --maintenance off
### propel -c | --create [name]
To create a new application bare repository ready to push application to.
propel -c mynewapp
# or
# It will place the repository inside of /myother-dir
propel -c mynewapp --basedir=/myother-dir
### propel --ps
To list all the running applications. Running applications are active apps on Supervisor.
propel -ps
---
# propel.yml
`propel.yml` is a config file that tells propel what to deploy and run.
### How does it work ?
## WEB
#### A simple flask app deployment would look something like this:
virtualenv:
name: "mynewsite.com"
web:
-
name: "mynewsite.com"
application: "run:flask_app"
nginx:
aliases:
"/static": "static"
**For Python application/sites, `virtualenv` is required. The requirements.txt must also exist to install the necessary packages.
Upon deploying a Python app, Propel will the following:
- Instantly set the site on maintenance mode. So when a visitor comes, the will a maintenance page
- create the virtualenv
- install the requirements.txt in the virtualenv
- create a random port and assign it to Gunicorn. By default it will assign `gevent`
as the worker-class for Gunicorn, set the numbers of workers and threads.
- add the Gunicorn command to Supervisor for process monitoring
- create the Nginx config file for the site and use it as proxy to point to the Gunicorn instance.
- ...
- Profit!
#### A basic PHP/HTML site would have the following structure. PHP-FPM is required.
web:
-
name: "my-php-html-site.com"
**For PHP/HTML site we don't need `virtualenv`.
Upon deploying, it will create the NGINX config file and use PHP-FPM.
#### Description of the config above
- **virtualenv**: A dict of the virtualenv info. It required for Python application
- **name**: The name of the virtualenv
- **web**: A list of dict website to deploy
- **name**: The website name
- **application**: The application path in the current directory: 'module:app'. Only for python
- **nginx**: A dict of Nginx config
- **aliases**: A dict of aliases to use in NGINX. The key is the nginx location, the value is the path
- "/static": "my-static"
**Concerning paths**
By default, all paths are relative to the current directory. So let's say you are under: `/home/myapp.com/www`, setting the aliases: `/static: "my-static"`, it will automatically add the current directory to the path. The alias will turn into: `/home/myapp.com/www/my-static`
That's how it would be in the Nginx file:
location /static {
alias /home/myapp.com/www/my-static
}
** To refer an absolute path, you must prefix the path with a slash `/`
#### Example of multiple sites
The same above, but with multiple sites and multiple aliases
virtualenv:
name: "mynewsite.com"
web:
-
name: "mynewsite.com"
application: "run:flask_app"
nginx:
aliases:
"/static": "mytothersite/static"
"/photos": "mytothersite/photos"
-
name: "my-php-html-site.com"
nginx:
root_dir: "html"
For the `my-php-html-site.com` the root dir is the `html` directory that's in the current working directory.
The above conf, will deploy multiple sites. The python app will be deployed in the virtualenv, the php/html site will be deployed as is.
## WEB: Advanced config
You can add more NGINX and Gunicorn config. Gunicorn config is only for Python app.
virtualenv:
name: "mynewsite.com"
rebuild: False
directory: ""
pip_options: ""
web:
-
name: "mynewsite.com"
application: "run:flask_app"
remove: False
exclude: False
environment: KEY1="value1",KEY2="value2"
# Nginx Config
nginx:
server_name: "site1.com admin.site2.com"
port: 80
root_dir: ""
logs_dir: ""
aliases:
"/static": "mysite/static"
force_non_www: True
force_www: False