Skip to content
Snippets Groups Projects
Unverified Commit 19010e6c authored by PICHOU Kyâne's avatar PICHOU Kyâne
Browse files

Add murmur server

parent 653bd4b6
No related branches found
No related tags found
1 merge request!49Add murmur server
README.md
docker-compose.yml
secrets/
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"]
# 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.
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: ¯\_(ツ)_/¯
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
#!/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
# 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)
zeroc-ice==3.7.3
prometheus_client==0.7.1
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment