├── scripts
├── clone.sh
├── install_qt_dev.sh
├── choose_qt_version.sh
├── install_qt.sh
├── copy_one_of.sh
└── build.sh
├── .github
└── workflows
│ ├── upstream_release.yml
│ ├── ci.yml
│ ├── manual_dispatch.yml
│ └── build_and_publish.yml
├── LICENSE
├── Dockerfile
├── entrypoint.sh
└── README.md
/scripts/clone.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | set -x
5 |
6 | git clone --filter=tree:0 https://github.com/mumble-voip/mumble/ /mumble/repo
7 |
8 | cd /mumble/repo
9 |
10 | git config advice.detachedHead false
11 |
12 | if [[ -n "$MUMBLE_VERSION" && ! "$MUMBLE_VERSION" == "latest" ]]; then
13 | git checkout "$MUMBLE_VERSION"
14 | fi
15 |
16 | git submodule update --init
17 | git submodule update --depth 1
18 |
--------------------------------------------------------------------------------
/scripts/install_qt_dev.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | set -x
5 |
6 | if [[ "$QT_VERSION" = 6 ]]; then
7 | QT_PACKAGES=(\
8 | qt6-base-dev \
9 | qt6-tools-dev \
10 | qt6-tools-dev-tools \
11 | qt6-qpa-plugins \
12 | )
13 | elif [[ "$QT_VERSION" = 5 ]]; then
14 | QT_PACKAGES=(\
15 | qtbase5-dev \
16 | qttools5-dev \
17 | qttools5-dev-tools
18 | )
19 | else
20 | 1>&2 echo "Error, unknown Qt version: '$QT_VERSION'"
21 | exit 1
22 | fi
23 |
24 | apt install --no-install-recommends -y "${QT_PACKAGES[@]}"
25 |
--------------------------------------------------------------------------------
/scripts/choose_qt_version.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | set -x
5 |
6 | case "${MUMBLE_VERSION}" in
7 | v1.4.* ) ;& # fallthrough
8 | 1.4.* ) ;& # fallthrough
9 | v1.5.* ) ;& # fallthrough
10 | 1.5.* ) QT_VERSION=5
11 | ;;
12 | v1.6.* ) ;& # fallthrough
13 | 1.6.* ) ;& # fallthrough
14 | latest ) ;& # fallthrough
15 | * ) QT_VERSION=6
16 | ;;
17 | esac
18 |
19 | if [[ -z "$QT_VERSION" ]]; then
20 | 1>&2 echo "Error: unable to determine Qt version from MUMBLE_VERSION=$MUMBLE_VERSION"
21 | exit 1
22 | fi
23 |
24 | echo -n "$QT_VERSION"
25 |
--------------------------------------------------------------------------------
/.github/workflows/upstream_release.yml:
--------------------------------------------------------------------------------
1 | name: Upstream Release
2 |
3 | on:
4 | repository_dispatch:
5 | types: [ new_release ]
6 |
7 | jobs:
8 | publish_new_release:
9 | uses: ./.github/workflows/build_and_publish.yml
10 | with:
11 | mumble_version: ${{ github.event.client_payload.tag }}
12 | docker_version: '0'
13 | publish: true
14 | update_latest: ${{ github.event.client_payload.is_latest == 'true' }}
15 | platforms: "linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8"
16 | secrets: inherit
17 |
--------------------------------------------------------------------------------
/scripts/install_qt.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | set -x
5 |
6 | if [[ "$QT_VERSION" = 6 ]]; then
7 | QT_PACKAGES=(\
8 | libqt6core6t64 \
9 | libqt6network6t64 \
10 | libqt6sql6t64 \
11 | libqt6sql6-mysql \
12 | libqt6sql6-psql \
13 | libqt6sql6-sqlite \
14 | libqt6xml6t64 \
15 | libqt6dbus6t64 \
16 | )
17 | elif [[ "$QT_VERSION" = 5 ]]; then
18 | QT_PACKAGES=(\
19 | libqt5core5t64 \
20 | libqt5network5t64 \
21 | libqt5sql5t64 \
22 | libqt5sql5-mysql \
23 | libqt5sql5-psql \
24 | libqt5sql5-sqlite \
25 | libqt5xml5t64 \
26 | libqt5dbus5t64 \
27 | )
28 | else
29 | 1>&2 echo "Error, unknown Qt version: '$QT_VERSION'"
30 | exit 1
31 | fi
32 |
33 | apt install --no-install-recommends -y "${QT_PACKAGES[@]}"
34 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [ push, pull_request ]
4 |
5 | # Note: As of now the strategy property is not supported when using reusable workflows, so we can't use a build
6 | # matrix to create the different build cases (see https://docs.github.com/en/actions/using-workflows/reusing-workflows#limitations)
7 | jobs:
8 | build_1_5_857:
9 | uses: ./.github/workflows/build_and_publish.yml
10 | with:
11 | mumble_version: "v1.5.857"
12 | docker_version: '0'
13 | publish: false
14 | update_latest: true
15 | platforms: "linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8"
16 | build_latest:
17 | uses: ./.github/workflows/build_and_publish.yml
18 | with:
19 | mumble_version: "latest"
20 | docker_version: '0'
21 | publish: false
22 | update_latest: true
23 | platforms: "linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8"
24 |
--------------------------------------------------------------------------------
/scripts/copy_one_of.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # This script can be used to copy the first existing file to the
4 | # target destination.
5 | # Thus
6 | # copy_one_of.sh a b c
7 | # copies either a or b to c. The first of the target files that
8 | # exists will be copied. The rest will be ignored.
9 |
10 | set -e
11 | set -x
12 |
13 | if [[ "$#" < 2 ]]; then
14 | >&2 echo "Too few arguments - expected at least two"
15 | exit 1
16 | fi
17 |
18 | parameters=( "$@" )
19 | target_file="${parameters[$(( $# - 1))]}"
20 |
21 | found=false
22 |
23 | # Make use of num. of arguments $# to iterate up to the i - 1st argument (last one is destination)
24 | for i in $(seq 0 $(( $# - 2 )) ); do
25 | current_file=${parameters[$i]}
26 |
27 | if [[ -f "$current_file" ]]; then
28 | cp "$current_file" "$target_file"
29 | found=true
30 | break
31 | fi
32 | done
33 |
34 | if [[ "$found" = "false" ]]; then
35 | >&2 echo "Did not find any of the source files - nothing was copied"
36 | exit 1
37 | fi
38 |
--------------------------------------------------------------------------------
/.github/workflows/manual_dispatch.yml:
--------------------------------------------------------------------------------
1 | name: Manual dispatch
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | mumble_version:
7 | description: "The version (tag or commit hash) of Mumble to build"
8 | required: true
9 | default: "latest"
10 | docker_version:
11 | description: "Docker image version, independent of mumble version"
12 | required: true
13 | default: "0"
14 | publish:
15 | description: "Whether the built image(s) shall be published to Dockerhub"
16 | required: true
17 | default: "false"
18 | update_latest:
19 | description: "Whether to update the 'latest' tag on Dockerhub"
20 | required: true
21 | default: "false"
22 |
23 | jobs:
24 | manual_dispatch:
25 | uses: ./.github/workflows/build_and_publish.yml
26 | with:
27 | mumble_version: ${{ github.event.inputs.mumble_version }}
28 | docker_version: ${{ github.event.inputs.docker_version }}
29 | publish: ${{ github.event.inputs.publish == 'true' }}
30 | update_latest: ${{ github.event.inputs.update_latest == 'true' }}
31 | platforms: "linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v8"
32 | secrets: inherit
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2022, Mumble
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 | set -x
5 |
6 | BUILD_NUMBER_SCRIPT="/mumble/repo/scripts/mumble-build-number.py"
7 | VERSION_SCRIPT="/mumble/repo/scripts/mumble-version.py"
8 |
9 | mkdir build && cd build
10 |
11 | buildNumber=0
12 | if [[ ! -z "$MUMBLE_BUILD_NUMBER" ]]; then
13 | buildNumber=$MUMBLE_BUILD_NUMBER
14 | echo "Build number read from argument: $buildNumber"
15 | elif [[ "$MUMBLE_VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
16 | buildNumber=$(echo "$MUMBLE_VERSION" | sed -E 's/v[0-9]+\.[0-9]+\.([0-9]+)/\1/' )
17 | echo "Build number read from version: $buildNumber"
18 | else
19 | if [[ -f "$BUILD_NUMBER_SCRIPT" && -f "$VERSION_SCRIPT" ]]; then
20 | version=$( python3 "$VERSION_SCRIPT" )
21 | commit=$( git rev-parse HEAD )
22 | buildNumber=$( timeout 20 python3 "$BUILD_NUMBER_SCRIPT" --commit "$commit" --version "$version" --default -1 || exitStatus=$? )
23 |
24 | if [[ "$exitStatus" -eq 0 && "$buildNumber" -ge 0 ]]; then
25 | echo "Determined build number to be $buildNumber"
26 | else
27 | echo "Failed to fetch the build number for commit $commit, defaulting to 0"
28 | buildNumber=0
29 | fi
30 | else
31 | echo "Defaulting to build number 0"
32 | fi
33 | fi
34 |
35 | cmake \
36 | -DCMAKE_BUILD_TYPE=Release \
37 | -DBUILD_NUMBER=$buildNumber \
38 | -Dclient=OFF \
39 | -Dserver=ON \
40 | -Dice=ON \
41 | -Dtests=ON \
42 | -Dwarnings-as-errors=OFF \
43 | -Dzeroconf=OFF \
44 | -DCMAKE_UNITY_BUILD=ON \
45 | $MUMBLE_CMAKE_ARGS \
46 | ..
47 |
48 | cmake --build . -j $(nproc)
49 |
50 | TEST_TIMEOUT=600 # seconds
51 | export QTEST_FUNCTION_TIMEOUT="$(( $TEST_TIMEOUT * 1000 ))" # milliseconds
52 | ctest --timeout $TIMEOUT --output-on-failure . -j $(nproc)
53 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:24.04 AS base
2 |
3 | ADD ./scripts/* /mumble/scripts/
4 | WORKDIR /mumble/scripts
5 |
6 | ARG DEBIAN_FRONTEND=noninteractive
7 | ARG MUMBLE_VERSION=latest
8 |
9 | RUN apt-get update && apt-get install --no-install-recommends -y \
10 | libcap2 \
11 | libzeroc-ice3.7t64 \
12 | '^libprotobuf[0-9]+$' \
13 | libavahi-compat-libdnssd1 \
14 | ca-certificates \
15 | sqlite3 \
16 | mysql-client \
17 | libpq5 \
18 | && export QT_VERSION="$( /mumble/scripts/choose_qt_version.sh )" \
19 | && /mumble/scripts/install_qt.sh \
20 | # Workaround for systems like CentOS 7 which won't load libQt5Core.so as expected:
21 | # see also https://stackoverflow.com/a/68897099/
22 | binutils \
23 | && find /lib* /usr/lib* -name 'libQt?Core.so.*' -exec strip --remove-section=.note.ABI-tag {} \; \
24 | && apt-get -y purge binutils \
25 | # End of workaround
26 | && apt-get clean \
27 | && rm -rf /var/lib/apt/lists/* \
28 | && mkdir -p /data \
29 | && rm -Rf /scripts
30 |
31 |
32 |
33 | FROM base AS build
34 | ARG DEBIAN_FRONTEND=noninteractive
35 |
36 | ADD ./scripts/* /mumble/scripts/
37 | WORKDIR /mumble/repo
38 |
39 | RUN apt-get update && apt-get install --no-install-recommends -y \
40 | git cmake build-essential ca-certificates pkg-config \
41 | libssl-dev \
42 | libboost-dev \
43 | libprotobuf-dev \
44 | protobuf-compiler \
45 | libprotoc-dev \
46 | libcap-dev \
47 | libxi-dev \
48 | libavahi-compat-libdnssd-dev \
49 | libzeroc-ice-dev \
50 | python3 \
51 | git \
52 | libsqlite3-dev \
53 | libmysqlclient-dev \
54 | libpq-dev \
55 | && export QT_VERSION="$( /mumble/scripts/choose_qt_version.sh )" \
56 | && /mumble/scripts/install_qt_dev.sh \
57 | && apt-get clean \
58 | && rm -rf /var/lib/apt/lists/*
59 |
60 | ARG MUMBLE_VERSION=latest
61 | ARG MUMBLE_BUILD_NUMBER=""
62 | ARG MUMBLE_CMAKE_ARGS=""
63 |
64 | # Clone the repo, build it and finally copy the default server ini file. Since this file may be at different locations and Docker
65 | # doesn't support conditional copies, we have to ensure that regardless of where the file is located in the repo, it will end
66 | # up at a unique path in our build container to be copied further down.
67 | RUN /mumble/scripts/clone.sh \
68 | && /mumble/scripts/build.sh \
69 | && /mumble/scripts/copy_one_of.sh ./scripts/murmur.ini ./auxiliary_files/mumble-server.ini default_config.ini
70 |
71 | RUN git clone https://github.com/ncopa/su-exec.git /mumble/repo/su-exec \
72 | && cd /mumble/repo/su-exec && make
73 |
74 |
75 |
76 | FROM base
77 |
78 | COPY --from=build /mumble/repo/build/mumble-server /usr/bin/mumble-server
79 | COPY --from=build /mumble/repo/default_config.ini /etc/mumble/bare_config.ini
80 | COPY --from=build --chmod=755 /mumble/repo/su-exec/su-exec /usr/local/bin/su-exec
81 |
82 |
83 | EXPOSE 64738/tcp 64738/udp
84 | COPY entrypoint.sh /entrypoint.sh
85 |
86 | VOLUME ["/data"]
87 | ENTRYPOINT ["/entrypoint.sh"]
88 | CMD ["/usr/bin/mumble-server", "-fg"]
89 |
90 |
--------------------------------------------------------------------------------
/.github/workflows/build_and_publish.yml:
--------------------------------------------------------------------------------
1 | name: Build and Publish
2 |
3 | on:
4 | workflow_call:
5 | inputs:
6 | mumble_version:
7 | required: true
8 | type: string
9 | docker_version:
10 | required: true
11 | type: string
12 | platforms:
13 | required: true
14 | type: string
15 | publish:
16 | required: true
17 | type: boolean
18 | update_latest:
19 | required: true
20 | type: boolean
21 |
22 | jobs:
23 | build:
24 | runs-on: ubuntu-latest
25 | steps:
26 | - name: Login to DockerHub
27 | if: ${{ inputs.publish }}
28 | uses: docker/login-action@v3
29 | with:
30 | username: ${{ secrets.DOCKERHUB_USERNAME }}
31 | password: ${{ secrets.DOCKERHUB_TOKEN }}
32 |
33 | - name: Login to GitHub Container registry
34 | if: ${{ inputs.publish }}
35 | uses: docker/login-action@v3
36 | with:
37 | registry: ghcr.io
38 | username: ${{ github.repository_owner }}
39 | password: ${{ secrets.GITHUB_TOKEN }}
40 |
41 | - name: Checkout
42 | uses: actions/checkout@v4
43 |
44 | - name: Set up QEMU
45 | uses: docker/setup-qemu-action@v3
46 |
47 | - name: Set up Docker Buildx
48 | uses: docker/setup-buildx-action@v3
49 |
50 | - name: Configure target tags (with latest)
51 | if: ${{ inputs.update_latest }}
52 | run: echo "PRE_TAGS=mumble-server:latest mumble-server:${{ inputs.mumble_version }} mumble-server:${{ inputs.mumble_version }}-${{ inputs.docker_version }}" >> $GITHUB_ENV
53 |
54 | - name: Configure target tags (without latest)
55 | if: ${{ ! inputs.update_latest }}
56 | run: echo "PRE_TAGS=mumble-server:${{ inputs.mumble_version }} mumble-server:${{ inputs.mumble_version }}-${{ inputs.docker_version }}" >> $GITHUB_ENV
57 |
58 | - name: Make tags for registries
59 | run: |
60 | TAG_ARRAY=()
61 | for current in $PRE_TAGS; do
62 | TAG_ARRAY+=("mumblevoip/$current" "ghcr.io/mumble-voip/$current")
63 | done
64 | TAGS="$( IFS=","; echo "${TAG_ARRAY[*]}" )"
65 | echo "TAGS=$TAGS" >> $GITHUB_ENV
66 |
67 | - name: Build and push
68 | uses: docker/build-push-action@v6
69 | with:
70 | context: .
71 | platforms: ${{ inputs.platforms }}
72 | push: ${{ inputs.publish }}
73 | build-args: |
74 | MUMBLE_VERSION=${{ inputs.mumble_version }}
75 | tags: ${{ env.TAGS }}
76 | env:
77 | MUMBLE_VERSION: ${{ inputs.mumble_version }}
78 |
--------------------------------------------------------------------------------
/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | export PUID=${PUID:-10000}
5 | export PGID=${PGID:-10000}
6 | MUMBLE_CHOWN_DATA=${MUMBLE_CHOWN_DATA:-true}
7 |
8 | readonly DATA_DIR="/data"
9 | readonly BARE_BONES_CONFIG_FILE="/etc/mumble/bare_config.ini"
10 | readonly CONFIG_REGEX="^(\;|\#)?\ *([a-zA-Z_0-9]+)=.*"
11 | CONFIG_FILE="${DATA_DIR}/mumble_server_config.ini"
12 |
13 | readonly SENSITIVE_CONFIGS=(
14 | "dbPassword"
15 | "icesecretread"
16 | "icesecretwrite"
17 | "serverpassword"
18 | "registerpassword"
19 | "sslPassPhrase"
20 | )
21 |
22 | # Compile list of configuration options from the bare-bones config
23 | readarray -t existing_config_options < <(sed -En "s/$CONFIG_REGEX/\2/p" "$BARE_BONES_CONFIG_FILE")
24 |
25 | # Grab the original command line that is supposed to start the Mumble server
26 | declare -a server_invocation=("${@}")
27 | declare -a used_configs
28 |
29 | normalize_name() {
30 | local uppercase="${1^^}"
31 | echo "${uppercase//_/}"
32 | }
33 |
34 | # Create an associative array for faster config option lookup
35 | declare -A option_for
36 |
37 | for config in "${existing_config_options[@]}"; do
38 | option_for["$(normalize_name "$config")"]="$config"
39 | done
40 |
41 | array_contains() {
42 | local array_expansion="$1[@]" seeking="$2"
43 | for element in "${!array_expansion}"; do
44 | [[ "$element" = "$seeking" ]] && return 0
45 | done
46 | return 1
47 | }
48 |
49 | set_config() {
50 | local config_name="$1" config_value="$2" is_default="$3"
51 | local apply_value=true
52 |
53 | [[ "$is_default" = true ]] && array_contains "used_configs" "$config_name" && \
54 | apply_value=false # Don't use default value if the user already set one!
55 |
56 | [[ "$apply_value" != true ]] && return 0
57 |
58 | if array_contains "SENSITIVE_CONFIGS" "$config_name"; then
59 | echo "Setting config \"$config_name\" to: *********"
60 | else
61 | echo "Setting config \"$config_name\" to: '$config_value'"
62 | fi
63 | used_configs+=("$config_name")
64 |
65 | # Append config to our on-the-fly-built config file
66 | echo "${config_name}=${config_value}" >> "$CONFIG_FILE"
67 | }
68 |
69 | # Drop the user into a shell, if they so wish
70 | if [[ "$1" = "bash" || "$1" = "sh" ]]; then
71 | echo "Dropping into interactive BASH session"
72 | exec "${@}"
73 | fi
74 |
75 | if [[ -f "$MUMBLE_CUSTOM_CONFIG_FILE" ]]; then
76 | echo "Using manually specified config file at $MUMBLE_CUSTOM_CONFIG_FILE"
77 | echo "All MUMBLE_CONFIG variables will be ignored"
78 | CONFIG_FILE="$MUMBLE_CUSTOM_CONFIG_FILE"
79 | else
80 | # Ensures the config file is empty, starting from a clean slate
81 | echo -e "# Config file automatically generated from the MUMBLE_CONFIG_* environment variables" > "${CONFIG_FILE}"
82 | echo -e "# or secrets in /run/secrets/MUMBLE_CONFIG_* files\n" >> "${CONFIG_FILE}"
83 |
84 | # Process settings through variables of format MUMBLE_CONFIG_*
85 |
86 | while IFS='=' read -d '' -r var value; do
87 | config_option="${option_for[$(normalize_name "$var")]}"
88 |
89 | if [[ -z "$config_option" ]]; then
90 | if [[ "$MUMBLE_ACCEPT_UNKNOWN_SETTINGS" = true ]]; then
91 | echo "[WARNING]: Unable to find config corresponding to variable \"$var\". Make sure that it is correctly spelled, using it as-is"
92 | set_config "$var" "$value"
93 | else
94 | >&2 echo "[ERROR]: Unable to find config corresponding to variable \"$var\""
95 | exit 1
96 | fi
97 | else
98 | set_config "$config_option" "$value"
99 | fi
100 |
101 | done < <( printenv --null | sed -zn 's/^MUMBLE_CONFIG_//p' )
102 | # ^ Feeding it in like this, prevents the creation of a subshell for the while-loop
103 |
104 | # Check any docker/podman secrets matching the pattern and set config from there
105 | while read -r var; do
106 | config_option="${option_for[$(normalize_name "$var")]}"
107 | secret_file="/run/secrets/MUMBLE_CONFIG_$var"
108 | if [[ -z "$config_option" ]]; then
109 | if [[ "$MUMBLE_ACCEPT_UNKNOWN_SETTINGS" = true ]]; then
110 | echo "[WARNING]: Unable to find config corresponding to container secret \"$secret_file\". Make sure that it is correctly spelled, using it as-is"
111 | set_config "$var" "$value"
112 | else
113 | >&2 echo "[ERROR]: Unable to find config corresponding to container secret \"$secret_file\""
114 | exit 1
115 | fi
116 | else
117 | set_config "$config_option" "$(cat $secret_file)"
118 | fi
119 | done < <( ls /run/secrets | sed -n 's/^MUMBLE_CONFIG_//p' )
120 |
121 | # Apply default settings if they're missing
122 |
123 | # Compatibilty with old DB filename
124 | OLD_DB_FILE="${DATA_DIR}/murmur.sqlite"
125 | if [[ -f "$OLD_DB_FILE" ]]; then
126 | set_config "database" "$OLD_DB_FILE" true
127 | else
128 | set_config "database" "${DATA_DIR}/mumble-server.sqlite" true
129 | fi
130 |
131 | set_config "ice" "\"tcp -h 127.0.0.1 -p 6502\"" true
132 |
133 | if ! array_contains "used_configs" "welcometextfile"; then
134 | set_config "welcometext" "\"
Welcome to this server, running the official Mumble Docker image.
Enjoy your stay!
\"" true
135 | fi
136 |
137 | set_config "port" 64738 true
138 | set_config "users" 100 true
139 |
140 | { # Add ICE section
141 | echo -e "\n[Ice]"
142 | echo "Ice.Warn.UnknownProperties=1"
143 | echo "Ice.MessageSizeMax=65536"
144 | } >> "$CONFIG_FILE"
145 | fi
146 |
147 | # Additional environment variables
148 |
149 | [[ "$MUMBLE_VERBOSE" = true ]] && server_invocation+=( "-v" )
150 |
151 | # Make sure the correct configuration file is used
152 | server_invocation+=( "-ini" "${CONFIG_FILE}")
153 |
154 | if [[ -f /run/secrets/MUMBLE_SUPERUSER_PASSWORD ]]; then
155 | MUMBLE_SUPERUSER_PASSWORD="$(cat /run/secrets/MUMBLE_SUPERUSER_PASSWORD)"
156 | echo "Read superuser password from container secret"
157 | fi
158 |
159 | if [[ -n "${MUMBLE_SUPERUSER_PASSWORD}" ]]; then
160 | #Variable to change the superuser password
161 | "${server_invocation[@]}" -supw "$MUMBLE_SUPERUSER_PASSWORD"
162 | echo "Successfully configured superuser password"
163 | fi
164 |
165 | # Set privileges for /app but only if pid 1 user is root and we are dropping privileges.
166 | # If container is run as an unprivileged user, it means owner already handled ownership setup on their own.
167 | # Running chown in that case (as non-root) will cause error
168 | if [[ "$(id -u)" = "0" ]] && [[ "${PUID}" != "0" ]] && [[ "${MUMBLE_CHOWN_DATA}" = true ]]; then
169 | chown -R ${PUID}:${PGID} /data
170 | fi
171 |
172 | # Show /data permissions, in case the user needs to match the mount point access
173 | echo "Running Mumble server as uid=${PUID} gid=${PGID}"
174 | echo "\"${DATA_DIR}\" has the following permissions set:"
175 | echo " $( stat ${DATA_DIR} --printf='%A, owner: \"%U\" (UID: %u), group: \"%G\" (GID: %g)' )"
176 |
177 | echo "Command run to start the service : ${server_invocation[*]}"
178 | echo "Starting..."
179 |
180 | # Drop privileges (when asked to) if root, otherwise run as current user
181 | if [[ "$(id -u)" = "0" ]] && [[ "${PUID}" != "0" ]]; then
182 | exec su-exec ${PUID}:${PGID} "${server_invocation[@]}"
183 | else
184 | exec "${server_invocation[@]}"
185 | fi
186 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mumble Docker
2 |
3 | 
4 | 
5 | 
6 |
7 |
8 | Mumble is a free, open source, low latency, high quality voice chat application.
9 |
10 |
Mumble Website • Mumble Source
11 | 12 | This is the official code of the Mumble Docker image for self-hosting the **Mumble server**. The image is available for download on 13 | **[Dockerhub](https://hub.docker.com/r/mumblevoip/mumble-server)** and the **[GHCR](https://github.com/mumble-voip/mumble-docker/pkgs/container/mumble-server)**. 14 | 15 | ----- 16 | 17 | ## Quick Start Guide 18 | 19 | 1. [Running the container](#running-the-container) 20 | 2. [Configuration](#configuration) 21 | 3. [Building the container](#building-the-container) 22 | 4. [More docs and usage examples in the Wiki](https://github.com/mumble-voip/mumble-docker/wiki) 23 | 24 | 25 | ## Running the container 26 | 27 | ### Requirements 28 | 29 | This documentation assumes that you already have Docker installed and configured on your target machine. You may find it more convenient to set up the 30 | Docker container using [docker-compose](https://docs.docker.com/compose/). Thus, we also provide instructions for that scenario (see below). 31 | 32 | In order for Mumble to store permanent data (most notably the database file (by default Mumble uses SQLite)), the image will use a 33 | [volume](https://docs.docker.com/storage/volumes/) which is mapped to the `/data/` path inside the image. By default the image uses a user with UID 34 | `10000` and GID of also `10000` but either can be adapted when building the image yourself (see below). You will have to make sure that all file 35 | permissions are set up accordingly. 36 | 37 | ### Running the container 38 | 39 | **Using docker**: 40 | ```bash 41 | $ docker run --detach \ 42 | --name mumble-server \ 43 | --publish 64738:64738/tcp \ 44 | --publish 64738:64738/udp \ 45 | --volume ./data/mumble:/data \ 46 | --restart on-failure \ 47 | mumblevoip/mumble-server: