diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 350629ab5784093af86df53bc80db2b3ccd594c8..b418c837495cc151d3ef062fa4387272bec7bfef 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -12,7 +12,7 @@ cache:
     - "$CI_PROJECT_DIR/pip-cache"
   key: "$CI_PROJECT_ID"
 
-molecule-lint:
+molecule:
   stage: test
   script:
-    - molecule lint
+    - molecule test
diff --git a/files/akplanning.service b/files/akplanning.service
new file mode 100644
index 0000000000000000000000000000000000000000..683f0abdf279960c6da5228f5e4f48831fbf419f
--- /dev/null
+++ b/files/akplanning.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=AKPlanning instance
+After=network.target
+
+[Service]
+User=django
+Group=django
+WorkingDirectory=/srv/AKPlanning/
+Environment="PATH=/srv/AKPlanning/venv/bin"
+ExecStart=/usr/bin/uwsgi --ini uwsgi-akplanning.ini
+Type=notify
+NotifyAccess=all
+Restart=always
+KillSignal=SIGQUIT
+
+[Install]
+WantedBy=multi-user.target
diff --git a/files/nginx.conf b/files/nginx.conf
new file mode 100644
index 0000000000000000000000000000000000000000..7a66cab720a0b915dd8135d647906481b4a98f1e
--- /dev/null
+++ b/files/nginx.conf
@@ -0,0 +1,17 @@
+server {
+    add_header Referrer-Policy same-origin;
+    add_header X-Content-Type-Options nosniff;
+    add_header Strict-Transport-Security "max-age=31536000";
+
+    location / {
+        uwsgi_pass 127.0.0.1:3035;
+        include uwsgi_params;
+    }
+
+    location /static/ {
+        alias /srv/AKPlanning/static;
+        access_log off;
+        expires 365d;
+        add_header Cache-Control "public";
+    }
+}
diff --git a/handlers/main.yml b/handlers/main.yml
index 5bab9ed69424beca9a4f80d0de2dfa457d5b4865..df4c047062fe9aae1efa09785f904381a904948d 100644
--- a/handlers/main.yml
+++ b/handlers/main.yml
@@ -1,2 +1,6 @@
 ---
-# handlers file for kif.akplanning
\ No newline at end of file
+- name: restart akplanning
+  service:
+    name: akplanning
+    state: restarted
+    enabled: yes
diff --git a/meta/main.yml b/meta/main.yml
index a28f980256cb1695b7a22793a5792f5270cd11f0..af7b32d3f75440520146999d3e49bebf3b428ad8 100644
--- a/meta/main.yml
+++ b/meta/main.yml
@@ -39,6 +39,6 @@ galaxy_info:
     # NOTE: A tag is limited to a single word comprised of alphanumeric characters.
     #       Maximum 20 tags per role.
 
-dependencies: []
-  # List your role dependencies here, one per line. Be sure to remove the '[]' above,
-  # if you add dependencies to this list.
+dependencies:
+  - nginx
+  - mariadb_client
diff --git a/molecule/default/INSTALL.rst b/molecule/default/INSTALL.rst
deleted file mode 100644
index d926ca2528e84912d6f7ecd0fb37a237e5e7e457..0000000000000000000000000000000000000000
--- a/molecule/default/INSTALL.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-*******
-Docker driver installation guide
-*******
-
-Requirements
-============
-
-* Docker Engine
-
-Install
-=======
-
-Please refer to the `Virtual environment`_ documentation for installation best
-practices. If not using a virtual environment, please consider passing the
-widely recommended `'--user' flag`_ when invoking ``pip``.
-
-.. _Virtual environment: https://virtualenv.pypa.io/en/latest/
-.. _'--user' flag: https://packaging.python.org/tutorials/installing-packages/#installing-to-the-user-site
-
-.. code-block:: bash
-
-    $ python3 -m pip install 'molecule[docker]'
diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml
index fdf80a39495210633f6745978123c63685c6a05f..e7d758ec5a4af94414fb8a83956df48a53a438d9 100644
--- a/molecule/default/converge.yml
+++ b/molecule/default/converge.yml
@@ -1,7 +1,25 @@
 ---
 - name: Converge
   hosts: all
+  become: true
+
   tasks:
-    - name: "Include kif.akplanning"
+    - name: Include kif.akplanning
       include_role:
-        name: "kif.akplanning"
+        name: kif.akplanning
+      vars:
+        akplanning_mariadb_host: instance
+        akplanning_mariadb_user: akplanning
+        akplanning_mariadb_pass: akplanning
+        akplanning_secret_key: this-is-a-secret
+        akplanning_allowed_hosts: "'127.0.0.1'"
+
+  post_tasks:
+    - name: Ensure AKPlanning is running
+      uri:
+        url: http://127.0.0.1/
+        status_code: 200
+      register: result
+      until: result.status == 200
+      retries: 60
+      delay: 1
diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml
index 62ffe26cde1d561b817693ac1ed8fe036b41db45..788ef5ae97c6bcf12982dcd4b01ed5dd00435b49 100644
--- a/molecule/default/molecule.yml
+++ b/molecule/default/molecule.yml
@@ -5,13 +5,38 @@ driver:
   name: docker
 platforms:
   - name: instance
-    image: docker.io/pycontribs/centos:8
+    image: docker.io/geerlingguy/docker-ubuntu2004-ansible
+    tmpfs:
+      - /run
+      - /tmp
+    volumes:
+      - /sys/fs/cgroup:/sys/fs/cgroup:ro
+    capabilities:
+      - SYS_ADMIN
+    command: /lib/systemd/systemd
     pre_build_image: true
 provisioner:
   name: ansible
+  playbooks:
+    converge: converge.yml
 verifier:
   name: ansible
 lint: |
   set -e
   yamllint .
   ansible-lint .
+scenario:
+  test_sequence:
+    - dependency
+    - lint
+    - cleanup
+    - destroy
+    - syntax
+    - create
+    - prepare
+    - converge
+    #- idempotence
+    - side_effect
+    - verify
+    - cleanup
+    - destroy
diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ab2b4849873e0dd974366c549de08fa94fc4b09a
--- /dev/null
+++ b/molecule/default/prepare.yml
@@ -0,0 +1,11 @@
+---
+- name: Prepare
+  hosts: all
+  tasks:
+    - name: Update apt cache
+      apt: update_cache=true cache_valid_time=600
+    - name: Install mariadb
+      include_role:
+        name: mariadb
+      vars:
+        mariadb_root_password: this-is-a-test
diff --git a/molecule/default/requirements.yml b/molecule/default/requirements.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c1fa08ce0d4d747c613f4e827190e5baaf86f00d
--- /dev/null
+++ b/molecule/default/requirements.yml
@@ -0,0 +1,7 @@
+---
+- src: https://gitlab.fachschaften.org/fsi-ansible/nginx.git
+  scm: git
+- src: https://gitlab.fachschaften.org/fsi-ansible/mariadb.git
+  scm: git
+- src: https://gitlab.fachschaften.org/fsi-ansible/mariadb_client.git
+  scm: git
diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml
index a82dd6fd0bce1c1742b2d5523fe06b8a51a84c8c..81d7a40a8baf5aef803dcd163822790f1708d3a1 100644
--- a/molecule/default/verify.yml
+++ b/molecule/default/verify.yml
@@ -4,6 +4,7 @@
 - name: Verify
   hosts: all
   tasks:
-  - name: Example assertion
-    assert:
-      that: true
+  - name: Ensure AKPlanning is running
+    uri:
+      url: http://127.0.0.1/
+      status_code: 200
diff --git a/tasks/main.yml b/tasks/main.yml
index f8051a8fdb53b08bf9c2d614ddcd7d75217886b3..7326db454bfe186a0ca2fc0ad7eb00b8482fa869 100644
--- a/tasks/main.yml
+++ b/tasks/main.yml
@@ -1,2 +1,131 @@
 ---
-# tasks file for kif.akplanning
\ No newline at end of file
+- name: Install dependencies
+  apt:
+    name:
+      - git
+      - build-essential
+      - python3-virtualenv
+      - python3
+      - python3-pip
+      - python3-dev
+      - libmysqlclient-dev
+      - gettext
+      - uwsgi
+      - uwsgi-plugin-python3
+    state: present
+    update-cache: yes
+
+- name: Check if this is a rerun
+  stat:
+    path: /srv/AKPlanning/AKPlanning/settings_production.py
+  register: akplanning_settings
+
+- name: Set the original db host so we can update
+  lineinfile:
+    path: /srv/AKPlanning/AKPlanning/settings_production.py
+    line: "        'HOST': 'localhost',"
+    regexp: "^        'HOST':"
+    mode: preserve
+  when: akplanning_settings.stat.exists
+  notify: restart akplanning
+
+- name: Clone AKPlanning
+  git:
+    repo: https://gitlab.fachschaften.org/kif/akplanning.git
+    dest: /srv/AKPlanning/
+    version: master
+  register: akplanning_installation
+
+- name: Create django group
+  group:
+    name: django
+    system: yes
+
+- name: Create django user
+  user:
+    name: django
+    comment: "django user"
+    group: django
+    home: /srv/AKPlanning/
+    system: yes
+
+- name: Give akplanning to user django
+  file:
+    path: /srv/AKPlanning/
+    state: directory
+    owner: django
+    group: django
+    mode: preserve
+    recurse: yes
+
+- name: Install python dependencies
+  pip:
+    requirements: requirements.txt
+    chdir: /srv/AKPlanning/
+    virtualenv: /srv/AKPlanning/venv
+    virtualenv_python: python3.8
+  become: yes
+  become_user: django
+
+- name: Create akplanning db
+  import_role:
+    name: mariadb_client
+  vars:
+    db_user:
+      name: "{{ akplanning_mariadb_user }}"
+      password: "{{ akplanning_mariadb_pass }}"
+    db_host: "{{ akplanning_mariadb_host }}"
+
+- name: Configure AKPlanning
+  template:
+    src: settings_secrets.py.j2
+    dest: /srv/AKPlanning/AKPlanning/settings_secrets.py
+    mode: 0600
+    owner: django
+    group: django
+  notify: restart akplanning
+
+- name: Set the correct db host
+  lineinfile:
+    path: /srv/AKPlanning/AKPlanning/settings_production.py
+    line: "        'HOST': 'instance',"
+    regexp: "^        'HOST':"
+    mode: preserve
+  notify: restart akplanning
+
+- name: AKPlanning migrate and stuff
+  shell: |
+    . /srv/AKPlanning/venv/bin/activate
+    /srv/AKPlanning/venv/bin/python manage.py migrate
+    /srv/AKPlanning/venv/bin/python manage.py collectstatic --noinput
+    /srv/AKPlanning/venv/bin/python manage.py compilemessages -l de_DE
+  args:
+    chdir: /srv/AKPlanning
+  environment:
+    DJANGO_SETTINGS_MODULE: AKPlanning.settings_production
+  become: yes
+  become_user: django
+  when: akplanning_installation.before != akplanning_installation.after
+  notify: restart akplanning
+
+- name: Install akplanning service file
+  copy:
+    src: akplanning.service
+    dest: /etc/systemd/system/akplanning.service
+    mode: 0644
+  notify: restart akplanning
+
+- name: Enable akplanning services
+  systemd:
+    daemon-reload: yes
+    enabled: true
+    name: akplanning
+
+- name: Install nginx config
+  copy:
+    src: nginx.conf
+    dest: /etc/nginx/conf.d/akplanning.conf
+    mode: 0600
+    owner: root
+    group: root
+  notify: restart nginx
diff --git a/templates/settings_secrets.py.j2 b/templates/settings_secrets.py.j2
new file mode 100644
index 0000000000000000000000000000000000000000..572927574e3cc0f75f4da07d0e88f1306883b61b
--- /dev/null
+++ b/templates/settings_secrets.py.j2
@@ -0,0 +1,9 @@
+SECRET_KEY = '{{ akplanning_secret_key }}'
+
+HOSTS = [{{ akplanning_allowed_hosts }}]
+
+DB_NAME = '{{ akplanning_mariadb_user }}'
+
+DB_USER = '{{ akplanning_mariadb_user }}'
+
+DB_PASSWORD = '{{ akplanning_mariadb_pass }}'