Complete mumble server using Docker-compose

14 Aug 2020

I went to the process of creating a mumble server with mumble-web as fronted, mumble-django as admin portal and murmur for the actual mumble server. All of them running in their own separate docker container.

Mumble server

Lets start with the mumble server, because both mumble-web and mumble-django depends on the mumble server.

First we create a folder to store all our files

mkdir ~/mumble-server

I decided to create my own docker container for the mumble-server. First create a subfolder to store the Dockerfile and maybe some more files for mumble-server later on. I called the subfolder murmur just because the actual mumble server is named murmur

mkdir -p ~/mumble-server/murmur

So to the actual Dockerfile for the murmur server

# murmur/Dockerfile
ROM debian:buster-slim

ARG VERSION="1.3.2"

RUN apt-get update
RUN apt-get install -y wget bzip2

WORKDIR /tmp
RUN wget https://dl.mumble.info/stable/murmur-static_x86-${VERSION}.tar.bz2

RUN mkdir -p /opt/mumble/cfg
RUN tar xjf /tmp/murmur-static_x86-${VERSION}.tar.bz2 --strip-components=1 -C /opt/mumble

RUN adduser --disabled-password --no-create-home --gecos '' murmur
RUN chown -R murmur:murmur /opt/mumble
RUN mv /opt/mumble/murmur.ini /opt/mumble/murmur-default.ini

WORKDIR /opt/mumble

EXPOSE 64738/tcp 64738/udp 6502/tcp

VOLUME ["/opt/mumble/ice", "/opt/mumble/cfg"]

USER murmur
CMD ["/opt/mumble/murmur.x86", "-fg", "-ini", "/opt/mumble/cfg/murmur.ini"]

I like Debian and there is a package for mumble-server, and by appending the -slim tag we get the smaller image.

Two ports need to be exposed, 64738 for both TCP and UDP and then 6502 for TCP. The 6502 port is used for the Internet Communication Engine (ICE) used by mumble-django and the 64738 is the mumble port for VoIP.

Now that was the actual building of the docker image file, now we need to be able to start the mumble server. Over to the docker-compose file

version: '2.0'

volumes:
  mumble_ice:

networks:
  mumble-net:

services:
  mumble-srv:
    build: murmur/.
    container_name: murmur
    restart: unless-stopped
    ports:
      - 64738:64738
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /srv/mumble/murmur:/opt/mumble/cfg
      - mumble_ice:/opt/mumble/slice
    networks:
      - mumble-net

First I create a separate network for our mumble containers. Then we create the server service, I wont go into all the details.

Notice I don’t expose the 6502 port here, it is only exposed by the container. And because we created a mumble-net network for our services the mumble-django service will run on the same network and will be able to access the 6502 port on the murmur server.

To change the exposed ports for the mumble-server just change the first number in the 64738:64738 ports instruction.

    ports:
      - <external port>:64738

To change the persistent storage path it’s the same as with the ports, change the first part of the : separated paths

    volumes:
      - <your path>:/opt/mumble/cfg

But don’t change the mumble_ice:/opt/mumble/slice volume, it is there to share the Murmur.ice file with mumble-django.

Murmur needs a settings file before we can start, in my case the file is /srv/mumble/murmur/murmur.ini this is what we need to add

welcometext="Welcome to Raddonix.com"
serverpassword=superhardpassword

ice="tcp -p 6502"

# DB in a persistent place
database=/opt/mumble/cfg/murmur.sqlite

use the docker-compose command to start the server

docker-compose up -d

Test the server using the client of your choice, if it is working we move on to the mumble-djanog admin page.

Mumble admin page using mumble-django

Once again I decided to build my own docker image. So first create a folder

mkdir -p ~/mumble-server/mumble-django

and then the Dockerfile

# mumble-django/Dockerfile
FROM debian:stretch-slim

RUN apt-get update
RUN apt-get install -y mercurial patch

WORKDIR /opt
RUN hg clone https://bitbucket.org/Svedrin/mumble-django

COPY IceEncodingVersion.patch /opt/mumble-django
WORKDIR /opt/mumble-django
RUN patch -p1 < IceEncodingVersion.patch

RUN mkdir -p /opt/mumble/ice

RUN apt-get install -y python-pil python-pip

# Install older version of django (mumble-django did not work with newer)
RUN pip install django==1.7

# Install zeroc-ice
RUN apt-get install -y libssl-dev libbz2-dev
RUN pip install zeroc-ice

# mumble-django is looking for Murmur.ice in /usr/share/slice
# our share volume will mount it at /opt/mumble/ice/Murmur.ice
# link it to the correct place
RUN mkdir -p /usr/share/slice
RUN ln -s /opt/mumble/ice/Murmur.ice /usr/share/slice/Murmur.ice

VOLUME ["/opt/mumble-django/db"]

EXPOSE 9000/tcp

CMD [ "python", "/opt/mumble-django/pyweb/manage.py", "runserver", "0.0.0.0:9000" ]

This docker container is not best practice, you should clone the repo outside of building the docker image. I don’t know if it is possible to do that using only docker-compose. But this is how I got the mumble-django up and running, I may rewrite this later.

Now we add the mumble-django as a service to the docker-compose file

  mumble-admin:
    build: mumble-django/.
    container_name: mumble-django
    restart: unless-stopped
    depends_on:
      - mumble-srv
    ports:
      - 9000:9000
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /srv/mumble/murmur:/mumble
      - /srv/mumble/mumble-django:/opt/mumble-django/db
      - mumble_ice:/opt/mumble/ice
    environment:
      - MURMUR_CONNSTR=Meta:tcp -h murmur -p 6502
      - MURMUR_ICESECRET=''
    networks:
      - mumble-net

add mumble-armin service to docker-compose.yaml The depends_on tag is used to describe the start order, because this service depends on mumble-srv docker-compose will start mumble-srv service first.

Once again change the ports & persistent storage paths to your needs

    ports:
      - <your port>:9000
    volumes:
      - <your path>:/mumble
      - <your path>:/opt/mumble-django/db

Just make sure that the mumble_ice:/opt/mumble/ice is not changed.

When all is done, start the server

docker-compose up -d

This will start the new service and restart the old if any changes has been made to it.

before we can test the admin pages we need to create the database and create a admin user

# docker exec -it mumble-django /bin/bash -c "python /usr/src/app/pyweb/manage.py syncdb"
perations to perform:
  Synchronize unmigrated apps: mumble
  Apply all migrations: admin, contenttypes, sites, auth, sessions
Synchronizing apps without migrations:
  Creating tables...
    Creating table mumble_mumbleserver
    Creating table mumble_mumble
    Creating table mumble_mumbleuser
  Installing custom SQL...
  Installing indexes...
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying sessions.0001_initial... OK
  Applying sites.0001_initial... OK
Found new Murmur instance 1 on bus 'Meta:tcp -h murmur -p 6502'... 
Successfully finished Servers and Players detection.
To add more servers, run this command again.

You have installed Django's auth system, and don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'root'):
Email address: <your email>
Password:
Password (again):
Superuser created successfully.

To test the admin pages just open your browser and go to the address of your docker host followd by the port exposed for mumble-django, in my case it looks like this

http://192.168.0.27:9000

Finally time for the last service

Our web frontend, mumble-web

The mumble-web repo already contains a Dockerfile, so no need to create our own. We go directly to our docker-compose file and add the service for our mumble-web frontend

  mumble-web:
    build: https://github.com/johni0702/mumble-web.git
    container_name: mumble-web
    restart: unless-stopped
    depends_on:
      - mumble-srv
    ports:
      - 8080:8080
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /srv/mumble/mumble-web/config.local.js:/home/node/app/config.local.js
      - /srv/mumble/mumble-web/config.local.js:/home/node/dist/config.local.js
    environment:
      - MUMBLE_SERVER=murmur:64738
    networks:
      - mumble-net

add mumble-web service to docker-compose.yaml and for the last time change the ports & persistent storage paths to your needs

    ports:
      - <your port>:8080
    volumes:
      - <your path>/config.local.js:/home/node/app/config.local.js
      - <your path>/config.local.js:/home/node/dist/config.local.js

then create the config.local.js file

// You can overwrite the default configuration values set in [config.js] here.
// There should never be any required changes to this file and you can always
// simply copy it over when updating to a new version.

let config = window.mumbleWebConfig // eslint-disable-line no-unused-vars

// E.g. changing default address and theme:
// config.defaults.address = 'voice.example.com'
// config.defaults.theme = 'MetroMumbleDark'

config.defaults.theme = 'MetroMumbleDark';
config.defaults.port = '443';
config.connectDialog.address = false;
config.connectDialog.port = false;
config.connectDialog.token = false;

start the mumble-web service

docker-compose up -d

Use the browser to se that it is working, in my case it was this URL

http://192.168.0.27:8080

Now the mumble server is ready. But only for internal use, to expose it to the internet you need to open firewall ports and maybe use a reverse proxy to access the mumble-web interface.

Github repo

All the files can be found over at github https://github.com/Raddinox/mumble-server