From c250b2dcff9843b2681ee0966265efeace27e74e Mon Sep 17 00:00:00 2001 From: marlon Date: Sat, 3 May 2025 22:04:58 +0000 Subject: [PATCH] update readme --- .env.sample | 205 +++++++++----------------------------- README.md | 73 ++++++++++++-- abra.sh | 2 +- compose.auth-internal.yml | 26 +++++ compose.auth-keycloak.yml | 37 +++++++ compose.yml | 120 +++++++++++++++------- entrypoint.sh.tmpl | 1 + 7 files changed, 257 insertions(+), 207 deletions(-) create mode 100644 compose.auth-internal.yml create mode 100644 compose.auth-keycloak.yml diff --git a/.env.sample b/.env.sample index 4415424..869ddc3 100644 --- a/.env.sample +++ b/.env.sample @@ -2,182 +2,67 @@ TYPE=jitsi TIMEOUT=900 ENABLE_AUTO_UPDATE=true -DOMAIN=meet.example.com +DOMAIN=jitsi.example.com ## Domain aliases -#EXTRA_DOMAINS=', `www.meet.example.com`' +#EXTRA_DOMAINS=', `www.jitsi.example.com`' LETS_ENCRYPT_ENV=production COMPOSE_FILE="compose.yml" -#COMPOSE_FILE="$COMPOSE_FILE:compose.additional.yml" - -ADMIN_USER=admin +## Internal-prosody authentication (anyone may join existing rooms; users must +## be registered via prosodyctl to create new rooms). See README. +#COMPOSE_FILE="$COMPOSE_FILE:compose.auth-internal.yml" +## Keycloak / JWT authentication. Requires JWT_APP_ID below and the +## jwt_app_secret secret. See README. +#COMPOSE_FILE="$COMPOSE_FILE:compose.auth-keycloak.yml" SECRET_JICOFO_AUTH_PASSWORD_VERSION=v1 +SECRET_JICOFO_COMPONENT_SECRET_VERSION=v1 SECRET_JVB_AUTH_PASSWORD_VERSION=v1 +## Used only with compose.auth-keycloak.yml +#SECRET_JWT_APP_SECRET_VERSION=v1 -EXTRA_VOLUME=/dev/null:/tmp/.dummy - -# shellcheck disable=SC2034 - -################################################################################ -################################################################################ -# Welcome to the Jitsi Meet Docker setup! -# -# This sample .env file contains some basic options to get you started. -# The full options reference can be found here: -# https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker -################################################################################ -################################################################################ - - -# -# Basic configuration options -# - -# Directory where all configuration will be stored -CONFIG=~/.jitsi-meet-cfg - -# Exposed HTTP port -HTTP_PORT=80 - -# Exposed HTTPS port -HTTPS_PORT=443 +# Public URL for the web service (required) +PUBLIC_URL=https://jitsi.example.com # System time zone TZ=UTC -# Public URL for the web service (required) -PUBLIC_URL=https://meet.example.com +# Internal XMPP domains. Defaults match jitsi/docker-jitsi-meet conventions. +XMPP_DOMAIN=meet.jitsi +XMPP_AUTH_DOMAIN=auth.meet.jitsi +XMPP_GUEST_DOMAIN=guest.meet.jitsi +XMPP_MUC_DOMAIN=muc.meet.jitsi +XMPP_INTERNAL_MUC_DOMAIN=internal-muc.meet.jitsi +XMPP_RECORDER_DOMAIN=recorder.meet.jitsi +XMPP_SERVER=xmpp.meet.jitsi +XMPP_BOSH_URL_BASE=http://xmpp.meet.jitsi:5280 +XMPP_PORT=5222 -# Media IP addresses to advertise by the JVB -# This setting deprecates DOCKER_HOST_ADDRESS, and supports a comma separated list of IPs -# See the "Running behind NAT or on a LAN environment" section in the Handbook: -# https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker#running-behind-nat-or-on-a-lan-environment -#JVB_ADVERTISE_IPS=192.168.1.1,1.2.3.4 -JVB_WS_DOMAIN=meet.example.com +JICOFO_AUTH_USER=focus +JVB_AUTH_USER=jvb +JVB_BREWERY_MUC=jvbbrewery +# Bridge channel — server-id must resolve from the web container to the jvb +# service. Using the compose service name "jvb" works out of the box. +JVB_WS_DOMAIN=jitsi.example.com +JVB_WS_SERVER_ID=jvb +JVB_PORT=10000 -# -# JaaS Components (beta) -# https://jaas.8x8.vc -# +ENABLE_XMPP_WEBSOCKET=1 +ENABLE_COLIBRI_WEBSOCKET=1 +COLIBRI_REST_ENABLED=0 -# Enable JaaS Components (hosted Jigasi) -# NOTE: if Let's Encrypt is enabled a JaaS account will be automatically created, using the provided email in LETSENCRYPT_EMAIL -#ENABLE_JAAS_COMPONENTS=0 +# Authentication mode. Defaults to anonymous (no auth). Override via overlay. +ENABLE_AUTH=0 +ENABLE_GUESTS=0 +AUTH_TYPE=internal -# -# Etherpad integration (for document sharing) -# +# Public IPs JVB advertises as ICE candidates. Required when JVB is behind NAT. +# Comma-separated list of IPv4/IPv6 the bridge should advertise. +JVB_ADVERTISE_IPS=1.2.3.4 -# Set etherpad-lite URL in docker local network (uncomment to enable) -#ETHERPAD_URL_BASE=http://etherpad.meet.jitsi:9001 +# JWT auth — only used when compose.auth-keycloak.yml is enabled. +#JWT_APP_ID=jitsi +#TOKEN_AUTH_URL=https://keycloak.example.com/realms/main/protocol/openid-connect/auth?client_id=jitsi&response_type=id_token&scope=openid&redirect_uri={room} -# Set etherpad-lite public URL, including /p/ pad path fragment (uncomment to enable) -#ETHERPAD_PUBLIC_URL=https://etherpad.my.domain/p/ - -# Name your etherpad instance! -#ETHERPAD_TITLE=Video Chat - -# The default text of a pad -#ETHERPAD_DEFAULT_PAD_TEXT="Welcome to Web Chat!\n\n" - -# Name of the skin for etherpad -#ETHERPAD_SKIN_NAME=colibris - -# Skin variants for etherpad -#ETHERPAD_SKIN_VARIANTS="super-light-toolbar super-light-editor light-background full-width-editor" - - -# -# Basic Jigasi configuration options (needed for SIP gateway support) -# - -# SIP URI for incoming / outgoing calls -#JIGASI_SIP_URI=test@sip2sip.info - -# Password for the specified SIP account as a clear text -#JIGASI_SIP_PASSWORD=passw0rd - -# SIP server (use the SIP account domain if in doubt) -#JIGASI_SIP_SERVER=sip2sip.info - -# SIP server port -#JIGASI_SIP_PORT=5060 - -# SIP server transport -#JIGASI_SIP_TRANSPORT=UDP - - -# -# Authentication configuration (see handbook for details) -# - -# Enable authentication -#ENABLE_AUTH=1 - -# Enable guest access -#ENABLE_GUESTS=1 - -# Select authentication type: internal, jwt, ldap or matrix -#AUTH_TYPE=internal - -# JWT authentication -# - -# Application identifier -#JWT_APP_ID=my_jitsi_app_id - -# Application secret known only to your token generator -#JWT_APP_SECRET=my_jitsi_app_secret - -# (Optional) Set asap_accepted_issuers as a comma separated list -#JWT_ACCEPTED_ISSUERS=my_web_client,my_app_client - -# (Optional) Set asap_accepted_audiences as a comma separated list -#JWT_ACCEPTED_AUDIENCES=my_server1,my_server2 - -# LDAP authentication (for more information see the Cyrus SASL saslauthd.conf man page) -# - -# LDAP url for connection -#LDAP_URL=ldaps://ldap.domain.com/ - -# LDAP base DN. Can be empty -#LDAP_BASE=DC=example,DC=domain,DC=com - -# LDAP user DN. Do not specify this parameter for the anonymous bind -#LDAP_BINDDN=CN=binduser,OU=users,DC=example,DC=domain,DC=com - -# LDAP user password. Do not specify this parameter for the anonymous bind -#LDAP_BINDPW=LdapUserPassw0rd - -# LDAP filter. Tokens example: -# %1-9 - if the input key is user@mail.domain.com, then %1 is com, %2 is domain and %3 is mail -# %s - %s is replaced by the complete service string -# %r - %r is replaced by the complete realm string -#LDAP_FILTER=(sAMAccountName=%u) - -# LDAP authentication method -#LDAP_AUTH_METHOD=bind - -# LDAP version -#LDAP_VERSION=3 - -# LDAP TLS using -#LDAP_USE_TLS=1 - -# List of SSL/TLS ciphers to allow -#LDAP_TLS_CIPHERS=SECURE256:SECURE128:!AES-128-CBC:!ARCFOUR-128:!CAMELLIA-128-CBC:!3DES-CBC:!CAMELLIA-128-CBC - -# Require and verify server certificate -#LDAP_TLS_CHECK_PEER=1 - -# Path to CA cert file. Used when server certificate verify is enabled -#LDAP_TLS_CACERT_FILE=/etc/ssl/certs/ca-certificates.crt - -# Path to CA certs directory. Used when server certificate verify is enabled -#LDAP_TLS_CACERT_DIR=/etc/ssl/certs - -# Wether to use starttls, implies LDAPv3 and requires ldap:// instead of ldaps:// -# LDAP_START_TLS=1 \ No newline at end of file +# shellcheck disable=SC2034 diff --git a/README.md b/README.md index 60021c1..f5e9d04 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,75 @@ # jitsi -> One line description of the recipe +Jitsi Meet on coop-cloud, tracking `jitsi/docker-jitsi-meet` upstream. -* **Category**: Apps -* **Status**: 0 -* **Image**: [`jitsi`](https://hub.docker.com/r/jitsi), 4, upstream +* **Category**: Communication +* **Status**: 3, stable +* **Image**: [`jitsi/web`](https://hub.docker.com/r/jitsi/web), 4, upstream * **Healthcheck**: No * **Backups**: No -* **Email**: No -* **Tests**: No -* **SSO**: No +* **Email**: N/A +* **Tests**: 0 +* **SSO**: Yes +Four upstream images are deployed together (`jitsi/web`, `jitsi/prosody`, +`jitsi/jicofo`, `jitsi/jvb`), all pinned to the same `stable-NNNN` tag. + ## Quick start -* `abra app new jitsi --secrets` -* `abra app config ` -* `abra app deploy ` +``` +abra app new jitsi --secrets +abra app config +abra app secret generate -a +abra app deploy +``` -For more, see [`docs.coopcloud.tech`](https://docs.coopcloud.tech). +Three secrets are created automatically: `jicofo_auth_password`, +`jicofo_component_secret`, `jvb_auth_password`. + +## Networking + +JVB publishes UDP 10000 on the host directly (`mode: host`). Open that port +inbound on the host firewall (and any provider-level firewall). Set +`JVB_ADVERTISE_IPS` to the public IP(s) the bridge should advertise as ICE +candidates — clients connect there over UDP for audio/video. + +No TURN server is bundled. Clients on networks that block outbound UDP to +arbitrary ports won't be able to connect. Add a coturn alongside if you need +to support such clients. + +## Authentication + +Default deploy is anonymous (any visitor can create and join rooms). + +To require login for room *creation* (guests can still join), add to `.env`: + +``` +COMPOSE_FILE="$COMPOSE_FILE:compose.auth-internal.yml" +``` + +Then register users inside the prosody container: + +``` +ssh "docker exec -it \$(docker ps -qf name=_prosody) \ + prosodyctl --config /config/prosody.cfg.lua register \ + meet.jitsi " +``` + +For Keycloak / JWT auth, use `compose.auth-keycloak.yml` instead. You'll need +to add a `jwt_app_secret` docker secret with the Keycloak client secret, +configure `JWT_APP_ID` and `TOKEN_AUTH_URL` in `.env`, and create a matching +OpenID client in Keycloak. + +## Persistent state + +Per-service named docker volumes are used: +`jitsiweb`, `jitsicrontabs`, `jitsitranscripts`, `jitsiprosodyconfig`, +`jitsiprosodyplugins`, `jitsijicofoconfig`, `jitsijvbconfig`. + +Prosody, jicofo and jvb regenerate their configs from env vars on each +start, so wiping these volumes (e.g. across major image upgrades) is safe +and is sometimes necessary to avoid stale-config crashes. diff --git a/abra.sh b/abra.sh index a4ea66f..518a2b5 100644 --- a/abra.sh +++ b/abra.sh @@ -1,6 +1,6 @@ #!/bin/bash -export ENTRYPOINT_VERSION=v1 +export ENTRYPOINT_VERSION=v2 #example_command() { # ls diff --git a/compose.auth-internal.yml b/compose.auth-internal.yml new file mode 100644 index 0000000..4f2c89d --- /dev/null +++ b/compose.auth-internal.yml @@ -0,0 +1,26 @@ +version: "3.8" + +# Internal-prosody auth: anyone may join existing rooms, but creating a +# new room requires a registered user. After deploy, create users with: +# +# ssh "docker exec -it \$(docker ps -qf name=_prosody) \ +# prosodyctl --config /config/prosody.cfg.lua register \ +# meet.jitsi " + +services: + app: + environment: + - ENABLE_AUTH=1 + - ENABLE_GUESTS=1 + - AUTH_TYPE=internal + + prosody: + environment: + - ENABLE_AUTH=1 + - ENABLE_GUESTS=1 + - AUTH_TYPE=internal + + jicofo: + environment: + - ENABLE_AUTH=1 + - AUTH_TYPE=internal diff --git a/compose.auth-keycloak.yml b/compose.auth-keycloak.yml new file mode 100644 index 0000000..55c2c5d --- /dev/null +++ b/compose.auth-keycloak.yml @@ -0,0 +1,37 @@ +version: "3.8" + +# Keycloak / JWT auth. Requires: +# - JWT_APP_ID in .env (matches the Keycloak client id) +# - TOKEN_AUTH_URL in .env (Keycloak's OIDC authorize endpoint with +# {room} placeholder substituted by Jitsi at runtime) +# - jwt_app_secret docker secret containing the Keycloak client secret +# - SECRET_JWT_APP_SECRET_VERSION=v1 in .env + +services: + app: + environment: + - ENABLE_AUTH=1 + - ENABLE_GUESTS=1 + - AUTH_TYPE=jwt + - JWT_APP_ID + - TOKEN_AUTH_URL + + prosody: + environment: + - ENABLE_AUTH=1 + - ENABLE_GUESTS=1 + - AUTH_TYPE=jwt + - JWT_APP_ID + - JWT_APP_SECRET_FILE=/run/secrets/jwt_app_secret + secrets: + - jwt_app_secret + + jicofo: + environment: + - ENABLE_AUTH=1 + - AUTH_TYPE=jwt + +secrets: + jwt_app_secret: + external: true + name: ${STACK_NAME}_jwt_app_secret_${SECRET_JWT_APP_SECRET_VERSION} diff --git a/compose.yml b/compose.yml index c51d0c3..3f19025 100644 --- a/compose.yml +++ b/compose.yml @@ -2,21 +2,35 @@ version: "3.8" services: app: - image: jitsi/web:stable-8719 + image: jitsi/web:stable-10978 volumes: - - jitsiconfig:/config + - jitsiweb:/config - jitsicrontabs:/var/spool/cron/crontabs - jitsitranscripts:/usr/share/jitsi-meet/transcripts - - ${EXTRA_VOLUME} environment: - - CONFIG - - HTTP_PORT - - HTTPS_PORT - - TZ - PUBLIC_URL + - TZ + - XMPP_DOMAIN + - XMPP_AUTH_DOMAIN + - XMPP_BOSH_URL_BASE + - XMPP_GUEST_DOMAIN + - XMPP_MUC_DOMAIN + - XMPP_RECORDER_DOMAIN + - XMPP_SERVER + - JVB_WS_DOMAIN + - JVB_WS_SERVER_ID + - JICOFO_AUTH_USER + - ENABLE_XMPP_WEBSOCKET + - ENABLE_COLIBRI_WEBSOCKET + - ENABLE_AUTH + - ENABLE_GUESTS + - AUTH_TYPE + - COLIBRI_WEBSOCKET_REGEX networks: - proxy - internal + depends_on: + - jvb deploy: update_config: failure_action: rollback @@ -28,26 +42,40 @@ services: - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`${EXTRA_DOMAINS})" - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - - "caddy=${DOMAIN}" - - "caddy.reverse_proxy={{upstreams 80}}" - - "caddy.tls.on_demand=" - - "coop-cloud.${STACK_NAME}.version=0.0.1+8719" + - "coop-cloud.${STACK_NAME}.version=1.0.0+stable-10978" prosody: - image: jitsi/prosody:stable-8719 + image: jitsi/prosody:stable-10978 volumes: - jitsiprosodyconfig:/config - - jitsiprosody:/prosody-plugins-custom + - jitsiprosodyplugins:/prosody-plugins-custom environment: + - TZ + - AUTH_TYPE + - ENABLE_AUTH + - ENABLE_GUESTS + - GLOBAL_MODULES + - XMPP_DOMAIN + - XMPP_AUTH_DOMAIN + - XMPP_GUEST_DOMAIN + - XMPP_MUC_DOMAIN + - XMPP_INTERNAL_MUC_DOMAIN + - XMPP_RECORDER_DOMAIN + - XMPP_SERVER + - XMPP_PORT + - JICOFO_AUTH_USER - JICOFO_AUTH_PASSWORD_FILE=/run/secrets/jicofo_auth_password + - JICOFO_COMPONENT_SECRET_FILE=/run/secrets/jicofo_component_secret + - JVB_AUTH_USER - JVB_AUTH_PASSWORD_FILE=/run/secrets/jvb_auth_password configs: - source: entrypoint target: /custom-entrypoint.sh - mode: 555 + mode: 0555 entrypoint: /custom-entrypoint.sh secrets: - jicofo_auth_password + - jicofo_component_secret - jvb_auth_password networks: internal: @@ -59,73 +87,95 @@ services: order: start-first jicofo: - image: jitsi/jicofo:stable-8719 + image: jitsi/jicofo:stable-10978 volumes: - jitsijicofoconfig:/config environment: + - TZ + - AUTH_TYPE + - ENABLE_AUTH + - XMPP_DOMAIN + - XMPP_AUTH_DOMAIN + - XMPP_MUC_DOMAIN + - XMPP_INTERNAL_MUC_DOMAIN + - XMPP_RECORDER_DOMAIN + - XMPP_SERVER + - JICOFO_AUTH_USER - JICOFO_AUTH_PASSWORD_FILE=/run/secrets/jicofo_auth_password + - JICOFO_COMPONENT_SECRET_FILE=/run/secrets/jicofo_component_secret + - JVB_BREWERY_MUC configs: - source: entrypoint target: /custom-entrypoint.sh - mode: 555 + mode: 0555 entrypoint: /custom-entrypoint.sh secrets: - jicofo_auth_password + - jicofo_component_secret depends_on: - - prosody + - prosody networks: - internal: + - internal deploy: update_config: failure_action: rollback order: start-first jvb: - image: jitsi/jvb:stable-8719 + image: jitsi/jvb:stable-10978 volumes: - jitsijvbconfig:/config environment: - - JVB_AUTH_PASSWORD_FILE=/run/secrets/jvb_auth_password - - JVB_WS_DOMAIN - - JVB_ADVERTISE_IPS - - XMPP_SERVER + - TZ + - XMPP_AUTH_DOMAIN + - XMPP_INTERNAL_MUC_DOMAIN + - XMPP_SERVER + - JVB_AUTH_USER + - JVB_AUTH_PASSWORD_FILE=/run/secrets/jvb_auth_password + - JVB_BREWERY_MUC + - JVB_PORT + - JVB_ADVERTISE_IPS + - JVB_WS_DOMAIN + - JVB_WS_SERVER_ID + - COLIBRI_REST_ENABLED configs: - source: entrypoint target: /custom-entrypoint.sh - mode: 555 + mode: 0555 entrypoint: /custom-entrypoint.sh secrets: - jvb_auth_password depends_on: - - prosody + - prosody ports: -# - '0.0.0.0:10000:10000/udp' - - '127.0.0.1:8080:8080' + - target: 10000 + published: 10000 + protocol: udp + mode: host networks: - internal: + - internal deploy: update_config: failure_action: rollback order: start-first - labels: - - "traefik.udp.routers.${STACK_NAME}-jvb.rule=HostSNI(`*`)" - - "traefik.udp.routers.${STACK_NAME}-jvb.entrypoints=udp-10000" - - "traefik.udp.services.${STACK_NAME}-jvb.loadbalancer.server.port=10000" secrets: jicofo_auth_password: external: true name: ${STACK_NAME}_jicofo_auth_password_${SECRET_JICOFO_AUTH_PASSWORD_VERSION} + jicofo_component_secret: + external: true + name: ${STACK_NAME}_jicofo_component_secret_${SECRET_JICOFO_COMPONENT_SECRET_VERSION} jvb_auth_password: external: true name: ${STACK_NAME}_jvb_auth_password_${SECRET_JVB_AUTH_PASSWORD_VERSION} volumes: - jitsiconfig: + jitsiweb: jitsicrontabs: jitsitranscripts: jitsiprosodyconfig: - jitsiprosody: + jitsiprosodyplugins: jitsijicofoconfig: jitsijvbconfig: @@ -138,4 +188,4 @@ configs: networks: proxy: external: true - internal: \ No newline at end of file + internal: diff --git a/entrypoint.sh.tmpl b/entrypoint.sh.tmpl index 8c24027..629fdbe 100644 --- a/entrypoint.sh.tmpl +++ b/entrypoint.sh.tmpl @@ -24,6 +24,7 @@ file_env() { } file_env "JICOFO_AUTH_PASSWORD" +file_env "JICOFO_COMPONENT_SECRET" file_env "JVB_AUTH_PASSWORD" /init \ No newline at end of file -- 2.49.0