diff --git a/host_vars/webserver b/host_vars/webserver
index 2d858232a4deb9712b9e1df9b596b9380a8bee3f..5b646c3192287db02b501fe9862fb554e0bf4fbf 100644
--- a/host_vars/webserver
+++ b/host_vars/webserver
@@ -9,6 +9,7 @@ debian_sources:
   - "deb http://ftp2.de.debian.org/debian/ buster main contrib non-free"
   - "deb http://security.debian.org/ buster/updates main contrib non-free"
   - "deb https://download.docker.com/linux/debian buster stable"
+  - "deb http://deb.debian.org/debian buster-backports main"
 
 debian_keys_id:
 
diff --git a/site.yml b/site.yml
index eba9ad06ce1854813c9258ee0f73be37712115bb..4527be8bae26eea8806c41fe037472e6d37b6490 100644
--- a/site.yml
+++ b/site.yml
@@ -163,38 +163,52 @@
     - { 
         role: webserver/docker_hackmd, tags: hackmd,
         servicename: "hackmd",
+        basedir: /srv/hackmd, 
         domain: "md.warpzone.ms"
       }
     - { 
         role: webserver/docker_keycloak, tags: keycloak,
         servicename: "keycloak",
+        basedir: /srv/keycloak, 
         domain: "keycloak.warpzone.ms"
       }
     - { 
-        role: webserver/docker_mail, tags: mail 
+        role: webserver/docker_mail, tags: mail, 
+        basedir: /srv/mail, 
       }
     - { 
         role: webserver/docker_matterbridge, tags: matterbridge,
+        basedir: /srv/matterbridge, 
         domain: "www.warpzone.ms" 
       }
     - { 
         role: webserver/docker_matrix, tags: matrix,
         servicename: "matrix",
+        basedir: /srv/matrix, 
         domain: "matrix.warpzone.ms"
       }
+    - { 
+        role: webserver/docker_vpnserver, tags: vpnserver,
+        servicename: "vpnserver",
+        basedir: /srv/vpnserver, 
+        domain: "vpn.warpzone.ms"
+      }
     - { 
         role: webserver/docker_warpapi, tags: warpapi,
         servicename: "warpapi",
+        basedir: /srv/warpapi, 
         domain: "api.warpzone.ms"
       }
     - { 
         role: webserver/docker_wordpress, tags: wordpress,
         servicename: "wordpress",
+        basedir: /srv/wordpress, 
         domain: "www.warpzone.ms"
       }
     - { 
         role: webserver/docker_workadventure, tags: workadventure,
         servicename: "workadventure",
+        basedir: /srv/workadventure, 
         domain: "workadventure.warpzone.ms"
       }
 
diff --git a/webserver/docker_vpnserver/tasks/main.yml b/webserver/docker_vpnserver/tasks/main.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9d49fd746bc4d77da71b6599217a0425a81e6031
--- /dev/null
+++ b/webserver/docker_vpnserver/tasks/main.yml
@@ -0,0 +1,37 @@
+---
+
+- include_tasks: ../functions/get_secret.yml
+  with_items:
+    - { path: "{{ basedir }}/wg_admin_pass",  length: 32 }
+    - { path: "{{ basedir }}/wg_private_key",  length: -1 } # 'wg genkey'
+
+
+- name: create folder struct for keycloak
+  file:
+    path: "{{ item }}"
+    state: "directory"
+  with_items:
+    - "{{ basedir }}"
+    - "{{ basedir }}/data"
+
+
+- name: "copy {{ servicename }} config files"
+  template:
+    src: "{{ item }}"
+    dest: "{{ basedir }}/{{ item }}"
+  with_items:
+    - docker-compose.yml
+  register: config
+
+
+- name: "stop {{ servicename }} docker"
+  docker_compose:
+    project_src: "{{ basedir }}"
+    state: absent
+  when: config.changed
+
+
+- name: "start {{ servicename }} docker"
+  docker_compose:
+    project_src: "{{ basedir }}"
+    state: present
diff --git a/webserver/docker_vpnserver/templates/docker-compose.yml b/webserver/docker_vpnserver/templates/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d3ee2382f408b6aae4b1ebdd7a9c6853d611613b
--- /dev/null
+++ b/webserver/docker_vpnserver/templates/docker-compose.yml
@@ -0,0 +1,42 @@
+version: "3"
+
+services:
+
+  app:
+    image: ghcr.io/freifunkmuc/wg-access-server:v0.8.2
+    restart: always
+    cap_add:
+      - NET_ADMIN
+    sysctls:
+      net.ipv6.conf.all.disable_ipv6: 0
+      net.ipv6.conf.all.forwarding: 1
+    volumes:
+      - "{{ basedir }}/data:/data"
+    #   - "{{ basedir }}/config.yaml:/config.yaml" # if you have a custom config file
+    ports:
+    #  - "8000:8000/tcp"
+      - "51820:51820/udp"
+    devices:
+      - "/dev/net/tun:/dev/net/tun"
+    environment:
+      - "WG_ADMIN_USERNAME=vpnadmin"
+      - "WG_ADMIN_PASSWORD={{ wg_admin_pass }}"
+      - "WG_WIREGUARD_PRIVATE_KEY={{ wg_private_key }}"
+      - "WG_VPN_CIDRV6=0" # to disable IPv6
+      - "WG_EXTERNAL_HOST={{ domain }}"
+      - "WG_DNS_ENABLED=true"
+      - "WG_DNS_UPSTREAM=10.0.0.1"
+      - "WG_LOG_LEVEL=info"
+    labels:
+      - traefik.enable=true
+      - traefik.http.routers.{{ servicename }}.rule=Host(`{{ domain }}`)
+      - traefik.http.routers.{{ servicename }}.entrypoints=websecure
+      - traefik.http.services.{{ servicename }}.loadbalancer.server.port=8000
+    networks:
+      - default
+      - web
+
+
+networks:
+  web:
+    external: true