diff --git a/.env.sample b/.env.sample
index dc1c153..a1afc54 100644
--- a/.env.sample
+++ b/.env.sample
@@ -1,11 +1,19 @@
TYPE=mumble
DOMAIN=mumble.example.com
-
-## Domain aliases
-#EXTRA_DOMAINS=', `www.mumble.example.com`'
LETS_ENCRYPT_ENV=production
-ENV=production
+
+## Superuser password secret version
+SECRET_SU_PASSWORD_VERSION=v1
+
+## Max concurrent users
+MUMBLE_USERS=100
+
+## Welcome message shown to connecting clients
+MUMBLE_WELCOMETEXT=
Welcome to this Mumble server.
+
+## Server-wide password (blank = open server)
+MUMBLE_SERVERPASSWORD=
# This is here so later lines can extend it; you likely don't wanna edit
COMPOSE_FILE="compose.yml"
diff --git a/README.md b/README.md
index c88be94..78680b8 100644
--- a/README.md
+++ b/README.md
@@ -7,10 +7,10 @@ Low latency, high quality voice chat application.
* **Category**: Apps
-* **Status**: 1, alpha
-* **Image**: [phlak/mumble](https://hub.docker.com/repository/docker/phlak/mumble), 2, 3rd-party
-* **Healthcheck**: No
-* **Backups**: No
+* **Status**: 2, beta
+* **Image**: [mumblevoip/mumble-server](https://github.com/mumble-voip/mumble-docker), 1, upstream
+* **Healthcheck**: Yes
+* **Backups**: Yes
* **Email**: N/A
* **Tests**: No
* **SSO**: N/A
@@ -19,15 +19,35 @@ Low latency, high quality voice chat application.
## Basic usage
-1. Set up Docker Swarm and [`abra`]
-2. Deploy [`coop-cloud/traefik`]
-3. `abra app new ${REPO_NAME} --secrets` (optionally with `--pass` if you'd like
- to save secrets in `pass`)
-4. `abra app config YOURAPPDOMAIN` - be sure to change `$DOMAIN` to something that resolves to
- your Docker swarm box
-5. `abra app deploy YOURAPPDOMAIN`
-6. Open the configured domain in your browser to finish set-up
+1. Set up Docker Swarm and [`abra`](https://git.coopcloud.tech/coop-cloud/abra)
+2. `abra app new mumble --server --domain `
+3. `abra app secret generate --all`
+4. `abra app deploy `
+5. Connect with a [Mumble client](https://www.mumble.info/downloads/) to port 64738 on your domain
+
+## Networking
+
+Mumble uses its own protocol (not HTTP), so port 64738 TCP+UDP is published
+directly on the host. No Traefik configuration is needed for the voice server.
+Make sure port 64738 is open in your firewall for both TCP and UDP.
+
+## Superuser
+
+A superuser password is generated as a Docker secret (`su_password`) during
+setup. To manage channels and permissions, connect with username `SuperUser`
+via a mumble client and the generated password.
+
+## Web client
+
+An optional browser-based client is available via the `compose.mumbleweb.yml`
+overlay. To enable it:
+
+1. `abra app config mumble.example.com` — uncomment the `compose.mumbleweb.yml` line:
+ ```
+ COMPOSE_FILE="$COMPOSE_FILE:compose.mumbleweb.yml"
+ ```
+2. `abra app deploy mumble.example.com --force`
+3. Open `https://YOURDOMAIN` in a browser and connect to your mumble server through the web
+
+By default there is no password, but you can set a password for your server via `abra app config`
-[`abra`]: https://git.coopcloud.tech/coop-cloud/abra
-[`coop-cloud/traefik`]: https://git.coopcloud.tech/coop-cloud/traefik
-coop-cloud/traefik
diff --git a/abra-entrypoint.sh b/abra-entrypoint.sh
new file mode 100644
index 0000000..9075005
--- /dev/null
+++ b/abra-entrypoint.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+set -e
+
+[ -f /run/secrets/su_password ] && export MUMBLE_SUPERUSER_PASSWORD="$(cat /run/secrets/su_password)"
+
+exec /entrypoint.sh "$@"
diff --git a/abra.sh b/abra.sh
new file mode 100644
index 0000000..7a218b6
--- /dev/null
+++ b/abra.sh
@@ -0,0 +1,3 @@
+# Set any config versions here
+# Docs: https://docs.coopcloud.tech/maintainers/handbook/#manage-configs
+export ABRA_ENTRYPOINT_VERSION=v1
diff --git a/compose.mumbleweb.yml b/compose.mumbleweb.yml
index 25caab0..8b11ca6 100644
--- a/compose.mumbleweb.yml
+++ b/compose.mumbleweb.yml
@@ -1,11 +1,17 @@
version: "3.8"
+
services:
+ app:
+ networks:
+ - internal
+
web:
image: rankenstein/mumble-web
environment:
- "MUMBLE_SERVER=${STACK_NAME}_app:64738"
networks:
- proxy
+ - internal
deploy:
labels:
- "traefik.enable=true"
@@ -13,3 +19,8 @@ services:
- "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure"
- "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}"
+
+networks:
+ proxy:
+ external: true
+ internal:
diff --git a/compose.yml b/compose.yml
index 44b7b14..90c8fd5 100644
--- a/compose.yml
+++ b/compose.yml
@@ -3,37 +3,61 @@ version: "3.8"
services:
app:
- image: phlak/mumble
- networks:
- - proxy
+ image: mumblevoip/mumble-server:v1.6.870
+ entrypoint: ["/abra-entrypoint.sh"]
+ command: ["/usr/bin/mumble-server"]
volumes:
- - "mumble_data:/etc/mumble"
+ - mumble_data:/data
+ environment:
+ - MUMBLE_CONFIG_WELCOMETEXT=${MUMBLE_WELCOMETEXT:-
Welcome to this Mumble server.
}
+ - MUMBLE_CONFIG_USERS=${MUMBLE_USERS:-100}
+ - MUMBLE_CONFIG_SERVERPASSWORD=${MUMBLE_SERVERPASSWORD:-}
+ # Mumble uses its own protocol on port 64738 (TCP+UDP), not HTTP.
+ # Published directly on the host — cannot be proxied through Traefik
+ # without custom entrypoints.
+ ports:
+ - target: 64738
+ published: 64738
+ protocol: tcp
+ mode: host
+ - target: 64738
+ published: 64738
+ protocol: udp
+ mode: host
+ configs:
+ - source: abra_entrypoint
+ target: /abra-entrypoint.sh
+ mode: 0555
+ secrets:
+ - su_password
+ healthcheck:
+ test: ["CMD-SHELL", "bash -c 'echo > /dev/tcp/localhost/64738'"]
+ interval: 30s
+ timeout: 10s
+ retries: 10
+ start_period: 30s
deploy:
restart_policy:
condition: on-failure
labels:
- - "traefik.enable=true"
- # note(3wc) see https://github.com/PHLAK/docker-mumble/issues/15
- - "traefik.tcp.routers.${STACK_NAME}.entrypoints=mumble"
- - "traefik.tcp.routers.${STACK_NAME}.service=${STACK_NAME}-tcp-service"
- - "traefik.tcp.routers.${STACK_NAME}.rule=HostSNI(`*`)"
- - "traefik.tcp.routers.${STACK_NAME}.tls.passthrough=true"
- - "traefik.tcp.services.${STACK_NAME}-tcp-service.loadbalancer.server.port=64738"
- - "traefik.udp.routers.${STACK_NAME}.entrypoints=mumble-udp"
- - "traefik.udp.routers.${STACK_NAME}.service=${STACK_NAME}-udp-service"
- - "traefik.udp.services.${STACK_NAME}-udp-service.loadbalancer.server.port=64738"
- # note(3wc): this image doesn't have curl, and wget doesn't seem to like
- # testing the TCP port
- #healthcheck
- # test: ["CMD", "curl", "-f", "http://localhost"]
- # interval: 30s
- # timeout: 10s
- # retries: 10
- # start_period: 1m
-
-networks:
- proxy:
- external: true
+ - "traefik.enable=false"
+ - "coop-cloud.${STACK_NAME}.version=0.1.0+1.6.870"
+ - "coop-cloud.${STACK_NAME}.timeout=${TIMEOUT:-60}"
+ - "backupbot.backup=${ENABLE_BACKUPS:-true}"
+ - 'backupbot.backup.pre-hook=sqlite3 /data/mumble-server.sqlite ".backup /data/backup.sqlite"'
+ - "backupbot.backup.post-hook=rm -f /data/backup.sqlite"
+ - "backupbot.backup.volumes.mumble_data.path=backup.sqlite"
+ - "backupbot.restore.post-hook=cp /data/backup.sqlite /data/mumble-server.sqlite"
volumes:
mumble_data:
+
+configs:
+ abra_entrypoint:
+ name: ${STACK_NAME}_entrypoint_${ABRA_ENTRYPOINT_VERSION}
+ file: abra-entrypoint.sh
+
+secrets:
+ su_password:
+ external: true
+ name: ${STACK_NAME}_su_password_${SECRET_SU_PASSWORD_VERSION}