Turbogears with Apache - jordy33/turbogears_tutorial GitHub Wiki

Setup Server

Login to your AWS ubuntu user using .pem file Update Server

sudo apt-get update
sudo apt-get upgrade

Allow to login with password:

sudo vim /etc/ssh/sshd_config

set password auth to yes

PasswordAuthentication yes

Restart service

sudo systemctl restart sshd

Create a wsgi user

sudo adduser wsgi
sudo usermod -aG sudo wsgi

Log with wsgi user

Installing Python 3.5.2

sudo apt-get install xz-utils
sudo apt-get install build-essential
sudo apt-get install libssl-dev
sudo apt-get install libsqlite3-dev
mkdir ~/python_src
cd python_src
wget https://www.python.org/ftp/python/3.5.2/Python-3.5.2.tar.xz
tar xf Python-3.5.2.tar.xz 
cd Python-3.5.2
./configure --enable-shared --prefix=/home/wsgi/Python-3.5.2 --with-ensurepip=install
make
make install

Now Python3 files are located in ~ directory

wsgi@ip-172-31-22-232:~$ ls
Python-3.5.2  python_src

Edit ~/.bashrc and insert the following

sudo vim ~/.bashrc

Paste the following:

export PATH=/home/wsgi/Python-3.5.2/bin:$PATH
export LD_LIBRARY_PATH=/home/wsgi/Python-3.5.2/lib
export LD_RUN_PATH=/home/wsgi/Python-3.5.2/lib

Log out and login, now you should see python3 with new date

python3

You should see:

Python 3.5.2 (default, May 14 2018, 17:08:12) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 

Apache Install

sudo apt-get install apache2

In a web browser: http:/// you should see apache page

Install Python 3 mod_wsgi

sudo apt-get install libapache2-mod-wsgi-py3

Check that your module is enabled

apache2ctl -M |grep -i wsgi

Compiling mod_wsgi last Version

Installing apache development tools

sudo apt install apache2-dev 
sudo apt-get install libtool    

Compiling mod_wsgi

mkdir ~/mod_wsgi_src
cd ~/mod_wsgi_src 
wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.6.4.tar.gz
tar xvzf 4.6.4.tar.gz 
cd mod_wsgi-4.6.4/
./configure --with-python=/home/wsgi/Python-3.5.2/bin/python3
make 
sudo service apache2 stop   
sudo rm /usr/lib/apache2/modules/mod_wsgi.so
cd src/server/.libs/
sudo cp mod_wsgi.so /usr/lib/apache2/modules/.
sudo chmod 644 /usr/lib/apache2/modules/mod_wsgi.so

Validate library

ldd mod_wsgi.so

Check the date of the new library

export LD_LIBRARY_PATH=""
cd /usr/lib/apache2/modules
ldd mod_wsgi.so

One line must say:

libpython3.5m.so.1.0 => /home/wsgi/Python-3.5.2/lib/libpython3.5m.so.1.0 (0x00007f4bf0403000)

If everything ok, logout and login then:

sudo service apache2 start

Upgrade pip and install virtualenv

pip3 install --upgrade pip
pip3 install virtualenv

Creating local directory to hold files

mkdir ~/public_wsgi
cd ~/public_wsgi
sudo chgrp -R www-data /home/wsgi/public_wsgi/
sudo chmod -R g+rwxs /home/wsgi/public_wsgi/

Install virtualenvwrapper

pip3 install virtualenvwrapper

Edit ~/.bashrc

export WORKON_HOME=/home/wsgi/public_wsgi/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/home/wsgi/Python-3.5.2/bin/python3
export PROJECT_HOME=$HOME/Devel
export p3=`which python3`
source /home/wsgi/Python-3.5.2/bin/virtualenvwrapper.sh

Logout and login

MySQL Install

sudo apt-get -y install mysql-server
# pick user root password
sudo apt-get -y install mysql-client

Dev for MySQL

sudo apt-get install libmysqlclient-dev

mysql -u root -p

CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'mypassword';
GRANT ALL PRIVILEGES ON * . * TO 'myuser'@'localhost';

mysql -u myuser -p

create database cygnus

Create virtual environment

mkvirtualenv --no-site-packages --python=$p3 tg2env
pip3 install tg.devtools mysqlclient
pip3 uninstall webob
pip3 install webob==1.7.4
pip3 install nose
pip3 install coverage

Installing HAproxy Ubuntu 16.04 install

sudo apt-get update
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot 
sudo certbot certonly --standalone -d dudewhereismy.mx -d www.dudewhereismy.mx -d sun.dudewhereismy.mx -d pluto.dudewhereismy.mx -d venus.dudewhereismy.mx -d mercury.dudewhereismy.mx -d earth.dudewhereismy.mx -d cygnus.dudewhereismy.mx -d stomp.dudewhereismy.mx -d cerberus.dudewhereismy.mx -d orion.dudewhereismy.mx -d jupiter.dudewhereismy.mx -d mars.dudewhereismy.mx
sudo mkdir -p /etc/haproxy/certs
DOMAIN='dudewhereismy.mx' sudo -E bash -c 'cat /etc/letsencrypt/live/$DOMAIN/fullchain.pem /etc/letsencrypt/live/$DOMAIN/privkey.pem > /etc/haproxy/certs/$DOMAIN.pem'
# Certs for RabbitMQ
mkdir /home/wsgi/certs
sudo cp /home/wsgi/Python-3.5.2/lib/python3.5/site-packages/pip/_vendor/certifi/cacert.pem  /home/wsgi/certs/.
sudo cp /etc/letsencrypt/live/dudewhereismy.mx/cert.pem /home/wsgi/certs/.
sudo cp /etc/letsencrypt/live/dudewhereismy.mx/privkey.pem /home/wsgi/certs/.
sudo chmod -R go-rwx /etc/haproxy/certs
sudo apt-get install haproxy
sudo vim /etc/haproxy/haproxy.cfg

Insert the following code:

global
  log         127.0.0.1 syslog
  maxconn     1000
  user        haproxy
  group       haproxy
  daemon
  tune.ssl.default-dh-param 4096
  ssl-default-bind-options no-sslv3 no-tls-tickets
  ssl-default-bind-ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH


defaults
  log  global
  mode  http
  option  httplog
  option  dontlognull
  option  http-server-close
  option  forwardfor except 127.0.0.0/8
  option  redispatch
  option  contstats
  retries  3
  timeout  http-request 10s
  timeout  queue 1m
  timeout  connect 10s
  timeout  client 1m
  timeout  server 1m
  timeout  check 10s

###########################################
#
# HAProxy Stats page
#
###########################################
listen stats
  bind *:9090
  mode  http
  maxconn  10
  stats  enable
  stats  hide-version
  stats  realm Haproxy\ Statistics
  stats  uri /
  stats  auth admin:GPSc0ntr0l1

###########################################
#
# Front end for all
#
###########################################
frontend ALL
  bind   *:80
  bind   *:443 ssl crt /etc/haproxy/certs/dudewhereismy.mx.pem
  mode   http
# Add CORS headers when Origin header is present
    capture request header origin len 128
    http-response add-header Access-Control-Allow-Origin %[capture.req.hdr(0)] if { capture.req.hdr(0) -m found }
    rspadd Access-Control-Allow-Headers:\ Origin,\ X-Requested-With,\ Content-Type,\ Accept  if { capture.req.hdr(0) -m found }
  # Define path for lets encrypt
  acl is_letsencrypt path_beg -i /.well-known/acme-challenge/
  use_backend letsencrypt if is_letsencrypt

  # Define hosts
  acl host_sun hdr(host) -i sun.dudewhereismy.mx
  acl host_earth hdr(host) -i earth.dudewhereismy.mx
  acl host_pluto hdr(host) -i pluto.dudewhereismy.mx
  acl host_mercury hdr(host) -i mercury.dudewhereismy.mx
  acl host_venus hdr(host) -i venus.dudewhereismy.mx
  acl is_options method OPTIONS  
  use_backend venus_cors_headers if METH_OPTIONS host_venus
  use_backend earth_cors_headers if METH_OPTIONS host_earth
  # Direct hosts to backend
  use_backend sun if host_sun
  use_backend earth if host_earth
  use_backend pluto if host_pluto
  use_backend mercury if host_mercury
  use_backend venus if host_venus

  # Redirect port 80 to 443
  # But do not redirect letsencrypt since it checks port 80 and not 443
  redirect scheme https code 301 if !{ ssl_fc } !is_letsencrypt

###########################################
#
# Back end letsencrypt
#
###########################################
backend letsencrypt
  server letsencrypt 127.0.0.1:54321

###########################################
#
# Back end for foo
#
###########################################

backend sun
  rspadd Access-Control-Allow-Origin:\ *
  rspadd Access-Control-Max-Age:\ 31536000
  balance         roundrobin
  option          httpchk GET /check
  http-check      expect rstring ^UP$
  default-server  inter 10s fall 3 rise 2
  server          sun1 127.0.0.1:8080 check

backend earth
  rspadd Access-Control-Max-Age:\ 31536000
  rspadd Access-Control-Allow-Credentials:\ true
  rspadd Access-Control-Allow-Methods:\ GET,\ HEAD,\ OPTIONS,\ POST,\ PUT
  rspadd Access-Control-Allow-Headers:\ Origin,\ Accept,\ X-Requested-With,\ Content-Type,\ Access-Control-Request-Method,\ Access-Control-Request-Headers,\ Authorization
  balance         roundrobin
  option          httpchk GET /check
  http-check      expect rstring ^UP$
  default-server  inter 10s fall 3 rise 2
  server          earth1 127.0.0.1:8082 check

backend pluto
  rspadd Access-Control-Allow-Origin:\ *
  rspadd Access-Control-Max-Age:\ 31536000
  balance         roundrobin
  option          httpchk GET /check
  http-check      expect rstring ^UP$
  default-server  inter 10s fall 3 rise 2
  server          pluto1 127.0.0.1:8084 check

backend mercury
  balance         roundrobin
  option          httpchk GET /check
  http-check      expect rstring ^UP$
  default-server  inter 10s fall 3 rise 2
  server          mercury1 127.0.0.1:8086 check
  server          mercury2 127.0.0.1:8087 check

backend venus
  rspadd Access-Control-Max-Age:\ 31536000
  rspadd Access-Control-Allow-Credentials:\ true
  rspadd Access-Control-Allow-Methods:\ GET,\ HEAD,\ OPTIONS,\ POST,\ PUT
  rspadd Access-Control-Allow-Headers:\ Origin,\ Accept,\ X-Requested-With,\ Content-Type,\ Access-Control-Request-Method,\ Access-Control-Request-Headers,\ Authorization
  balance         roundrobin
  option          httpchk GET /check
  http-check      expect rstring ^UP$
  default-server  inter 10s fall 3 rise 2
  server          venus1 127.0.0.1:8088 check


backend venus_cors_headers
errorfile 503 /root/venus.http 

backend earth_cors_headers
errorfile 503 /root/earth.http 

Create venus.http and insert the following (leave the two empty rows):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://mercury.dudewhereismy.mx, https://sun.dudewhereismy.mx 
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,PATCH,OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
Access-Control-Max-Age: 31536000
Access-Control-Allow-Credentials: true
Content-Length: 0
Cache-Control: private


Create earth.http and insert the following (leave the two empty rows):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://sun.dudewhereismy.mx
Access-Control-Allow-Methods: GET,PUT,POST,DELETE,PATCH,OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
Access-Control-Max-Age: 31536000
Access-Control-Allow-Credentials: true
Content-Length: 0
Cache-Control: private

HAproxy Run

sudo service haproxy restart
sudo service haproxy reload

Installing RabbitMQ 3.7.5 Follow directions from here

Install plugins

sudo rabbitmqctl status | grep RabbitMQ
sudo rabbitmq-plugins enable rabbitmq_management
sudo rabbitmq-plugins enable rabbitmq_web_stomp
sudo rabbitmqctl add_user admin pass12345
sudo rabbitmqctl set_user_tags admin administrator
sudo rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
sudo rabbitmqctl delete_user guest
sudo service rabbitmq-server stop
sudo service rabbitmq-server start
sudo service rabbitmq-server status

Create User:

sudo rabbitmqctl add_user dwim gpscontrol1
sudo rabbitmqctl set_user_tags dwim administrator
sudo rabbitmqctl set_permissions -p / dwim ".*" ".*" ".*"

Check service:

http://<ip>:15672

Configure Rabbit:

sudo vim /etc/rabbitmq/rabbitmq.conf

Insert the following

stomp.listeners.tcp.default = 0.0.0.0:61613
web_stomp.ssl.port = 15671
web_stomp.ssl.ip = 0.0.0.0
web_stomp.ssl.backlog  = 1024
web_stomp.ssl.certfile   = /home/wsgi/certs/cert.pem
web_stomp.ssl.keyfile    = /home/wsgi/certs/privkey.pem
web_stomp.ssl.cacertfile = /home/wsgi/certs/cacert.pem
management.listener.port = 15672
management.listener.ip   = 0.0.0.0
management.listener.ssl  = true
management.listener.ssl_opts.cacertfile = /home/wsgi/certs/cacert.pem
management.listener.ssl_opts.certfile   = /home/wsgi/certs/cert.pem
management.listener.ssl_opts.keyfile    = /home/wsgi/certs/privkey.pem

If the above don't work, insert first config example from here

ONLY if RabbitMQ version is < 3.7.5 insert the following

[
  {rabbitmq_stomp, [{tcp_listeners, [{"0.0.0.0", 61613},
                                     {"::1",       61613}]}]},
  {rabbitmq_web_stomp,
      [{ssl_config, [{port,       15671},
                     {backlog,    1024},
                     {ip, "0.0.0.0"},
                     {certfile,   "/home/wsgi/certs/cert.pem"},
                     {keyfile,    "/home/wsgi/certs/key.pem"},
                     {cacertfile, "/home/wsgi/certs/cacert.pem"}
                     ]}]}
].

Create Turbogears project

cd ~/public_wsgi
gearbox quickstart -s -a -m cygnus 
cd cygnus

Edit and change development.ini:

debug=false
host=0.0.0.0
sqlalchemy.url = mysql://user:[email protected]/cygnus

Create file app.wsgi

APP_CONFIG = "/home/wsgi/public_wsgi/cygnus/development.ini"

#Setup logging
import logging.config
logging.config.fileConfig(APP_CONFIG)

#Load the application
from paste.deploy import loadapp
application = loadapp('config:%s' % APP_CONFIG)

Install Distribution

pip install -e .

Install Environment

gearbox setup-app -c development.ini

Edit ports

sudo vim /etc/apache2/ports.conf

Add another port

Listen 80
Listen 8080
Listen 8090

Create Virtual Host

sudo vim /etc/apache2/sites-available/tg2.conf

Insert the following

<VirtualHost *:8080>
 ServerName cygnus
 WSGIProcessGroup cygnus
 WSGIDaemonProcess cygnus user=wsgi group=wsgi threads=4 python-path=/home/wsgi/public_wsgi/.virtualenvs/tg2env/lib/python3.5/site-packages
 WSGIScriptAlias / /home/wsgi/public_wsgi/cygnus/app.wsgi
 #Serve static files directly without TurboGears
 Alias /images  /home/wsgi/public_wsgi/cygnus/cygnus/public/images
 Alias /css /home/wsgi/public_wsgi/cygnus/cygnus/public/css
 Alias /js /home/wsgi/public_wsgi/cygnus/cygnus/public/js
 <Directory /home/wsgi/public_wsgi/cygnus/>
     WSGIProcessGroup cygnus
     WSGIApplicationGroup %{GLOBAL}
     WSGIScriptReloading On
     Require all granted
 </Directory>
 ErrorLog ${APACHE_LOG_DIR}/error.log
 CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
WSGIPythonHome /home/wsgi/public_wsgi/.virtualenvs/tg2env
WSGIPythonPath /home/wsgi/public_wsgi/.virtualenvs/tg2env/lib/python3.5

Apache Disable Default site

sudo a2dissite 000-default

Enable Site

sudo a2ensite tg2

Restart Service

sudo service apache2 reload

Test Site

http://<ip>:8080/

Test for errors

sudo apache2ctl configtest
sudo tail -20 /var/log/apache2/error.log

Add another site

Important!!

For the second site use the same virtual environment tg2env. Don't create a new one.

Create the project with quickstart and then install distribution and environment in the directory ~/public_wsgi.

Edit /etc/apache2/sites-available/tg2.conf

<VirtualHost *:8080>
 ServerName sun
 WSGIPassAuthorization On
 WSGIProcessGroup sun
 WSGIDaemonProcess sun user=wsgi group=wsgi threads=4 python-path=/home/wsgi/public_wsgi/.virtualenvs/tg2env/lib/python3.5/site-packages
 WSGIScriptAlias / /home/wsgi/public_wsgi/python.sun/app.wsgi
 <Location />
 WSGIPassAuthorization On
 </Location>
 #Serve static files directly without TurboGears
 Alias /images  /home/wsgi/public_wsgi/python.sun/pythonsun/public/images
 Alias /css /home/wsgi/public_wsgi/python.sun/pythonsun/public/css
 Alias /js /home/wsgi/public_wsgi/python.sun/pythonsun/public/js
<Directory /home/wsgi/public_wsgi/python.sun/>
     WSGIProcessGroup sun
     WSGIPassAuthorization On
     WSGIApplicationGroup %{GLOBAL}
     WSGIScriptReloading On
     Require all granted
</Directory>
 ErrorLog ${APACHE_LOG_DIR}/error.log
 CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:8082>
 ServerName earth
 WSGIProcessGroup earth
 WSGIDaemonProcess earth user=wsgi group=wsgi threads=4 python-path=/home/wsgi/.virtualenvs/public_wsgi/tg2env/lib/python3.5/site-package
 WSGIScriptAlias / /home/wsgi/public_wsgi/python.earth/app.wsgi
 <Location />
 WSGIPassAuthorization On
 </Location>
 #Serve static files directly without TurboGears
 Alias /images  /home/wsgi/public_wsgi/python.earth/pythonearth/public/images
 Alias /css /home/wsgi/public_wsgi/python.earth/pythonearth/public/css
 Alias /js /home/wsgi/public_wsgi/python.earth/pythonearth/public/js
 <Directory /home/wsgi/public_wsgi/python.earth/>
     WSGIProcessGroup earth
     WSGIApplicationGroup %{GLOBAL}
     WSGIScriptReloading On
     Require all granted
 </Directory>
 ErrorLog ${APACHE_LOG_DIR}/error.log
 CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
WSGIPythonHome /home/wsgi/public_wsgi/.virtualenvs/tg2env
WSGIPythonPath /home/wsgi/public_wsgi/.virtualenvs/tg2env/lib/python3.5

Important!!

Modify config/app_cfg.py with full directory for the passwd_file

base_config.sa_auth.authenticators = [('htpasswd', HTPasswdPlugin('/home/wsgi/public_wsgi/python.sun/passwd_file', plain_check))]
⚠️ **GitHub.com Fallback** ⚠️