# Khaganat's web site ## Requirements * Python 3.6 or newer * pipenv * git * gettext ## Code formatting In order to have a single Python coding style, please use [black](https://github.com/psf/black). However, auto-generated files and parts of external projects should not be reformatted. ``` $ black $(find . -type f -name "*\.py" -not -path "*/migrations/*" -print) ``` ## Quick-start (development) ``` $ git clone https://git.khaganat.net/Tycho/khaganat-web.git khaganat-web $ cd khaganat-web $ vim .env $ PIPENV_VENV_IN_PROJECT=1 pipenv --three update $ pipenv run ./manage.py compilemessages ``` When editing the `.env` file, you should at least set `KHAGANAT_SECRET_KEY` to a random value, `KHAGANAT_DEBUG` to `"True"` and `KHAGANAT_HOSTNAMES` to `"localhost"`. To run this web application, you need a database. The simplest way is to download the one from the test server (`scp cipra.khaganat.net:/var/www/khaganat-web/db.sqlite3 db.sqlite3`). If you really want to start from scratch, you have to run the following commands: ``` $ pipenv run ./manage.py migrate $ pipenv run ./manage.py compilemessages $ pipenv run ./manage.py createsuperuser ``` Now that everything has been set-up, you may run Django's internal debug server. ``` $ pipenv run ./manage.py runserver ``` If you created the database from scratch, Django will show an error when visiting the home page. To fix it, you need to go to `/admin/` and create a page with the `default` flag on. ## Environment variables You can set the following variables in the `.env` file: * `KHAGANAT_SECRET_KEY` (required): Django's secret key, keep it secret (tip: generate one using `pipenv run python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'`). * `KHAGANAT_DEBUG`: Debug mode, default is false. * `KHAGANAT_HOSTNAMES`: Allowed hostnames, coma separated. * `KHAGANAT_LANGUAGE_CODE`: Language code, default is `fr`. * `KHAGANAT_TIME_ZONE`: Time zone, default is `Europe/Paris`. * `KHAGANAT_STATIC_URL`: URL for static files, default is `/static/`. * `KHAGANAT_STATIC_ROOT`: Absolute path to the directory where static files should be collected. Default is `None`. * `KHAGANAT_LOGS_MIN_DAYS`: Numbers of days before logs are hidden, default is 7. * `KHAGANAT_LOGS_MAX_DAYS`: Number of days before logs are published, default is 0. * `KHAGANAT_LOGIN_REDIRECT_URL`: URL to redirect after user login. Will be reversed, default is `index`. * `KHAGANAT_REGISTER_REQUIRE_VALIDATION`: require email validation upon registration, default is true. * `KHAGANAT_EMAIL_HOST`: The host to use for sending email, default is `localhost`. * `KHAGANAT_EMAIL_PORT`: Port to use for the SMTP server, default is `25`. * `KHAGANAT_EMAIL_HOST_USER`: Username to use for the SMTP server, default is empty (no authentication). * `KHAGANAT_EMAIL_HOST_PASSWORD`: Password to use for the SMTP server, default is empty. * `KHAGANAT_EMAIL_USE_STARTTLS`: Whether to use STARTTLS to connect to the SMTP server, default is `False`. * `KHAGANAT_EMAIL_USE_TLS`: Whether to use a TLS connection to the SMTP server, default is `False`. * `KHAGANAT_EMAIL_SUBJECT_PREFIX`: Subject-line prefix for email, default is empty. * `KHAGANAT_DEFAULT_FROM_EMAIL`: Default email address to use, default is `no-reply@localhost`. * `KHAGANAT_FORCE_HTTPS`: If True, enable the use of `KHAGANAT_HTTPS_HEADER_NAME` and `KHAGANAT_HTTPS_HEADER_VALUE` to set the `SECURE_PROXY_SSL_HEADER` configuration option. Default is `False`. * `KHAGANAT_HTTPS_HEADER_NAME`: Header name for `SECURE_PROXY_SSL_HEADER`, default is `HTTP_X_FORWARDED_PROTO`. * `KHAGANAT_HTTPS_HEADER_VALUE`: Header value for `SECURE_PROXY_SSL_HEADER`, default is `https`. * `KHAGANAT_NSFW_TAGS`: Coma-separated list of words that triggers the content warning in logs, default is `\#nsfw`. * `KHAGANAT_NSFW_NAME`: Name of the cookie holding the NSFW allowance, default is `nsfw_allowed`. * `KHAGANAT_INTERNAL_IPS`: List of IP considered as internal, coma separated, default is `127.0.0.1,::1`. * `KHAGANAT_XMPP_BOSH_URL`: URL of the BOSH server used to contact the XMPP server. Default is empty. * `KHAGANAT_XMPP_JID`: The JID to use for the XMPP session. Default is empty. * `KHAGANAT_XMPP_ROOMS`: List of rooms to automatically join when connecting. Default is empty. * `KHAGANAT_XMPP_WEBSOCKET_URL`: URL of the websocket server used to contact the XMPP server. Default is empty. ## Quick update ``` $ cd khaganat-web $ git pull $ pipenv --three update $ pipenv run ./manage.py migrate $ pipenv run ./manage.py compilemessages ``` If you are not in a development environment (runserver), you also have to run `pipenv run ./manage.py collectstatic --clear --noinput` and may have to restart the WSGI server. ## Nginx + uWSGI on ArchLinux Before deploying, you may read the following guides: * [How to use Django with uWSGI](https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/uwsgi/) * [Setting up Django and your web server with uWSGI and nginx](https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html) Install `nginx-mainline`, `uwsgi` and `uwsgi-plugin-python`. ``` # mkdir -p /srv/http/khaganat/static # cd /srv/http/khaganat # git clone https://git.khaganat.net/Tycho/khaganat-web.git app # cd app # PIPENV_VENV_IN_PROJECT=1 pipenv --three update ``` Create `/etc/uwsgi/khaganat.ini` with the appropriate environment variables: ``` [uwsgi] chdir = /srv/http/khaganat/app home = /srv/http/khaganat/app/.venv module = khaganat.wsgi:application plugins = python socket = /srv/http/khaganat/uwsgi.sock uid = http gid = http threads = 2 vacuum = True env = KHAGANAT_SECRET_KEY="generate a new one" env = KHAGANAT_DEBUG=False env = KHAGANAT_STATIC_ROOT=/srv/http/khaganat/static env = KHAGANAT_HOSTNAMES=khaganat.local ``` Create `/etc/systemd/system/multi-user.target.wants/uwsgi@.service` : ``` [Unit] Description=uWSGI service unit After=syslog.target [Service] ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/%I.ini ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -INT $MAINPID Restart=always Type=notify StandardError=syslog NotifyAccess=all KillSignal=SIGQUIT [Install] WantedBy=multi-user.target ``` Configure nginx : ``` server { listen 80; listen [::]:80; server_name "khaganat.local"; include custom/headers.conf; location /static { root /srv/http/khaganat/; } location / { uwsgi_pass unix:///srv/http/khaganat/uwsgi.sock; include uwsgi_params; } } ``` Finish the installation: ``` # cd /srv/http/khaganat/app # pipenv run ./manage.py migrate # pipenv run ./manage.py collectstatic --clear --noinput # pipenv run ./manage.py compilemessages # pipenv run ./manage.py createsuperuser # chown -R http:http /srv/http/khaganat/ # systemctl enable uwsgi@khaganat.service # systemctl start uwsgi@khaganat.service # systemctl enable nginx.service # systemctl start nginx.service ``` Do not forget to check the [deployment checklist](https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/).