Updated standalone docker file and install guide

This commit is contained in:
Raphael Michel
2016-05-08 17:04:15 +02:00
parent 9433c76a4c
commit f999b9ffd9
18 changed files with 499 additions and 107 deletions

3
.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
doc/
env/
res/

View File

@@ -4,7 +4,7 @@ RUN apt-get update && apt-get install -y python3 git python3-pip \
libxml2-dev libxslt1-dev python-dev python-virtualenv locales libffi-dev \
build-essential python3-dev zlib1g-dev libssl-dev gettext git \
libpq-dev libmysqlclient-dev libmemcached-dev libjpeg-dev \
aqbanking-tools \
aqbanking-tools supervisor nginx sudo \
--no-install-recommends
WORKDIR /
@@ -16,21 +16,32 @@ ENV LC_ALL C.UTF-8
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
RUN git clone --recursive --depth 1 https://github.com/pretix/pretix.git /pretix
WORKDIR /pretix/src
RUN pip3 install -r requirements.txt -r requirements/mysql.txt -r requirements/postgres.txt \
-r requirements/memcached.txt -r requirements/celery.txt -r requirements/redis.txt \
-r requirements/py34.txt gunicorn
RUN make
RUN useradd -ms /bin/bash -d /pretix -u 15371 pretixuser
RUN echo 'pretixuser ALL=(ALL) NOPASSWD: /usr/bin/supervisord' >> /etc/sudoers
RUN mkdir /etc/pretix
RUN mkdir /data
VOLUME /etc/pretix
ADD pretix.bash /usr/local/bin/pretix
COPY deployment/docker/pretix.bash /usr/local/bin/pretix
RUN chmod +x /usr/local/bin/pretix
COPY deployment/docker/supervisord.conf /etc/supervisord.conf
COPY deployment/docker/nginx.conf /etc/nginx/nginx.conf
RUN rm /etc/nginx/sites-enabled/default
COPY src /pretix/src
WORKDIR /pretix/src
ADD deployment/docker/production_settings.py /pretix/src/production_settings.py
ENV DJANGO_SETTINGS_MODULE production_settings
RUN pip3 install -r requirements.txt -r requirements/mysql.txt -r requirements/postgres.txt \
-r requirements/memcached.txt -r requirements/celery.txt -r requirements/redis.txt \
-r requirements/py34.txt gunicorn
RUN mkdir /static && chown -R pretixuser:pretixuser /static /pretix /data
USER pretixuser
RUN make production
EXPOSE 80

View File

@@ -0,0 +1,64 @@
user www-data www-data;
worker_processes 1;
pid /var/run/nginx.pid;
daemon off;
events {
worker_connections 768;
}
http {
sendfile on;
charset utf-8;
tcp_nopush on;
tcp_nodelay on;
client_max_body_size 100M;
log_format private '[$time_local] $host "$request" $status $body_bytes_sent';
types_hash_max_size 2048;
server_names_hash_bucket_size 64;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log private;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
gzip_types text/plain text/html text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml image/svg+xml;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 ipv6only=on default_server;
server_name _;
index index.php index.html;
root /var/www;
location /media/ {
alias /data/media/;
expires 7d;
access_log off;
}
location /static/ {
alias /static/;
access_log off;
expires 365d;
add_header Cache-Control "public";
}
location / {
proxy_pass http://unix:/tmp/pretix.sock:/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
}
}
}

View File

@@ -0,0 +1,44 @@
#!/bin/bash
cd /pretix/src
export DJANGO_SETTINGS_MODULE=production_settings
export DATA_DIR=/data/
NUM_WORKERS=10
if [ ! -d /data/logs ]; then
mkdir /data/logs;
fi
if [ ! -d /data/media ]; then
mkdir /data/media;
fi
if [ "$1" == "cron" ]; then
exec python3 -m pretix runperiodic
fi
python3 -m pretix migrate --noinput
if [ "$1" == "all" ]; then
exec sudo /usr/bin/supervisord -n -c /etc/supervisord.conf
fi
if [ "$1" == "webworker" ]; then
exec gunicorn pretix.wsgi \
--name pretix \
--workers $NUM_WORKERS \
--max-requests 1200 \
--max-requests-jitter 50 \
--log-level=info \
--bind=unix:/tmp/pretix.sock
fi
if [ "$1" == "taskworker" ]; then
export C_FORCE_ROOT=True
exec celery -A pretix worker -l info
fi
if [ "$1" == "shell" ]; then
exec python3 -m pretix shell
fi
echo "Specify argument: all|cron|webworker|taskworker|shell"
exit 1

View File

@@ -0,0 +1,6 @@
from pretix.settings import *
LOGGING['handlers']['mail_admins']['include_html'] = True
STATIC_ROOT = '/static'
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'

View File

@@ -1,3 +0,0 @@
main:
#tar ch --exclude=_static --exclude=htmlcov --exclude=db.sqlite3 . |
docker build -t pretix/standalone .

View File

@@ -1,39 +0,0 @@
#!/bin/bash
cd /pretix/src
export DJANGO_SETTINGS_MODULE=pretix.settings
export DATA_DIR=/data/
NUM_WORKERS=25
if [ ! -d /data/logs ]; then
mkdir /data/logs;
fi
if [ ! -d /data/media ]; then
mkdir /data/media;
fi
if [ "$1" == "web" ]; then
python3 manage.py collectstatic --noinput
python3 manage.py compress
exec gunicorn pretix.wsgi \
--name pretix \
--workers $NUM_WORKERS \
--max-requests 1200 \
--max-requests-jitter 50 \
--log-level=info \
--bind=0.0.0.0:80
fi
if [ "$1" == "worker" ]; then
exec celery -A pretix worker -l info
fi
if [ "$1" == "migrate" ]; then
exec python manage.py migrate --noinput
fi
if [ "$1" == "shell" ]; then
exec python manage.py shell
fi
echo "Specify argument: web|worker|migrate|shell"
exit 1

View File

@@ -0,0 +1,43 @@
[unix_http_server]
file=/tmp/supervisor.sock
[supervisord]
logfile=/tmp/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
pidfile=/tmp/supervisord.pid
nodaemon=false
minfds=1024
minprocs=200
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///tmp/supervisor.sock
[program:pretixweb]
command=/usr/local/bin/pretix webworker
autostart=true
autorestart=true
priority=5
user=pretixuser
[program:pretixtask]
command=/usr/local/bin/pretix taskworker
autostart=true
autorestart=true
priority=5
user=pretixuser
[program:nginx]
command=/usr/sbin/nginx
autostart=true
autorestart=true
priority=10
stdout_events_enabled=true
stderr_events_enabled=true
[include]
files = /etc/supervisord-*.conf

View File

@@ -111,6 +111,8 @@ Example::
The URL to be used to serve static files. You should not need to modify
this. Default: ``/static/``
.. _`mail-settings`:
Email
-----

View File

@@ -8,5 +8,5 @@ Contents:
.. toctree::
:maxdepth: 2
installation
installation/index
config

View File

@@ -1,50 +0,0 @@
.. highlight:: ini
Installation
============
Requirements
------------
To use pretix, the most minimal setup consists of:
* **pretix** and the python packages it depends on
* An **WSGI application server** (we recommend gunicorn)
* A periodic task runner, e.g. ``cron``
You get those two bundled in the ``pretix/standalone`` docker image.
If you want to set them up manually, you can also get pretix from GitHub or wait for us to set up proper
``pip`` packages and set up a simple gunicorn instance pointing to the ``pretix.wsgi`` endpoint.
To run pretix, you will need **at least Python 3.4**.
You can get the direct dependencies by doing a ``pip install -r requirements.txt`` in the pretix source
directory. We'll provide detailled documentation on this as soon as pretix will be officially released.
If you have real users on your system you'll **really** want to use
* A database (MySQL or PostgreSQL)
* A reverse proxy web server (nginx or Apache)
Optionally, you can speed up pretix by adding
* A memcached instance
* A redis database
* A celery background task-queue (using redis or RabbitMQ for messaging)
Depending on your choice at this options, you should also install ``pip install -r requirements/<service>.txt``
where ``<service>`` is one of ``celery``, ``memcached``, ``mysql``, ``postgres`` or ``redis``.
If you want to use one of the payment providers shipping with pretix, you should also install
``pip install -r requirements/<plugin>.txt`` where ``<plugin>`` is one of ``banktransfer``, ``paypal`` or ``stripe``.
We will provide a step-by-step tutorial with the first stable release, but all configuration
already :ref:`is documented <config>`.
Set up a cronjob
----------------
You need to set up a cronjob that runs the management command ``runperiodic``. The exact interval is not important
but should be something between every minute and every hour. You could for example configure cron like this::
15,45 * * * * python3 /path/to/pretix/manage.py runperiodic

View File

@@ -0,0 +1,241 @@
.. highlight:: none
Small-scale deployment with Docker
==================================
This guide describes the installation of a small-scale installation of pretix using docker. By small-scale, we mean
that everything is being run on one host and you don't expect thousands of participants trying to get a ticket within
a few minutes. In this setup, as many parts of pretix as possible are hidden away in one single docker container.
This has some trade-offs in terms of performance and isolation but allows a rather easy installation.
.. warning:: Even though we try to make it straightforward to run pretix, it still requires some Linux experience to
get it right. If you're not feeling comfortable managing a Linux server, check out our hosting and service
offers at `pretix.eu`_.
We tested this guide on the Linux distribution **Debian 8.0** but it should work very similar on other
modern distributions, especially on all systemd-based ones.
Requirements
------------
Please set up the following systems beforehand, we'll not explain them here (but link to installation guides
somewhere else):
* `Docker`_
* A SMTP server to send out mails, e.g. `Postfix`_ on your machine or some third-party server you have credentials for
* A HTTP reverse proxy, e.g. `nginx`_ or Apache to allow HTTPS connections
* A `MySQL`_ or `PostgreSQL`_ database server
* A `redis`_ server
We also recommend that you use a firewall, although this is not a pretix-specific recommendation. If you're new to
Linux and firewalls, we recommend that you start with `ufw`_.
.. note:: Please, do not run pretix without HTTPS encryption. You'll handle user data and thanks to `Let's Encrypt`_
SSL certificates can be obtained for free these days. We also *do not* provide support for HTTP-only
installations except for evaluation purposes.
On this guide
-------------
All code lines prepended with a ``#`` symbol are commands that you need to execute on your server as ``root`` user;
all lines prepended with a ``$`` symbol can also be run by an unprivileged user.
Data files
----------
First of all, you need a directory on your server that pretix can use to store data files and make that directory
writable to the user that runs pretix inside the docker container::
# mkdir /var/pretix-data
# chown -R 15371:15371 /var/pretix-data
Database
--------
Next, we need a database and a database user. We create this with any kind of database managing tool or directly on
our database's shell, e.g. for MySQL::
$ mysql -u root -p
mysql> CREATE DATABASE pretix DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
mysql> GRANT ALL PRIVILEGES ON pretix.* TO pretix@'localhost' IDENTIFIED BY '*********';
mysql> FLUSH PRIVILEGES;
Replace the asterisks with a password of your own. For MySQL, we will use a unix domain socket to connect to the
database. For PostgreSQL, be sure to configure the interface binding and your firewall such that the docker container
can reach PostgreSQL.
Redis
-----
For caching and messaging in small-scale setups, pretix recomments using redis. In this small-scale setup we assume a
redis instance running on the same host. To avoid the hassle about network configurations and firewalls, we recommend
connecting to redis via an unix socket. To enable redis on unix sockets, add the following to your
``/etc/redis/redis.conf``::
unixsocket /tmp/redis.sock
unixsocketperm 777
Now restart redis-server::
# systemctl restart redis-server
.. warning:: Setting the socket permissions to 777 is a possible security problem. If you have untrusted users on your
system or have high security requirements, please don't do this and let redis listen to a TCP socket
instead. We recommend the socket approach because the TCP socket in combination with docker's networking
can easily become an even worse security hole when configured slightly wrong. Read more about security
on the `redis website`_.
Another possible solution is to run `redis in docker`_ and link the containers using dockers networking
features.
Config file
-----------
We now create a config directory and config file for pretix::
# mkdir /etc/pretix
# touch /etc/pretix/pretix.cfg
# chown -R 15371:15371 /etc/pretix/
# chmod 0700 /etc/pretix/pretix.cfg
Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following content (adjusted to your environment)::
[pretix]
instance_name=My pretix installation
url=https://pretix.mydomain.com
currency=EUR
; DO NOT change the following value, it has to be set to the location of the
; directory *inside* the docker container
datadir=/data
[database]
; Replace mysql with psycopg2 for PostgreSQL
backend=mysql
name=pretix
user=pretix
password=*********
; Replace with host IP address for PostgreSQL
host=/var/run/mysqld/mysqld.sock
[mail]
; See config file documentation for more options
from=tickets@yourdomain.com
; This is the default IP address of your docker host in docker's virtual
; network. Make sure postfix listens on this address.
host=172.17.0.1
[redis]
location=unix:///tmp/redis.sock?db=0
; Remove the following line if you are unsure about your redis' security
; to reduce impact if redis gets compromised.
sessions=true
[celery]
backend=redis+socket:///tmp/redis.sock?virtual_host=1
broker=redis+socket:///tmp/redis.sock?virtual_host=2
See :ref:`email configuration <mail-settings>` to learn more about configuring mail features.
Docker image and service
------------------------
First of all, download the latest pretix image by running::
$ docker pull pretix/standalone:latest
We recommend starting the docker container using systemd to make sure it runs correctly after a reboot. Create a file
named ``/etc/systemd/system/pretix.service`` with the following content::
[Unit]
Description=pretix
After=docker.service
Requires=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStart=/usr/bin/docker run --name %n -p 8345:80 \
-v /var/pretix-data:/data \
-v /etc/pretix:/etc/pretix \
-v /tmp/redis.sock:/tmp/redis.sock \
-v /var/run/mysqld:/var/run/mysqld \
pretix/standalone all
ExecStop=/usr/bin/docker stop %n
[Install]
WantedBy=multi-user.target
You can leave the MySQL socket volume out if you're using PostgreSQL.
Cronjob
-------
You need to set up a cronjob that runs the management command ``runperiodic``. The exact interval is not important
but should be something between every minute and every hour. You could for example configure cron like this::
15,45 * * * * /usr/bin/docker exec pretix.service pretix cron
The cronjob may run as any user that can use the docker daemon.
SSL
---
The following snippet is an example on how to configure a nginx proxy for pretix::
server {
listen 80 default_server;
listen [::]:80 ipv6only=on default_server;
server_name pretix.mydomain.com;
}
server {
listen 443 default_server;
listen [::]:443 ipv6only=on default_server;
server_name pretix.mydomain.com;
ssl on;
ssl_certificate /path/to/cert.chain.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8345/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
}
}
We recommend reading about setting `strong encryption settings`_ for your web server.
Next steps
----------
Yay, you are done! You should now be able to reach pretix at https://pretix.yourdomain.com/control/ and log in as
*admin@localhost* with a passwort of *admin*. Don't forget to change that password! Create an organizer first, then
create an event and start selling tickets!
Updates
-------
.. warning:: While we try hard not to break things, **please perform a backup before every upgrade**.
Updates are fairly simple, but require at least a small downtime::
# docker pull pretix/standalone
# systemctl restart pretix.service
Restarting the service can take a few seconds, especially if the update requires changes to the database.
.. _Docker: https://docs.docker.com/engine/installation/linux/debian/
.. _Postfix: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04
.. _nginx: https://botleg.com/stories/https-with-lets-encrypt-and-nginx/
.. _Let's Encrypt: https://letsencrypt.org/
.. _pretix.eu: https://pretix.eu/
.. _MySQL: https://dev.mysql.com/doc/refman/5.7/en/linux-installation-apt-repo.html
.. _PostgreSQL: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-9-4-on-debian-8
.. _redis: http://blog.programster.org/debian-8-install-redis-server/
.. _ufw: https://en.wikipedia.org/wiki/Uncomplicated_Firewall
.. _redis website: http://redis.io/topics/security
.. _redis in docker: https://hub.docker.com/r/_/redis/
.. _strong encryption settings: https://mozilla.github.io/server-side-tls/ssl-config-generator/

View File

@@ -0,0 +1,55 @@
.. highlight:: ini
General remarks
===============
Requirements
------------
To use pretix, the most minimal setup consists of:
* **pretix** and the python packages it depends on
* An **WSGI application server** (we recommend gunicorn)
* A periodic task runner, e.g. ``cron``
To run pretix, you will need **at least Python 3.4**. We only recommend installations on **Linux**, Windows is not
officially supported (but might work).
Optional requirements
---------------------
pretix is built in a way that makes many of the following requirements optional. However, performance or security might
be very low if you skip some of them, therefore they are only partly optional.
Database
A good SQL-based database to run on that is supported by Django. We highly recommend to either go for **PostgreSQL**
or **MySQL/MariaDB**.
If you do not provide one, pretix will run on SQLite, which is useful for evaluation and development purposes.
.. warning:: Do not ever use SQLite in production. It will break.
Reverse proxy
pretix needs to deliver some static content to your users (e.g. CSS, images, ...). While pretix is capable of
doing this, having this handled by a proper webserver like **nginx** or **Apache** will be much faster. Also, you
need a proxying web server in front to provide SSL encryption.
.. warning:: Do not ever run without SSL in production. Your users deserve encrypted connections and thanks to
`Let's Encrypt`_ SSL certificates can be obtained for free these days.
Task worker
When pretix has to do heavy stuff, it is better to offload it into a background process instead of having the
users connection wait. Therefore pretix provides a background service that can be used to work on those
longer-running tasks.
This requires at least Redis (and optionally RabbitMQ).
Redis
If you provide a redis instance, pretix is able to make use of it in the three following ways:
* Caching
* Fast session storage
* Queuing and result storage for the task worker queue
RabbitMQ
RabbitMQ can be used as a more advanced queue manager for the task workers, if necessary.
.. _Let's Encrypt: https://letsencrypt.org/

View File

@@ -0,0 +1,11 @@
Installation guide
==================
We provide you with multiple installation guides for multiple types of setups so you can choose the one appropriate
for your needs.
.. toctree::
:maxdepth: 1
general
docker_smallscale

View File

@@ -1,7 +1,7 @@
General remarks
===============
You are interesting in contributing to pretix? That is awesome!
You are interested in contributing to pretix? That is awesome!
If youre new to contributing to open source software, dont be afraid. Well happily review your code and give you
constructive and friendly feedback on your changes.

View File

@@ -1,4 +1,3 @@
import importlib
import importlib.util
from django.apps import apps

View File

@@ -36,8 +36,11 @@ control_patterns = [
debug_patterns = []
if settings.DEBUG:
import debug_toolbar
try:
import debug_toolbar
debug_patterns.append(url(r'^__debug__/', include(debug_toolbar.urls)))
debug_patterns.append(url(r'^__debug__/', include(debug_toolbar.urls)))
except ImportError:
pass
common_patterns = base_patterns + control_patterns + debug_patterns

View File

@@ -1,2 +1,4 @@
django-redis>=4.1,<4.2
redis>=2.10,<2.11
# until the following issue is fixed, we need our own kombu version
git+https://github.com/pretix/kombu.git@pretix#egg=kombu