diff --git a/README.md b/README.md
index 2ecbca3cc730606220a66479b166405525ecf4f6..f7166abed00dc1d220001f9966da47bcb1916e1f 100644
--- a/README.md
+++ b/README.md
@@ -14,3 +14,47 @@ System zur Verwaltung von Protokollen und Sitzungen.
 * Rechteverwaltung (interne Abschnitte)
 * Hochladen der Tagesordnung in einen Kalender
 * externe Protokolle ohne Protokollsyntax
+
+# HowTo Setup
+
+Required infrastructure:
+
+* some WSGI-capable webserver (nginx + uwsgi, …)
+* some database (postgres, …)
+* some LDAP server (Samba 4, slapd, …) for accounts and groups
+* texlive
+* some message broker for [celery](http://docs.celeryproject.org/en/latest/getting-started/brokers/) (redis, …)
+
+Optional infrastructure:
+
+* a mail server (for sending protocols and invitations)
+* a CUPS printing server (for printing protocols and decisions)
+* an [Etherpad](https://github.com/ether/etherpad-lite) (for writing the protocol collectively)
+* a Mediawiki instance (for uploading the protocols there)
+* a CalDAV server (for uploading the events)
+
+Steps:
+
+1. clone the [repository](https://git.fsmpi.rwth-aachen.de/protokollsystem/proto3)
+2. create a python virtualenv and install the packages from `requirements.txt` there
+3. create a database (tested with postgres and sqlite, but feel free to use whatever you like and [SQLAlchemy](http://docs.sqlalchemy.org/en/latest/dialects/index.html) supports
+4. copy `config.py.example` to `config.py` and edit it
+  * **do** change everything commented with `change this`
+  * do **not** change the lines commented with `do not change`
+  * deactivate unwanted features with `SOMETHING_ACTIVE = False`
+  * if you want to use a feature, set the connection configuration lines accordingly
+  * define a list of authentication backends (usually one):
+    - use LdapManager for slapd
+    - use ADManager for Samba
+    - write your own for anything else (see `auth.py`, just the methods `authenticate` and `groups` are required)
+  * define the available printers (if wanted) with a list of options they should use (see lpoptions)
+  * if you do not know what a MediaWiki-domain is, you probably don't need it
+  * fix the path to the fonts (and select which to use)
+  * most points should be documented in the example config
+5. create the database schema with `./server.py db upgrade`
+6. configure your server to run the wsgi-application and the celery-server
+  * if you use systemd, example service files are located in `example-config/` in this repository
+7. configure your webserver to serve the wsgi-application
+  * if you use uwsgi+nginx, example config if located in `example-config/`
+  * don't forget to pass the correct IP if you use some proxy-setup and want to use IP-based access per protocol type
+8. Test if it is working properly
diff --git a/config.py.example b/config.py.example
index 9956202134b379f591e1ffb4bcb5fc60ce092e60..4de9e5bfb32cd20313b0f22a1918c5319b2e2b17 100644
--- a/config.py.example
+++ b/config.py.example
@@ -4,7 +4,7 @@ SQLALCHEMY_TRACK_MODIFICATIONS = False # do not change
 
 SECRET_KEY = "something random" # change this
 
-DEBUG = False
+DEBUG = False # do not change
 
 # mailserver (optional)
 MAIL_ACTIVE = True
@@ -13,10 +13,10 @@ MAIL_HOST = "mail.example.com:465"
 MAIL_USER = "user" # set to "" for unauthenticated sending
 MAIL_PASSWORD = "password" # set to "" for unauthenticated sending
 MAIL_USE_TLS = True # should match the port in MAIL_HOST (if present there)
-MAIL_USE_STARTTLS = False # Usually, it's either this or SMTPS
+MAIL_USE_STARTTLS = False # Usually, it's either this or SMTPS, not both
 
 # (local) message queue (necessary)
-CELERY_BROKER_URL = "redis://localhost:6379/0"
+CELERY_BROKER_URL = "redis://localhost:6379/0" # change this if you do not use redis or it is running somewhere else
 CELERY_TASK_SERIALIZER = "pickle" # do not change
 CELERY_ACCEPT_CONTENT = ["pickle"] # do not change
 
@@ -31,7 +31,7 @@ PRINTING_PRINTERS = [
 
 # etherpad (optional)
 ETHERPAD_ACTIVE = True
-ETHERPAD_URL = "https://example.com/etherpad"
+ETHERPAD_URL = "https://example.com/etherpad" # without /p/…
 EMPTY_ETHERPAD = """Welcome to Etherpad!
 
 This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!
@@ -52,7 +52,7 @@ WIKI_DOMAIN = "domain" # set to None if not necessary
 CALENDAR_ACTIVE = True
 CALENDAR_URL = "https://user:password@calendar.example.com/dav/"
 CALENDAR_DEFAULT_DURATION = 3 # default meeting length in hours
-CALENDAR_MAX_REQUESTS = 10
+CALENDAR_MAX_REQUESTS = 10 # number of retries before giving up (some caldav servers like to randomly reply with errors)
 
 SESSION_PROTECTION = "strong" # do not change
 
@@ -72,7 +72,7 @@ AUTH_BACKENDS = [
         ca_cert="/etc/ssl/certs/example-ca.pem")
 ]
 
-OBSOLETION_WARNING = """Please migrate your account!"""
+OBSOLETION_WARNING = """Please migrate your account!""" # not important
 
 # lines of error description
 ERROR_CONTEXT_LINES = 3
@@ -86,6 +86,7 @@ MAX_INDEX_DAYS = 14
 
 # mail to contact in case of complex errors
 ADMIN_MAIL = "admin@example.com"
+# users with this group may see and do everything
 ADMIN_GROUP = "admin"
 
 # accept protocols even with some errors
@@ -93,45 +94,55 @@ ADMIN_GROUP = "admin"
 # not recommended for regular operation
 PARSER_LAZY = False
 
-# minimum similarity (0-100) todos need to have to be considered equal
+# minimum similarity (0-100) todos need to have to be considered equal while importing
 FUZZY_MIN_SCORE = 90
 
 # choose something nice from fc-list
 # Nimbus Sans looks very much like Computer Modern
 FONTS = {
     "main": {
-        "regular": "Nimbus Sans",
-        "bold": "NimbusSans",
-        "italic": "NimbusSans",
-        "bolditalic": "NimbusSans"
+        "extension": ".otf",
+        "path": "/usr/share/fonts/OTF/",
+        "regular": "NimbusSans-Regular",
+        "bold": "NimbusSans-Bold",
+        "italic": "NimbusSans-Oblique",
+        "bolditalic": "NimbusSans-BoldOblique"
     },
     "roman": {
-        "regular": "Nimbus Roman",
-        "bold": "Nimbus Roman",
-        "italic": "Nimbus Roman",
-        "bolditalic": "Nimbus Roman"
+        "extension": ".otf",
+        "path": "/usr/share/fonts/OTF/",
+        "regular": "NimbusRoman-Regular",
+        "bold": "NimbusRoman-Bold",
+        "italic": "NimbusRoman-Italic",
+        "bolditalic": "NimbusRoman-BoldItalic"
     },
     "sans": {
-        "regular": "Nimbus Sans",
-        "bold": "NimbusSans",
-        "italic": "NimbusSans",
-        "bolditalic": "NimbusSans"
+        "extension": ".otf",
+        "path": "/usr/share/fonts/OTF/",
+        "regular": "NimbusSans-Regular",
+        "bold": "NimbusSans-Bold",
+        "italic": "NimbusSans-Oblique",
+        "bolditalic": "NimbusSans-BoldOblique"
     },
     "mono": {
-        "regular": "Nimbus Mono PS",
-        "bold": "Nimbus Mono PS",
-        "italic": "Nimbus Mono PS",
-        "bolditalic": "Nimbus Mono PS"
+        "extension": ".otf",
+        "path": "/usr/share/fonts/OTF/",
+        "regular": "NimbusMonoPS-Regular",
+        "bold": "NimbusMonoPS-Bold",
+        "italic": "NimbusMonoPS-Italic",
+        "bolditalic": "NimbusMonoPS-BoldItalic"
     }
 }
 
-# local filesystem path to save documents
+# local filesystem path to save compiled and uploaded protocols (and attachments)
 DOCUMENTS_PATH = "documents"
 
 # keywords indicating private protocol parts
 PRIVATE_KEYWORDS = ["private", "internal", "privat", "intern"]
 
 # list of bulletpoints to use in latex
+# these are latex-defaults, add more if you like more
+# they are cycled as often as necessary to allow (theoretically) infinite nesting depth
 LATEX_BULLETPOINTS = [
     r"\textbullet",
     r"\normalfont \bfseries \textendash",
@@ -157,6 +168,8 @@ HTML_LEVEL_OFFSET = 3
 def dummy_todomail_provider():
     return {"example": ("Name", "mail@example.com")}
 
+# if you want to generate this mapping automatically
+# manually creating todomails through the web interface will still be possible for every authenticated user
 # list of functions that return dicts mapping todomail-keys to a tuple containing name and mail address
 ADDITIONAL_TODOMAIL_PROVIDERS = [
     dummy_todomail_provider
diff --git a/example-config/celery.service b/example-config/celery.service
new file mode 100644
index 0000000000000000000000000000000000000000..ba74cf1e312fa42a92bfa4cf53b4228734dd89a2
--- /dev/null
+++ b/example-config/celery.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Protokollsystem-Celery
+After=network.target
+
+[Service]
+User=protokolle
+Group=protokolle
+WorkingDirectory=/var/www/protokollsystem
+Environment=VIRTUAL_ENV="/var/www/protokollsystem"
+ExecStart=/var/www/protokollsystem/program/bin/celery -A server.celery worker --loglevel=DEBUG --concurrency=4
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/example-config/protokollsystem b/example-config/protokollsystem
new file mode 100644
index 0000000000000000000000000000000000000000..5d0fbc30fc39c67a535d7dc850f52b5a74fcfd61
--- /dev/null
+++ b/example-config/protokollsystem
@@ -0,0 +1,20 @@
+server {
+	listen 62000;
+	server_name protokolle.example.com;
+	root /var/www/protokolle;
+	index index.html index.py;
+
+	location / {
+		include uwsgi_params;
+		client_max_body_size 5M;
+		proxy_set_header        X-Real-IP       $realip_remote_addr;
+		proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
+		uwsgi_param  REMOTE_ADDR        $realip_remote_addr;
+		uwsgi_pass unix:///run/uwsgi/app/protokollsystem.sock;
+	}
+	location /static {
+		alias /var/www/protokolle/static;
+		try_files $uri $uri/ =404;
+	}
+}
+
diff --git a/example-config/protokollsystem.service b/example-config/protokollsystem.service
new file mode 100644
index 0000000000000000000000000000000000000000..d8d2a0dc99ce253ec623df6be1b03d4073482581
--- /dev/null
+++ b/example-config/protokollsystem.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Protokollsystem
+After=network.target
+Wants=protokollsystem-celery.service
+
+[Service]
+Environment=LDAPTLS_CACERT=/etc/ssl/certs/ldap_chain.pem
+ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/protokollsystem.ini
+Restart=always
+KillSignal=SIGTERM
+Type=notify
+NotifyAccess=all
+
+[Install]
+WantedBy=multi-user.target
diff --git a/example-config/uwsgi.ini b/example-config/uwsgi.ini
new file mode 100644
index 0000000000000000000000000000000000000000..2b32063229ca2b0481f592185300ca8c5785757e
--- /dev/null
+++ b/example-config/uwsgi.ini
@@ -0,0 +1,31 @@
+[uwsgi]
+uwsgi-socket = /run/uwsgi/app/protokollsystem/protokollsystem.sock
+#http = localhost:5000
+chmod-socket = 660
+chown-socket = protokolle:www-data
+autoload =
+master =
+processes = 4
+workers = 4
+prio = -5
+harakiri = 5
+buffer-size=32768
+mule = 
+#umask = 227
+chdir = /var/www/protokollsystem
+uid = protokolle
+gid = protokolle
+logto = /var/log/uwsgi/protokollsystem.log
+logfile-chown = protokolle:protokolle
+logfile-chmod = 664
+log-date =
+log-4xx = 
+log-5xx = 
+log-x-forwarded-for =
+plugin = python35
+virtualenv = /var/www/protokollsystem
+wsgi-file = /var/www/protokollsystem/server.py
+callable = app
+pyargv = server.py runserver
+manage-script-name =
+mount=/=/var/www/protokollsystem/server.py