Setup a production-like environment in vagrant

- We already use Daphne and channels to prepare the future use of
  websockets.
- The app is served behind an nginx reverse-proxy
- The services we need are managed by systemctl

The production-like running instance of GestionÉvénementiel can be
accessed on localhost:8080 outside vagrant.
This commit is contained in:
Martin Pépin 2017-05-16 16:13:31 +01:00
parent 981c5cade5
commit e64c3d0b37
8 changed files with 193 additions and 43 deletions

7
evenementiel/asgi.py Normal file
View file

@ -0,0 +1,7 @@
import os
from channels.asgi import get_channel_layer
if "DJANGO_SETTINGS_MODULE" not in os.environ:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "evenementiel.settings")
channel_layer = get_channel_layer()

2
evenementiel/routing.py Normal file
View file

@ -0,0 +1,2 @@
# Nothing yet
channel_routing = []

View file

@ -43,6 +43,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'bootstrapform',
'debug_toolbar',
'widget_tweaks',
@ -82,21 +83,19 @@ TEMPLATES = [
},
]
WSGI_APPLICATION = 'evenementiel.wsgi.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts": [(
"redis://:{passwd}@{host}:{port}/{db}"
.format(passwd="dummy", host="localhost", port=6379, db=0)
)],
},
"ROUTING": "evenementiel.routing.channel_routing",
}
}
# Database
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
# # MySQL
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
# PostGreSQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
@ -108,6 +107,9 @@ DATABASES = {
}
}
STATIC_ROOT = "/srv/GE/static/"
MEDIA_ROOT = "/srv/GE/media/"
# Password validation
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators

View file

@ -1,25 +1,102 @@
#!/bin/sh
#!/bin/bash
# Configuration de la base de données. Le mot de passe est constant car c'est
# pour une installation de dév locale qui ne sera accessible que depuis la
# machine virtuelle.
# The credentials of the database. Can be public since they will only be used in
# the local development environment
DBUSER="event_gestion"
DBNAME="event_gestion"
DBPASSWD="4KZt3nGPLVeWSvtBZPsd9jdssdJMds78"
# Installation de paquets utiles
# Not critical either
REDIS_PASSWD="dummy"
# It is used in quite a few places
SETTINGS="evenementiel.settings_dev"
# ---
# Installs the dependencies
# ---
# System packages
apt-get update && apt-get upgrade
apt-get install -y python3-pip python3-dev python3-venv libpq-dev postgresql \
postgresql-contrib libjpeg-dev
postgresql-contrib libjpeg-dev nginx redis-server
# Setup Database and User
# Python packages, in a virtual environment
sudo -H -u vagrant python3 -m venv ~vagrant/venv
sudo -H -u vagrant ~vagrant/venv/bin/pip install -U pip wheel
sudo -H -u vagrant ~vagrant/venv/bin/pip install -U -r /vagrant/requirements-devel.txt
# ---
# Setup the production-like environment
# ---
# Database and User
sudo -u postgres createdb $DBNAME
sudo -u postgres createuser -SDR $DBUSER
sudo -u postgres psql -c "ALTER USER $DBUSER WITH PASSWORD '$DBPASSWD';"
sudo -u postgres psql -c "ALTER USER $DBUSER CREATEDB;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DBNAME TO $DBUSER;"
# Mise en place du .bash_profile pour tout configurer lors du `vagrant ssh`
# The working directory for Daphne and cie
mkdir -p /srv/GE/{media,static}
chown -R vagrant:vagrant /srv/GE
# Nginx
cp /vagrant/provisioning/nginx.conf /etc/nginx/sites-available/ge.conf
if [ ! -h /etc/nginx/sites-enabled/ge.conf ]
then
# If the configuration file is not activated yet, activates it
ln -s /etc/nginx/sites-available/ge.conf /etc/nginx/sites-enabled/ge.conf
fi
rm -f /etc/nginx/sites-enabled/default # We do not need this
service nginx restart
# Daphne and the worker(s)
for service in {daphne,worker}.service
do
cp /vagrant/provisioning/$service /etc/systemd/system/$service
sed "s/{{DBUSER}}/$DBUSER/" -i /etc/systemd/system/$service
sed "s/{{DBNAME}}/$DBNAME/" -i /etc/systemd/system/$service
sed "s/{{DBPASSWD}}/$DBPASSWD/" -i /etc/systemd/system/$service
sed "s/{{SETTINGS}}/$SETTINGS/" -i /etc/systemd/system/$service
systemctl enable $service
systemctl start $service
done
# Redis
redis-cli CONFIG SET requirepass $REDIS_PASSWD
if [ ! $? ]
then
# In case the requirepass command failed, checks that it was because the
# password was already set *to the right value*.
redis-cli AUTH $REDIS_PASSWD
fi
redis-cli -a $REDIS_PASSWD CONFIG REWRITE
# ---
# Prepare Django
# ---
function venv_python {
sudo -H -u vagrant DJANGO_SETTINGS_MODULE=$SETTINGS \
DBUSER=$DBUSER DBNAME=$DBNAME DBPASSWD=$DBPASSWD \
~vagrant/venv/bin/python \
$@
}
cd /vagrant
venv_python manage.py collectstatic --noinput
venv_python manage.py migrate
unset venv_python
# ---
# Setup a friendly environment for the user
# ---
cat >> ~vagrant/.bashrc <<EOF
# On utilise les settings de développement
@ -37,24 +114,3 @@ cd /vagrant
source ~vagrant/venv/bin/activate
EOF
chown vagrant: ~vagrant/.bashrc
# On va dans /vagrant où se trouve le code
cd /vagrant
# Installation des dépendances python
# Notes :
# - Je ne comprends pas trop pourquoi j'ai besoin d'installer wheel, il devrait
# venir avec pip il me semble… Mais sans ça, l'installation de
# django-boostrap-form échoue.
# - A priori upgrade pip via pip est inutile au moment où j'écris ce script mais
# la version de pip de PyPi peut être mise à jour plus vite que celle des
# paquets Debian et on préfère la version la plus récente (ça nous a déjà posé
# des problèmes).
sudo -H -u vagrant python3 -m venv ~vagrant/venv
sudo -H -u vagrant ~vagrant/venv/bin/pip install -U pip wheel
sudo -H -u vagrant ~vagrant/venv/bin/pip install -U -r requirements-devel.txt
# Préparation de Django
sudo -H -u vagrant DJANGO_SETTINGS_MODULE='evenementiel.settings_dev' \
DBUSER=$DBUSER DBNAME=$DBNAME DBPASSWD=$DBPASSWD \
~vagrant/venv/bin/python manage.py migrate

View file

@ -0,0 +1,19 @@
Description="Gestion Événementiel - Daphne"
After=syslog.target
After=network.target
[Service]
Type=simple
User=vagrant
Group=vagrant
TimeoutSec=300
WorkingDirectory=/vagrant
Environment="DJANGO_SETTINGS_MODULE={{SETTINGS}}"
Environment="DBNAME={{DBNAME}}"
Environment="DBUSER={{DBUSER}}"
Environment="DBPASSWD={{DBPASSWD}}"
ExecStart=/home/vagrant/venv/bin/daphne -u /srv/GE/GE.sock \
evenementiel.asgi:channel_layer
[Install]
WantedBy=multi-user.target

40
provisioning/nginx.conf Normal file
View file

@ -0,0 +1,40 @@
upstream GE {
# Daphne listens on a unix socket
server unix:/srv/GE/GE.sock;
}
server {
listen 80;
server_name localhost;
# All the trafic is routed to Daphne
location ~ ^/ {
# A copy-paste of what we have in production
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-SSL-Client-Serial $ssl_client_serial;
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
proxy_set_header X-SSL-Client-S-DN $ssl_client_s_dn;
# Reverse-proxy
proxy_pass http://GE;
}
# Static files
location ~ ^/static/ {
root /srv/GE/static/;
access_log off;
add_header Cache-Control "public";
expires 7d;
}
# Uploaded media
location ~ ^/media/ {
root /srv/GE/static/;
access_log off;
add_header Cache-Control "public";
expires 7d;
}
}

View file

@ -0,0 +1,19 @@
[Unit]
Description="Gestion Événementiel - Worker"
After=syslog.target
After=network.target
[Service]
Type=simple
User=vagrant
Group=vagrant
TimeoutSec=300
WorkingDirectory=/vagrant
Environment="DJANGO_SETTINGS_MODULE={{SETTINGS}}"
Environment="DBNAME={{DBNAME}}"
Environment="DBUSER={{DBUSER}}"
Environment="DBPASSWD={{DBPASSWD}}"
ExecStart=/home/vagrant/venv/bin/python manage.py runworker
[Install]
WantedBy=multi-user.target

View file

@ -1,5 +1,10 @@
Django==1.11.*
psycopg2
asgi-redis
Pillow
channels
django-bootstrap-form==3.2.1
django-widget-tweaks
# Production specific
daphne