diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..95f293fe37b2e17496ce685a164742e359633226
--- /dev/null
+++ b/README.md
@@ -0,0 +1,91 @@
+# Webservices 
+
+
+## Roles
+
+- `acmetool`, manages let's encrypt certificates via acmetool
+- `debian-repository`, installs the software reprepro (very basic)
+- `lehrpreis`, teaching award nomination web app
+- `meckerkasten`, mimimi web app
+- `mediawiki`, setups mediawiki with php-fpm
+- `php-fpm`, setups php-fpm pools
+- `protokollsystem`, protocols, meetings, and everything management web app (TM)
+- `schildergenerator`, sign generator web app
+- `sentry`, error collection api and web app
+- `sso`, single signon web app 
+- `uwsgi-php`, deprecated
+- `uwsgi-python`, unified web app deployment role for python-based web apps 
+- `wahlhelfer`, setups wahlhelfer registration and scheduling web app
+- `wahlsystem`, setups an election management system
+- `webserver`,  configures nginx 
+- `wordpress`, setups wordpresses via an overlayfs technology 
+
+*Note:* Some roles are still undocumented.
+
+## uwsgi-python
+
+The idea of the role is to have only one role for all the python-based web apps. Instead of a role (and group) for every single app. 
+We distinguish between apps and instances. An app is the actual program, which can be instaciated more than once, which we call the instance.
+
+The role iterates over the list `webapps` (in the host vars) and import app and instance specific variable files.
+An app specific task snippet is imported if it configured in the variable files (see below). 
+
+We place the instance specific variable file under <inventory_dir>/vars/<instance>.yml. The app specific variable file is <role_dir>/vars/<app>.yml. 
+In the latter file there should be sensible defaults for _every_ variable used within the role. 
+
+This role needs the patch from this [pull-request](https://github.com/ansible/ansible/pull/39762) or ansible 2.6 or later.
+
+### Variables
+
+- `app_name`: the name of the app
+- `app_user`: the user which runs the app---will be created
+- `app_group`: the user's group which runs the app---will be created
+- `app_home`: home directory of the user, usually `/var/www/<app_user>`
+- `app_path`: the path where the program can be found, usually same as `app_home`
+- `app_python_version`: the app's python version as number (2|3)
+- `app_venv`: the absolut path to the virtualenv, which shall be used for the app
+- `app_program`: the python executable, which lies in `app_path`
+- `app_callable`: uwsgi variable <callable>, mostly app
+- `app_command`: commandline arguments for the app
+- `app_mountpoint`: the path in the URI, if the app shall be reachable under https://www.example.com/app, usually /
+
+- `app_db_name`: name of the db for the app, can be `""` if not any database is needed, usally same as `app_user`
+- `app_db_type`: db type: (postgres|mysql|sqlite) 
+
+- `app_additional_software`: list of software, which is additionally needed by the app e.g. LaTeX. If no additional software is needed it is `[]`
+
+- `app_deploy_key`: path to a ssh-key which is needed to get the software usaally, "{{ inventory_dir }}/files/deploy-keys/<app_name>"
+- `app_git_url`: git url of the project 
+- `app_git_version`: git version usually `HEAD`
+
+- `app_config_file`: config file, usally `config.py`
+- `app_secret_config`: it might be useful to have the cookie's key in seperate config (true|false)
+
+
+### How to create a new app
+
+Create the following files
+* `uwsgi-python/vars/<app_name>.yml`
+Define the variable in it from above and the variables, you need for you config file. We recommend to define them as defaults (and as documentation)
+* `uwsgi-python/templates/apps/<app_name>.j2` 
+    That's your config template.
+* `uwsgi-python/tasks/apps/<app_name>.j2` 
+    If you need some additional tasks, you can define them in this file
+    
+If you have done this, you can create an instance of the app. Note, you have to define for every app an instance altough you only want to deploy it once.
+
+### How to create a new app's instance
+
+Create for every instance <inventory_dir>/vars/<instance_name>.yml a variable in which you can override the defaults from uwsgi-python/vars/<app_name>.yml
+
+Define in your host_vars/<host> the dictionary `webapps`
+
+    webapps:
+    - instance: <instancen_name>
+        app: <app_name>
+        app_vars: "<instance_name>.yml" <-- path to variable file from above
+
+! Note, it very important, to add the handler 
+
+- name: restart uwsgi instance <instance_name>
+  service: name="uwsgi@<instance_name>" state=restarted
diff --git a/lehrpreis/handlers/main.yml b/lehrpreis/handlers/main.yml
deleted file mode 100644
index ac45266f487fb6f6004ca4a10bb6f62af01012ea..0000000000000000000000000000000000000000
--- a/lehrpreis/handlers/main.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-# file: roles/lehrpreis/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart uwsgi for lehrpreis 
-  service: name=lehrpreis state=restarted enabled=yes
-
-- name: create tmpfiles
-  command: systemd-tmpfiles --create
-
-- name: recompile translations
-  command: ./bin/pybabel compile -d translations
-  args:
-    chdir: "{{ lehrpreis_web_root }}"
diff --git a/lehrpreis/meta/main.yml b/lehrpreis/meta/main.yml
deleted file mode 100644
index 428715e25fd4f3c2ffafb7224332c04099f29475..0000000000000000000000000000000000000000
--- a/lehrpreis/meta/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-# file:roles/lehrpreis/meta/main.yml
-
-dependencies:
-  - { role: uwsgi-python, uwsgi_name: "lehrpreis", uwsgi_user: "{{lehrpreis_user}}", uwsgi_group: "{{lehrpreis_group}}", uwsgi_path: "{{lehrpreis_web_root}}", uwsgi_home: "{{lehrpreis_web_root}}", uwsgi_program: "lehrpreis.py", uwsgi_callable: "app", uwsgi_command: "", uwsgi_python: 3, uwsgi_db: "postgres" }
diff --git a/lehrpreis/tasks/main.yml b/lehrpreis/tasks/main.yml
deleted file mode 100644
index 7cba023c98841dff3078be71d45e4162dfa2fe0d..0000000000000000000000000000000000000000
--- a/lehrpreis/tasks/main.yml
+++ /dev/null
@@ -1,116 +0,0 @@
----
-# file: roles/lehrpreis/tasks/main.yml
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ lehrpreis_deploy_key }}"
-    dest: /root/.ssh/lehrpreis
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - lehrpreis
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure we have the program
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:studi-systeme/lehrpreis.git
-    dest: "{{ lehrpreis_web_root }}"
-    key_file: /root/.ssh/lehrpreis
-    version: HEAD
-  notify:
-    - recompile translations
-    - restart uwsgi for lehrpreis
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ lehrpreis_web_root }}/requirements.txt"
-    virtualenv: "{{ lehrpreis_web_root }}"
-    virtualenv_python: python3
-  notify:
-    - restart uwsgi for lehrpreis
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: config.py.j2
-    dest: "{{ lehrpreis_web_root }}/config.py"
-    owner: "{{ lehrpreis_user }}"
-    group: "{{ lehrpreis_group }}"
-    mode: 0640
-  notify:
-    - restart uwsgi for lehrpreis
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure we have our secret config
-  template:
-    src: secret_config.py.j2
-    dest: "{{ lehrpreis_web_root }}/secret_config.py"
-    owner: "{{ lehrpreis_user }}"
-    group: "{{ lehrpreis_group }}"
-    mode: 0600
-    force: no
-  notify:
-    - restart uwsgi for lehrpreis
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure we have our branded logo
-  copy:
-    src: "{{ lehrpreis_branding_logo_src }}"
-    dest: "{{ lehrpreis_web_root }}/static/images/{{ lehrpreis_branding_logo }}"
-    owner: "{{ lehrpreis_user }}"
-    group: "{{ lehrpreis_group }}"
-    mode: 0644
-  notify:
-    - restart uwsgi for lehrpreis
-  when: lehrpreis_branding_logo and lehrpreis_branding_logo_src
-  tags:
-    - lehrpreis
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: lehrpreis.service.j2
-    dest: "/etc/systemd/system/lehrpreis.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for lehrpreis
-  tags:
-    - lehrpreis
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the service is enabled
-  service:
-    name: lehrpreis
-    enabled: yes
-    state: started
-  tags:
-    - lehrpreis
-    - webservices
diff --git a/lehrpreis/templates/lehrpreis.service.j2 b/lehrpreis/templates/lehrpreis.service.j2
deleted file mode 100644
index c6241a69d4cfb359dcb7dbf49a47571dfcea3af4..0000000000000000000000000000000000000000
--- a/lehrpreis/templates/lehrpreis.service.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-[Unit]
-Description=Lehrpreis-Nominierungs-WebApp
-After=network.target
-
-[Service]
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/lehrpreis.ini
-Restart=always
-KillSignal=SIGQUIT
-Type=notify
-NotifyAccess=all
-
-[Install]
-WantedBy=multi-user.target
diff --git a/lehrpreis/templates/secret_config.py.j2 b/lehrpreis/templates/secret_config.py.j2
deleted file mode 100644
index 4fe5c96549857b61df5312e62a3283976da32ff7..0000000000000000000000000000000000000000
--- a/lehrpreis/templates/secret_config.py.j2
+++ /dev/null
@@ -1 +0,0 @@
-secret_key = '{{ (2**2048)|random }}'
diff --git a/meckerkasten/defaults/main.yml b/meckerkasten/defaults/main.yml
deleted file mode 100644
index 89a98a675cdcb21575553ec1b786da12ca52e126..0000000000000000000000000000000000000000
--- a/meckerkasten/defaults/main.yml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-# file: meckerkasten/defaults/main.yml
-
-meckerkasten_web_root: /var/www/meckerkasten
-meckerkasten_name: meckerkasten
-meckerkasten_user: meckerkasten
-meckerkasten_group: meckerkasten
-meckerkasten_admins: [['Admins', 'admin@example.com']]
-meckerkasten_sender: 'meckerkasten@example.com'
-meckerkasten_mail_host: 'mail.example.invalid'
-meckerkasten_allowed_hosts: ['example.com']
-meckerkasten_ldap_cert: ''
diff --git a/meckerkasten/handlers/main.yml b/meckerkasten/handlers/main.yml
deleted file mode 100644
index 056b2bd343bd402b896ea7e57cfb90e7260a9b55..0000000000000000000000000000000000000000
--- a/meckerkasten/handlers/main.yml
+++ /dev/null
@@ -1,14 +0,0 @@
----
-# file: meckerkasten/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart uwsgi for meckerkasten
-  service:
-    name: "{{ meckerkasten_name }}"
-    state: restarted
-    enabled: yes
-
-- name: create tmpfiles
-  command: systemd-tmpfiles --create
diff --git a/meckerkasten/meta/main.yml b/meckerkasten/meta/main.yml
deleted file mode 100644
index 43e6374864ccaaef813c0dbb478ea6a80d915752..0000000000000000000000000000000000000000
--- a/meckerkasten/meta/main.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-# file: meckerkasten/meta/main.yml
-dependencies:
-  - { role: uwsgi-python, uwsgi_name: "{{meckerkasten_name}}", uwsgi_user: "{{meckerkasten_user}}", uwsgi_group: "{{meckerkasten_group}}", uwsgi_path: "{{meckerkasten_web_root}}/program", uwsgi_home: "{{meckerkasten_web_root}}", uwsgi_program: "meckerkasten/wsgi.py", uwsgi_callable: "application", uwsgi_command: "runserver", uwsgi_db: "sqlite", uwsgi_python: 2 }
diff --git a/meckerkasten/tasks/main.yml b/meckerkasten/tasks/main.yml
deleted file mode 100644
index 0e4e42ec055c3d8c2dcc5bf32a7dd53027e7b23c..0000000000000000000000000000000000000000
--- a/meckerkasten/tasks/main.yml
+++ /dev/null
@@ -1,87 +0,0 @@
----
-# file: meckerkasten/tasks/main.yml
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ meckerkasten_deploy_key }}"
-    dest: /root/.ssh/meckerkasten
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - meckerkasten
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure fucking git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - meckerkasten
-    - webservices
-
-- name: ensure we have the program
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:studi-systeme/meckerkasten.git
-    dest: "{{ meckerkasten_web_root }}"
-    key_file: /root/.ssh/meckerkasten
-    version: HEAD
-  notify:
-    - restart uwsgi for meckerkasten
-  tags:
-    - meckerkasten
-    - webservices
-
-- name: ensure fucking git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - meckerkasten
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ meckerkasten_web_root }}/requirements.txt"
-    virtualenv: "{{ meckerkasten_web_root }}"
-    virtualenv_python: python2
-  notify:
-    - restart uwsgi for meckerkasten
-  tags:
-    - meckerkasten
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: settings.py.j2
-    dest: "{{ meckerkasten_web_root }}/meckerkasten/settings.py"
-    owner: "{{ meckerkasten_user }}"
-    group: "{{ meckerkasten_group }}"
-    mode: 0640
-  notify:
-    - restart uwsgi for meckerkasten
-  tags:
-    - meckerkasten
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: meckerkasten.service.j2
-    dest: "/etc/systemd/system/{{ meckerkasten_name }}.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for meckerkasten
-  tags:
-    - meckerkasten
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the service is enabled
-  service:
-    name: "{{ meckerkasten_name }}"
-    enabled: yes
-    state: started
-  tags:
-    - meckerkasten
-    - webservices
diff --git a/meckerkasten/templates/meckerkasten.service.j2 b/meckerkasten/templates/meckerkasten.service.j2
deleted file mode 100644
index ea9b89cfe4a1a94155cfdbec07560f5c013f8cf7..0000000000000000000000000000000000000000
--- a/meckerkasten/templates/meckerkasten.service.j2
+++ /dev/null
@@ -1,18 +0,0 @@
-[Unit]
-Description=Meckerkasten
-After=network.target
-
-[Service]
-{% if meckerkasten_ldap_cert %}
-Environment=LDAPTLS_CACERT={{ meckerkasten_ldap_cert }}
-{% endif %}
-Environment=MECKERKASTEN_WEB_ROOT={{meckerkasten_web_root}}/
-Environment=MECKERKASTEN_WEB_SUBDIR=meckerkasten
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/{{meckerkasten_name}}.ini
-Restart=always
-KillSignal=SIGQUIT
-Type=notify
-NotifyAccess=all
-
-[Install]
-WantedBy=multi-user.target
diff --git a/protokollsystem/defaults/main.yml b/protokollsystem/defaults/main.yml
deleted file mode 100644
index b11eb70d55b758e0aa90b87086f79838f5fc483e..0000000000000000000000000000000000000000
--- a/protokollsystem/defaults/main.yml
+++ /dev/null
@@ -1,56 +0,0 @@
----
-# file: protokollsystem/defaults/main.yml
-
-protokolle_web_root: /var/www/protokollsystem
-protokolle_name: protokollsystem
-protokolle_user: protokolle
-protokolle_group: protokolle
-protokolle_celery_concurrency: 4
-protokolle_ldap_cert: ''
-protokolle_mail: True
-protokolle_mail_from: 'sender@example.com'
-protokolle_mail_host: 'mail.example.com:25'
-protokolle_mail_user: ''
-protokolle_mail_password: ''
-protokolle_mail_tls: False # 'tls' or 'starttls'
-protokolle_celery_broker: 'redis://localhost:6379/0'
-protokolle_url_root: 'protokolle.example.com'
-protokolle_url_proto: 'https'
-protokolle_url_path: '/'
-protokolle_printing: True
-protokolle_printing_server: 'printsrv.example.com:631'
-protokolle_printing_user: 'protokolle'
-protokolle_printing_printers:
-  - printer: kopierer
-    options: ["ColorModel=Gray", "KCStaple=Center", "KCPunch=2HoleEUR", "Duplex=DuplexNoTumble"]
-protokolle_etherpad: True
-protokolle_etherpad_url: 'https://pad.example.com'
-protokolle_wiki: True
-protokolle_wiki_type: MEDIAWIKI
-protokolle_wiki_api: 'https://wiki.example.com/wiki/api.php'
-protokolle_wiki_anonymous: False
-protokolle_wiki_user: ''
-protokolle_wiki_password: ''
-protokolle_wiki_domain: ''
-protokolle_calendar: True
-protokolle_calendar_url: 'https://user:password@groupware.example.com/SOGo/dav/user/Calendar/personal'
-protokolle_admin_mail: 'admin@example.com'
-protokolle_admin_group: 'protokolladmin'
-protokolle_latex_local_templates: '' # local-templates
-protokolle_latex_logo_template: '' # logo.tex
-protokolle_latex_geometry: '' # bottom=1.6cm,top=1.6cm,inner=2.5cm,outer=1.0cm,footskip=1.0cm,headsep=0.6cm
-protokolle_latex_pagestyle: '' # fancy
-protokolle_latex_packages: [] # ["[absolute]{textpos}", "{fancyheadings}"]
-protokolle_latex_header_footer: None # True
-protokolle_logos: []
-protokolle_auth_max_duration: 86400
-protokolle_auth_backends:
-  - type: ADManager
-    host: auth.example.com
-    domain: EXAMPLE
-    user_dn: 'cn=users,dc=example,dc=com'
-    group_dn: 'dc=example,dc=com'
-    ca_cert: ''
-    obsolete: False
-protokolle_auth_obsoletion_warning: ''
-
diff --git a/protokollsystem/handlers/main.yml b/protokollsystem/handlers/main.yml
deleted file mode 100644
index 6a11f0a90f6e2fb5d6be19f0fff95a49061e22a5..0000000000000000000000000000000000000000
--- a/protokollsystem/handlers/main.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-# file: protokollsystem/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart uwsgi for protokollsystem
-  service:
-    name: "{{ item }}"
-    state: restarted
-  with_items:
-    - "{{ protokolle_name }}"
-    - "{{ protokolle_name }}-celery"
-
-- name: create tmpfiles
-  command: systemd-tmpfiles --create
diff --git a/protokollsystem/meta/main.yml b/protokollsystem/meta/main.yml
deleted file mode 100644
index 010a6a3d8fe3704df9797a33f26b18d421290c69..0000000000000000000000000000000000000000
--- a/protokollsystem/meta/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-# file: protokollsystem/meta/main.yml
-dependencies:
-  - { role: texlive }
-  - { role: cups-client }
-  - { role: uwsgi-python, uwsgi_name: "{{protokolle_name}}", uwsgi_user: "{{protokolle_user}}", uwsgi_group: "{{protokolle_group}}", uwsgi_path: "{{protokolle_web_root}}", uwsgi_home: "{{protokolle_web_root}}", uwsgi_program: "server.py", uwsgi_callable: "app", uwsgi_command: "runserver", uwsgi_db: "postgres", uwsgi_python: 3, uwsgi_mules: 1, uwsgi_options: ["enable-threads"] }
diff --git a/protokollsystem/tasks/main.yml b/protokollsystem/tasks/main.yml
deleted file mode 100644
index 4bcbafc263e06eeca3edf06875157cdc6a1aee7f..0000000000000000000000000000000000000000
--- a/protokollsystem/tasks/main.yml
+++ /dev/null
@@ -1,169 +0,0 @@
----
-# file: protokollsystem/tasks/main.yml
-
-- name: ensure we have all required software and fonts
-  apt:
-    name: "{{ item }}"
-    state: present
-  with_items:
-    - python3-virtualenv
-    - virtualenv
-    - libxml2-dev
-    - libxslt-dev
-    - fontconfig
-    - tex-gyre
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ protokolle_deploy_key }}"
-    dest: /root/.ssh/protokolle
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - protokollsystem
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure fucking git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure we have the program
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:protokollsystem/proto3.git
-    dest: "{{ protokolle_web_root }}"
-    accept_hostkey: True # TODO remove this
-    key_file: /root/.ssh/protokolle
-  notify:
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure fucking git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ protokolle_web_root }}/requirements.txt"
-    virtualenv: "{{ protokolle_web_root }}/"
-    virtualenv_python: python3
-  notify:
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: config.py.j2
-    dest: "{{ protokolle_web_root }}/config.py"
-    owner: "{{ protokolle_user }}"
-    group: "{{ protokolle_group }}"
-    mode: 0640
-  notify:
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: check our config
-  command: "{{protokolle_web_root}}/bin/python {{protokolle_web_root}}/configproxy.py check --log-level warning"
-  args:
-    chdir: "{{protokolle_web_root}}"
-  become: yes
-  become_user: "{{protokolle_user}}"
-  changed_when: no
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure data model upgrades are applied
-  command: "{{protokolle_web_root}}/bin/python {{protokolle_web_root}}/server.py db upgrade"
-  args:
-    chdir: "{{protokolle_web_root}}"
-  become: yes
-  become_user: "{{protokolle_user}}"
-  notify:
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure we have our local templates
-  copy:
-    src: "{{ protokolle_local_templates }}"
-    dest: "{{ protokolle_web_root }}/"
-    owner: "{{ protokolle_user }}"
-    group: "{{ protokolle_group }}"
-    mode: 0644
-  when: protokolle_local_templates|default('') != ''
-  notify:
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure one local template is the default
-  file:
-    src: "{{ protokolle_web_root }}/{{ protokolle_latex_local_templates }}/{{ protokolle_local_templates_default }}/{{ item.path }}"
-    dest: "{{ protokolle_web_root }}/{{ protokolle_latex_local_templates }}/{{ item.path }}"
-    state: link
-  with_filetree: "{{ protokolle_local_templates }}/{{ protokolle_local_templates_default }}"
-  when: protokolle_local_templates|default(False) and protokolle_local_templates_default|default(False)
-  notify:
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: protokollsystem.service.j2
-    dest: "/etc/systemd/system/{{ protokolle_name }}.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- name: ensure the celery unit file exists
-  template:
-    src: celery.service.j2
-    dest: "/etc/systemd/system/{{ protokolle_name }}-celery.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for protokollsystem
-  tags:
-    - protokollsystem
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the services are enabled
-  service:
-    name: "{{ item }}"
-    enabled: yes
-    state: started
-  with_items:
-    - "{{ protokolle_name }}"
-    - "{{ protokolle_name }}-celery"
-  tags:
-    - protokollsystem
-    - webservices
diff --git a/protokollsystem/templates/celery.service.j2 b/protokollsystem/templates/celery.service.j2
deleted file mode 100644
index 512f08b503de9212034d44b02b1e9f3a39d9481c..0000000000000000000000000000000000000000
--- a/protokollsystem/templates/celery.service.j2
+++ /dev/null
@@ -1,14 +0,0 @@
-[Unit]
-Description={{ protokolle_name }}-Celery
-After=network.target
-
-[Service]
-User={{ protokolle_user }}
-Group={{ protokolle_group }}
-WorkingDirectory={{ protokolle_web_root }}
-Environment=VIRTUAL_ENV="{{ protokolle_web_root }}"
-ExecStart={{ protokolle_web_root }}/bin/celery -A server.celery worker --loglevel=DEBUG --concurrency={{ protokolle_celery_concurrency }}
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
diff --git a/protokollsystem/templates/protokollsystem.service.j2 b/protokollsystem/templates/protokollsystem.service.j2
deleted file mode 100644
index 6668f7d245f2472a327622653202e67029d7945d..0000000000000000000000000000000000000000
--- a/protokollsystem/templates/protokollsystem.service.j2
+++ /dev/null
@@ -1,19 +0,0 @@
-[Unit]
-Description={{ protokolle_name }}
-After=network.target
-Wants=protokollsystem-celery.service
-
-[Service]
-{% if protokolle_ldap_cert %}
-Environment=LDAPTLS_CACERT={{ protokolle_ldap_cert }}
-{% endif %}
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/{{ protokolle_name }}.ini
-ExecReload=/bin/kill -HUP $MAINPID
-ExecStop=/bin/kill -INT $MAINPID
-Restart=always
-Type=notify
-NotifyAccess=all
-KillSignal=SIGQUIT
-
-[Install]
-WantedBy=multi-user.target
diff --git a/schildergenerator/defaults/main.yml b/schildergenerator/defaults/main.yml
deleted file mode 100644
index dbd30f85f768d574c703f322407f29d7bbc0cbfa..0000000000000000000000000000000000000000
--- a/schildergenerator/defaults/main.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-# file: schildergenerator/defaults/main.yml
-
-schilder_web_root: /var/www/schilder
-schilder_name: schilder
-schilder_user: schilder
-schilder_group: schilder
-schilder_printsrv: printsrv.fsmpi.rwth-aachen.de
-schilder_printers:
-  - description: "1 - Kopierer"
-    name: "Kopierer"
-schilder_lproptions:
-  - "-Fa4g"
-  - "-N1"
-  - "-o fitplot"
-schilder_templates_url: ''
diff --git a/schildergenerator/files/requirements.txt b/schildergenerator/files/requirements.txt
deleted file mode 100644
index 93aaf2a934547cd0236a8071ebd4ad1dce5a3c4f..0000000000000000000000000000000000000000
--- a/schildergenerator/files/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Flask
-Flask-Genshi
-Genshi
-docutils
diff --git a/schildergenerator/handlers/main.yml b/schildergenerator/handlers/main.yml
deleted file mode 100644
index 9453d1bfcfb93d3824cd9aeb4eecd642ff35da17..0000000000000000000000000000000000000000
--- a/schildergenerator/handlers/main.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-# file: schildergenerator/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart uwsgi for schilder
-  service:
-    name: "{{ schilder_name }}"
-    state: restarted
-
-- name: create tmpfiles
-  command: systemd-tmpfiles --create
diff --git a/schildergenerator/meta/main.yml b/schildergenerator/meta/main.yml
deleted file mode 100644
index a2939c374ebf9e8c5871ec44def63b2d52c36774..0000000000000000000000000000000000000000
--- a/schildergenerator/meta/main.yml
+++ /dev/null
@@ -1,7 +0,0 @@
----
-# file: schildergenerator/meta/main.yml
-
-dependencies:
-  - { role: texlive }
-  - { role: cups-client }
-  - { role: uwsgi-python, uwsgi_name: "{{schilder_name}}", uwsgi_user: "{{schilder_user}}", uwsgi_group: "{{schilder_group}}", uwsgi_path: "{{schilder_web_root}}/program", uwsgi_home: "{{schilder_web_root}}", uwsgi_program: "schilder.py", uwsgi_callable: "app", uwsgi_command: "", uwsgi_db: "", uwsgi_python: 2, uwsgi_mules: 0 }
diff --git a/schildergenerator/tasks/main.yml b/schildergenerator/tasks/main.yml
deleted file mode 100644
index ebaa0055128725d0f7017872a761f5ac404feaa4..0000000000000000000000000000000000000000
--- a/schildergenerator/tasks/main.yml
+++ /dev/null
@@ -1,137 +0,0 @@
----
-# file: schildergenerator/tasks/main.yml
-
-- name: ensure we have necessary software installed
-  apt:
-    name: "{{ item }}"
-    state: present
-  with_items:
-    - graphicsmagick
-    - python-pythonmagick
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ schilder_deploy_key }}"
-    dest: /root/.ssh/schildergenerator
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - schildergenerator
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure fucking git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure the git is at the current revision
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:schilder/schildergenerator.git
-    dest: "{{ schilder_web_root }}"
-    key_file: /root/.ssh/schildergenerator
-    version: HEAD
-  notify:
-    - restart uwsgi for schilder
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure fucking git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure git ignores local files
-  lineinfile:
-    dest: "{{ schilder_web_root }}/.git/info/exclude"
-    line: "{{ item }}"
-    state: present
-  with_items:
-    - data/
-    - include/
-    - lib/
-    - local/
-    - share/
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure we have our requirements
-  copy:
-    src: requirements.txt
-    dest: "{{ schilder_web_root }}/requirements.txt"
-    owner: "{{ schilder_user }}"
-    group: "{{ schilder_group }}"
-    mode: 0644
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ schilder_web_root }}/requirements.txt"
-    virtualenv: "{{ schilder_web_root }}"
-    virtualenv_python: python2
-    virtualenv_site_packages: yes
-  notify:
-    - restart uwsgi for schilder
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: config.py.j2
-    dest: "{{ schilder_web_root }}/config.py"
-    owner: "{{ schilder_user }}"
-    group: "{{ schilder_group }}"
-    mode: 0644
-  notify:
-    - restart uwsgi for schilder
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure we have our templates
-  git:
-    repo: "{{ schilder_templates_url }}"
-    dest: "{{ schilder_web_root }}/tex"
-    key_file: /root/.ssh/schildergenerator
-    version: HEAD
-  notify:
-    - restart uwsgi for schilder
-  tags:
-    - schildergenerator
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: schilder.service.j2
-    dest: "/etc/systemd/system/{{ schilder_name }}.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for schilder
-  tags:
-    - schildergenerator
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the service is enabled
-  service:
-    name: "{{ schilder_name }}"
-    enabled: yes
-    state: started
-  tags:
-    - schildergenerator
-    - webservices
diff --git a/schildergenerator/templates/schilder.service.j2 b/schildergenerator/templates/schilder.service.j2
deleted file mode 100644
index fdd6e0a06f0e831d4ca366e223bb0973ecd8c35e..0000000000000000000000000000000000000000
--- a/schildergenerator/templates/schilder.service.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-[Unit]
-Description={{ schilder_name }}
-After=network.target
-
-[Service]
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/{{ schilder_name }}.ini
-Restart=always
-KillSignal=SIGQUIT
-Type=notify
-NotifyAccess=all
-
-[Install]
-WantedBy=multi-user.target
diff --git a/sso/defaults/main.yml b/sso/defaults/main.yml
deleted file mode 100644
index e47bca9c3c91d89dacaf337f5b1b045b16a07b33..0000000000000000000000000000000000000000
--- a/sso/defaults/main.yml
+++ /dev/null
@@ -1,17 +0,0 @@
----
-# file: sso/defaults/main.yml
-
-program_name: sso
-program_user: sso
-program_group: sso
-program_repository: git@git.fsmpi.rwth-aachen.de:infra/sso.git
-
-sso_auth_use_ad: yes
-sso_auth_host: auth.example.com
-sso_auth_user_dn: "cn=users,dc=example,dc=com"
-sso_auth_group_dn: "dc=example,dc=com"
-sso_auth_ca_cert: ''
-sso_auth_domain: EXAMPLE
-
-sso_domain: "{{ domain }}"
-program_dir: '/var/www/sso'
diff --git a/sso/handlers/main.yml b/sso/handlers/main.yml
deleted file mode 100644
index e1ae721b5051f231f71e53bc18f107c438dd6d4b..0000000000000000000000000000000000000000
--- a/sso/handlers/main.yml
+++ /dev/null
@@ -1,10 +0,0 @@
----
-# file: sso/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart program
-  service:
-    name: "{{ program_name }}"
-    state: restarted
diff --git a/sso/meta/main.yml b/sso/meta/main.yml
deleted file mode 100644
index 7c7a58297721b24cf275b4110bf03311595d64e5..0000000000000000000000000000000000000000
--- a/sso/meta/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-# file: sso/meta/main.yml
-
-dependencies:
-  - { role: uwsgi-python, uwsgi_name: "{{program_name}}", uwsgi_user: "{{program_user}}", uwsgi_group: "{{program_group}}", uwsgi_path: "{{web_root}}/{{program_name}}/program", uwsgi_home: "{{web_root}}/{{program_name}}", uwsgi_program: "sso.py", uwsgi_callable: "app", uwsgi_command: "runserver", tags: ["sso"] }
diff --git a/sso/tasks/main.yml b/sso/tasks/main.yml
deleted file mode 100644
index 6cb83ecde9e9f872f992aee79d2a4046e1a3539a..0000000000000000000000000000000000000000
--- a/sso/tasks/main.yml
+++ /dev/null
@@ -1,110 +0,0 @@
----
-# file: sso/tasks/main.yml
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ sso_deploy_key }}"
-    dest: /root/.ssh/sso
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - sso
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure fucking git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - sso
-    - webservices
-
-- name: ensure the git is at the current revision
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:infra/sso.git
-    dest: "{{ program_dir }}"
-    key_file: /root/.ssh/sso
-    version: HEAD
-  notify:
-    - restart program
-  tags:
-    - sso
-    - webservices
-
-- name: ensure fucking git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - sso
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ program_dir }}/requirements.txt"
-    virtualenv: "{{ program_dir }}"
-    virtualenv_python: python3
-  notify:
-    - restart program
-  tags:
-    - sso
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: config.py.j2
-    dest: "{{ program_dir }}/config.py"
-    owner: "{{ program_user }}"
-    group: "{{ program_group }}"
-    mode: 0644
-  notify:
-    - restart program
-  tags:
-    - sso
-    - webservices
-
-- name: ensure we have our secret config
-  template:
-    src: secret_config.py.j2
-    dest: "{{ program_dir }}/secret_config.py"
-    owner: "{{ program_user }}"
-    group: "{{ program_group }}"
-    mode: 0600
-    force: no
-  notify:
-    - restart program
-  tags:
-    - sso
-    - webservices
-
-- name: ensure git ignores our secret config
-  lineinfile:
-    dest: "{{ program_dir }}/.git/info/exclude"
-    line: "secret_config.py"
-    state: present
-  tags:
-    - sso
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: sso.service.j2
-    dest: "/etc/systemd/system/{{ program_name }}.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart program
-  tags:
-    - sso
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the service is enabled
-  service:
-    name: "{{program_name}}"
-    enabled: yes
-    state: started
-  tags:
-    - sso
-    - webservices
diff --git a/sso/templates/secret_config.py.j2 b/sso/templates/secret_config.py.j2
deleted file mode 100644
index 4fe5c96549857b61df5312e62a3283976da32ff7..0000000000000000000000000000000000000000
--- a/sso/templates/secret_config.py.j2
+++ /dev/null
@@ -1 +0,0 @@
-secret_key = '{{ (2**2048)|random }}'
diff --git a/sso/templates/sso.service.j2 b/sso/templates/sso.service.j2
deleted file mode 100644
index a727ea3dce4ce8912283a67663e4250910e9bd42..0000000000000000000000000000000000000000
--- a/sso/templates/sso.service.j2
+++ /dev/null
@@ -1,13 +0,0 @@
-[Unit]
-Description=Single sign-on
-After=network.target
-
-[Service]
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/{{ program_name }}.ini
-Restart=always
-KillSignal=SIGTERM
-Type=notify
-NotifyAccess=all
-
-[Install]
-WantedBy=multi-user.target
diff --git a/uwsgi-python/defaults/main.yml b/uwsgi-python/defaults/main.yml
deleted file mode 100644
index 9f66a12d030543a43742e8f057ffdaf8c6e546b7..0000000000000000000000000000000000000000
--- a/uwsgi-python/defaults/main.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-# files: uwsgi-python/defaults/main.yml
-
-uwsgi_name: uwsgi
-uwsgi_user: uwsgi
-uwsgi_group: uwsgi
-uwsgi_home: /var/www
-uwsgi_path: /var/www
-uwsgi_program: server.py
-uwsgi_callable: app
-uwsgi_command: runserver
-uwsgi_db: none
-uwsgi_python: 3
-uwsgi_mules: 0
-uwsgi_mountpoint: /
-uwsgi_enable_threads: false
diff --git a/wahlhelfer/files/scip b/uwsgi-python/files/apps/scip
similarity index 100%
rename from wahlhelfer/files/scip
rename to uwsgi-python/files/apps/scip
diff --git a/wahlhelfer/files/zimpl b/uwsgi-python/files/apps/zimpl
similarity index 100%
rename from wahlhelfer/files/zimpl
rename to uwsgi-python/files/apps/zimpl
diff --git a/uwsgi-python/files/uwsgi@.service b/uwsgi-python/files/uwsgi@.service
new file mode 100644
index 0000000000000000000000000000000000000000..d6a346133dc10044b6af6435e3833af79ba464c2
--- /dev/null
+++ b/uwsgi-python/files/uwsgi@.service
@@ -0,0 +1,16 @@
+[Unit]
+Description=uWSGI service unit
+After=syslog.target
+
+[Service]
+ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps/%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
diff --git a/uwsgi-python/files/uwsgi@.socket b/uwsgi-python/files/uwsgi@.socket
new file mode 100644
index 0000000000000000000000000000000000000000..641182e9ae065baad531f1ceac7d9f48fa81d1b4
--- /dev/null
+++ b/uwsgi-python/files/uwsgi@.socket
@@ -0,0 +1,9 @@
+[Unit]
+Description=Socket for uWSGI %I
+
+[Socket]
+# Change this to your uwsgi application port or unix socket location
+ListenStream=/run/uwsgi/%I.sock
+
+[Install]
+WantedBy=sockets.target
diff --git a/uwsgi-python/handlers/main.yml b/uwsgi-python/handlers/main.yml
index c28bb7dd9f2d88756bf3f99a344f849d9946a905..d14e558fee6c18812a1c2108ef1eb3d8dfbac976 100644
--- a/uwsgi-python/handlers/main.yml
+++ b/uwsgi-python/handlers/main.yml
@@ -3,3 +3,76 @@
 
 - name: create tmpfiles
   command: systemd-tmpfiles --create
+
+- name: reload systemd service files
+  command: systemctl daemon-reload
+
+- name: restart uwsgi instance shorturl
+  service: name="uwsgi@shorturl" state=restarted
+
+- name: restart uwsgi instance lehrpreis
+  service: name="uwsgi@lehrpreis" state=restarted
+
+- name: restart uwsgi instance schilder
+  service: name="uwsgi@schilder" state=restarted
+  
+- name: restart uwsgi instance boxes
+  service: name="uwsgi@boxes" state=restarted
+
+- name: restart uwsgi instance sso
+  service: name="uwsgi@sso" state=restarted
+
+- name: restart uwsgi instance migration-webapp
+  service: name="uwsgi@migration-webapp" state=restarted
+
+- name: restart uwsgi instance protokollsystem uwsgi
+  service: name="uwsgi@protokollsystem" state=restarted
+  listen: "restart uwsgi instance protokollsystem"
+
+- name: restart uwsgi instance protokollsystem celery
+  service: name="protokollsystem-celery" state=restarted
+  listen: "restart uwsgi instance protokollsystem"
+
+- name: restart uwsgi instance wahlsystem uwsgi
+  service: name="uwsgi@wahlsystem" state=restarted
+  listen: "restart uwsgi instance wahlsystem"
+
+- name: restart uwsgi instance wahlsystem celery
+  service: name="wahlsystem-celery" state=restarted
+  listen: "restart uwsgi instance wahlsystem"
+
+- name: restart uwsgi instance meckerkasten
+  service: name="uwsgi@meckerkasten" state=restarted
+
+- name: restart uwsgi instance wahlhelfer
+  service: name="uwsgi@wahlhelfer" state=restarted
+
+- name: restart uwsgi instance nfs-api
+  service: name="uwsgi@nfs-api" state=restarted
+
+- name: restart uwsgi instance mail-api
+  service: name="uwsgi@mail-api" state=restarted
+
+- name: restart uwsgi instance printercount
+  service: name="uwsgi@printercount" state=restarted
+
+- name: restart uwsgi instance gnt-web
+  service: name="uwsgi@gnt-web" state=restarted
+
+- name: restart uwsgi instance isic
+  service: name="uwsgi@isic" state=restarted
+
+- name: restart uwsgi instance repo-sync
+  service: name="uwsgi@repo-sync" state=restarted
+
+- name: restart uwsgi instance timer
+  service: name="uwsgi@timer" state=restarted
+
+- name: restart uwsgi instance redeleitsystem
+  service: name="uwsgi@redeleitsystem" state=restarted
+
+- name: restart uwsgi instance lipclms
+  service: name="uwsgi@lipclms" state=restarted
+
+- name: restart uwsgi instance schrank
+  service: name="uwsgi@schrank" state=restarted
diff --git a/uwsgi-python/meta/main.yml b/uwsgi-python/meta/main.yml
deleted file mode 100644
index 97abf43d219480c45fd9c13a3d68585dadacb4a3..0000000000000000000000000000000000000000
--- a/uwsgi-python/meta/main.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-# file: uwsgi-python/meta/main.yml
-dependencies:
-  - { role: uwsgi }
diff --git a/uwsgi-python/tasks/app.yml b/uwsgi-python/tasks/app.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a646ee8b60a3071fe87ca2efbb5f8bb3265e9bd6
--- /dev/null
+++ b/uwsgi-python/tasks/app.yml
@@ -0,0 +1,255 @@
+---
+
+- include_vars: "{{ item }}"
+  with_items:
+    - "../vars/default.yml"
+    - "../vars/{{ app.app }}.yml"
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- include_vars: "{{ inventory_dir }}/vars/{{ app.app_vars }}"
+  when: app.app_vars is defined
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have python 2
+  apt:
+    name: "{{ item }}"
+    state: installed
+  with_items:
+    - python
+    - python-dev
+    - python-virtualenv
+    - uwsgi-plugin-python
+    - virtualenv
+  when: app_python_version == 2
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have python 3
+  apt:
+    name: "{{ item }}"
+    state: installed
+  with_items:
+    - python3
+    - python3-dev
+    - python3-virtualenv
+    - uwsgi-plugin-python3
+    - virtualenv
+  when: app_python_version == 3
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- block:
+  - include: sqlite.yml
+    when: app_db_type == "sqlite"
+  - include: mysql.yml
+    when: app_db_type == "mysql"
+  - include: postgres.yml
+    when: app_db_type == "postgres"
+  when: app_db_type is defined
+
+- name: ensure we have a group
+  group:
+    name: "{{ app_group }}"
+    system: yes
+    state: present
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have a user
+  user:
+    name: "{{ app_user }}"
+    group: "{{ app_group }}"
+    system: yes
+    home: "{{ app_home }}"
+    shell: /usr/bin/nologin
+    createhome: no
+    state: present
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure a temporary directory exists
+  template:
+    src: tmpfiles.conf.j2
+    dest: "/etc/tmpfiles.d/10-{{ app.instance }}.conf"
+    owner: root
+    group: root
+    mode: 0644
+  notify:
+    - create tmpfiles
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have our uwsgi config file
+  template:
+    src: uwsgi.ini.j2
+    dest: "/etc/uwsgi/apps/{{ app.instance }}.ini"
+    owner: root
+    group: root
+    mode: 0644
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure additional software is installed
+  apt: name="{{ item }}" state=present
+  with_items: "{{ app_additional_software }}"
+  when: 
+    - app_additional_software is defined
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure the deploy key is available
+  copy:
+    src: "{{ app_deploy_key }}"
+    dest: "/root/.ssh/{{ app.app }}"
+    owner: root
+    group: root
+    mode: 0600
+  when:
+    - app_deploy_key is defined
+    - app_deploy_key != ''
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+# https://github.com/ansible/ansible/issues/27699
+- name: ensure git module is able to clone
+  command: mount -o remount,exec /tmp
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have the program
+  git:
+    repo: "{{ app_git_url }}"
+    dest: "{{ app_path }}"
+    key_file: "/root/.ssh/{{ app.app }}"
+    version: "{{ app_git_version }}"
+  notify:
+    - "restart uwsgi instance {{ app.instance }}"
+  when:
+    - app_deploy_key is defined
+    - app_deploy_key != ''
+  register: git
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have the program (without key file)
+  git:
+    repo: "{{ app_git_url }}"
+    dest: "{{ app_path }}"
+    version: "{{ app_git_version }}"
+  notify:
+    - "restart uwsgi instance {{ app.instance }}"
+  when:
+    - (app_deploy_key is not defined) or (app_deploy_key == '')
+  register: git
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure git module is not able to clone anymore
+  command: mount -o remount,noexec /tmp
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have a virtualenv
+  pip:
+    requirements: "{{ app_path }}/{{ app_requirements_file }}"
+    virtualenv: "{{ app_venv }}"
+    virtualenv_python: "python{{ app_python_version }}"
+  notify:
+    - "restart uwsgi instance {{ app.instance }}"
+  when:
+    - app_requirements_file is defined
+    - app_requirements_file != ''
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have our config
+  template:
+    src: "apps/{{ app.app }}.j2"
+    dest: "{{ app_path }}/{{ app_config_file }}"
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0640
+  notify:
+    - "restart uwsgi instance {{ app.instance }}"
+  when:
+    - app_config_file is defined
+    - app_config_file != ''
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- name: ensure we have our secret config
+  template:
+    src: secret_config.py.j2
+    dest: "{{ app_path }}/secret_config.py"
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0600
+    force: no
+  notify:
+    - "restart uwsgi instance {{ app.instance }}"
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+  when: 
+    - app_secret_config is defined
+    - app_secret_config == True
+
+
+- include_tasks: "{{ item }}"
+  with_first_found:
+    - files:
+        - "apps/{{ app.app }}.yml"
+      skip: true 
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+- meta: flush_handlers
+
+- name: ensure the service is enabled
+  service:
+    name: "uwsgi@{{ app.instance }}"
+    enabled: yes
+    state: started
+  tags:
+    - uwsgi-app
+    - "{{ app.app }}"
+    - "{{ app.instance }}"
+
+
diff --git a/uwsgi-python/tasks/apps/lehrpreis.yml b/uwsgi-python/tasks/apps/lehrpreis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ce1b3df295b079dd472feb407cd579813c7e5ca1
--- /dev/null
+++ b/uwsgi-python/tasks/apps/lehrpreis.yml
@@ -0,0 +1,18 @@
+- name: ensure we have our branded logo
+  copy:
+    src: "{{ lehrpreis_branding_logo_src }}"
+    dest: "{{ app_path }}/static/images/{{ lehrpreis_branding_logo }}"
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0644
+  notify:
+    - restart uwsgi instance {{ app.instance }}
+  when: lehrpreis_branding_logo and lehrpreis_branding_logo_src
+
+- name: ensure the translations are compiled
+  command: "{{ app_venv }}/bin/pybabel compile -d translations"
+  args:
+    chdir: "{{ app_path }}"
+  when: git.changed
+  notify:
+    - restart uwsgi instance {{ app.instance }}
diff --git a/uwsgi-python/tasks/apps/lipclms.yml b/uwsgi-python/tasks/apps/lipclms.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f725b759c0d9920390f2bb6ad7bfbc83e183078e
--- /dev/null
+++ b/uwsgi-python/tasks/apps/lipclms.yml
@@ -0,0 +1,26 @@
+---
+
+#https://github.com/ansible/ansible/issues/42983
+- name: ensure there exists a .ansible folder
+  file:
+    path: "{{app_path}}/.ansible"
+    state: directory
+    owner: "{{app_user}}"
+    group: "{{app_group}}"
+
+- name: ensure data model upgrades are applied
+  command: "{{app_venv}}/bin/python {{app_path}}/lipclms.py db upgrade"
+  args:
+    chdir: "{{app_path}}"
+  become: yes
+  become_user: "{{app_user}}"
+  notify:
+    - "restart uwsgi instance {{app.instance}}" 
+
+- name: ensure the folder from above is not present anymore
+  file:
+    path: "{{app_path}}/.ansible"
+    state: absent
+
+
+
diff --git a/uwsgi-python/tasks/apps/mail-api.yml b/uwsgi-python/tasks/apps/mail-api.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d64e4156800d0556197cd3958cac761483e61efd
--- /dev/null
+++ b/uwsgi-python/tasks/apps/mail-api.yml
@@ -0,0 +1,21 @@
+---
+
+- name: ensure mail-api can create maildirs
+  template:
+    src: apps/mail-api-sudoers.j2
+    dest: /etc/sudoers.d/mailapi
+    owner: root
+    group: root
+    mode: 0440
+  tags:
+    - usercripts
+    - mailapi
+    - webservices
+
+- name: check the sudo config
+  command: visudo -q -c -f /etc/sudoers
+  changed_when: no
+  tags:
+    - userscripts
+    - mailapi
+    - webservices
diff --git a/uwsgi-python/tasks/apps/nfs-api.yml b/uwsgi-python/tasks/apps/nfs-api.yml
new file mode 100644
index 0000000000000000000000000000000000000000..32fd576de16bf7d66d1835cc5938835e76d9bbb9
--- /dev/null
+++ b/uwsgi-python/tasks/apps/nfs-api.yml
@@ -0,0 +1,21 @@
+---
+
+- name: ensure nfs-api can create homedirs
+  template:
+    src: apps/nfs-api-sudoers.j2
+    dest: /etc/sudoers.d/nfsapi
+    owner: root
+    group: root
+    mode: 0440
+  tags:
+    - usercripts
+    - nfsapi
+    - webservices
+
+- name: check the sudo config
+  command: visudo -q -c -f /etc/sudoers
+  changed_when: no
+  tags:
+    - userscripts
+    - nfsapi
+    - webservices
diff --git a/uwsgi-python/tasks/apps/printercount.yml b/uwsgi-python/tasks/apps/printercount.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9b09441e50a72af5e5787ddcadff648fe76f486c
--- /dev/null
+++ b/uwsgi-python/tasks/apps/printercount.yml
@@ -0,0 +1,42 @@
+---
+
+- name: ensure git ignores our secret config
+  lineinfile:
+    dest: "{{app_path}}/.git/info/exclude"
+    line: "secret_config.py"
+    state: present
+  tags:
+    - printercount
+
+- name: ensure the program has access to all the logs
+  acl:
+    path: "{{printercount_log_dir}}"
+    entity: "{{app_user}}"
+    etype: user
+    permissions: r
+    state: present
+    recursive: yes
+  tags:
+    - printercount
+
+- name: ensure the program will have access to all the logs
+  acl:
+    path: "{{printercount_log_dir}}"
+    entity: "{{app_user}}"
+    etype: user
+    permissions: r
+    default: yes
+    state: present
+  tags:
+    - printercount
+
+- name: ensure the program may see all the logs
+  acl:
+    path: "{{printercount_log_dir}}"
+    entity: "{{app_user}}"
+    etype: user
+    permissions: rx
+    state: present
+  tags:
+    - printercount
+
diff --git a/uwsgi-python/tasks/apps/protokollsystem.yml b/uwsgi-python/tasks/apps/protokollsystem.yml
new file mode 100644
index 0000000000000000000000000000000000000000..99b2d1b82eb8e51fbd1844c8fdbb6c0a665b77b0
--- /dev/null
+++ b/uwsgi-python/tasks/apps/protokollsystem.yml
@@ -0,0 +1,71 @@
+---
+# file: protokollsystem/tasks/main.yml
+
+
+#https://github.com/ansible/ansible/issues/42983
+- name: ensure there exists a .ansible folder
+  file:
+    path: "{{app_path}}/.ansible"
+    state: directory
+    owner: "{{app_user}}"
+    group: "{{app_group}}"
+
+- name: check our config
+  command: "{{app_venv}}/bin/python {{app_path}}/configproxy.py check --log-level warning"
+  args:
+    chdir: "{{app_path}}"
+  become: yes
+  become_user: "{{app_user}}"
+  changed_when: no
+
+- name: ensure data model upgrades are applied
+  command: "{{app_venv}}/bin/python {{app_path}}/server.py db upgrade"
+  args:
+    chdir: "{{app_path}}"
+  become: yes
+  become_user: "{{app_user}}"
+  notify:
+    - "restart uwsgi instance {{app.instance}}" 
+
+- name: ensure the folder from above is not present anymore
+  file:
+    path: "{{app_path}}/.ansible"
+    state: absent
+
+- name: ensure we have our local templates
+  copy:
+    src: "{{ protokolle_local_templates }}"
+    dest: "{{ app_path }}/"
+    owner: "{{ protokolle_user }}"
+    group: "{{ protokolle_group }}"
+    mode: 0644
+  when: protokolle_local_templates|default('') != ''
+  notify:
+    - "restart uwsgi instance {{app.instance}}"
+
+- name: ensure one local template is the default
+  file:
+    src: "{{ app_path }}/{{ protokolle_latex_local_templates }}/{{ protokolle_local_templates_default }}/{{ item.path }}"
+    dest: "{{ app_path }}/{{ protokolle_latex_local_templates }}/{{ item.path }}"
+    state: link
+  with_filetree: "{{ protokolle_local_templates }}/{{ protokolle_local_templates_default }}"
+  when: protokolle_local_templates|default(False) and protokolle_local_templates_default|default(False)
+  notify:
+    - "restart uwsgi instance {{app.instance}}"
+
+- name: ensure the celery unit file exists
+  template:
+    src: apps/protokollsystem-celery.service.j2
+    dest: "/etc/systemd/system/{{ app_name }}-celery.service"
+    owner: root
+    group: root
+    mode: 0644
+  notify:
+    - reload systemd service files
+    - "restart uwsgi instance {{app.instance}}"
+
+- name: ensure the celery service is enabled
+  service:
+    name: "{{app_name}}-celery"
+    enabled: yes
+    state: started
diff --git a/uwsgi-python/tasks/apps/redeleitsystem.yml b/uwsgi-python/tasks/apps/redeleitsystem.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e21cc14d710dc51c0358996dee33996d2ae6e541
--- /dev/null
+++ b/uwsgi-python/tasks/apps/redeleitsystem.yml
@@ -0,0 +1,24 @@
+---
+
+
+#https://github.com/ansible/ansible/issues/42983
+- name: ensure there exists a .ansible folder
+  file:
+    path: "{{app_path}}/.ansible"
+    state: directory
+    owner: "{{app_user}}"
+    group: "{{app_group}}"
+
+- name: ensure data model upgrades are applied
+  command: "{{app_venv}}/bin/python {{app_path}}/server.py db upgrade"
+  args:
+    chdir: "{{app_path}}"
+  become: yes
+  become_user: "{{app_user}}"
+  notify:
+    - "restart uwsgi instance {{app.instance}}" 
+    
+- name: ensure the folder from above is not present anymore
+  file:
+    path: "{{app_path}}/.ansible"
+    state: absent
diff --git a/uwsgi-python/tasks/apps/repo-sync.yml b/uwsgi-python/tasks/apps/repo-sync.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1b8973e3f9e52517ec15662d5f067bcf1d4eaf77
--- /dev/null
+++ b/uwsgi-python/tasks/apps/repo-sync.yml
@@ -0,0 +1,18 @@
+- name: ensure we have a directory for additional ssh keys
+  file:
+    state: directory
+    dest: "{{ app_home }}/.ssh/"
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0700
+
+- name: ensure we have additional ssh keys
+  copy:
+    src: "{{ item }}"
+    dest: "{{ app_home }}/.ssh/"
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0600
+  with_items:
+    - "{{ repo_sync_ssh_keys }}"
+    - "{{ repo_sync_ssh_keys }}".pub
diff --git a/uwsgi-python/tasks/apps/schilder.yml b/uwsgi-python/tasks/apps/schilder.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d51093e58adbca88fdc5b39eb42229466e9cdbc0
--- /dev/null
+++ b/uwsgi-python/tasks/apps/schilder.yml
@@ -0,0 +1,15 @@
+# https://github.com/ansible/ansible/issues/27699
+- name: ensure git module is able to clone
+  command: mount -o remount,exec /tmp
+
+- name: ensure we have our templates
+  git:
+    repo: "{{ schilder_templates_url }}"
+    dest: "{{ app_home }}/tex"
+    key_file: /root/.ssh/schilder
+    version: HEAD
+  notify:
+    - "restart uwsgi instance {{ app.instance }}"
+
+- name: ensure git module is not able to clone anymore
+  command: mount -o remount,noexec /tmp
diff --git a/uwsgi-python/tasks/apps/wahlhelfer.yml b/uwsgi-python/tasks/apps/wahlhelfer.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9d889f335352250764090db12e7fd4ab05445b42
--- /dev/null
+++ b/uwsgi-python/tasks/apps/wahlhelfer.yml
@@ -0,0 +1,16 @@
+---
+
+- name: ensure we have the linear solver
+  copy:
+    src: "apps/{{ item }}"
+    dest: "{{ app_path }}/zibopt/"
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0755
+  with_items:
+    - scip
+    - zimpl
+  tags:
+    - wahlhelfer
+    - webservices
+
diff --git a/uwsgi-python/tasks/apps/wahlsystem.yml b/uwsgi-python/tasks/apps/wahlsystem.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5d029af634105aef81b97d7bf69e8948b32b7188
--- /dev/null
+++ b/uwsgi-python/tasks/apps/wahlsystem.yml
@@ -0,0 +1,29 @@
+---
+
+- name: ensure we have the blogfiles folder
+  file:
+    name: "{{ app_path }}/blogfiles"
+    state: directory
+    owner: "{{ app_user }}"
+    group: "{{ app_group }}"
+    mode: 0755
+  tags:
+    - wahlsystem
+    - webservices
+
+- name: ensure the celery unit file exists
+  template:
+    src: apps/wahlsystem-celery.service.j2
+    dest: "/etc/systemd/system/{{ app_name }}-celery.service"
+    owner: root
+    group: root
+    mode: 0644
+  notify:
+    - reload systemd service files
+    - "restart uwsgi instance {{app.instance}}"
+
+- name: ensure the celery service is enabled
+  service:
+    name: "{{app_name}}-celery"
+    enabled: yes
+    state: started
diff --git a/uwsgi-python/tasks/main.yml b/uwsgi-python/tasks/main.yml
index f63c6bee3d5571e604cdb488579da634097e6616..cc87390ae5960b0979f2296b7cc9bd951f2bffe7 100644
--- a/uwsgi-python/tasks/main.yml
+++ b/uwsgi-python/tasks/main.yml
@@ -1,99 +1,45 @@
 ---
 # file: uwsgi-python/tasks/main.yml
 
-- name: ensure we have python 2
-  apt:
-    name: "{{ item }}"
-    state: installed
-  with_items:
-    - python
-    - python-dev
-    - python-virtualenv
-    - uwsgi-plugin-python
-    - virtualenv
-  when: uwsgi_python == 2
-  tags:
-    - uwsgi-python
-    - webservices
-
-- name: ensure we have python 3
-  apt:
-    name: "{{ item }}"
-    state: installed
-  with_items:
-    - python3
-    - python3-dev
-    - python3-virtualenv
-    - uwsgi-plugin-python3
-    - virtualenv
-  when: uwsgi_python == 3
-  tags:
-    - uwsgi-python
-    - webservices
 
-- name: ensure we have the necessary libraries for ldap
+- name: ensure uwsgi is installed
   apt:
-    name: "{{ item }}"
+    name: uwsgi
     state: installed
-  with_items:
-    - libsasl2-dev
-    - libssl-dev
-    - libldap2-dev
   tags:
-    - uwsgi-python
+    - uwsgi
     - webservices
 
-- include: sqlite.yml
-  when: uwsgi_db == "sqlite"
-
-- include: mysql.yml
-  when: uwsgi_db == "mysql"
-
-- include: postgres.yml
-  when: uwsgi_db == "postgres"
-
-- name: ensure we have a group
-  group:
-    name: "{{ uwsgi_group }}"
-    system: yes
-    state: present
-  tags:
-    - uwsgi-python
-    - webservices
-
-- name: ensure we have a user
-  user:
-    name: "{{ uwsgi_user }}"
-    group: "{{ uwsgi_group }}"
-    system: yes
-    home: "{{ uwsgi_home }}"
-    shell: /usr/bin/nologin
-    createhome: no
-    state: present
-  tags:
-    - uwsgi-python
-    - webservices
-
-- name: ensure a temporary directory exists
-  template:
-    src: tmpfiles.conf.j2
-    dest: "/etc/tmpfiles.d/10-{{uwsgi_name}}.conf"
+- name: ensure we have archlinux's systemd-service file
+  copy: 
+    src: uwsgi@.service
+    dest: /etc/systemd/system/uwsgi@.service
     owner: root
     group: root
     mode: 0644
-  notify:
-    - create tmpfiles
+  notify: 
+    - reload systemd service files
   tags:
-    - uwsgi-python
+    - uwsgi
     - webservices
 
-- name: ensure we have our uwsgi config file
-  template:
-    src: uwsgi.ini.j2
-    dest: "/etc/uwsgi/apps-available/{{ uwsgi_name }}.ini"
+- name: ensure the uwsgi app folder is present
+  file: 
+    path: /etc/uwsgi/apps/
+    state: directory
     owner: root
     group: root
-    mode: 0644
+    mode: 0755
   tags:
-    - uwsgi-python
+    - uwsgi
     - webservices
+
+- include_tasks: app.yml  
+  with_items: "{{ webapps }}"
+  loop_control:
+    loop_var: app
+    label: "{{app.app}} {{app.instance}}"
+  tags:
+    - uwsgi
+    - webservices
+
diff --git a/uwsgi-python/tasks/mysql.yml b/uwsgi-python/tasks/mysql.yml
index 28bf42daf2d60a1fc8547c18e0a7320ddd70dbab..7001771ecc4d4a3de4993e424826b2c042abc675 100644
--- a/uwsgi-python/tasks/mysql.yml
+++ b/uwsgi-python/tasks/mysql.yml
@@ -15,10 +15,10 @@
 
 - name: ensure the mysql database exists
   mysql_db:
-    name: "{{ uwsgi_name }}"
+    name: "{{ app_db_name }}"
     state: present
     login_user: root
-    login_password: "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql create=true length=20')}}"
+    login_password: "{{ lookup('passwordstore', 'db/{{ansible_hostname}}-mysql create=true length=20') }}"
   no_log: True
   tags:
     - uwsgi-python
@@ -26,12 +26,12 @@
 
 - name: ensure the database user for mysql exists
   mysql_user:
-    name: "{{uwsgi_user}}"
-    password: "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql-{{uwsgi_user}} create=true length=20')}}"
+    name: "{{ app_user }}"
+    password: "{{ lookup('passwordstore', 'db/{{ansible_hostname}}-mysql-{{app_user}} create=true length=20') }}"
     state: present
     login_user: root
     login_password: "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql create=true length=20')}}"
-    priv: "{{uwsgi_name}}.*:ALL"
+    priv: "{{ app_db_name }}.*:ALL"
   no_log: True
   tags:
     - uwsgi-python
diff --git a/uwsgi-python/tasks/postgres.yml b/uwsgi-python/tasks/postgres.yml
index 5b0a5b5b8f7535f2f02ce5ce9f77d7dfe03f4d18..c05f688345a5685bcd314ce1ec77a40ca9299e74 100644
--- a/uwsgi-python/tasks/postgres.yml
+++ b/uwsgi-python/tasks/postgres.yml
@@ -3,7 +3,7 @@
 
 - name: ensure we have a postgres database user
   postgresql_user:
-    name: "{{ uwsgi_user }}"
+    name: "{{ app_user }}"
     state: present
   become: yes
   become_user: postgres
@@ -13,8 +13,8 @@
 
 - name: ensure we have a postgres database
   postgresql_db:
-    name: "{{ uwsgi_name }}"
-    owner: "{{ uwsgi_user }}"
+    name: "{{ app_db_name }}"
+    owner: "{{ app_user }}"
     state: present
   become: yes
   become_user: postgres
@@ -24,8 +24,8 @@
 
 - name: ensure the database user has privileges
   postgresql_privs:
-    database: "{{ uwsgi_name }}"
-    roles: "{{ uwsgi_user }}"
+    database: "{{ app_db_name }}"
+    roles: "{{ app_user }}"
     privs: ALL
     state: present
     type: database
diff --git a/uwsgi-python/templates/apps/gnt-web.j2 b/uwsgi-python/templates/apps/gnt-web.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b42dbd45a013eee66349724d81a56467b32bdc00
--- /dev/null
+++ b/uwsgi-python/templates/apps/gnt-web.j2
@@ -0,0 +1,12 @@
+from secret_config import secret_key as SECRET_KEY, security_key as SECURITY_KEY
+
+DEBUG = False
+
+#RAPI_ENDPOINT = "localhost"
+RAPI_ENDPOINT="{{ gnt_web_rapi_endpoint }}"
+RAPI_USER = "{{ gnt_web_rapi_user }}"
+RAPI_PASSWORD = "{{ gnt_web_rapi_password }}"
+
+SESSION_PROTECTION = "strong"
+
+ADMIN_GROUP = "{{ gnt_web_admin_group }}"
diff --git a/uwsgi-python/templates/apps/isic.j2 b/uwsgi-python/templates/apps/isic.j2
new file mode 100644
index 0000000000000000000000000000000000000000..fb71a7b638ded16e21c86bad534e668374ff5f60
--- /dev/null
+++ b/uwsgi-python/templates/apps/isic.j2
@@ -0,0 +1,22 @@
+from secret_config import secret_key as SECRET_KEY
+DEBUG = False
+SESSION_COOKIE_SECURE = True
+
+import datetime
+REMEMBER_COOKIE_NAME = 'remember_token'
+REMEMBER_COOKIE_DURATION = datetime.timedelta(30)
+REMEMBER_COOKIE_DOMAIN = None
+REMEMBER_COOKIE_PATH = '/'
+REMEMBER_COOKIE_SECURE = True
+REMEMBER_COOKIE_HTTPONLY = True
+
+AD_HOST = '{{ isic_ad_host }}'
+AD_DOMAIN = '{{ isic_ad_domain }}'
+AD_USER_DN = '{{ isic_ad_user_dn }}'
+AD_GROUP_DN = '{{ isic_ad_group_dn }}'
+AD_CA_CERT = '{{ isic_ad_ca_cert }}'
+AD_AUTH_GROUP = '{{ isic_ad_auth_group }}'
+
+USE_EXTERNAL_COMMAND = {{ isic_use_external_command }}
+PRINTER_HOST = '{{ isic_printer_host }}'
+PRINTER_PORT = {{ isic_printer_port }}
diff --git a/lehrpreis/templates/config.py.j2 b/uwsgi-python/templates/apps/lehrpreis.j2
similarity index 94%
rename from lehrpreis/templates/config.py.j2
rename to uwsgi-python/templates/apps/lehrpreis.j2
index 45311a69b15502eb36f1f3c6eb88c5245d608ac4..d4f8a805975dc475a416a92b51044fa63b00fc44 100644
--- a/lehrpreis/templates/config.py.j2
+++ b/uwsgi-python/templates/apps/lehrpreis.j2
@@ -1,5 +1,5 @@
 from secret_config import secret_key as SECRET_KEY
-SQLALCHEMY_DATABASE_URI = 'postgresql://lehrpreis:@/lehrpreis'
+SQLALCHEMY_DATABASE_URI = 'postgresql://{{ app_user }}:@/{{ app_db_name }}'
 DEBUG = False
 PORT = 5001
 SESSION_COOKIE_SECURE = True
diff --git a/uwsgi-python/templates/apps/lipclms.j2 b/uwsgi-python/templates/apps/lipclms.j2
new file mode 100644
index 0000000000000000000000000000000000000000..1c0b61d44d6ad8191820caea550d83e4658664e9
--- /dev/null
+++ b/uwsgi-python/templates/apps/lipclms.j2
@@ -0,0 +1,13 @@
+SQLALCHEMY_DATABASE_URI = 'postgresql://{{ app_user }}:@/{{ app_db_name }}'
+MAILMAN_API_URL = '{{ lipclms_mailman_api_url }}'
+MAILMAN_API_KEY = '{{ lipclms_mailman_api_key }}'
+PRINTING_ACTIVE = {{ lipclms_printing_active }}
+
+DEBUG = False
+from secret_config import secret_key as SECRET_KEY
+SQLALCHEMY_TRACK_MODIFICATIONS = False
+SESSION_COOKIE_SECURE = True
+REMEMBER_COOKIE_DOMAIN = None
+REMEMBER_COOKIE_PATH = '/'
+REMEMBER_COOKIE_SECURE = True
+REMEMBER_COOKIE_HTTPONLY = True
diff --git a/uwsgi-python/templates/apps/mail-api-sudoers.j2 b/uwsgi-python/templates/apps/mail-api-sudoers.j2
new file mode 100644
index 0000000000000000000000000000000000000000..14e84ae7b16127fc6e8a3dbc7f9ac6dc0f5c34fb
--- /dev/null
+++ b/uwsgi-python/templates/apps/mail-api-sudoers.j2
@@ -0,0 +1 @@
+{{app_user}} ALL=NOPASSWD: {{app_path}}/create-maildir.py
diff --git a/uwsgi-python/templates/apps/mail-api.j2 b/uwsgi-python/templates/apps/mail-api.j2
new file mode 100644
index 0000000000000000000000000000000000000000..f6bdae9c0aaa3231fb72aea23a7a7aff3f0d8f57
--- /dev/null
+++ b/uwsgi-python/templates/apps/mail-api.j2
@@ -0,0 +1,29 @@
+AUTH_GROUP = '{{ mail_api_auth_group }}'
+AD_HOST = '{{ mail_api_ad_host }}'
+AD_DOMAIN = '{{ mail_api_domain }}'
+AD_USER_DN = '{{ mail_api_user_dn }}'
+AD_GROUP_DN = '{{ mail_api_group_dn }}'
+AD_CA_CERT = '{{ mail_api_ca_cert }}'
+
+MAIL = '{{ mail_api_maildirs }}'
+APPEND_PATH = '{{ mail_api_append_path }}'
+SUB_MAILDIRS = [
+{% for sdir in mail_api_sub_maildirs %}
+    '{{ sdir }}',
+{% endfor %}
+]
+
+SMTP_TEMPLATE = '{{ mail_api_smtp_template }}'
+SMTP_SUBJECT = '{{ mail_api_smtp_subject }}'
+SMTP_DOMAIN = '{{ mail_api_smtp_domain }}'
+SMTP_REPLY_TO = '{{ mail_api_smtp_reply_to }}'
+SMTP_NOTIFY_TEMPLATE = '{{ mail_api_smtp_notify_template }}'
+SMTP_NOTIFY_SUBJECT = '{{ mail_api_smtp_notify_subject }}'
+SMTP_NOTIFY_MAIL = '{{ mail_api_smtp_notify_mail }}'
+SMTP_ENCRYPTION = '{{ mail_api_smtp_encryption }}' # 'starttls', 'ssl', 'none'
+SMTP_HOST = '{{ mail_api_smtp_host }}'
+SMTP_PORT = '{{ mail_api_smtp_port }}'
+SMTP_AUTH = {{ mail_api_smtp_auth }}
+ONBOARDING_ORGANIZATION = '{{ mail_api_onboarding_organization }}'
+ONBOARDING_WIKI = '{{ mail_api_onboarding_wiki }}'
+ONBOARDING_WIKI_HOWTO = '{{ mail_api_onboarding_wiki_howto }}'
diff --git a/meckerkasten/templates/settings.py.j2 b/uwsgi-python/templates/apps/meckerkasten.j2
similarity index 97%
rename from meckerkasten/templates/settings.py.j2
rename to uwsgi-python/templates/apps/meckerkasten.j2
index 965b63f89d21b9f22b55c9328d817f30cc9fbb1e..982f9f49f90bf821657e24b5e982498e0af6b52c 100644
--- a/meckerkasten/templates/settings.py.j2
+++ b/uwsgi-python/templates/apps/meckerkasten.j2
@@ -19,7 +19,7 @@ DEFAUL_FROM_EMAIL = "{{ meckerkasten_sender }}"
 DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.sqlite3',
-        'NAME': 'meckerkasten.sqlite3',
+        'NAME': '{{ app_db_name }}',
         'USER': '',
         'PASSWORD': '',
         'HOST': '',
@@ -93,7 +93,9 @@ STATICFILES_FINDERS = (
 )
 
 # Make this unique, and don't share it with anybody.
-SECRET_KEY = '{{ (2**2048)|random }}'
+import sys
+sys.path.append('..')
+from secret_config import secret_key as SECRET_KEY
 
 TEMPLATES = [
     {
diff --git a/uwsgi-python/templates/apps/nfs-api-sudoers.j2 b/uwsgi-python/templates/apps/nfs-api-sudoers.j2
new file mode 100644
index 0000000000000000000000000000000000000000..aee238f0a717b462a5486f3f5737b97567c75c72
--- /dev/null
+++ b/uwsgi-python/templates/apps/nfs-api-sudoers.j2
@@ -0,0 +1 @@
+{{app_user}} ALL=NOPASSWD: {{app_path}}/create-homedir.py
diff --git a/uwsgi-python/templates/apps/nfs-api.j2 b/uwsgi-python/templates/apps/nfs-api.j2
new file mode 100644
index 0000000000000000000000000000000000000000..b123ef8e249e6f5c1bcbcc315af30090658e1919
--- /dev/null
+++ b/uwsgi-python/templates/apps/nfs-api.j2
@@ -0,0 +1,7 @@
+HOMEDIRS = '{{nfs_api_homedirs}}'
+AUTH_GROUP = '{{nfs_api_auth_group}}'
+AD_HOST = '{{nfs_api_ad_host}}'
+AD_DOMAIN = '{{nfs_api_domain}}'
+AD_USER_DN = '{{nfs_api_user_dn}}'
+AD_GROUP_DN = '{{nfs_api_group_dn}}'
+AD_CA_CERT = '{{nfs_api_ca_cert}}'
diff --git a/uwsgi-python/templates/apps/printercount.j2 b/uwsgi-python/templates/apps/printercount.j2
new file mode 100644
index 0000000000000000000000000000000000000000..cb06fbf62b881b448d9d0fcd0da762da59d1d6ff
--- /dev/null
+++ b/uwsgi-python/templates/apps/printercount.j2
@@ -0,0 +1,8 @@
+DEBUG = False
+
+TIMEZONE = "{{printercount_timezone}}"
+DATE_FORMAT = "{{printercount_date_format}}"
+
+PRINTER_LOG_DIR = "{{printercount_log_dir}}"
+
+from secret_config import secret_key as SECRET_KEY
diff --git a/uwsgi-python/templates/apps/protokollsystem-celery.service.j2 b/uwsgi-python/templates/apps/protokollsystem-celery.service.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ad5b30878559674d0b0526c705870ddfa7c58b9c
--- /dev/null
+++ b/uwsgi-python/templates/apps/protokollsystem-celery.service.j2
@@ -0,0 +1,14 @@
+[Unit]
+Description={{ app_name }}-Celery
+After=network.target
+
+[Service]
+User={{ app_user }}
+Group={{ app_group }}
+WorkingDirectory={{ app_path }}
+Environment=VIRTUAL_ENV="{{ app_path }}"
+ExecStart={{ app_path }}/bin/celery -A server.celery worker --loglevel=DEBUG --concurrency={{ protokolle_celery_concurrency }}
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/protokollsystem/templates/config.py.j2 b/uwsgi-python/templates/apps/protokollsystem.j2
similarity index 97%
rename from protokollsystem/templates/config.py.j2
rename to uwsgi-python/templates/apps/protokollsystem.j2
index 57e0880931701a48243858f72d5cc75e851cde7b..8efddb747275eae6cab6b68574527a08c2a05c51 100644
--- a/protokollsystem/templates/config.py.j2
+++ b/uwsgi-python/templates/apps/protokollsystem.j2
@@ -1,7 +1,7 @@
-SQLALCHEMY_DATABASE_URI = "postgresql://{{ protokolle_user }}:@/{{ protokolle_name }}"
+SQLALCHEMY_DATABASE_URI = "postgresql://{{app_user}}:@/{{app_name}}"
 SQLALCHEMY_TRACK_MODIFICATIONS = False
 
-SECRET_KEY = "{{ protokolle_secret }}"
+from secret_config import secret_key as SECRET_KEY, security_key as SECURITY_KEY
 
 DEBUG = False
 
@@ -78,7 +78,6 @@ CALENDAR_TIMEZONE_MAP = {
 
 SESSION_PROTECTION = "strong"
 
-SECURITY_KEY = "{{ protokolle_security_key }}"
 from common.auth import LdapManager, ADManager
 AUTH_MAX_DURATION = {{ protokolle_auth_max_duration }}
 AUTH_BACKENDS = [
diff --git a/uwsgi-python/templates/apps/redeleitsystem.j2 b/uwsgi-python/templates/apps/redeleitsystem.j2
new file mode 100644
index 0000000000000000000000000000000000000000..99d9a7b4298d00cdf49b07894301b94bd6b5ae0f
--- /dev/null
+++ b/uwsgi-python/templates/apps/redeleitsystem.j2
@@ -0,0 +1,12 @@
+from secret_config import secret_key as SECRET_KEY
+SQLALCHEMY_DATABASE_URI = "postgresql://{{ app_user }}:@/{{ app_db_name }}"
+SQLALCHEMY_TRACK_MODIFICATIONS = False
+DEBUG = False
+UPDATE_INDEX_INTERVAL = {{ redeleitsystem_update_index }}
+UPDATE_TIME_INTERVAL = {{ redeleitsystem_update_time }}
+
+SESSION_COOKIE_SECURE = True
+REMEMBER_COOKIE_DOMAIN = None
+REMEMBER_COOKIE_PATH = '/'
+REMEMBER_COOKIE_SECURE = True
+REMEMBER_COOKIE_HTTPONLY = True
diff --git a/uwsgi-python/templates/apps/repo-sync.j2 b/uwsgi-python/templates/apps/repo-sync.j2
new file mode 100644
index 0000000000000000000000000000000000000000..9394ce3ad6e52f6fdb92e0c4290ed6ff1b37872a
--- /dev/null
+++ b/uwsgi-python/templates/apps/repo-sync.j2
@@ -0,0 +1,12 @@
+DEBUG = False
+WORKERS = {{ repo_sync_workers }}
+REPOS = {
+{% for repo in repo_sync_repos %}
+    '{{ repo.source }}': '{{ repo.dest }}',
+{% endfor %}
+}
+ALLOWED_SECRETS = {
+{% for repo in repo_sync_secrets %}
+    '{{ repo.source }}': '{{ repo.secret }}',
+{% endfor %}
+}
diff --git a/schildergenerator/templates/config.py.j2 b/uwsgi-python/templates/apps/schilder.j2
similarity index 93%
rename from schildergenerator/templates/config.py.j2
rename to uwsgi-python/templates/apps/schilder.j2
index 956b84cd52bc1aeaaf6cf837e21881ea12e6c342..0952fa5ee905d1da91c0971da263ea1e0eb5144a 100644
--- a/schildergenerator/templates/config.py.j2
+++ b/uwsgi-python/templates/apps/schilder.j2
@@ -3,12 +3,13 @@
 # Secret key (used for session cookie encryption). Needs to be set to some random string.
 # Yes, just smash your keyboard for some random characters. No, don't publish them anywhere.
 # Yes, you will need this. If you get random RuntimeErrors, you did not set this.
-app_secret = '{{ range(10**15, 10**16)|random }}'
+
+from secret_config import secret_key as app_secret
 
 ## You will need to use absolute paths!
 
 # Base directory. You need to set this again in schilder.wsgi if you use WSGI.
-basedir = '{{ schilder_web_root }}'
+basedir = '{{ app_path }}'
 
 # Temp directory for imagemagick/pdflatex work files (needs to be writeable)
 tmpdir = '/tmp'
@@ -22,7 +23,7 @@ datadir = basedir + '/data'
 templatedir = basedir + '/templates'
 
 # TeX template directory
-textemplatedir = '{{ schilder_web_root }}/tex'
+textemplatedir = '{{ app_home }}/tex'
 
 # TeX support file directory (all files that might be needed by a tex template)
 texsupportdir = textemplatedir + '/support'
diff --git a/uwsgi-python/templates/apps/shorturl.j2 b/uwsgi-python/templates/apps/shorturl.j2
new file mode 100644
index 0000000000000000000000000000000000000000..913537f2312c0639350351ac265ead6c5ad118c5
--- /dev/null
+++ b/uwsgi-python/templates/apps/shorturl.j2
@@ -0,0 +1,34 @@
+from secret_config import secret_key as SECRET_KEY
+SQLALCHEMY_DATABASE_URI = 'postgresql://{{ app_user }}:@/{{ app_db_name }}'
+DEFAULT_REDIRECT = '{{ shorturl_default_redirect }}'
+DEBUG = False
+SESSION_COOKIE_SECURE = True
+
+import datetime
+REMEMBER_COOKIE_NAME = 'remember_token'
+REMEMBER_COOKIE_DURATION = datetime.timedelta(30)
+REMEMBER_COOKIE_DOMAIN = None
+REMEMBER_COOKIE_PATH = '/'
+REMEMBER_COOKIE_SECURE = True
+REMEMBER_COOKIE_HTTPONLY = True
+
+ADMIN_GROUP = '{{ shorturl_admin_group }}'
+USER_GROUP = '{{ shorturl_user_group }}'
+
+AD_HOST = '{{ shorturl_ad_host }}'
+AD_DOMAIN = '{{ shorturl_ad_domain }}'
+AD_USER_DN = '{{ shorturl_ad_user_dn }}'
+AD_GROUP_DN = '{{ shorturl_ad_group_dn }}'
+AD_CA_CERT = '{{ shorturl_ad_cert }}'
+
+TARGET_REGEX = '{{ shorturl_target_regex }}'
+
+BRANDING_NAME = '{{ shorturl_branding_name }}'
+BRANDING_DOMAIN = '{{ shorturl_branding_domain }}'
+BRANDING_DOMAIN_REGEX = '{{ shorturl_branding_domain_regex }}'
+BRANDING_CONTACT = '{{ shorturl_branding_contact }}'
+
+MAIL_SUBJECT = '{{ shorturl_mail_subject }}'
+MAIL_DOMAIN = '{{ shorturl_mail_domain }}'
+MAIL_ADMIN = '{{ shorturl_mail_admin }}'
+MAIL_HOST = '{{ shorturl_mail_host }}'
diff --git a/sso/templates/config.py.j2 b/uwsgi-python/templates/apps/sso.j2
similarity index 100%
rename from sso/templates/config.py.j2
rename to uwsgi-python/templates/apps/sso.j2
diff --git a/wahlhelfer/templates/settings.py.j2 b/uwsgi-python/templates/apps/wahlhelfer.j2
similarity index 94%
rename from wahlhelfer/templates/settings.py.j2
rename to uwsgi-python/templates/apps/wahlhelfer.j2
index 48abbcf7c3ffc6ee9e0ab31c44443d59e093806a..ea88172c407dcd8f7669c7cb1c9a0a8d4d9a4e30 100644
--- a/wahlhelfer/templates/settings.py.j2
+++ b/uwsgi-python/templates/apps/wahlhelfer.j2
@@ -13,6 +13,8 @@ SERVER_EMAIL = "{{ wahlhelfer_sender }}"
 EMAIL_HOST = "{{ wahlhelfer_mail_host }}"
 EMAIL_HOST_USER = "{{ wahlhelfer_mail_user|default('') }}"
 EMAIL_HOST_PASSWORD = "{{ wahlhelfer_mail_password|default('') }}"
+EMAIL_PORT = {{ wahlhelfer_mail_port|default('25') }}
+DEFAUL_FROM_EMAIL = "{{ wahlhelfer_sender }}"
 
 LOGIN_URL = '/'
 LOGIN_REDIRECT_URL = '/'
@@ -20,9 +22,9 @@ LOGIN_REDIRECT_URL = '/'
 DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.mysql',
-        'NAME': '{{ wahlhelfer_name }}',
-        'USER': '{{ wahlhelfer_user }}',
-        'PASSWORD': "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql-{{wahlhelfer_user}} create=true length=20')}}",
+        'NAME': '{{ app_db_name }}',
+        'USER': '{{ app_user }}',
+        'PASSWORD': "{{lookup('passwordstore', 'db/{{ansible_hostname}}-mysql-{{app_user}} create=true length=20')}}",
         'HOST': '',
         'PORT': '',
     }
@@ -94,7 +96,9 @@ STATICFILES_FINDERS = (
 )
 
 # Make this unique, and don't share it with anybody.
-SECRET_KEY = '{{ (2**2048)|random }}'
+import sys
+sys.path.append('..')
+from secret_config import secret_key as SECRET_KEY
 
 TEMPLATES = [
     {
diff --git a/uwsgi-python/templates/apps/wahlsystem-celery.service.j2 b/uwsgi-python/templates/apps/wahlsystem-celery.service.j2
new file mode 100644
index 0000000000000000000000000000000000000000..ef365d22ac9bca7d806307e76cad6633dc5d1f12
--- /dev/null
+++ b/uwsgi-python/templates/apps/wahlsystem-celery.service.j2
@@ -0,0 +1,14 @@
+[Unit]
+Description={{ app_name }}-Celery
+After=network.target
+
+[Service]
+User={{ app_user }}
+Group={{ app_group }}
+WorkingDirectory={{ app_path }}
+Environment=VIRTUAL_ENV="{{ app_path }}"
+ExecStart={{ app_path }}/bin/celery -A server.celery worker --loglevel=DEBUG --concurrency={{ wahl_celery_concurrency }}
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/wahlsystem/templates/config.py.j2 b/uwsgi-python/templates/apps/wahlsystem.j2
similarity index 89%
rename from wahlsystem/templates/config.py.j2
rename to uwsgi-python/templates/apps/wahlsystem.j2
index a4a7fdace473e1a8d51fce41c94656e6424b3b45..ef7a7685152533b854864d705c56d2f816fdec00 100644
--- a/wahlsystem/templates/config.py.j2
+++ b/uwsgi-python/templates/apps/wahlsystem.j2
@@ -1,6 +1,6 @@
-SQLALCHEMY_DATABASE_URI = "postgresql://{{ wahl_user }}:@/{{ wahl_name }}"
+from secret_config import secret_key as SECRET_KEY
+SQLALCHEMY_DATABASE_URI = "postgresql://{{ app_user }}:@/{{ app_name }}"
 SQLALCHEMY_TRACK_MODIFICATIONS = False
-SECRET_KEY = "{{ wahl_secret }}"
 DEBUG = False
 MAIL_ACTIVE = {{ wahl_mail }}
 MAIL_FROM = "{{ wahl_mail_from }}"
diff --git a/uwsgi-python/templates/secret_config.py.j2 b/uwsgi-python/templates/secret_config.py.j2
new file mode 100644
index 0000000000000000000000000000000000000000..20aae5bcc4ce7a5239bab38edb767a6ce3aae911
--- /dev/null
+++ b/uwsgi-python/templates/secret_config.py.j2
@@ -0,0 +1,6 @@
+secret_key = '{{ (2**2048)|random }}'
+{% if app_secret_config_keys is defined %}
+{% for key in app_secret_config_keys %}
+{{key}} = '{{ (2**2048)|random }}'
+{% endfor %}
+{% endif %}
diff --git a/uwsgi-python/templates/tmpfiles.conf.j2 b/uwsgi-python/templates/tmpfiles.conf.j2
index 4dba06e9a3e556ed71bf92bee0797c52c9b521af..378ee5b8823d61ad5f92f028030b20ee71362e7f 100644
--- a/uwsgi-python/templates/tmpfiles.conf.j2
+++ b/uwsgi-python/templates/tmpfiles.conf.j2
@@ -1 +1 @@
-d /run/uwsgi/app/{{uwsgi_name}} 0775 {{uwsgi_user}} {{uwsgi_group}} - -
+d /run/uwsgi/{{app.instance}} 0775 {{app_user}} {{app_group}} - -
diff --git a/uwsgi-python/templates/uwsgi.ini.j2 b/uwsgi-python/templates/uwsgi.ini.j2
index 8337e3cc11f983f05373ed19d28dcf2a7b586cbd..3bc2bec56784c9f708804a78bba696082dddf043 100644
--- a/uwsgi-python/templates/uwsgi.ini.j2
+++ b/uwsgi-python/templates/uwsgi.ini.j2
@@ -1,54 +1,52 @@
 [uwsgi]
-uwsgi-socket = /run/uwsgi/app/{{uwsgi_name}}/{{uwsgi_name}}.sock
+uwsgi-socket = /run/uwsgi/{{app.instance}}/{{app.instance}}.sock
 #http = localhost:5000
 chmod-socket = 660
-chown-socket = {{uwsgi_user}}:www-data
+chown-socket = {{app_user}}:www-data
 autoload =
 master =
 processes = 4
 workers = 4
 prio = -5
-harakiri = {{uwsgi_harakiri|default(5)}}
+harakiri = {{app_harakiri|default(5)}}
 buffer-size=32768
-{% if uwsgi_enable_threads %}
+{% if app_enable_threads|default(false) %}
 enable-threads = 
 {% endif %}
-{% if uwsgi_options is defined %}
-{% for option in uwsgi_options %}
+{% if app_uwsgi_options is defined %}
+{% for option in app_uwsgi_options %}
 {{option}}{% if "=" not in option %} ={% endif %}
 {% endfor %}
 {% endif %}
+{% for env in app_service_env %}
+env = {{ env }}
+{% endfor %}
 
-{% for mule in range(uwsgi_mules) %}
+{% for mule in range(app_mules|default(0)) %}
 mule = 
 {% endfor %}
 #umask = 227
-chdir = {{uwsgi_path}}
-uid = {{uwsgi_user}}
-gid = {{uwsgi_group}}
-logto = /var/log/uwsgi/{{uwsgi_name}}.log
-logfile-chown = {{uwsgi_user}}:{{uwsgi_group}}
-logfile-chmod = 664
+chdir = {{app_path}}
+uid = {{app_user}}
+gid = {{app_group}}
 log-date =
 log-4xx = 
 log-5xx = 
 log-x-forwarded-for =
-{% if uwsgi_python == 2 %}
+{% if app_python_version == 2 %}
 plugin = python27
-{% elif uwsgi_python == 3 %}
-{% if debian_version == "jessie" %}
+{% elif app_python_version == 3 %}
+{% if ansible_distribution_release == "jessie" %}
 plugin = python34
-{% elif debian_version == "stretch" %}
+{% elif ansible_distribution_release == "stretch" %}
 plugin = python35
-{% else %}
-plugin = {{uwsgi_python_plugin|mandatory}}{# or add new debian versions here #}
 {% endif %}
-{% else %}
-plugin = {{uwsgi_python_plugin|mandatory}}{# or add new python versions here #}
 {% endif %}
-virtualenv = {{uwsgi_venv|default(uwsgi_path)}}
-wsgi-file = {{uwsgi_path}}/{{uwsgi_program}}
-callable = {{uwsgi_callable}}
-pyargv = {{uwsgi_program}} {{uwsgi_command}}
+{% if app_venv != '' %}
+virtualenv = {{app_venv}}
+{% endif %}
+wsgi-file = {{app_path}}/{{app_program}}
+callable = {{app_callable}}
+pyargv = {{app_program}} {{app_command}}
 manage-script-name =
-mount={{uwsgi_mountpoint}}={{uwsgi_path}}/{{uwsgi_program}}
+mount={{app_mountpoint}}={{app_path}}/{{app_program}}
diff --git a/uwsgi-python/vars/default.yml b/uwsgi-python/vars/default.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f3fa3a2863c44542cb97a4967ab1968205dd84f7
--- /dev/null
+++ b/uwsgi-python/vars/default.yml
@@ -0,0 +1,31 @@
+app_name: "{{ app.app }}"
+app_user: "{{ app.app }}"
+app_group: "{{ app.app }}"
+app_home: "/var/www/{{ app.app }}"
+app_path: "/var/www/{{ app.app }}"
+app_python_version: 3
+app_venv: "/var/www/{{ app.app }}/venv/"
+app_program: "{{ app.app }}.py"
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/{{ app.app }}"
+app_git_url: ""
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
diff --git a/uwsgi-python/vars/gnt-web.yml b/uwsgi-python/vars/gnt-web.yml
new file mode 100644
index 0000000000000000000000000000000000000000..86a58f76c069b781aaf128edc7cc43071b36571c
--- /dev/null
+++ b/uwsgi-python/vars/gnt-web.yml
@@ -0,0 +1,39 @@
+app_name: gnt-web
+app_user: gnt-web
+app_group: gnt-web
+app_home: /opt/gnt-web
+app_path: /opt/gnt-web/program
+app_python_version: 2
+app_venv: /opt/gnt-web/program
+app_program: server.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software:
+  - libcurl4-openssl-dev
+  - libssl-dev
+  - libldap2-dev
+  - libsasl2-dev
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/gnt-web"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/gnt-web.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: ["security_key"]
+
+gnt_web_rapi_endpoint: cloud.example.com
+gnt_web_rapi_user: ''
+gnt_web_rapi_password: ''
+gnt_web_admin_group: admin
diff --git a/uwsgi-python/vars/isic.yml b/uwsgi-python/vars/isic.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4cb8a1a89c22936e93e077d70b7c600610012854
--- /dev/null
+++ b/uwsgi-python/vars/isic.yml
@@ -0,0 +1,40 @@
+app_name: isic
+app_user: isic
+app_group: isic
+app_home: /var/www/asta-isic
+app_path: /var/www/asta-isic
+app_python_version: 3
+app_venv: /var/www/asta-isic/venv/"
+app_program: isic.py
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: ['netcat-openbsd']
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/isic"
+app_git_url: "git@git.stud.rwth-aachen.de:infra/isic.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+isic_ad_host: 'ad.example.com'
+isic_ad_domain: 'EXAMPLE'
+isic_ad_user_dn: 'cn=users,dc=example,dc=com'
+isic_ad_group_dn: 'cn=users,dc=example,dc=com'
+isic_ad_ca_cert: ''
+isic_ad_auth_group: 'users'
+isic_use_external_command: false
+isic_printer_host: '10.10.72.2'
+isic_printer_port: 9100
diff --git a/lehrpreis/defaults/main.yml b/uwsgi-python/vars/lehrpreis.yml
similarity index 53%
rename from lehrpreis/defaults/main.yml
rename to uwsgi-python/vars/lehrpreis.yml
index 3466f7125a80604549794d7e59b8bbf2a2569188..70d0ec2537ea9918b18aac43f23346868fecd138 100644
--- a/lehrpreis/defaults/main.yml
+++ b/uwsgi-python/vars/lehrpreis.yml
@@ -1,10 +1,33 @@
----
-# file: roles/lehrpreis/defaults/main.yml
+app_name: lehrpreis
+app_user: lehrpreis
+app_group: lehrpreis
+app_home: /var/www/lehrpreis
+app_path: /var/www/lehrpreis
+app_python_version: 3
+app_venv: /var/www/lehrpreis/venv/
+app_program: lehrpreis.py
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
 
-lehrpreis_web_root: /var/www/lehrpreis
-lehrpreis_name: lehrpreis
-lehrpreis_user: lehrpreis
-lehrpreis_group: lehrpreis
+app_db_name: lehrpreis
+app_db_type: postgres
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/lehrpreis"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:studi-systeme/lehrpreis.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
 
 lehrpreis_default_locale: en
 lehrpreis_default_timezone: Europe/Berlin
diff --git a/uwsgi-python/vars/lipclms.yml b/uwsgi-python/vars/lipclms.yml
new file mode 100644
index 0000000000000000000000000000000000000000..7d0f7489cd0f3b9faa12ac3f6bf5e7d131aae6d5
--- /dev/null
+++ b/uwsgi-python/vars/lipclms.yml
@@ -0,0 +1,34 @@
+app_name: lipclms
+app_user: lipclms
+app_group: lipclms
+app_home: /var/www/lipclms
+app_path: /var/www/lipclms
+app_python_version: 3
+app_venv: /var/www/lipclms/venv/
+app_program: lipclms.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /anmeldung
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: 'lipclms'
+app_db_type: 'postgres'
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/lipclms"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:osak/lipclms.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+lipclms_mailman_api_url: 'https://lists.example.com/api/'
+lipclms_mailman_api_key: ''
+lipclms_printing_active: false
diff --git a/uwsgi-python/vars/mail-api.yml b/uwsgi-python/vars/mail-api.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8806391f846fa1d03de76a4988b1a61315bd39e1
--- /dev/null
+++ b/uwsgi-python/vars/mail-api.yml
@@ -0,0 +1,57 @@
+app_name: mail-api
+app_user: mailapi
+app_group: mailapi
+app_home: /var/www/mail-api
+app_path: /var/www/mail-api
+app_python_version: 3
+app_venv: /var/www/mail-api/venv
+app_program: mailapi.py
+app_callable: app
+app_command: ""
+app_mountpoint: /api
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: ['close-on-exec']
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/mail-api"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/user-scripts.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements-mail.txt
+app_config_file: config.py
+app_secret_config: false
+app_secret_config_keys: []
+
+mail_api_auth_group: "Domain Admins"
+mail_api_ad_host: "auth.example.com"
+mail_api_domain: "EXAMPLE"
+mail_api_user_dn: "cn=users,dc=example,dc=com"
+mail_api_group_dn: "cn=users,dc=example,dc=com"
+mail_api_ca_cert: ""
+
+mail_api_maildirs: "/maildirs"
+mail_api_append_path: "Maildir"
+mail_api_sub_maildirs:
+  - 'public'
+  - 'public/.Test'
+mail_api_smtp_template: 'welcome.txt.j2'
+mail_api_smtp_subject: 'Your New Account'
+mail_api_smtp_domain: 'example.com'
+mail_api_smtp_reply_to: 'ticket@example.com'
+mail_api_smtp_notify_template: 'notify.txt.j2'
+mail_api_smtp_notify_subject: 'New Account created: {username}'
+mail_api_smtp_notify_mail: 'admin@example.com'
+mail_api_smtp_encryption: 'starttls'
+mail_api_smtp_host: 'mail.example.com'
+mail_api_smtp_port: 587
+mail_api_smtp_auth: true
+mail_api_onboarding_organization: 'EXAMPLE'
+mail_api_onboarding_wiki: 'https://wiki.example.com/'
+mail_api_onboarding_wiki_howto: 'https://wiki.example.com/infra:onboarding'
diff --git a/uwsgi-python/vars/meckerkasten.yml b/uwsgi-python/vars/meckerkasten.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6a7e0345de32c051d68ac119b1271356d177ba83
--- /dev/null
+++ b/uwsgi-python/vars/meckerkasten.yml
@@ -0,0 +1,43 @@
+app_name: meckerkasten
+app_user: meckerkasten
+app_group: meckerkasten
+app_home: /var/www/meckerkasten
+app_path: /var/www/meckerkasten
+app_python_version: 2
+app_venv: /var/www/meckerkasten
+app_program: meckerkasten/wsgi.py
+app_callable: application
+app_command: "runserver"
+app_mountpoint: /
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_type: sqlite
+app_db_name: "meckerkasten.sqlite3"
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/meckerkasten"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:studi-systeme/meckerkasten.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: meckerkasten/settings.py
+app_secret_config: true
+app_secret_config_keys: []
+
+app_additional_software: []
+
+meckerkasten_admins: [['Admins', 'admin@example.com']]
+meckerkasten_sender: 'meckerkasten@example.com'
+meckerkasten_mail_host: 'mail.example.invalid'
+meckerkasten_allowed_hosts: ['example.com']
+meckerkasten_mail_user: ''
+meckerkasten_mail_password: ''
+meckerkasten_mail_port: '25'
+
+app_service_env:
+  - MECKERKASTEN_WEB_ROOT=/var/www/meckerkasten/
+  - MECKERKASTEN_WEB_SUBDIR=meckerkasten
+#  - LDAPTLS_CACERT=
+
diff --git a/uwsgi-python/vars/nfs-api.yml b/uwsgi-python/vars/nfs-api.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8dec6e6b820a2783f6ff4b7e809f97474205ec15
--- /dev/null
+++ b/uwsgi-python/vars/nfs-api.yml
@@ -0,0 +1,38 @@
+app_name: nfs-api
+app_user: nfsapi
+app_group: nfsapi
+app_home: /var/www/nfs-api
+app_path: /var/www/nfs-api
+app_python_version: 3
+app_venv: /var/www/nfs-api/venv
+app_program: nfsapi.py
+app_callable: app
+app_command: ""
+app_mountpoint: /api
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: ['close-on-exec']
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/nfs-api"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/user-scripts.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements-nfs.txt
+app_config_file: config.py
+app_secret_config: false
+app_secret_config_keys: []
+
+nfs_api_homedirs: "/home"
+nfs_api_auth_group: "Domain Admins"
+nfs_api_ad_host: "auth.example.com"
+nfs_api_domain: "EXAMPLE"
+nfs_api_user_dn: "cn=users,dc=example,dc=com"
+nfs_api_group_dn: "cn=users,dc=example,dc=com"
+nfs_api_ca_cert: ""
diff --git a/uwsgi-python/vars/printercount.yml b/uwsgi-python/vars/printercount.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4304a5daab3f78375efa053ae0653ad92a579f58
--- /dev/null
+++ b/uwsgi-python/vars/printercount.yml
@@ -0,0 +1,34 @@
+app_name: printercount
+app_user: printercount
+app_group: printercount
+app_home: /var/www/printercount
+app_path: /var/www/printercount/program
+app_python_version: 3
+app_venv: /var/www/printercount/program
+app_program: server.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /kasse
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/printercount"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:kasse/printercount.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+printercount_timezone: Europe/Berlin
+printercount_date_format: "%d.%m.%Y"
+printercount_log_dir: /var/log/cups/
diff --git a/uwsgi-python/vars/protokollsystem.yml b/uwsgi-python/vars/protokollsystem.yml
new file mode 100644
index 0000000000000000000000000000000000000000..77232d4dedd971322d9a13284d67e3a80f26bf5b
--- /dev/null
+++ b/uwsgi-python/vars/protokollsystem.yml
@@ -0,0 +1,41 @@
+app_name: protokollsystem
+app_user: protokolle
+app_group: protokolle
+app_home: /var/www/protokollsystem
+app_path: /var/www/protokollsystem/program
+app_python_version: 3
+app_mules: 1
+app_enable_threads: true
+app_harakiri: 5
+app_uwsgi_options: []
+app_venv: /var/www/protokollsystem/program/
+app_program: server.py
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+
+app_db_name: protokollsystem
+app_db_type: postgres
+
+app_additional_software:
+  - "libxml2-dev"
+  - "libxslt-dev"
+  - "fontconfig"
+  - "tex-gyre"
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/protokollsystem"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:protokollsystem/proto3.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: ["security_key"]
+
+protokolle_celery_broker: 'redis://localhost:6379/0'
+protokolle_celery_concurrency: 4
+protokolle_wiki_type: MEDIAWIKI
+protokolle_logos: []
+
+protokolle_sentry_dsn: "https://3bbe6efca11645488bc1fb7297013e3a:4747c40e928d401e8e5e9aac49d3b42d@sentry.fsmpi.rwth-aachen.de//4"
diff --git a/uwsgi-python/vars/redeleitsystem.yml b/uwsgi-python/vars/redeleitsystem.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8d74a7bbf49064ab8aa563651d96a50d334d833c
--- /dev/null
+++ b/uwsgi-python/vars/redeleitsystem.yml
@@ -0,0 +1,33 @@
+app_name: redeleitsystem
+app_user: redeleitsystem
+app_group: redeleitsystem
+app_home: /var/www/redeleitsystem
+app_path: /var/www/redeleitsystem
+app_python_version: 3
+app_venv: /var/www/redeleitsystem/venv/
+app_program: server.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /redeleitsystem
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: 'redeleitsystem'
+app_db_type: 'postgres'
+
+app_additional_software: []
+
+app_deploy_key: ""
+app_git_url: "https://git.fsmpi.rwth-aachen.de/redl/redeleitsystem.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+redeleitsystem_update_index: 5
+redeleitsystem_update_time: 10
diff --git a/uwsgi-python/vars/repo-sync.yml b/uwsgi-python/vars/repo-sync.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ed6ac1cc686a9a0c84ef2498e84c76800ec9e08f
--- /dev/null
+++ b/uwsgi-python/vars/repo-sync.yml
@@ -0,0 +1,39 @@
+app_name: repo-sync
+app_user: repo-sync
+app_group: repo-sync
+app_home: /var/www/stud-repo-sync
+app_path: /var/www/stud-repo-sync
+app_python_version: 3
+app_venv: /var/www/stud-repo-sync/venv/
+app_program: sync.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: true
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: ['git']
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/repo-sync"
+app_git_url: "git@git.stud.rwth-aachen.de:infra/repo-sync.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: false
+app_secret_config_keys: []
+
+repo_sync_ssh_key: "{{ inventory_dir }}/files/deploy-keys/repo-sync-rw"
+repo_sync_workers: 2
+repo_sync_repos:
+  - source: 'git@git.example.com:test/from.git'
+    dest: 'git@git.example.com:test/to.git'
+repo_sync_secrets:
+  - source: 'git@git.example.com:test/from.git'
+    secret: 'ALLOW'
diff --git a/uwsgi-python/vars/samba-migration.yml b/uwsgi-python/vars/samba-migration.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e6f9eb178b53a0a46d3226b6ee61d17f60d4c962
--- /dev/null
+++ b/uwsgi-python/vars/samba-migration.yml
@@ -0,0 +1,31 @@
+app_name: migration-webapp
+app_user: migration-webapp
+app_group: migration-webapp
+app_home: /var/www/samba-migration-webapp
+app_path: /var/www/samba-migration-webapp/program
+app_python_version: 3
+app_venv: /var/www/samba-migration-webapp/program
+app_program: server.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: []
+
+app_requirements_file: requirements.txt
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/samba-migration"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/samba-migration-webapp.git"
+app_git_version: HEAD
+
+app_config_file: ''
+app_secret_config: false
+app_secret_config_keys: []
+
diff --git a/uwsgi-python/vars/schilder.yml b/uwsgi-python/vars/schilder.yml
new file mode 100644
index 0000000000000000000000000000000000000000..faa380f058366c320980875fc67049db3aa19002
--- /dev/null
+++ b/uwsgi-python/vars/schilder.yml
@@ -0,0 +1,40 @@
+app_name: schilder
+app_user: schilder
+app_group: schilder
+app_home: /var/www/schilder
+app_path: /var/www/schilder/program
+app_python_version: 2
+app_venv: /var/www/schilder/program
+app_program: schilder.py
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_type: ""
+
+app_additional_software: ["graphicsmagick", "python-pythonmagick"]
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/schildergenerator"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:schilder/schildergenerator.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+
+schilder_printsrv: printsrv.example.de
+schilder_printers:
+  - description: "1 - Kopierer Turing"
+    name: "Kopierer1"
+  - description: "2 - Kopierer Moore"
+    name: "Kopierer2"
+schilder_lproptions:
+  - "-o fitplot"
+schilder_templates_url: git@git.example.com:schilder/templates-example-schilder.git
diff --git a/uwsgi-python/vars/schrank.yml b/uwsgi-python/vars/schrank.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c033a1cd9c1e851702e8d90669c8c09609405bf1
--- /dev/null
+++ b/uwsgi-python/vars/schrank.yml
@@ -0,0 +1,33 @@
+app_name: schrank
+app_user: schrankweb
+app_group: schrankweb
+app_home: /var/www/schrank
+app_path: /var/www/schrank
+app_python_version: 2
+app_venv: ''
+app_program: main/wsgi.py
+app_callable: application
+app_command: ''
+app_mountpoint: /
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+app_service_env: []
+
+# There is a mysql database named schrank, but it is unmanaged by ansible.
+app_db_type: ''
+app_db_name: ''
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/schrank"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:schrank/web.git"
+app_git_version: HEAD
+
+# There is no requirements.txt file and no other documentation (e.g. venv)
+# on needed software. The settings (including secret_key and db password)
+# are also checked into the repository.
+app_requirements_file: ''
+app_config_file: ''
+app_secret_config: false
+app_secret_config_keys: []
+app_additional_software: []
diff --git a/uwsgi-python/vars/shorturl.yml b/uwsgi-python/vars/shorturl.yml
new file mode 100644
index 0000000000000000000000000000000000000000..eccb172cb5bd0d37dea0101b725f0780f5ed5797
--- /dev/null
+++ b/uwsgi-python/vars/shorturl.yml
@@ -0,0 +1,52 @@
+app_name: shorturl
+app_user: shorturl
+app_group: shorturl
+app_home: /var/www/shorturl
+app_path: /var/www/shorturl
+app_python_version: 3
+app_venv: /var/www/shorturl/venv
+app_program: shorturl.py
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: shorturl
+app_db_type: postgres
+
+app_additional_software: []
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/shorturl"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/shorturl.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+shorturl_default_redirect: "https://www.example.com"
+shorturl_admin_group: admin
+shorturl_user_group: users
+
+shorturl_ad_host: 'ad.example.com'
+shorturl_ad_domain: 'EXAMPLE'
+shorturl_ad_user_dn: "cn=users,dc=example,dc=com"
+shorturl_ad_group_dn: "cn=users,dc=example,dc=com"
+shorturl_ad_cert: "/etc/ssl/certs/example_cacert.pem"
+
+shorturl_target_regex: '^https://([a-zA-Z0-9-]+\.)*example\.com(/(.*))?$'
+shorturl_branding_name: 'Example'
+shorturl_branding_domain: 'short.example'
+shorturl_branding_domain_regex: '^(?!(https?://)?(www\.)?(short\.example)/?)(.*)'
+shorturl_branding_contact: 'contact@example.com'
+
+shorturl_mail_subject: 'confirmation request ShortURL service'
+shorturl_mail_domain: 'example.com'
+shorturl_mail_admin: 'contact@example.com'
+shorturl_mail_host: 'mail.example.com'
+
diff --git a/uwsgi-python/vars/sso.yml b/uwsgi-python/vars/sso.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c7be87d7a28567ec06071b4d3d988aa61cf95939
--- /dev/null
+++ b/uwsgi-python/vars/sso.yml
@@ -0,0 +1,39 @@
+app_name: sso
+app_user: sso
+app_group: sso
+app_home: /var/www/sso
+app_path: /var/www/sso/program
+app_python_version: 3
+app_venv: /var/www/sso/program
+app_program: sso.py
+app_callable: app
+app_command: ""
+app_mountpoint: /
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ""
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/sso"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:infra/sso.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+app_additional_software: []
+
+sso_auth_use_ad: yes
+sso_auth_host: auth.example.com
+sso_auth_user_dn: "cn=users,dc=example,dc=com"
+sso_auth_group_dn: "dc=example,dc=com"
+sso_auth_ca_cert: ''
+sso_auth_domain: EXAMPLE
+
+sso_domain: "{{ domain }}"
+
diff --git a/uwsgi-python/vars/timer.yml b/uwsgi-python/vars/timer.yml
new file mode 100644
index 0000000000000000000000000000000000000000..5ba6383cbafb8b9b32af1ddbba385a36920e20e5
--- /dev/null
+++ b/uwsgi-python/vars/timer.yml
@@ -0,0 +1,29 @@
+app_name: timer
+app_user: timer
+app_group: timer
+app_home: /var/www/timer
+app_path: /var/www/timer
+app_python_version: 2
+app_venv: /var/www/timer/venv/
+app_program: timer.py
+app_callable: app
+app_command: ""
+app_mountpoint: /timer
+app_service_env: []
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_name: ''
+app_db_type: ''
+
+app_additional_software: []
+
+app_deploy_key: ''
+app_git_url: 'https://github.com/orithena/timer-impress.git'
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: ''
+app_secret_config: false
diff --git a/uwsgi-python/vars/wahlhelfer.yml b/uwsgi-python/vars/wahlhelfer.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2bae6bb74ccb1ef67732169ff96cc20e0ec36d8d
--- /dev/null
+++ b/uwsgi-python/vars/wahlhelfer.yml
@@ -0,0 +1,42 @@
+app_name: wahlhelfer
+app_user: wahlhelfer
+app_group: wahlhelfer
+app_home: /var/www/wahlhelfer
+app_path: /var/www/wahlhelfer/program
+app_python_version: 3
+app_venv: /var/www/wahlhelfer/program
+app_program: main/wsgi.py
+app_callable: application
+app_command: "runserver"
+app_mountpoint: /
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 5
+app_uwsgi_options: []
+
+app_db_type: mysql
+app_db_name: "wahlhelfer"
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/wahlhelfer"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:wahl/wahlhelfer.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: main/settings.py
+app_secret_config: true
+app_secret_config_keys: []
+
+app_additional_software: []
+
+wahlhelfer_admins: [['Admins', 'admin@example.com']]
+wahlhelfer_sender: 'wahlhelfer@example.com'
+wahlhelfer_mail_host: 'mail.example.com'
+wahlhelfer_mail_user: ''
+wahlhelfer_mail_password: ''
+wahlhelfer_mail_port: ''
+wahlhelfer_allowed_hosts: ['example.com']
+
+app_service_env:
+  - WAHLHELFER_WEB_ROOT=/var/www/wahlhelfer/
+#  - LDAPTLS_CACERT=
+
diff --git a/uwsgi-python/vars/wahlsystem.yml b/uwsgi-python/vars/wahlsystem.yml
new file mode 100644
index 0000000000000000000000000000000000000000..61c7bb71407b75b01ba88a49fa4b3c5e3d078a0a
--- /dev/null
+++ b/uwsgi-python/vars/wahlsystem.yml
@@ -0,0 +1,52 @@
+app_name: wahlsystem
+app_user: wahl
+app_group: wahl
+app_home: /var/www/wahlsystem
+app_path: /var/www/wahlsystem/program
+app_python_version: 3
+app_mules: 0
+app_enable_threads: false
+app_harakiri: 30
+app_uwsgi_options: []
+app_venv: /var/www/wahlsystem/program/
+app_program: server.py
+app_callable: app
+app_command: "runserver"
+app_mountpoint: /
+app_service_env: []
+
+app_db_name: wahlsystem
+app_db_type: postgres
+
+app_additional_software:
+  - "fontconfig"
+  - "tex-gyre"
+
+app_deploy_key: "{{ inventory_dir }}/files/deploy-keys/wahlsystem"
+app_git_url: "git@git.fsmpi.rwth-aachen.de:wahl/wahlsys.git"
+app_git_version: HEAD
+
+app_requirements_file: requirements.txt
+app_config_file: config.py
+app_secret_config: true
+app_secret_config_keys: []
+
+wahl_celery_broker: 'redis://localhost:6379/0'
+wahl_celery_concurrency: 1
+
+wahl_ldap_cert: ''
+wahl_mail: True
+wahl_mail_from: 'wahl@example.com'
+wahl_mail_host: 'mail.example.com:25'
+wahl_mail_user: ''
+wahl_mail_password: ''
+wahl_mail_tls: False
+wahl_mail_prefix: 'Wahlsystem'
+wahl_server_name: 'wahl.example.com'
+wahl_url_root: 'wahl.example.com'
+wahl_url_proto: 'https'
+wahl_url_path: '/'
+wahl_mailman_api_url: 'https://lists.example.com/mailmanAPI'
+wahl_mailman_api_key: ''
+wahl_mailman_default_newpw: ''
+wahl_mailman_host: 'lists.example.com'
diff --git a/uwsgi/files/tmpfiles.conf b/uwsgi/files/tmpfiles.conf
deleted file mode 100644
index 50b2862b7b5bfbdf7fafd0f4e6a54f0280e8c743..0000000000000000000000000000000000000000
--- a/uwsgi/files/tmpfiles.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-d /run/uwsgi 0755 root root - -
-d /run/uwsgi/app 0755 root root - -
diff --git a/uwsgi/handlers/main.yml b/uwsgi/handlers/main.yml
deleted file mode 100644
index 66f7827fa119ae9bea42ffacb3eaca529fbef45e..0000000000000000000000000000000000000000
--- a/uwsgi/handlers/main.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-# file: uwsgi/handlers/main.yml
-
-- name: create tmpfiles
-  shell: systemd-tmpfiles --create
diff --git a/uwsgi/tasks/main.yml b/uwsgi/tasks/main.yml
deleted file mode 100644
index d8ffa47e659449ce5439b991d94bfd8aa5e794a1..0000000000000000000000000000000000000000
--- a/uwsgi/tasks/main.yml
+++ /dev/null
@@ -1,24 +0,0 @@
----
-# file: uwsgi/tasks/main.yml
-
-- name: ensure uwsgi is installed
-  apt:
-    name: uwsgi
-    state: installed
-  tags:
-    - uwsgi
-    - webservices
-
-- name: ensure a temporary directory exists
-  copy:
-    src: tmpfiles.conf
-    dest: /etc/tmpfiles.d/10-uwsgi.conf
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - create tmpfiles
-  tags:
-    - uwsgi
-    - webservices
-
diff --git a/wahlhelfer/defaults/main.yml b/wahlhelfer/defaults/main.yml
deleted file mode 100644
index dc1e370dd67c77df986a41f9ec5a446627382905..0000000000000000000000000000000000000000
--- a/wahlhelfer/defaults/main.yml
+++ /dev/null
@@ -1,12 +0,0 @@
----
-# file: wahlhelfer/defaults/main.yml
-
-wahlhelfer_web_root: /var/www/wahlhelfer
-wahlhelfer_name: wahlhelfer
-wahlhelfer_user: wahlhelfer
-wahlhelfer_group: wahlhelfer
-wahlhelfer_admins: [["Admin", "admin@example.com"]]
-wahlhelfer_sender: wahlhelfer@example.com
-wahlhelfer_mail_host: mail.example.com
-wahlhelfer_allowed_hosts: ["wahlhelfer.example.com"]
-wahlhelfer_ldap_cert: ''
diff --git a/wahlhelfer/handlers/main.yml b/wahlhelfer/handlers/main.yml
deleted file mode 100644
index 47338d1870dc30cdd4422dc947f39d89795eb922..0000000000000000000000000000000000000000
--- a/wahlhelfer/handlers/main.yml
+++ /dev/null
@@ -1,13 +0,0 @@
----
-# file: wahlhelfer/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart uwsgi for wahlhelfer
-  service:
-    name: "{{ wahlhelfer_name }}"
-    state: restarted
-
-- name: create tmpfiles
-  command: systemd-tmpfiles --create
diff --git a/wahlhelfer/meta/main.yml b/wahlhelfer/meta/main.yml
deleted file mode 100644
index 93f17bf5fd4868a47b3e05a2ce222ccf1eb1ff36..0000000000000000000000000000000000000000
--- a/wahlhelfer/meta/main.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-# file: wahlhelfer/meta/main.yml
-dependencies:
-  - { role: uwsgi-python, uwsgi_name: "{{wahlhelfer_name}}", uwsgi_user: "{{wahlhelfer_user}}", uwsgi_group: "{{wahlhelfer_group}}", uwsgi_path: "{{wahlhelfer_web_root}}/program", uwsgi_home: "{{wahlhelfer_web_root}}", uwsgi_program: "main/wsgi.py", uwsgi_callable: "application", uwsgi_command: "runserver", uwsgi_db: "mysql", uwsgi_python: 3 }
diff --git a/wahlhelfer/tasks/main.yml b/wahlhelfer/tasks/main.yml
deleted file mode 100644
index 62fc2982786991c7946d7c89fa411657ce6a50a1..0000000000000000000000000000000000000000
--- a/wahlhelfer/tasks/main.yml
+++ /dev/null
@@ -1,101 +0,0 @@
----
-# file: wahlhelfer/tasks/main.yml
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ wahlhelfer_deploy_key }}"
-    dest: /root/.ssh/wahlhelfer
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - wahlhelfer
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure fucking git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - wahlhelfer
-    - webservices
-
-- name: ensure the git is at the current revision
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:wahl/wahlhelfer.git
-    dest: "{{ wahlhelfer_web_root }}/program"
-    key_file: /root/.ssh/wahlhelfer
-    version: HEAD
-  notify:
-    - restart uwsgi for wahlhelfer
-  tags:
-    - wahlhelfer
-    - webservices
-
-- name: ensure fucking git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - wahlhelfer
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ wahlhelfer_web_root }}/program/requirements.txt"
-    virtualenv: "{{ wahlhelfer_web_root }}/program"
-    virtualenv_python: python3
-  notify:
-    - restart uwsgi for wahlhelfer
-  tags:
-    - wahlhelfer
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: settings.py.j2
-    dest: "{{ wahlhelfer_web_root }}/program/main/settings.py"
-    owner: "{{ wahlhelfer_user }}"
-    group: "{{ wahlhelfer_group }}"
-    mode: 0644
-  notify:
-    - restart uwsgi for wahlhelfer
-  tags:
-    - wahlhelfer
-    - webservices
-
-- name: ensure we have the linear solver
-  copy:
-    src: "{{ item }}"
-    dest: "{{ wahlhelfer_web_root }}/program/zibopt/"
-    owner: "{{ wahlhelfer_user }}"
-    group: "{{ wahlhelfer_group }}"
-    mode: 0755
-  with_items:
-    - scip
-    - zimpl
-  tags:
-    - wahlhelfer
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: wahlhelfer.service.j2
-    dest: "/etc/systemd/system/{{ wahlhelfer_name }}.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for wahlhelfer
-  tags:
-    - wahlhelfer
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the services are enabled
-  service:
-    name: "{{ wahlhelfer_name }}"
-    enabled: yes
-    state: started
-  tags:
-    - wahlhelfer
-    - webservices
diff --git a/wahlhelfer/templates/wahlhelfer.service.j2 b/wahlhelfer/templates/wahlhelfer.service.j2
deleted file mode 100644
index ea742dbed8d430d9d125985c0fa681b5c46245a3..0000000000000000000000000000000000000000
--- a/wahlhelfer/templates/wahlhelfer.service.j2
+++ /dev/null
@@ -1,17 +0,0 @@
-[Unit]
-Description=Wahlhelferorganisation
-After=network.target
-
-[Service]
-{% if wahlhelfer_ldap_cert %}
-Environment=LDAPTLS_CACERT={{ wahlhelfer_ldap_cert }}
-{% endif %}
-Environment=WAHLHELFER_WEB_ROOT={{wahlhelfer_web_root}}/
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/{{ wahlhelfer_name }}.ini
-Restart=always
-KillSignal=SIGQUIT
-Type=notify
-NotifyAccess=all
-
-[Install]
-WantedBy=multi-user.target
diff --git a/wahlsystem/defaults/main.yml b/wahlsystem/defaults/main.yml
deleted file mode 100644
index 973fdd13300053ce9c01d0429ddb245a34624955..0000000000000000000000000000000000000000
--- a/wahlsystem/defaults/main.yml
+++ /dev/null
@@ -1,27 +0,0 @@
----
-# file: wahlsystem/defaults/main.yml
-
-wahl_web_root: /var/www/wahlsystem
-wahl_name: wahlsystem
-wahl_user: wahl
-wahl_group: wahl
-wahl_celery_concurrency: 1
-wahl_ldap_cert: ''
-wahl_secret: ''
-wahl_mail: True
-wahl_mail_from: 'wahl@example.com'
-wahl_mail_host: 'mail.example.com:25'
-wahl_mail_user: ''
-wahl_mail_password: ''
-wahl_mail_tls: False
-wahl_mail_prefix: 'Wahlsystem'
-wahl_celery_broker: 'redis://localhost:6379/0'
-wahl_server_name: 'wahl.example.com'
-wahl_url_root: 'wahl.example.com'
-wahl_url_proto: 'https'
-wahl_url_path: '/'
-wahl_mailman_api_url: 'https://lists.example.com/mailmanAPI'
-wahl_mailman_api_key: ''
-wahl_mailman_default_newpw: ''
-wahl_mailman_host: 'lists.example.com'
-
diff --git a/wahlsystem/handlers/main.yml b/wahlsystem/handlers/main.yml
deleted file mode 100644
index 99db7419882837bc316f696f13b59b370fdc5b9f..0000000000000000000000000000000000000000
--- a/wahlsystem/handlers/main.yml
+++ /dev/null
@@ -1,16 +0,0 @@
----
-# file: wahlsystem/handlers/main.yml
-
-- name: reload systemd service files
-  command: systemctl daemon-reload
-
-- name: restart uwsgi for wahlsystem
-  service:
-    name: "{{ item }}"
-    state: restarted
-  with_items:
-    - "{{ wahl_name }}"
-    - "{{ wahl_name }}-celery"
-
-- name: create tmpfiles
-  command: systemd-tmpfiles --create
diff --git a/wahlsystem/meta/main.yml b/wahlsystem/meta/main.yml
deleted file mode 100644
index 2a053bfa62096128bd41ac14e0cac65a7cac42ee..0000000000000000000000000000000000000000
--- a/wahlsystem/meta/main.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-# file: wahlsystem/meta/main.yml
-dependencies:
-  - { role: texlive }
-  - { role: cups-client }
-  - { role: uwsgi-python, uwsgi_name: "{{wahl_name}}", uwsgi_user: "{{wahl_user}}", uwsgi_group: "{{wahl_group}}", uwsgi_path: "{{wahl_web_root}}/program", uwsgi_home: "{{wahl_web_root}}", uwsgi_program: "server.py", uwsgi_callable: "app", uwsgi_command: "runserver", uwsgi_db: "postgres", uwsgi_python: 3, uwsgi_mules: 0, uwsgi_harakiri: 30 }
diff --git a/wahlsystem/tasks/main.yml b/wahlsystem/tasks/main.yml
deleted file mode 100644
index 782a568117526c67ba52b8bede22d78a86301923..0000000000000000000000000000000000000000
--- a/wahlsystem/tasks/main.yml
+++ /dev/null
@@ -1,127 +0,0 @@
----
-# file: wahlsystem/tasks/main.yml
-
-- name: ensure we have the required software and fonts
-  apt:
-    name: "{{ item }}"
-    state: present
-  with_items:
-    - fontconfig
-    - tex-gyre
-    - virtualenv
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure the deploy key is available
-  copy:
-    src: "{{ wahl_deploy_key }}"
-    dest: /root/.ssh/wahlsystem
-    owner: root
-    group: root
-    mode: 0600
-  tags:
-    - wahlsystem
-    - webservices
-
-# https://github.com/ansible/ansible/issues/27699
-- name: ensure fucking git module is able to clone
-  command: mount -o remount,exec /tmp
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure the git is at the current revision
-  git:
-    repo: git@git.fsmpi.rwth-aachen.de:wahl/wahlsys.git
-    dest: "{{ wahl_web_root }}/program"
-    key_file: /root/.ssh/wahlsystem
-    version: HEAD
-  notify:
-    - restart uwsgi for wahlsystem
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure fucking git module is not able to clone anymore
-  command: mount -o remount,noexec /tmp
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure we have a virtualenv
-  pip:
-    requirements: "{{ wahl_web_root }}/program/requirements.txt"
-    virtualenv: "{{ wahl_web_root }}/program"
-    virtualenv_python: python3
-  notify:
-    - restart uwsgi for wahlsystem
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure we have the necessary folder
-  file:
-    name: "{{ wahl_web_root }}/program/blogfiles"
-    state: directory
-    owner: "{{ wahl_user }}"
-    group: "{{ wahl_group }}"
-    mode: 0755
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure we have our config
-  template:
-    src: config.py.j2
-    dest: "{{ wahl_web_root }}/program/config.py"
-    owner: "{{ wahl_user }}"
-    group: "{{ wahl_group }}"
-    mode: 0644
-  notify:
-    - restart uwsgi for wahlsystem
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure the unit file exists
-  template:
-    src: wahlsystem.service.j2
-    dest: "/etc/systemd/system/{{ wahl_name }}.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for wahlsystem
-  tags:
-    - wahlsystem
-    - webservices
-
-- name: ensure the celery unit file exists
-  template:
-    src: celery.service.j2
-    dest: "/etc/systemd/system/{{ wahl_name }}-celery.service"
-    owner: root
-    group: root
-    mode: 0644
-  notify:
-    - reload systemd service files
-    - restart uwsgi for wahlsystem
-  tags:
-    - wahlsystem
-    - webservices
-
-- meta: flush_handlers
-
-- name: ensure the services are enabled
-  service:
-    name: "{{ item }}"
-    enabled: yes
-    state: started
-  with_items:
-    - "{{ wahl_name }}"
-    - "{{ wahl_name }}-celery"
-  tags:
-    - wahlsystem
-    - webservices
diff --git a/wahlsystem/templates/celery.service.j2 b/wahlsystem/templates/celery.service.j2
deleted file mode 100644
index a03225272feafad76ed43862de83d69143bd68fb..0000000000000000000000000000000000000000
--- a/wahlsystem/templates/celery.service.j2
+++ /dev/null
@@ -1,14 +0,0 @@
-[Unit]
-Description=Wahlsystem-Celery
-After=network.target
-
-[Service]
-User={{ wahl_user }}
-Group={{ wahl_group }}
-WorkingDirectory={{ wahl_web_root }}/program
-Environment=VIRTUAL_ENV="{{ wahl_web_root }}/program"
-ExecStart={{ wahl_web_root }}/program/bin/celery -A server.celery worker --loglevel=DEBUG --concurrency={{ wahl_celery_concurrency }}
-Restart=always
-
-[Install]
-WantedBy=multi-user.target
diff --git a/wahlsystem/templates/wahlsystem.service.j2 b/wahlsystem/templates/wahlsystem.service.j2
deleted file mode 100644
index c035bba44baa5bb781a0cc80f3a683d36546082d..0000000000000000000000000000000000000000
--- a/wahlsystem/templates/wahlsystem.service.j2
+++ /dev/null
@@ -1,17 +0,0 @@
-[Unit]
-Description=Wahlsystem
-After=network.target
-Wants=wahlsystem-celery.service
-
-[Service]
-{% if wahl_ldap_cert %}
-Environment=LDAPTLS_CACERT={{ wahl_ldap_cert }}
-{% endif %}
-ExecStart=/usr/bin/uwsgi --ini /etc/uwsgi/apps-available/{{ wahl_name }}.ini
-Restart=always
-KillSignal=SIGQUIT
-Type=notify
-NotifyAccess=all
-
-[Install]
-WantedBy=multi-user.target