Skip to content

Instantly share code, notes, and snippets.

@Siltaar
Forked from pyguerder/ Django-on-OVH-tutorial.md
Last active November 12, 2022 19:01
Show Gist options
  • Save Siltaar/9441a525d3a580311035fa2f3f431baa to your computer and use it in GitHub Desktop.
Save Siltaar/9441a525d3a580311035fa2f3f431baa to your computer and use it in GitHub Desktop.
Installation de Django sur un hébergement mutualisé OVH
Options +ExecCGI
AddHandler cgi-script .cgi
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ django.cgi/$1 [QSA,L]

OVH permet l'exécution du code Python sur son hébergement mutualisé. Il est possible d'utiliser (en 2018) Python 3.4.2.

La version de Django la plus intéressante à utiliser avec Python 3.4 est la 1.11, car c'est une version étendue dont le support se prolongera jusqu'en 2020 alors que la 2.0 ne sera supportée que jusqu'en 2019, et que la 2.1 ne supportera pas Python 3.4 :

Dans un fichier requirements.txt, préciser :

    Django = 1.11.*

Puis installer vos requirements.txt (y compris tous modules complémentaire) via :

    pip3 install --root . -r requirements.txt

Dans votre dossier racine de projet, contenant manage.py et django.cgi.

L'arborescence proposée pour le code est la suivante :

/
├ projects/
│ ├ home/user/.local/lib/python3.4/site-packages
│ └ app/
│   ├ django_app/
│   | ├ __init__.py
│   | ├ settings.py
│   | ├ urls.py
│   | └ wsgi.py
│   ├ monsite/
│   | ├ migrations/
│   | ├ static/
│   | ├ template/
│   | ├ __init__.py
│   | ├ admin.py
│   | ├ models.py
│   | ├ tests.py
│   | ├ urls.py
│   | └ views.py
│   ├ manage.py
│   ├ requirements.txt
│   ├ git_bundle_scp.sh
│   └ database.sqlite
└ www/
  ├ static/
  │ ├ admin/
  │ │ ├ css/
  │ │ ├ img/
  │ │ └ js/
  │ └ monsite/
  │   ├ style.css
  │   └ favicon.png
  ├ django.cgi
  ├ .htaccess
  ├ sitemap.gz
  └ robots.txt

Le code de Django se place donc dans le dossier /projects/home/$user/.local/lib/python3.4/site-packages et le code « maison » dans le dossier /projects/app. Il est possible de personnaliser cela grâce aux instructions sys.path.append du fichier django.cgi.

Ces instructions sont également à adapter en fonction du nom de votre compte OVH (moncompte dans le fichier ci-joint). En cas de doute, vous pouvez obtenir cette information en créant dans le dossier www un fichier PHP contenant <?php echo getcwd(); ?>.

Une fois le tout fonctionnel en local chez vous, zipper et uploader le tout.

Le fonctionnement repose sur les fichiers /www/.htaccess et /www/django.cgi donnés ci-joints.

Il est essentiel que les permissions du fichier /www/django.cgi soient 755 ou supérieures. Le problème est que le serveur OVH remet les permissions à 604 dès que le fichier est modifié. Pensez-y quand vous rencontrez des erreurs 500 !

Astuce : si vous hébergez votre site sur un contrat start10m (donc avec 10 Mo d'espace disque), il est tout-à-fait possible de faire fonctionner Django. Commencez par supprimer les dossiers correspondant aux traductions que vous n'utilisez pas, dans les répertoires /locale/. Pour ma part, je ne garde que les dossiers /locale/en. Le dossier Django-1.6.10/django passe alors de 26 Mo à 6 Mo et il vous reste donc 4 Mo pour héberger votre code, votre base de données et les fichiers statiques. Cependant, par défaut, Python va stocker les fichiers bytecode (*.pyc) et ceux-ci réduiront d'autant l'espace disponible pour l'hébergement. Les lignes suivantes, à ajouter au fichier django.cgi, permettent d'empêcher Python de stocker ces fichiers (au prix d'une réduction des performances) :

os.environ['PYTHONDONTWRITEBYTECODE'] = '1'
sys.dont_write_bytecode = True

N'oubliez pas de configurer les variables ALLOWED_HOSTS au(x) bon(s) nom(s) de domaine et DEBUG et TEMPLATE_DEBUG à False dans /projects/app/django_app/settings.py.

La méthode présentée ici permet d'installer un site Django sur un hébergement mutualisé OVH.

Lisez d'abord le fichier README puis copiez les fichiers .htaccess et django.cgi vers votre hébergement, ainsi que le code source de Django et le code source de votre site web.

#!/usr/bin/python3 -Ou
# encoding: utf-8
import os, sys, pprint
OVH_PREFIX = '/homez.17/$ovh_user/$project_name/' # À modifier
ENV_PREFIX = 'home/$local_user/.local/' # À modifier
SITE_PACKAGES_PREFIX = 'lib/python3.5/site-packages/' # À modifier
sys.path.insert(0, OVH_PREFIX + ENV_PREFIX + SITE_PACKAGES_PREFIX)
sys.path.insert(0, OVH_PREFIX + ENV_PREFIX + "bin/")
sys.path.insert(0, OVH_PREFIX)
os.environ['DJANGO_SETTINGS_MODULE'] = 'main_app.settings' # À modifier
def run_with_cgi(application):
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin.buffer
environ['wsgi.errors'] = sys.stderr.buffer
environ['wsgi.version'] = (1, 0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
if environ.get('HTTPS', 'off') in ('on', '1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
headers_set = []
headers_sent = []
def write(data):
if not headers_set:
raise AssertionError("write() before start_response()")
elif not headers_sent: # Before the first output, send the stored headers
status, response_headers = headers_sent[:] = headers_set
sys.stdout.write('Status: %s\r\n' % status)
for header in response_headers:
sys.stdout.write('%s: %s\r\n' % header)
sys.stdout.write('\r\n')
sys.stdout.buffer.write(data)
sys.stdout.flush()
def start_response(status, response_headers, exc_info=None):
if exc_info:
try:
if headers_sent: # Re-raise original exception if headers sent
raise (exc_info[0], exc_info[1], exc_info[2])
finally:
exc_info = None # avoid dangling circular ref
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status, response_headers]
return write
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result, 'close'):
result.close()
try:
from django.core.wsgi import get_wsgi_application
run_with_cgi(get_wsgi_application())
except Exception as exc:
print("Content-type: text/html\n\n")
print('<html><body><pre>')
print('<h1>Server Error 500 by django.cgi</h1>')
import django
print('<b>django.VERSION</b> :', django.VERSION)
print('<b>Python version</b> :', sys.version)
print('<b>sys.stdout.encoding</b> :', sys.stdout.encoding)
import datetime
print('<b>Exception datetime : </b>', datetime.now())
print(exc)
print(traceback.format_exc())
pprint.pprint(sys.path)
print('')
pprint.pprint(os.environ)
print('</pre></body></html>')
#!/bin/bash
# Send and deploy your last commits to OVH
# we need git bundle because Hébergés OVH can't access internet from SSH sessions
# A repository have been created first, from a full bundle on the Hébergé
git bundle create prj.bundle last_bundle..mastergit # you need a tag 'last_bundle' already set
tag -f last_bundle master # sets the tag for next bundle
scp prj.bundle [email protected]:
CMDS=$(cat <<EOF
cd prj
git pull
./manage.py migrate
./manage.py collectstatic --no-input
EOF
)
ssh [email protected] "$CMDS"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment