diff --git a/pica-murmur/.dockerignore b/pica-murmur/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..8d3188d51af5570cae953804a4db830dc67f7799
--- /dev/null
+++ b/pica-murmur/.dockerignore
@@ -0,0 +1,3 @@
+README.md
+docker-compose.yml
+secrets/
diff --git a/pica-murmur/Dockerfile b/pica-murmur/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..0cfd9bd253034b1d9c1f146e33d336c03f95dc6f
--- /dev/null
+++ b/pica-murmur/Dockerfile
@@ -0,0 +1,28 @@
+FROM debian:buster-slim
+
+# Install Mumble server
+RUN apt-get update -y \
+    && apt-get dist-upgrade -y \
+    && apt-get install -y \
+      libssl-dev \
+      libbz2-dev \
+      mumble-server=1.3.0~git20190125.440b173+dfsg-2 \
+      pcproc \
+      python3 \
+      python3-pip \
+      zeroc-ice-slice \
+    && rm -rf /var/lib/apt/lists/*
+
+# Install prometheus exporter and Python dependencies
+COPY requirements.txt /
+RUN pip3 install --no-cache-dir -r requirements.txt
+COPY exporter.py /
+
+EXPOSE 64738/tcp 64738/udp 8000/tcp
+
+# Volume for persistent storage (config file and database)
+VOLUME ["/data"]
+
+# Add entrypoint
+COPY entrypoint.sh /
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/pica-murmur/README.md b/pica-murmur/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..94e274429f16a12b15ccbdbde70fe1b1d100d00e
--- /dev/null
+++ b/pica-murmur/README.md
@@ -0,0 +1,15 @@
+# Murmur
+
+Docker image for a simple Mumble server (Murmur)
+
+## Configuration
+Some environment variables allow to configure Murmur at startup :
+- `MAX_BANDWIDTH` : integer, maximum bandwidth clients are allowed speech at (default is `128000` bps)
+- `MAX_USERS` : integer, maximum number of users on the server (default is `100`)
+- `METRICS_SERVER_LABEL` : Name of this Murmur server to add as metrics label
+
+## Mounted volumes
+Murmur store its server database and configuration files under `/data/` folder. You should mount this directory on your host.
+
+## Network
+Murmur is listening both TCP and UDP on port 64738. You should bind this container port to your host.
diff --git a/pica-murmur/clair-whitelist.yml b/pica-murmur/clair-whitelist.yml
new file mode 100644
index 0000000000000000000000000000000000000000..82e705c5a9dda07792d93b2b24af4eb1e201b693
--- /dev/null
+++ b/pica-murmur/clair-whitelist.yml
@@ -0,0 +1,12 @@
+generalwhitelist:
+  CVE-2019-19816: On utilise pas btrfs
+  CVE-2019-19814: On utilise pas f2fs
+  CVE-2019-19074: ¯\_(ツ)_/¯
+  CVE-2020-10543: ¯\_(ツ)_/¯
+  CVE-2020-10878: ¯\_(ツ)_/¯
+  CVE-2019-19813: On utilise pas btrfs
+  CVE-2019-19815: On utilise pas f2fs
+  CVE-2020-8492: ¯\_(ツ)_/¯
+  CVE-2013-7445: ¯\_(ツ)_/¯
+  CVE-2020-13974: DISPUTED
+  CVE-2020-14155: ¯\_(ツ)_/¯
diff --git a/pica-murmur/docker-compose.yml b/pica-murmur/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..b05c0c11dccb70e3fc805157d8de3cca311dbd5e
--- /dev/null
+++ b/pica-murmur/docker-compose.yml
@@ -0,0 +1,33 @@
+version: "2.4"
+networks:
+  docker_default:
+    external: true
+    name: "docker_default"
+
+volumes:
+  murmur-data:
+    name: murmur-data
+
+services:
+  murmur:
+    image: registry.picasoft.net/pica-murmur:1.3.0
+    container_name: murmur
+    environment:
+      MAX_USERS: 2000
+      METRICS_SERVER_LABEL: voice.picasoft.net
+    ports:
+      - "64738:64738"
+      - "64738:64738/udp"
+    volumes:
+      - murmur-data:/data
+      - /DATA/docker/certs/voice.picasoft.net/:/certs
+    networks:
+      - docker_default
+    labels:
+      - "traefik.enable=true"
+      - "traefik.port=8000"
+      - "traefik.frontend.rule=Host:voice.picasoft.net;Path:/metrics"
+      - "tls-certs-monitor.enable=true"
+      - "tls-certs-monitor.action=kill:SIGUSR1"
+      - "tls-certs-monitor.owner=103"
+    restart: unless-stopped
diff --git a/pica-murmur/entrypoint.sh b/pica-murmur/entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..3b28d616911f3a78a3207181db55bcb0034164e1
--- /dev/null
+++ b/pica-murmur/entrypoint.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+CONFIG_FILE="/data/mumble-server.ini"
+MAX_BANDWIDTH=${MAX_BANDWIDTH:-128000}
+MAX_USERS=${MAX_USERS:-100}
+
+# Copy configuration file if not exists
+if [ ! -f $CONFIG_FILE ]
+then
+  cp /etc/mumble-server.ini $CONFIG_FILE
+fi
+
+# Change configuration
+sed -i -E "s/^(\/\/ )?database( )?=.*/database=\/data\/murmur.sqlite/g" $CONFIG_FILE
+sed -i -E "s/^(\/\/ )?logfile( )?=.*/logfile=/g" $CONFIG_FILE
+sed -i -E "s/^(\/\/ )?bandwidth( )?=.*/bandwidth=$MAX_BANDWIDTH/g" $CONFIG_FILE
+sed -i -E "s/^(\/\/ )?users( )?=.*/users=$MAX_USERS/g" $CONFIG_FILE
+
+# Set correct rights on murmur files
+chown -R mumble-server:mumble-server /data
+
+# Run exporter if variable set
+if [ -n "$METRICS_SERVER_LABEL" ]
+then
+  python3 /exporter.py &
+fi
+
+# Trap SIGUSR1 signal to reload certificates without restarting
+_reload() {
+  echo "Caught SIGUSR1 signal!"
+  /usr/bin/pkill -USR1 murmurd
+}
+trap _term SIGUSR1
+
+# Run murmur
+murmurd -fg -v -ini $CONFIG_FILE
diff --git a/pica-murmur/exporter.py b/pica-murmur/exporter.py
new file mode 100644
index 0000000000000000000000000000000000000000..0c806b73c143f13ba8e0e000b80c65d030e5b569
--- /dev/null
+++ b/pica-murmur/exporter.py
@@ -0,0 +1,151 @@
+# This script is adapted from another script developped by
+# Stefan Hacker <dd0t@users.sourceforge.net> : https://github.com/Natenom/munin-plugins/tree/master/murmur
+
+# Imports
+import tempfile
+import os
+import sys
+import signal
+import time
+import IcePy
+import Ice
+from prometheus_client import start_http_server, Counter, Gauge, REGISTRY, PROCESS_COLLECTOR, PLATFORM_COLLECTOR
+
+# Path to Murmur.ice; the script tries first to retrieve this file dynamically from Murmur itself; if this fails it tries this file.
+SLICE_FILE = "/usr/share/slice/Murmur.ice"
+# Ice.MessageSizeMax from Murmur server
+ICE_MESSAGE_SIZE_MAX = "65535"
+# ICE connection variable
+ICE_HOST = "127.0.0.1"
+ICE_PORT = 6502
+PROXY_STRING = "Meta -e 1.0:tcp -h %s -p %d -t 1000" % (ICE_HOST, ICE_PORT)
+
+# Number of seconds between 2 metrics collection
+COLLECT_INTERVAL = os.getenv('EXPORTER_COLLECT_INTERVAL', 10)
+
+# Get server name
+METRICS_SERVER_LABEL = os.getenv('METRICS_SERVER_LABEL')
+if not METRICS_SERVER_LABEL:
+    print('Must define METRICS_SERVER_LABEL environment variable !')
+    sys.exit(1)
+
+# Prepare ICE properties
+ice_props = Ice.createProperties()
+ice_props.setProperty("Ice.ImplicitContext", "Shared")
+ice_props.setProperty("Ice.MessageSizeMax", str(ICE_MESSAGE_SIZE_MAX))
+# Initialize ICE
+idata = Ice.InitializationData()
+idata.properties = ice_props
+ice = Ice.initialize(idata)
+
+###########################################################################################
+###### This part is (almost) an entire copy of the original script to connect to ICE ######
+####################### To be clear : I HAVE NO IDEA WHAT I'M DOING #######################
+###########################################################################################
+
+connection_done = False
+while not connection_done:
+    try:
+        ice_proxy = ice.stringToProxy(PROXY_STRING)
+
+        # Get slice directory
+        slice_dir = Ice.getSliceDir()
+        slice_dir = ['-I' + slice_dir]
+
+        try:
+            op = IcePy.Operation('getSlice', Ice.OperationMode.Idempotent, Ice.OperationMode.Idempotent,
+                                 True, None, (), (), (), ((), IcePy._t_string, False, 0), ())
+
+            slice = op.invoke(ice_proxy, ((), None))
+            (dynslicefiledesc, dynslicefilepath) = tempfile.mkstemp(suffix='.ice')
+            dynslicefile = os.fdopen(dynslicefiledesc, 'w')
+            dynslicefile.write(slice)
+            dynslicefile.flush()
+            Ice.loadSlice('', slice_dir + [dynslicefilepath])
+            dynslicefile.close()
+            os.remove(dynslicefilepath)
+        except Exception as e:
+            try:
+                Ice.loadSlice('', slice_dir + [SLICE_FILE])
+            except:
+                raise Ice.ConnectionRefusedException
+
+        import Murmur
+
+        # Check connection is working
+        Murmur.MetaPrx.checkedCast(ice_proxy)
+        connection_done = True
+
+    except Ice.ConnectionRefusedException:
+        print('Cannot connect exporter to ICE, retry in 5 seconds')
+        time.sleep(5)
+
+###########################################################################################
+######################## End of the "NO IDEA WHAT I'M DOING PART" #########################
+###########################################################################################
+
+# Remove unwanted Prometheus metrics
+[REGISTRY.unregister(c) for c in [PROCESS_COLLECTOR, PLATFORM_COLLECTOR,
+                                  REGISTRY._names_to_collectors['python_gc_objects_collected_total']]]
+
+# Start Prometheus exporter server
+start_http_server(8000)
+
+# Register metrics
+users_all_gauge = Gauge('murmur_online_users_all', 'Number of online users', ['server'])
+users_unregistered_gauge = Gauge('murmur_online_users_unregistered',
+                                 'Number of online unregistered users', ['server'])
+users_registered_gauge = Gauge('murmur_online_users_registered', 'Number of online registered users', ['server'])
+users_muted_gauge = Gauge('murmur_online_users_muted', 'Number of online muted users', ['server'])
+users_banned_gauge = Gauge('murmur_users_banned', 'Number of banned users', ['server'])
+chan_count_gauge = Gauge('murmur_channels', 'Number of channels', ['server'])
+uptime_gauge = Gauge('murmur_uptime', 'Number of seconds the server is uptime', ['server'])
+
+
+def exit_handler(sig, frame):
+    # Define handler for stop signals
+    print('Terminating...')
+    ice.destroy()
+    sys.exit(0)
+
+
+# Catch several signals
+signal.signal(signal.SIGINT, exit_handler)
+signal.signal(signal.SIGTERM, exit_handler)
+
+
+# Loop forever
+while True:
+    # Get data from Murmur server
+    meta = Murmur.MetaPrx.checkedCast(ice_proxy)
+    server = meta.getServer(1)
+
+    # Initialize metrics counters
+    users_muted_count = 0
+    users_unregistered_count = 0
+    users_registered_count = 0
+
+    # Collect and count users
+    onlineusers = server.getUsers()
+    for key in onlineusers.keys():
+        # Count user as registered
+        if onlineusers[key].userid == -1:
+            users_unregistered_count += 1
+        # Count user as not registered
+        if onlineusers[key].userid > 0:
+            users_registered_count += 1
+        # Count muted users
+        if onlineusers[key].mute or onlineusers[key].selfMute or onlineusers[key].suppress:
+            users_muted_count += 1
+
+    # Set metrics
+    users_all_gauge.labels(server=METRICS_SERVER_LABEL).set(len(onlineusers))
+    users_muted_gauge.labels(server=METRICS_SERVER_LABEL).set(users_muted_count)
+    users_unregistered_gauge.labels(server=METRICS_SERVER_LABEL).set(users_unregistered_count)
+    users_registered_gauge.labels(server=METRICS_SERVER_LABEL).set(users_registered_count)
+    users_banned_gauge.labels(server=METRICS_SERVER_LABEL).set(len(server.getBans()))
+    chan_count_gauge.labels(server=METRICS_SERVER_LABEL).set(len(server.getChannels()))
+    uptime_gauge.labels(server=METRICS_SERVER_LABEL).set(meta.getUptime())
+
+    # Wait beforce next metrics collection
+    time.sleep(COLLECT_INTERVAL)
diff --git a/pica-murmur/requirements.txt b/pica-murmur/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5e01e40a21dddfc329f183c6d662849f8004482c
--- /dev/null
+++ b/pica-murmur/requirements.txt
@@ -0,0 +1,3 @@
+zeroc-ice==3.7.3 
+prometheus_client==0.7.1
+