diff --git a/Dockerfile b/Dockerfile
index e728db06154cca6868c7da4bfdee92fafe15d27e..65da15df0a16cd8f33eadab9ab21adf78306f032 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,16 +1,49 @@
-FROM alpine:edge
+# multi stage dockerfile
+# it defines three different images
+# 1. mumble-web
+# 2. mumble-web with nginx
+# 3. websockfiy as web socket
 
-LABEL maintainer="Armin Co <armin.co@hs-bochum.de"
 
+# mumble-web base image
+FROM alpine:edge AS mumble-web
+LABEL maintainer="Armin Co <armin.co@hs-bochum.de"
 # copy mumble-web repository into docker image
 COPY ./mumble-web /home/node
-
-# install git and npm
-RUN apk add --no-cache git npm 
-
-# "install" mumble-web
+# install deps for building mumble web
+RUN apk add --no-cache \
+        git \
+        nodejs \
+        npm \
+        && \
+    adduser -D -g 1001 -u 1001 -h /home/node node && \
+    mkdir -p /home/node && \
+    mkdir -p /home/node/.npm-global && \
+    mkdir -p /home/node/app  && \
+    chown -R node: /home/node 
+USER node
+ENV PATH=/home/node/.npm-global/bin:$PATH
+ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
+# build mumble-web
 RUN cd /home/node   && \
     npm install     && \
     npm run build   && \
     npm audit fix   && \
     npm audit
+
+
+# add nginx as webserver to mumble web
+FROM nginx:alpine AS mumble-web-nginx
+USER root
+COPY --from=mumble-web /home/node/dist /home/node/dist
+RUN apk add --no-cache nginx && \
+    adduser -D -g 'www' www && \
+    mkdir /data
+EXPOSE 443
+
+
+# websockify
+FROM alpine:edge AS websockify
+RUN echo http://nl.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories && \
+    apk add --no-cache websockify 
+EXPOSE 64737
diff --git a/README.md b/README.md
index a61380d0d67ad197e426306bcc158cff7993eaad..37961f893d5449fc3cbfae9cd8b7e012a7d0beb8 100644
--- a/README.md
+++ b/README.md
@@ -1,47 +1,40 @@
 # Build Mumble Web
 
-A script to build the mumble-web app in a docker image.
+You can use the `build_mumble_web.sh` script to build the mumble-web application, which
+can be deployed with an webserver. The application
+will be stored at `./dist`.
 
 The script will clone the [mumble-web](https://github.com/Johni0702/mumble-web) repository.
 If the repository already was cloned it will pull the latest commits.
 Afterwards the docker image, defined in the [Dockerfile](https://gitlab.cvh-server.de/aco/build-mumble-web/-/blob/master/Dockerfile), will be build.
 
-**Dockerfile**
+## build
 
-  - alpine:edge
-  - copy content of repository into image
-  - install git and npm
-  - npm: install, run build, audit fix, audit
+To build the mumble-web application: just run the script!
 
-The image contains the generated files of the app, which can be published by a webserver.
-To copy these files out of the image it is necessary to create a container out of this image.
-Therefore the command 'docker create' needs to be executed.
-Afterwards the directory can be copied with 'docker cp'.
-
-The container and the image are not longer needed, so they will be removed at the end.
-
-
-**Verifying commits**
-
-Commits made from the online editor are signed with the github web-flow key.
-Other commits are not verified.
-
-[https://github.com/web-flow.gpg](https://github.com/web-flow.gpg)
-
-
-
-**Testing**
+```bash
+./build_mumble_web.sh
+```
 
-To test if the generation of the website files was succesfully
-a test version can be run with websockify.
+## testing
 
+If you want to test mumble web, you can deploy it together with mumble and websockify
+via the provided 'docker-compose.yml' file.
 ```
-openssl req -newkey rsa:2048 -nodes -keyout test.key -x509 -days 365 -out test.crt
-websockify --cert=test.crt --key=test.key --ssl-only --ssl-target --web=/home/node/dist 443 MUMBLE_SERVER:64738
+# to deploy run:
+docker-compose up -d
 ```
+This will build two containers. One with mumble-web and nginx as a webserver and the second container
+just contains websockify. The imae for the third container will not be build localy but 
+pulled from DockerHub. The container will serve murmur (mumble server)
+for this test deployment.
+The web application will be accessible via: [https://localhost](https://localhost).
+The certificate is self signed, so your browser will warn you when you try to access the site.
 
-**Deploy**
 
-When the website is not deployed with websockify, it is still needed for the websocket.
+**verifying the mumble-web repository**
+
+Commits made from the online editor are signed with the github web-flow key.
+Other commits are not verified.
 
-```websockify --ssl-target 64737 MUMBLE_SERVER:64738```
\ No newline at end of file
+[https://github.com/web-flow.gpg](https://github.com/web-flow.gpg)
\ No newline at end of file
diff --git a/build_mumble_web.sh b/build_mumble_web.sh
index 4588bf09b12b34dcecb304a0967fe27377aa8080..2eaca85bdc9a975ebd381cbfed1a28e1300d01d6 100755
--- a/build_mumble_web.sh
+++ b/build_mumble_web.sh
@@ -36,14 +36,19 @@ function verify_commit_HEAD() {
     cd ../
 }
 
+echo "buildung mumble-web"
+echo "files will be stored at:  ${DESTINATION_HOST}"
+
 # check if git repository is already cloned
 # then pull updates
 # if not clone repository
 if cd $REPOSITORY
 then
-   git pull
-   cd ../
+    echo "updating mumble-web repository"
+    git pull
+    cd ../
 else
+    echo "cloning mumble-web repository"
     git clone $URL_GITHUB
 fi
 
@@ -51,18 +56,15 @@ fi
 verify_commit_HEAD
 
 # build docker image 
-printf "\nBuilding image\n"
-docker build -t $IMAGE_NAME . > build.log
+echo "building mumble-web image"
+echo "logs will be stored in: build.log"
+time docker build --target mumble-web -t "${IMAGE_NAME}" . > build.log
 # create temporary container
 docker create --name $CONTAINER_NAME "${IMAGE_NAME}"
 # remove previously copied files
-rm -rf dist/
-# copy files from container to host
+rm -rf dist
+# # copy files from container to host
 docker cp $CONTAINER_NAME:"${DIST_DIR}" $DESTINATION_HOST
 # remove created container
 docker rm -f $CONTAINER_NAME
-# remove the created image
-# otherwise it would only pull updates
-# from other node dependenices
-# if there was an update in the repository
 docker rmi $IMAGE_NAME
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..27d750e589881bb1d8b375e5e0ac5a8c48520818
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,33 @@
+version: '3.4'
+
+services:
+    mumble-web-nginx:
+        build:
+            context: ./
+            target: mumble-web-nginx
+        container_name: mumble-web-nginx
+        ports:
+            - 443:443
+        volumes: 
+            - ./webserver:/data:ro
+        restart: unless-stopped
+        command: ["/data/entrypoint.sh"]
+
+    websockify:
+        build:
+            context: ./
+            target: websockify
+        container_name: websockify
+        ports:
+            - 64737:64737
+        restart: unless-stopped
+        command: websockify --ssl-target 64737 murmur:64738
+
+    murmur:
+        container_name: murmur
+        image: coppit/mumble-server
+        ports: 
+            - 64738:64738
+        volumes: 
+            - ./murmur:/data
+        restart: unless-stopped
diff --git a/murmur/mumble-server.ini b/murmur/mumble-server.ini
new file mode 100644
index 0000000000000000000000000000000000000000..4c09b4594560be6524fef8996929d9331a641f2a
--- /dev/null
+++ b/murmur/mumble-server.ini
@@ -0,0 +1,199 @@
+# Murmur configuration file.
+#
+# General notes:
+# * Settings in this file are default settings and many of them can be overridden
+#   with virtual server specific configuration via the Ice or DBus interface.
+# * Due to the way this configuration file is read some rules have to be
+#   followed when specifying variable values (as in variable = value):
+#     * Make sure to quote the value when using commas in strings or passwords.
+#        NOT variable = super,secret BUT variable = "super,secret"
+#     * Make sure to escape special characters like '\' or '"' correctly
+#        NOT variable = """ BUT variable = "\""
+#        NOT regex = \w* BUT regex = \\w*
+
+# Path to database. If blank, will search for
+# murmur.sqlite in default locations or create it if not found.
+database=
+
+# If you wish to use something other than SQLite, you'll need to set the name
+# of the database above, and also uncomment the below.
+# Sticking with SQLite is strongly recommended, as it's the most well tested
+# and by far the fastest solution.
+#
+#dbDriver=QMYSQL
+#dbUsername=
+#dbPassword=
+#dbHost=
+#dbPort=
+#dbPrefix=murmur_
+#dbOpts=
+
+# Murmur defaults to not using D-Bus. If you wish to use dbus, which is one of the
+# RPC methods available in Murmur, please specify so here.
+#
+dbus=system
+
+# Alternate D-Bus service name. Only use if you are running distinct
+# murmurd processes connected to the same D-Bus daemon.
+#dbusservice=net.sourceforge.mumble.murmur
+
+# If you want to use ZeroC Ice to communicate with Murmur, you need
+# to specify the endpoint to use. Since there is no authentication
+# with ICE, you should only use it if you trust all the users who have
+# shell access to your machine.
+# Please see the ICE documentation on how to specify endpoints.
+ice="tcp -h 127.0.0.1 -p 6502"
+
+# Ice primarily uses local sockets. This means anyone who has a
+# user account on your machine can connect to the Ice services.
+# You can set a plaintext "secret" on the Ice connection, and
+# any script attempting to access must then have this secret
+# (as context with name "secret").
+# Access is split in read (look only) and write (modify) 
+# operations. Write access always includes read access,
+# unless read is explicitly denied (see note below).
+#
+# Note that if this is uncommented and with empty content,
+# access will be denied.
+
+#icesecretread=
+icesecretwrite=
+
+# How many login attempts do we tolerate from one IP
+# inside a given timeframe before we ban the connection?
+# Note that this is global (shared between all virtual servers), and that
+# it counts both successfull and unsuccessfull connection attempts.
+# Set either Attempts or Timeframe to 0 to disable.
+#autobanAttempts = 10
+#autobanTimeframe = 120
+#autobanTime = 300
+
+# Specifies the file Murmur should log to. By default, Murmur
+# logs to the file 'murmur.log'. If you leave this field blank
+# on Unix-like systems, Murmur will force itself into foreground
+# mode which logs to the console.
+logfile=/data/mumble-server.log
+
+# If set, Murmur will write its process ID to this file
+# when running in daemon mode (when the -fg flag is not
+# specified on the command line). Only available on
+# Unix-like systems.
+pidfile=/var/run/mumble-server/mumble-server.pid
+
+# The below will be used as defaults for new configured servers.
+# If you're just running one server (the default), it's easier to
+# configure it here than through D-Bus or Ice.
+#
+# Welcome message sent to clients when they connect.
+welcometext="<br />Welcome to this server running <b>Murmur</b>.<br />Enjoy your stay!<br />"
+
+# Port to bind TCP and UDP sockets to.
+port=64738
+
+# Specific IP or hostname to bind to.
+# If this is left blank (default), Murmur will bind to all available addresses.
+#host=
+
+# Password to join server.
+serverpassword=
+
+# Maximum bandwidth (in bits per second) clients are allowed
+# to send speech at.
+bandwidth=72000
+
+# Maximum number of concurrent clients allowed.
+users=100
+
+# Amount of users with Opus support needed to force Opus usage, in percent.
+# 0 = Always enable Opus, 100 = enable Opus if it's supported by all clients.
+#opusthreshold=100
+
+# Maximum depth of channel nesting. Note that some databases like MySQL using
+# InnoDB will fail when operating on deeply nested channels.
+#channelnestinglimit=10
+
+# Regular expression used to validate channel names.
+# (Note that you have to escape backslashes with \ )
+#channelname=[ \\-=\\w\\#\\[\\]\\{\\}\\(\\)\\@\\|]+
+
+# Regular expression used to validate user names.
+# (Note that you have to escape backslashes with \ )
+#username=[-=\\w\\[\\]\\{\\}\\(\\)\\@\\|\\.]+
+
+# Maximum length of text messages in characters. 0 for no limit.
+#textmessagelength=5000
+
+# Maximum length of text messages in characters, with image data. 0 for no limit.
+#imagemessagelength=131072
+
+# Allow clients to use HTML in messages, user comments and channel descriptions?
+#allowhtml=true
+
+# Murmur retains the per-server log entries in an internal database which
+# allows it to be accessed over D-Bus/ICE.
+# How many days should such entries be kept?
+# Set to 0 to keep forever, or -1 to disable logging to the DB.
+#logdays=31
+
+# To enable public server registration, the serverpassword must be blank, and
+# this must all be filled out.
+# The password here is used to create a registry for the server name; subsequent
+# updates will need the same password. Don't lose your password.
+# The URL is your own website, and only set the registerHostname for static IP
+# addresses.
+# Only uncomment the 'registerName' parameter if you wish to give your "Root" channel a custom name.
+#
+#registerName=Mumble Server
+#registerPassword=secret
+#registerUrl=https://www.mumble.info/
+#registerHostname=
+
+# If this option is enabled, the server will announce its presence via the 
+# bonjour service discovery protocol. To change the name announced by bonjour
+# adjust the registerName variable.
+# See http://developer.apple.com/networking/bonjour/index.html for more information
+# about bonjour.
+#bonjour=True
+
+# If you have a proper SSL certificate, you can provide the filenames here.
+# Otherwise, Murmur will create it's own certificate automatically.
+#sslCert=
+#sslKey=
+
+# The sslCiphers option chooses the cipher suites to make available for use
+# in SSL/TLS. This option is server-wide, and cannot be set on a
+# per-virtual-server basis.
+#
+# This option is specified using OpenSSL cipher list notation (see
+# https://www.openssl.org/docs/apps/ciphers.html#CIPHER-LIST-FORMAT).
+#
+# It is recommended that you try your cipher string using 'openssl ciphers <string>'
+# before setting it here, to get a feel for which cipher suites you will get.
+#
+# After setting this option, it is recommend that you inspect your Murmur log
+# to ensure that Murmur is using the cipher suites that you expected it to.
+#
+# Note: Changing this option may impact the backwards compatibility of your
+# Murmur server, and can remove the ability for older Mumble clients to be able
+# to connect to it.
+#sslCiphers=EECDH+AESGCM:AES256-SHA:AES128-SHA
+
+# If Murmur is started as root, which user should it switch to?
+# This option is ignored if Murmur isn't started with root privileges.
+uname=mumble-server
+
+# If this options is enabled, only clients which have a certificate are allowed
+# to connect.
+#certrequired=False
+
+# If enabled, clients are sent information about the servers version and operating
+# system.
+#sendversion=True
+
+# You can configure any of the configuration options for Ice here. We recommend
+# leave the defaults as they are.
+# Please note that this section has to be last in the configuration file.
+#
+[Ice]
+Ice.Warn.UnknownProperties=1
+Ice.MessageSizeMax=65536
diff --git a/webserver/certs/test.crt b/webserver/certs/test.crt
new file mode 100644
index 0000000000000000000000000000000000000000..e20f663ad867b929c1cac696dabe7687f9835857
--- /dev/null
+++ b/webserver/certs/test.crt
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDazCCAlOgAwIBAgIUV/1KSmiz97r880nZQ91GAX8YFCUwDQYJKoZIhvcNAQEL
+BQAwRTELMAkGA1UEBhMCREUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
+GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDA2MTAwOTQ5MTZaFw0yMTA2
+MTAwOTQ5MTZaMEUxCzAJBgNVBAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
+HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCer0AbjQ/nsil/oF1kznswiXnizix6iO7RVSxr07ys
+4EFdYXgzm/qEG8uaRnSk6pgpLzAB5t0HE84f6oT+bBetJsyv5gdZsNoXQJb55GAn
+ZxvxsckKBS8/qlvGg6gA6e6ZTS1ZIc15wEXwpYfcCGFXX839AcQRMqCFFDshUstH
+tIjt2JS9e60+ZXD5Gvl/CtJ+faYWV7T+yIrvY5vCT05LEt+XPgIOP9rdnMKmcpBR
+wlfLepYV3sbeAMuj6GIx7ZYAZfHTCj8CeiYyVRykGP3BRccocgz7ZsSgFqH6p6tM
+FfVDeNXQUzvsjmIGYyPhXFnR/WYgoLZJEvPmgLgzYr5hAgMBAAGjUzBRMB0GA1Ud
+DgQWBBT6OHE8Yd1AZnh9Mt5Q5yjRSYoVujAfBgNVHSMEGDAWgBT6OHE8Yd1AZnh9
+Mt5Q5yjRSYoVujAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAV
+Vyc9epCKBsNXu1RyDmv0CqIPmSeJGkaTz9IFsMZ1GZhWF2XUCuRr+zWsBiOCf+zH
+G5zKi5oU+crUQmaFvC9M3JxoeHjxzDsg6+kW+8acoCBxhRwml7e4cor+Z1Ghb9Rm
+jOlQuuKnJy0UHp4JyLrxZrwhZuMfN16/jYNnAH9o7vYqvFMrfuZuPvSyPERp3EVL
+DIGUy4+7kseP+Uc0U2vNDcMMllaqpKjFyDmoPQfsBldKKOFvyCYJdAkcXrm47SSf
+IQvsRblPKvW6FTEOZ1fQKR2S8OTTqExq6uP0hoy1qmeRXI3m+5tmsYIxLdjZBD+Z
+jsKklG3dnPSOY0BSIjdk
+-----END CERTIFICATE-----
diff --git a/webserver/certs/test.key b/webserver/certs/test.key
new file mode 100644
index 0000000000000000000000000000000000000000..32cb48d6cac27e19e97a30c32f997015cc37d432
--- /dev/null
+++ b/webserver/certs/test.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCer0AbjQ/nsil/
+oF1kznswiXnizix6iO7RVSxr07ys4EFdYXgzm/qEG8uaRnSk6pgpLzAB5t0HE84f
+6oT+bBetJsyv5gdZsNoXQJb55GAnZxvxsckKBS8/qlvGg6gA6e6ZTS1ZIc15wEXw
+pYfcCGFXX839AcQRMqCFFDshUstHtIjt2JS9e60+ZXD5Gvl/CtJ+faYWV7T+yIrv
+Y5vCT05LEt+XPgIOP9rdnMKmcpBRwlfLepYV3sbeAMuj6GIx7ZYAZfHTCj8CeiYy
+VRykGP3BRccocgz7ZsSgFqH6p6tMFfVDeNXQUzvsjmIGYyPhXFnR/WYgoLZJEvPm
+gLgzYr5hAgMBAAECggEAdnn8UFWy0VfI+hweftxXR7btBPTQarCANlT0dJFDJoPM
+6c6TM1063pXuHwKJpnPtJZqwqkrXLaiQ1m1/3IGR79qvKomBZWrQelnkHzFuxRyL
+1ZnasxuJ2mv0V7QGpKAEX/sqZ4kAY+21imXcmOC85MKIBmXiIMD+7j1bpJavZZnt
+RWYzpGBsz4cG3QARO76oxfoG3G4qKsbZrpB0ro5ZenB5Gp1c9WjeGmdlaKBi+qIH
+zu4ltd++1TEfcM6lZAfd6dsyzD65N822xQLApUs6PXjCo2zQYfy7Yb8ob+2UsGda
+mpwWoOsd8PCvqXirj4rOfAFVKr49BgygT4Gq9AlxPQKBgQDKfhKapxU+Fq/bRFNO
+W50tv/FTK7O/gnQpm0X7E2TYKLm/4TQrPHG+ALqhJPArXEXgkaxXGHRm9pkfdrA3
+epm+WqV37rLRkVAHERPmZe42WfQ1Mr5E9jagDYM/a8vQANEse7mJvACjE5Cx5xIm
+ARQ6RHPEuMxZeYfrVHwLneOgCwKBgQDInbjm+6OKk1WuzErTIF+aj0+NLm3z295T
+f6ThXrC+Ube2h4UBKCxsvHV6BgiKj2hKFI9vK4LTGsGBZr5DeEA6eovt3pQZU6Q6
+6vCp/Ko4DAssyP+5BYW1PHOIUN8mQunGrrbkwWIi69fieQ/ZhNEFF1R6qc0Xa0lv
+QAeqFFdCwwKBgQCMTu1PMgUbH5c9BMwAmKSBxeVO7xI+2gLprYjBH8AZs6Z52W9P
+ojNiJ5kp/bFZKjfVErtrIivOCIMzdQdHefE8IA1V3BUV922PZ/r1A54bFRuNHRsQ
+J9bT8mkGMghomZhXDWgTkyyR0wXI78b4hHjiovngzvfx668Nll3Zos7N3wKBgQCs
+zYbOl6S4Ic7lQR2WnEUdeiI45uxY6GOqIsHgStMNLJCFTlhXtcYGZ5L9Z6MFzx8y
+6GDgjmci9eIGV3y92x/f/1z2qQmCg1RsV6Czm2r32g/qJLx5H/ObOBYALkD40RxT
+Qn1Rr+2bTPDpKARqBgiRTRY8jnSVnpljlZDEhL7hRwKBgQCdeqqkq5nO7uxmzq8Y
+WM69JEvDTwCtRFi6748iWuntYqfKes5EajxzzhHk7Yb1AL2pyVWAqpxGPxi4Ed9b
+j45SdyYmBs0mZwUpkwjCFF12vry+SXDvLrhygTmBEjRWpPBFKMewhy3RRi4fbsqg
+IG9YnM1/WJOvjSQ0/ZvEKeJ6Bg==
+-----END PRIVATE KEY-----
diff --git a/webserver/conf/nginx.conf b/webserver/conf/nginx.conf
new file mode 100644
index 0000000000000000000000000000000000000000..3236f87d6c293c5685a78a72c01859ecf420fcf1
--- /dev/null
+++ b/webserver/conf/nginx.conf
@@ -0,0 +1,44 @@
+user                    www;
+worker_processes        auto;
+
+error_log               /var/log/nginx/error.log warn;
+
+events {
+    worker_connections 1024;
+}
+
+http {
+    include             /etc/nginx/mime.types;
+    default_type        application/octet-stream;
+    sendfile            on;
+    access_log          /var/log/nginx/access.log;
+    keepalive_timeout   3000;
+
+    server {
+        listen 443 ssl;
+        server_name localhost;
+        ssl_certificate /data/certs/test.crt;
+        ssl_certificate_key /data/certs/test.key;
+
+        location / {
+            root /home/node/dist;
+        }
+
+        location /demo {
+            resolver 127.0.0.11 valid=30s;
+            # get websockify ip address
+            # of the container it is running in
+            # name of the container has to be websockify
+            set $websock_address websockify;
+            proxy_pass http://$websock_address:64737;
+            proxy_http_version 1.1;
+            proxy_set_header Upgrade $http_upgrade;
+            proxy_set_header Connection $connection_upgrade;
+        }
+    }
+    
+    map $http_upgrade $connection_upgrade {
+        default upgrade;
+        '' close;
+    }
+}
\ No newline at end of file
diff --git a/webserver/entrypoint.sh b/webserver/entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a49bd005c1633d5b6823719d48fb470008714bdd
--- /dev/null
+++ b/webserver/entrypoint.sh
@@ -0,0 +1,4 @@
+# copy config for nginx 
+cp /data/conf/nginx.conf /etc/nginx/nginx.conf;
+# start nginx
+nginx -g 'daemon off;'; nginx -s reload;
\ No newline at end of file