From a55845e57bb1972672674bbdd76ee52435d49b5b Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 13:39:49 +0200 Subject: [PATCH 01/37] refact(/docs/examples): Refactoring the example docs WIP * init version of the TLS docs * including: * why tls is needed * what to do if you own a domain of if you don't * a troubleshooting * refactored version of the Janus readme --- docs/examples/TLS.md | 97 +++++++++++++++++++++++++++++++++++ docs/examples/janus/README.md | 51 ++---------------- 2 files changed, 100 insertions(+), 48 deletions(-) create mode 100644 docs/examples/TLS.md diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md new file mode 100644 index 0000000..8a6ba71 --- /dev/null +++ b/docs/examples/TLS.md @@ -0,0 +1,97 @@ +# TLS + +This documentation sums up the the TLS and certificate issues you will encounter deploying the examples. + +## The issue + +Some client-side application must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. In the demos, we will aim to obtain a proper CA-signed certificate (self-signed certificates haven't been tested). Obtaining a valid TLS certificate is a challenge. Thus, the majority of the installation guides will be about securing client connections to the client-side apps and the WebRTC mediaservers over TLS. Once HTTPS is correctly working, integrating the mediaservers with STUNner is very simple. + +## TLS certificates + +Some WebRTC servers will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't, we still have a solution for that. + +> [!NOTE] +> +> By default, the examples and the commands included are setup for the case you don't have your own domain. + +### If you don't have your own domain + +[nip.io](https://nip.io) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for the mediaserver. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. + +### If you have your own domain + +> [!NOTE] +> +> Do not forget to create a new DNS record pointing to your ingress' IP address! + +## Installation + +### Ingress + +The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. + +Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. + +```console +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +helm install ingress-nginx ingress-nginx/ingress-nginx +``` + +Wait until Kubernetes assigns an external IP to the Ingress. + +```console +until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done +``` + +Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. + +```console +kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' +export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') +``` + +### Cert manager + +We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. + +Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: + +```console +helm repo add cert-manager https://charts.jetstack.io +helm repo update +helm install cert-manager jetstack/cert-manager --namespace cert-manager \ + --create-namespace --set global.leaderElection.namespace=cert-manager \ + --set crds.enabled=true --timeout 600s +``` + +At this point we have all the necessary boilerplate set up to automate TLS issuance for the demo. + +## Troubleshooting + +#### Wildcard DNS domain rate limiting + +Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of `nip.io`. + +#### Certificate issuance + +If you work with certificates you must be aware that signing a certificate request takes some time and it differs for every CA (certificate authority). If you sense there is a problem with the certificate being signed or issued, you can check it directly and see what is going on. + +First, you'll need to find the certificate and its related resources in your cluster. +```bash +kubectl get certificate -A + +kubectl get certificaterequests.cert-manager.io -A + +kubectl get certificatesigningrequests.certificates.k8s.io +``` + +To find more information about them +```bash +kubectl describe certificate -A + +kubectl describe certificaterequests.cert-manager.io -A + +kubectl describe certificatesigningrequests.certificates.k8s.io +``` \ No newline at end of file diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index d7e87c5..4c1e334 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -27,7 +27,7 @@ In this tutorial we deploy [Janus Gateway](https://github.com/meetecho/janus-gat > [!NOTE] > -> Let's start with a disclaimer. The Janus client-side application must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. In this demo, we will aim to obtain a proper CA-signed certificate (self-signed certificates haven't been tested). Obtaining a valid TLS certificate is a challenge. Thus, the majority of the below installation guide will be about securing client connections to Janus over TLS; as it turns out, once HTTPS is correctly working integrating Janus with STUNner is very simple. +> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Janus and the Ingress gateway will live in the `default` namespace. @@ -35,54 +35,9 @@ In the below example, STUNner will be installed into the identically named names Janus does not come with an official Docker image; thus, we built one using a self-made Dockerfile based on the available documents in the official [Janus repository](https://github.com/meetecho/janus-gateway). Actually, we've made two Dockerfiles. One for the Janus Gateway server and one for the Janus Web Demos. The [Janus Gateway server Dockerfile](./DOCKERFILE-janus-gateway) should be ran in the root directory of the [Janus repository](https://github.com/meetecho/janus-gateway). The Janus Web Demos Dockerfile should be used in the `/html` directory of the [same repository](https://github.com/meetecho/janus-gateway/tree/master/html). The images (`l7mp/janus-gateway:v1.2.4` and `l7mp/janus-web:latest`) used in the following demo are hosted on Docker Hub under the L7MP organization. +### Ingress and Cert manager installation -### TLS certificates - -As mentioned above, the Janus WebRTC server will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't then [nip.io](https://nip.io) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for Janus. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. - -Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of `nip.io`. - -### Ingress - -The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. - -Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. - -```console -helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -helm repo update -helm install ingress-nginx ingress-nginx/ingress-nginx -``` - -Wait until Kubernetes assigns an external IP to the Ingress. - -```console -until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done -``` - -Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. - -```console -kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') -export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') -``` - -### Cert manager - -We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. - -Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: - -```console -helm repo add cert-manager https://charts.jetstack.io -helm repo update -helm install cert-manager jetstack/cert-manager --namespace cert-manager \ - --create-namespace --set global.leaderElection.namespace=cert-manager \ - --set crds.enabled=true --timeout 600s -``` - -At this point we have all the necessary boilerplate set up to automate TLS issuance for Janus. +To ingest secured traffic into the cluster, you need to install some required resources. Please follow the instructions in [this section](../TLS.md#installation). ### STUNner From 17f3b2ee1edd516bf6c1e5d2c838a0000ca69284 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 17:33:19 +0200 Subject: [PATCH 02/37] fix(/docs/install): Typo --- docs/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 34b4c29..f6004f4 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -28,7 +28,7 @@ helm install stunner-gateway-operator stunner/stunner-gateway-operator --create- --namespace=stunner-system ``` -And that's all: you don't need to install the dataplane separately, this is handled automatically by the operator. The `stunnerd` pods created by the operator can be customized using the Dataplane custom resource: you can specify the `stunnerd` container image version, provision resources per each `stunenrd` pod, deploy into the host network namespace, etc.; see the documentation [here](https://pkg.go.dev/github.com/l7mp/stunner-gateway-operator/api/v1alpha1#DataplaneSpec). +And that's all: you don't need to install the dataplane separately, this is handled automatically by the operator. The `stunnerd` pods created by the operator can be customized using the Dataplane custom resource: you can specify the `stunnerd` container image version, provision resources per each `stunnerd` pod, deploy into the host network namespace, etc.; see the documentation [here](https://pkg.go.dev/github.com/l7mp/stunner-gateway-operator/api/v1alpha1#DataplaneSpec). ### Development version From 2f9f64e56f7d110c26d980669718bd45a409b2dc Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 17:36:11 +0200 Subject: [PATCH 03/37] refact(/docs/example/janus): Simplify prerequisites --- docs/examples/janus/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index 4c1e334..994598a 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -11,7 +11,11 @@ In this demo you will learn to: ## Prerequisites -The below installation instructions require an operational cluster running a supported version of Kubernetes (>1.22). Most hosted or private Kubernetes cluster services will work, but make sure that the cluster comes with a functional load-balancer integration (all major hosted Kubernetes services should support this). Otherwise, STUNner will not be able to allocate a public IP address for clients to reach your WebRTC infra. As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. +See prerequisites [here](../../INSTALL.md#prerequisites). + +> [!NOTE] +> +> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. ## Setup From 71aa3eaee9a7774e33bff141552fd4cd7974b56c Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 17:38:27 +0200 Subject: [PATCH 04/37] refact(examples/janus): Simplify Ingress and cert mananger install section. It is included --- docs/examples/janus/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index 994598a..03242b8 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -41,7 +41,7 @@ Janus does not come with an official Docker image; thus, we built one using a se ### Ingress and Cert manager installation -To ingest secured traffic into the cluster, you need to install some required resources. Please follow the instructions in [this section](../TLS.md#installation). +To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. ### STUNner From 3aac95debded9a86b08f95b5390bf1c7379f02e1 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 17:49:19 +0200 Subject: [PATCH 05/37] refact(examples/janus): Refer to stunner install guide instead of redundantly include --- docs/examples/janus/README.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index 03242b8..bcf92c7 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -47,13 +47,7 @@ To ingest secured traffic into the cluster, you need to install some resources. Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](janus-server.yaml) packaged with STUNner. -Install the STUNner gateway operator and STUNner via [Helm](https://github.com/l7mp/stunner-helm): - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner -``` +To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the Janus Gateway pods. From 05912777dfd04d41773b988b8bb5e70189fe4e32 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 17:49:34 +0200 Subject: [PATCH 06/37] fix: Remove extra space --- docs/examples/janus/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index bcf92c7..dfef33e 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -159,7 +159,7 @@ After installing everything, execute the following command to retrieve the URL o echo client-$INGRESSIP.nip.io ``` -Copy the URL into your browser, and now you should be greeted with the About page. On the landing page navigate to the Video call plugin demo (`/demos/videocall.html`). Duplicate the tab and register two users in the system and make a call. If everything is set up correctly, you should be able to connect to a room. If you repeat the procedure in a separate browser tab you can enjoy a nice video-conferencing session with yourself, with the twist that all media between the browser tabs is flowing through STUNner and the Janus Gateway server deployed in you Kubernetes cluster. +Copy the URL into your browser, and now you should be greeted with the About page. On the landing page navigate to the Video call plugin demo (`/demos/videocall.html`). Duplicate the tab and register two users in the system and make a call. If everything is set up correctly, you should be able to connect to a room. If you repeat the procedure in a separate browser tab you can enjoy a nice video-conferencing session with yourself, with the twist that all media between the browser tabs is flowing through STUNner and the Janus Gateway server deployed in you Kubernetes cluster. # Help From 6fcdb0025e8e8cd4665601b957508c389c6ac4f2 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 29 Sep 2024 17:49:58 +0200 Subject: [PATCH 07/37] fix: Wording --- docs/examples/TLS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md index 8a6ba71..06d4f46 100644 --- a/docs/examples/TLS.md +++ b/docs/examples/TLS.md @@ -12,7 +12,7 @@ Some WebRTC servers will need a valid TLS cert, which means it must run behind a > [!NOTE] > -> By default, the examples and the commands included are setup for the case you don't have your own domain. +> By default, the examples and the commands included are set up in case you don't have your domain. ### If you don't have your own domain @@ -79,7 +79,7 @@ Note that public wildcard DNS domains might run into [rate limiting](https://let If you work with certificates you must be aware that signing a certificate request takes some time and it differs for every CA (certificate authority). If you sense there is a problem with the certificate being signed or issued, you can check it directly and see what is going on. First, you'll need to find the certificate and its related resources in your cluster. -```bash +```console kubectl get certificate -A kubectl get certificaterequests.cert-manager.io -A @@ -88,7 +88,7 @@ kubectl get certificatesigningrequests.certificates.k8s.io ``` To find more information about them -```bash +```console kubectl describe certificate -A kubectl describe certificaterequests.cert-manager.io -A From efcb150c6995087178bb1a2b016965e36e6fec07 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Wed, 9 Oct 2024 15:38:22 +0200 Subject: [PATCH 08/37] docs: Move kurento back in the examples --- README.md | 22 +++++++++++----------- docs/README.md | 4 ++-- mkdocs.yml | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 696cbc0..6ac41ec 100644 --- a/README.md +++ b/README.md @@ -555,17 +555,6 @@ applications into Kubernetes. ### Media-plane deployment model -* [One to one video call with Kurento](/docs/examples/kurento-one2one-call/README.md): This tutorial - shows how to use STUNner to connect WebRTC clients to a media server deployed into Kubernetes - behind STUNner in the [media-plane deployment model](/docs/DEPLOYMENT.md). All this happens - *without* modifying the media server code in any way, just by adding 5-10 lines of - straightforward JavaScript to configure clients to use STUNner as the TURN server. -* [Magic mirror with Kurento](/docs/examples/kurento-magic-mirror/README.md): This tutorial has been - adopted from the [Kurento](https://www.kurento.org) [magic - mirror](https://doc-kurento.readthedocs.io/en/stable/tutorials/node/tutorial-magicmirror.html) - demo, deploying a basic WebRTC loopback server behind STUNner with some media processing - added. In particular, the application uses computer vision and augmented reality techniques to - add a funny hat on top of faces. * [Video-conferencing with LiveKit](/docs/examples/livekit/README.md): This tutorial helps you deploy the [LiveKit](https://livekit.io) WebRTC media server behind STUNner. The docs also show how to obtain a valid TLS certificate to secure your signaling connections, courtesy of the @@ -595,6 +584,17 @@ applications into Kubernetes. providing an ingress gateway service to a remote desktop application. We use [neko.io](https://neko.m1k1o.net) to run a browser in a secure container inside the Kubernetes cluster, and stream the desktop to clients via STUNner. +* [One to one video call with Kurento](/docs/examples/kurento-one2one-call/README.md): This tutorial + shows how to use STUNner to connect WebRTC clients to a media server deployed into Kubernetes + behind STUNner in the [media-plane deployment model](/docs/DEPLOYMENT.md). All this happens + *without* modifying the media server code in any way, just by adding 5-10 lines of + straightforward JavaScript to configure clients to use STUNner as the TURN server. +* [Magic mirror with Kurento](/docs/examples/kurento-magic-mirror/README.md): This tutorial has been + adopted from the [Kurento](https://www.kurento.org) [magic + mirror](https://doc-kurento.readthedocs.io/en/stable/tutorials/node/tutorial-magicmirror.html) + demo, deploying a basic WebRTC loopback server behind STUNner with some media processing + added. In particular, the application uses computer vision and augmented reality techniques to + add a funny hat on top of faces. ## Documentation diff --git a/docs/README.md b/docs/README.md index adc9cf7..771ea28 100644 --- a/docs/README.md +++ b/docs/README.md @@ -36,14 +36,14 @@ ### Media-plane deployment model -* [One to one video call with Kurento](examples/kurento-one2one-call) -* [Magic mirror with Kurento](examples/kurento-magic-mirror/README.md) * [Video-conferencing with LiveKit](examples/livekit/README.md) * [Video-conferencing with mediasoup](examples/mediasoup/README.md) * [Video-conferencing with Janus](examples/janus/README.md) * [Video-conferencing with Jitsi](examples/jitsi/README.md) * [Cloud-gaming with CloudRetro](examples/cloudretro/README.md) * [Remote desktop access with Neko](examples/neko/README.md) +* [One to one video call with Kurento](examples/kurento-one2one-call) +* [Magic mirror with Kurento](examples/kurento-magic-mirror/README.md) ## Manuals diff --git a/mkdocs.yml b/mkdocs.yml index 6ec4d40..91bcd05 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -21,14 +21,14 @@ nav: - 'Examples': - 'Simple tunnel': 'examples/simple-tunnel/README.md' - 'Direct one to one call': 'examples/direct-one2one-call/README.md' - - 'Kurento one to one call': 'examples/kurento-one2one-call/README.md' - - 'Kurento Magic Mirror': 'examples/kurento-magic-mirror/README.md' - 'LiveKit': 'examples/livekit/README.md' - 'Janus': 'examples/janus/README.md' - 'Jitsi': 'examples/jitsi/README.md' - 'mediasoup': 'examples/mediasoup/README.md' - 'CloudRetro': 'examples/cloudretro/README.md' - 'N.eko': 'examples/neko/README.md' + - 'Kurento one to one call': 'examples/kurento-one2one-call/README.md' + - 'Kurento Magic Mirror': 'examples/kurento-magic-mirror/README.md' - 'Benchmark': 'examples/benchmark/README.md' - 'CMD': - 'stunnerctl': 'cmd/stunnerctl.md' From 682efee8498eb7479a0682c0c95ceed864c960e1 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Wed, 9 Oct 2024 16:01:09 +0200 Subject: [PATCH 09/37] fix: Typos --- docs/examples/TLS.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md index 06d4f46..c9bb766 100644 --- a/docs/examples/TLS.md +++ b/docs/examples/TLS.md @@ -1,6 +1,6 @@ # TLS -This documentation sums up the the TLS and certificate issues you will encounter deploying the examples. +This documentation sums up the TLS and certificate issues you will encounter deploying the examples. ## The issue @@ -12,7 +12,7 @@ Some WebRTC servers will need a valid TLS cert, which means it must run behind a > [!NOTE] > -> By default, the examples and the commands included are set up in case you don't have your domain. +> By default, the examples and commands snippets assume you don't own a domain. ### If you don't have your own domain @@ -81,17 +81,13 @@ If you work with certificates you must be aware that signing a certificate reque First, you'll need to find the certificate and its related resources in your cluster. ```console kubectl get certificate -A - kubectl get certificaterequests.cert-manager.io -A - kubectl get certificatesigningrequests.certificates.k8s.io ``` To find more information about them ```console kubectl describe certificate -A - kubectl describe certificaterequests.cert-manager.io -A - kubectl describe certificatesigningrequests.certificates.k8s.io ``` \ No newline at end of file From 0f0a600f351efc2a5eba93d9a5d6a2192c132a32 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Wed, 9 Oct 2024 16:25:19 +0200 Subject: [PATCH 10/37] docs(TLS): Extend the If you have your own domain section --- docs/examples/TLS.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md index c9bb766..e480cdb 100644 --- a/docs/examples/TLS.md +++ b/docs/examples/TLS.md @@ -20,9 +20,15 @@ Some WebRTC servers will need a valid TLS cert, which means it must run behind a ### If you have your own domain +We use `nip.io` to "own a domain" in some examples. To replace it with your own domain, you must locate the corresponding lines in the specific mediaserver's configuration file and overwrite them. + +> [!NOTE] +> +> Although they might look similar, every mediaserver has a different configuration. You might need to (re)configure more things in one mediaserver than another. + > [!NOTE] > -> Do not forget to create a new DNS record pointing to your ingress' IP address! +> Make sure to set up your Ingress correctly and do not forget to create a new DNS record pointing to your Ingress' IP address! ## Installation From 578814dca98e4230dea9e25bc1e31df94efc3f5b Mon Sep 17 00:00:00 2001 From: Kornel David Date: Fri, 11 Oct 2024 19:55:10 +0200 Subject: [PATCH 11/37] docs(RTD): Add TLS doc --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 91bcd05..c02ee83 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -19,6 +19,7 @@ nav: - 'Scaling': 'SCALING.md' - 'Monitoring': 'MONITORING.md' - 'Examples': + - 'Configuring TLS for examples': 'examples/TLS.md' - 'Simple tunnel': 'examples/simple-tunnel/README.md' - 'Direct one to one call': 'examples/direct-one2one-call/README.md' - 'LiveKit': 'examples/livekit/README.md' From 47d5bd8d5682378db7b382130249ea34426324fe Mon Sep 17 00:00:00 2001 From: Kornel David Date: Fri, 11 Oct 2024 20:19:00 +0200 Subject: [PATCH 12/37] refact(/examples/livekit): Refactor LiveKit example doc --- docs/examples/livekit/README.md | 83 +++++++-------------------------- 1 file changed, 16 insertions(+), 67 deletions(-) diff --git a/docs/examples/livekit/README.md b/docs/examples/livekit/README.md index 60a3468..d006256 100644 --- a/docs/examples/livekit/README.md +++ b/docs/examples/livekit/README.md @@ -11,7 +11,11 @@ In this demo you will learn to: ## Prerequisites -The below installation instructions require an operational cluster running a supported version of Kubernetes (>1.22). Most hosted or private Kubernetes cluster services will work, but make sure that the cluster comes with a functional load-balancer integration (all major hosted Kubernetes services should support this). Otherwise, STUNner will not be able to allocate a public IP address for clients to reach your WebRTC infra. As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); late on you will learn more about why this is crucial above. +See prerequisites [here](../../INSTALL.md#prerequisites). + +> [!NOTE] +> +> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. ## Setup @@ -25,80 +29,21 @@ In this tutorial we deploy a video room example using [LiveKit's React SDK](http ## Installation -Let's start with a disclaimer. The LiveKit client example browser must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. Unfortunately, self-signed TLS certs [will not work](https://docs.livekit.io/deploy/#domain,-ssl-certificates,-and-load-balancer), so we have to come up with a way to provide our clients with a valid TLS cert. This will have the unfortunate consequence that the majority of the below installation guide will be about securing client connections to LiveKit over TLS; as it turns out, once HTTPS is correctly working integrating LiveKit with STUNner is very simple. +> [!NOTE] +> +> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). In the below example, STUNner will be installed into the identically named namespace, while LiveKit and the Ingress gateway will live in the default namespace. -### TLS certificates - -As mentioned above, the LiveKit server will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't then [nip.io](https://nip.io) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for LiveKit. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. - -Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of `nip.io`. - -### Ingress - -The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. - -Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. - -```console -helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -helm repo update -helm install ingress-nginx ingress-nginx/ingress-nginx -``` - -Wait until Kubernetes assigns an external IP to the Ingress. - -```console -until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done -``` - -Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. - -```console -kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') -export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') -``` +### Ingress and Cert manager installation -### Cert manager - -We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. - -Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: - -```console -helm repo add cert-manager https://charts.jetstack.io -helm repo update -helm install cert-manager jetstack/cert-manager --namespace cert-manager \ - --create-namespace --set global.leaderElection.namespace=cert-manager \ - --set installCRDs=true --timeout 600s -``` - -At this point we have all the necessary boilerplate set up to automate TLS issuance for LiveKit. +To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. ### STUNner -Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy the [manifest](livekit-server.yaml) packaged with STUNner. - -Install the STUNner gateway operator and STUNner via [Helm](https://github.com/l7mp/stunner-helm): - -Legacy mode: +Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](livekit-server.yaml) packaged with STUNner. -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner-system --set stunnerGatewayOperator.dataplane.mode=legacy -helm install stunner stunner/stunner --create-namespace --namespace=stunner -``` - -Managed mode: - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner-system -``` +To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the LiveKit server pods. @@ -231,3 +176,7 @@ livekit-cli create-token \ ``` Copy the access token into the token field and hit the Connect button. If everything is set up correctly, you should be able to connect to a room. If you repeat the procedure in a separate browser tab you can enjoy a nice video-conferencing session with yourself, with the twist that all media between the browser tabs is flowing through STUNner and the LiveKit-server deployed in you Kubernetes cluster. + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file From a0556fd83b5ef6456d760203ab0914c4abbde372 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Fri, 11 Oct 2024 20:19:57 +0200 Subject: [PATCH 13/37] fix(/examples/livekit): Remove unnecessary stun server configuration from the LiveKit server's config --- docs/examples/livekit/livekit-server.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/examples/livekit/livekit-server.yaml b/docs/examples/livekit/livekit-server.yaml index 04f6ea0..95b257b 100644 --- a/docs/examples/livekit/livekit-server.yaml +++ b/docs/examples/livekit/livekit-server.yaml @@ -84,8 +84,7 @@ data: port_range_end: 60000 port_range_start: 50000 tcp_port: 7801 - stun_servers: - - stunner_ip:3478 + stun_servers: [] turn_servers: - credential: pass-1 host: stunner_ip From 78a57857dc9e09073c82fce86fa37a95a19b3d09 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Fri, 11 Oct 2024 21:38:05 +0200 Subject: [PATCH 14/37] refact(/examples/livekit): Minor changes --- docs/examples/livekit/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/livekit/README.md b/docs/examples/livekit/README.md index d006256..ce04c5d 100644 --- a/docs/examples/livekit/README.md +++ b/docs/examples/livekit/README.md @@ -33,7 +33,7 @@ In this tutorial we deploy a video room example using [LiveKit's React SDK](http > > Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). -In the below example, STUNner will be installed into the identically named namespace, while LiveKit and the Ingress gateway will live in the default namespace. +In the below example, STUNner will be installed into the identically named namespace (`stunner`), while LiveKit and the Ingress gateway will live in the `default` namespace. ### Ingress and Cert manager installation From 1f36672db1d9eb9de301a78e748d4d1e9474ac04 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Fri, 11 Oct 2024 21:45:21 +0200 Subject: [PATCH 15/37] refactor(/examples/mediasoup): Refactor mediasoup example doc --- docs/examples/mediasoup/README.md | 82 ++++++------------------------- 1 file changed, 14 insertions(+), 68 deletions(-) diff --git a/docs/examples/mediasoup/README.md b/docs/examples/mediasoup/README.md index ec0ed40..675947d 100644 --- a/docs/examples/mediasoup/README.md +++ b/docs/examples/mediasoup/README.md @@ -11,7 +11,12 @@ In this demo you will learn to: ## Prerequisites -The below installation instructions require an operational cluster running a supported version of Kubernetes (>1.22). Most hosted or private Kubernetes cluster services will work, but make sure that the cluster comes with a functional load-balancer integration (all major hosted Kubernetes services should support this). Otherwise, STUNner will not be able to allocate a public IP address for clients to reach your WebRTC infra. As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io when using local/private IPs](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on, you will learn more about why this is crucial above. +See prerequisites [here](../../INSTALL.md#prerequisites). + +> [!NOTE] +> +> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. + ## Setup @@ -43,80 +48,21 @@ with an additional environment variable we can load the pod's private IP into th ## Installation -Let's start with a disclaimer. The mediasoup demo example must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. According to the [documentation](https://github.com/versatica/mediasoup-demo/blob/a59c6ab8e50fb950c3df54f4b85167a4e3f8497a/README.md?plain=1#L96) mediasoup should work with self-signed certs, however this haven't been tested. In the following we will deploy mediasoup configured with a valid signed TLS certificate. This will have the unfortunate consequence that the majority of the below installation guide will be about securing client connections to mediasoup over TLS; as it turns out, once HTTPS is correctly working integrating mediasoup with STUNner is very simple. - -In the below example, STUNner will be installed into the identically named namespace, while mediasoup and the Ingress gateway will live in the default namespace. - -### TLS certificates - -As mentioned above, the mediasoup server will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't then [nip.io](https://nip.io) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for mediasoup. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. - -Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of `nip.io`. - -### Ingress - -The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. - -Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. - -```console -helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -helm repo update -helm install ingress-nginx ingress-nginx/ingress-nginx -``` - -Wait until Kubernetes assigns an external IP to the Ingress. - -```console -until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done -``` - -Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. - -```console -kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') -export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') -``` - -### Cert manager - -We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. +> [!NOTE] +> +> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). -Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: +In the below example, STUNner will be installed into the identically named namespace (`stunner`), while mediasoup and the Ingress gateway will live in the `default` namespace. -```console -helm repo add cert-manager https://charts.jetstack.io -helm repo update -helm install cert-manager jetstack/cert-manager --namespace cert-manager \ - --create-namespace --set global.leaderElection.namespace=cert-manager \ - --set installCRDs=true --timeout 600s -``` +### Ingress and Cert manager installation -At this point we have all the necessary boilerplate set up to automate TLS issuance for mediasoup. +To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. ### STUNner -Now comes the fun part. +Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](mediasoup-server.yaml) packaged with STUNner. -Install the STUNner gateway operator and STUNner via [Helm](https://github.com/l7mp/stunner-helm): - -Legacy mode: - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator-dev --create-namespace --namespace=stunner-system --set stunnerGatewayOperator.dataplane.mode=legacy -helm install stunner stunner/stunner-dev --create-namespace --namespace=stunner-system -``` - -Managed mode (recommended): - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator-dev --create-namespace --namespace=stunner-system -``` +To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the mediasoup server pods. From b8c1748794cff2a20d53f4669b039dab22cbf6a5 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Mon, 14 Oct 2024 16:24:05 +0200 Subject: [PATCH 16/37] refactor(/examples/jitsi): Refactor Jitsi example doc --- docs/examples/jitsi/README.md | 81 ++++++----------------------------- 1 file changed, 12 insertions(+), 69 deletions(-) diff --git a/docs/examples/jitsi/README.md b/docs/examples/jitsi/README.md index 380aaaf..e302c78 100644 --- a/docs/examples/jitsi/README.md +++ b/docs/examples/jitsi/README.md @@ -11,9 +11,11 @@ In this demo you will learn to: ## Prerequisites -The tutorial assumes a fresh STUNner installation; see the STUNner installation and configuration guide. Create a namespace called stunner if there is none. You need a WebRTC-compatible browser to run this tutorial. Basically any modern browser will do; we usually test our WebRTC applications with Firefox and Chrome. +See prerequisites [here](../../INSTALL.md#prerequisites). -As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); late on you will learn more about why this is crucial above. +> [!NOTE] +> +> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. ## Setup @@ -27,80 +29,21 @@ In this tutorial we deploy a video room example using the [Jitsi framework](http ## Installation -Let's start with a disclaimer. The Jitsi client example browser must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. Unfortunately, self-signed TLS certs will not work, so we have to come up with a way to provide our clients with a valid TLS cert. +> [!NOTE] +> +> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). -In the below example, STUNner will be installed into the identically named namespace, while Jitsi and the Ingress gateway will live in the default namespace. +In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Jitsi and the Ingress gateway will live in the `default` namespace. -### TLS certificates +### Ingress and Cert manager installation -As mentioned above, the Jitsi server will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't then [nip.io](https://nip.io/) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for Jitsi. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. - -Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of nip.io. - -### Ingress - -The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. - -Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. - -```console -helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -helm repo update -helm install ingress-nginx ingress-nginx/ingress-nginx -``` - -Wait until Kubernetes assigns an external IP to the Ingress. - -```console -until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done -``` - -Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. - -```console -kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') -export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') -``` - -### Cert manger - -We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. - -Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: - -```console -helm repo add cert-manager https://charts.jetstack.io -helm repo update -helm install cert-manager jetstack/cert-manager --namespace cert-manager \ - --create-namespace --set global.leaderElection.namespace=cert-manager \ - --set installCRDs=true --timeout 600s -``` - -At this point we have all the necessary boilerplate set up to automate TLS issuance for Jitsi. +To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. ### STUNner -Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy the [manifest](jitsi-server.yaml) packaged with STUNner. - -Install the STUNner gateway operator and STUNner via [Helm](https://github.com/l7mp/stunner-helm): +Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](livekit-server.yaml) packaged with STUNner. -Legacy mode: - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner-system --set stunnerGatewayOperator.dataplane.mode=legacy -helm install stunner stunner/stunner --create-namespace --namespace=stunner -``` - -Managed mode: - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner-system -``` +To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the Jitsi server pods. From e88566f48c0a70716456fd35945b94f24147d24d Mon Sep 17 00:00:00 2001 From: Kornel David Date: Mon, 14 Oct 2024 16:29:12 +0200 Subject: [PATCH 17/37] fix: Fix wrong doc reference --- docs/examples/jitsi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/jitsi/README.md b/docs/examples/jitsi/README.md index e302c78..6b6f9bd 100644 --- a/docs/examples/jitsi/README.md +++ b/docs/examples/jitsi/README.md @@ -41,7 +41,7 @@ To ingest secured traffic into the cluster, you need to install some resources. ### STUNner -Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](livekit-server.yaml) packaged with STUNner. +Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](jitsi-server.yaml) packaged with STUNner. To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). From 041510618add62adde37e169841f8de8a1e9de59 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Tue, 15 Oct 2024 20:54:08 +0200 Subject: [PATCH 18/37] fix: Revert removing stun config from livekit --- docs/examples/livekit/livekit-server.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/examples/livekit/livekit-server.yaml b/docs/examples/livekit/livekit-server.yaml index 95b257b..2304b49 100644 --- a/docs/examples/livekit/livekit-server.yaml +++ b/docs/examples/livekit/livekit-server.yaml @@ -84,7 +84,8 @@ data: port_range_end: 60000 port_range_start: 50000 tcp_port: 7801 - stun_servers: [] + stun_servers: + - stunner_ip:3478 turn_servers: - credential: pass-1 host: stunner_ip @@ -212,10 +213,10 @@ metadata: name: tls-example-ingress namespace: default annotations: - kubernetes.io/ingress.class: "nginx" + # kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: - # ingressClassName: nginx + ingressClassName: nginx tls: - hosts: - client-ingressserviceip.nip.io From 2ec37b16a8556447b7c035db8e62ddc139b4cadb Mon Sep 17 00:00:00 2001 From: Kornel David Date: Tue, 15 Oct 2024 21:13:56 +0200 Subject: [PATCH 19/37] refact(/examples/neko): Minor refactor --- docs/examples/neko/README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/examples/neko/README.md b/docs/examples/neko/README.md index 2a64159..d22689e 100644 --- a/docs/examples/neko/README.md +++ b/docs/examples/neko/README.md @@ -15,19 +15,13 @@ In this demo you will learn the following steps to: ### Prerequisites -Consult the [STUNner installation and configuration guide](/docs/INSTALL.md) to set up STUNner. +See prerequisites [here](../../INSTALL.md#prerequisites). ### Quick installation The simplest way to deploy the demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy the [manifest](neko.yaml) packaged with STUNner. -Install the STUNner gateway operator and STUNner ([more info](https://github.com/l7mp/stunner-helm)): - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner-system -``` +To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Configure STUNner to act as a STUN server towards clients, and to let media reach the media server. From 636febebdd8ac24cfb022cccec3d00995eabde93 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Tue, 15 Oct 2024 21:18:37 +0200 Subject: [PATCH 20/37] refact(examples): Minor refact and adding missing Help section --- docs/examples/TLS.md | 6 +++++- docs/examples/benchmark/README.md | 4 ++++ docs/examples/cloudretro/README.md | 17 ++++++----------- docs/examples/direct-one2one-call/README.md | 4 ++++ docs/examples/jitsi/README.md | 4 ++++ docs/examples/kurento-magic-mirror/README.md | 4 ++++ docs/examples/kurento-one2one-call/README.md | 4 ++++ docs/examples/simple-tunnel/README.md | 4 ++++ 8 files changed, 35 insertions(+), 12 deletions(-) diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md index e480cdb..71e0a97 100644 --- a/docs/examples/TLS.md +++ b/docs/examples/TLS.md @@ -96,4 +96,8 @@ To find more information about them kubectl describe certificate -A kubectl describe certificaterequests.cert-manager.io -A kubectl describe certificatesigningrequests.certificates.k8s.io -``` \ No newline at end of file +``` + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/benchmark/README.md b/docs/examples/benchmark/README.md index 605abe7..75497e9 100644 --- a/docs/examples/benchmark/README.md +++ b/docs/examples/benchmark/README.md @@ -165,3 +165,7 @@ Notice that the average packets/second rate will be slightly lower in case of a * It is advised to repeat the measurment with different packet sizes. Recommended packet sizes in bytes are 64, 128, 256, 512, 1024, and 1200. Small packet sizes result lower effective throughput (when packet drop is < 1%). * Measuring [measuring one-way latency](https://stackoverflow.com/questions/63793030/iperf2-latency-is-a-two-way-or-one-way-latency) with `iperf` requires the clocks at the iperf client and server to be synchronized. Without this the results may be corrupted, and you may even see negative latencies. + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/cloudretro/README.md b/docs/examples/cloudretro/README.md index 206aa25..79797f3 100644 --- a/docs/examples/cloudretro/README.md +++ b/docs/examples/cloudretro/README.md @@ -15,11 +15,7 @@ In this demo you will learn how to: ## Prerequisites -The below installation instructions require an operational cluster running a supported version of -Kubernetes (>1.22). Most hosted or private Kubernetes cluster services will work, but make sure -that the cluster comes with a functional load-balancer integration (all major hosted Kubernetes -services should support this). Otherwise, STUNner will not be able to allocate a public IP address -for clients to reach your WebRTC infra. +See prerequisites [here](../../INSTALL.md#prerequisites). You will need a basic familiarity [with the CloudRetro architecture](https://webrtchacks.com/open-source-cloud-gaming-with-webrtc), especially the concept @@ -79,12 +75,7 @@ the CloudRetro servers running on a private pod IP address. That is where STUNne ### STUNner -First we install STUNner gateway operator with helm ([more info](https://github.com/l7mp/stunner-helm)): -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner -``` +First we install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Wait until all the necessary resources are up and running, then you are ready to continue. @@ -242,3 +233,7 @@ kubectl delete -f cloudretro-setup-coordinator.yaml kubectl delete -f cloudretro-setup-workers.yaml kubectl delete -f cloudretro-stunner-cleanup.yaml ``` + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/direct-one2one-call/README.md b/docs/examples/direct-one2one-call/README.md index 398ab61..30dca9e 100644 --- a/docs/examples/direct-one2one-call/README.md +++ b/docs/examples/direct-one2one-call/README.md @@ -296,3 +296,7 @@ Delete the demo deployment using the below command: kubectl delete -f docs/examples/direct-one2one-call/direct-one2one-call-server.yaml kubectl delete -f docs/examples/direct-one2one-call/direct-one2one-call-stunner.yaml ``` + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/jitsi/README.md b/docs/examples/jitsi/README.md index 6b6f9bd..887b15f 100644 --- a/docs/examples/jitsi/README.md +++ b/docs/examples/jitsi/README.md @@ -148,3 +148,7 @@ echo $INGRESSIP.nip.io ``` Copy the URL into your browser, and now you should be greeted with the Jitsi webpage. In the landing page you should create a room first. After you created a room you can set your username and join the room. On another page you have to open this page again and you should see the previously created room in the list. You only have to connect this room with another user. + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/kurento-magic-mirror/README.md b/docs/examples/kurento-magic-mirror/README.md index 4ef2905..dbffe57 100644 --- a/docs/examples/kurento-magic-mirror/README.md +++ b/docs/examples/kurento-magic-mirror/README.md @@ -79,3 +79,7 @@ health-checks and load-balancing should just work as expected. ```console $ kubectl scale deployment kms --replicas=4 ``` + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/kurento-one2one-call/README.md b/docs/examples/kurento-one2one-call/README.md index fa5c827..bb5dc3a 100644 --- a/docs/examples/kurento-one2one-call/README.md +++ b/docs/examples/kurento-one2one-call/README.md @@ -371,3 +371,7 @@ Delete the demo deployment using the below command: kubectl delete -f docs/examples/kurento-one2one-call/kurento-one2one-call-server.yaml kubectl delete -f docs/examples/kurento-one2one-call/kurento-one2one-call-stunner.yaml ``` + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/simple-tunnel/README.md b/docs/examples/simple-tunnel/README.md index 76773f9..99de957 100644 --- a/docs/examples/simple-tunnel/README.md +++ b/docs/examples/simple-tunnel/README.md @@ -215,3 +215,7 @@ Stop `turncat` and wipe all Kubernetes configuration. kubectl delete -f docs/examples/simple-tunnel/iperf-server.yaml kubectl delete -f docs/examples/simple-tunnel/iperf-stunner.yaml ``` + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file From 77c3a92f20152beb710163c61f2df70ae63768f6 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Tue, 15 Oct 2024 21:30:08 +0200 Subject: [PATCH 21/37] docs(/examples/mediasoup): Add missing mediasoup arch fig --- docs/examples/mediasoup/README.md | 2 ++ docs/img/stunner_mediasoup.svg | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 docs/img/stunner_mediasoup.svg diff --git a/docs/examples/mediasoup/README.md b/docs/examples/mediasoup/README.md index 675947d..d9815f0 100644 --- a/docs/examples/mediasoup/README.md +++ b/docs/examples/mediasoup/README.md @@ -24,6 +24,8 @@ The recommended way to install mediasoup ([link](https://mediasoup.discourse.gro The figure below shows mediasoup deployed into regular Kubernetes pods behind STUNner without the host-networking hack. Here, mediasoup is deployed behind STUNner in the [*media-plane deployment model*](../../DEPLOYMENT.md), so that STUNner acts as a "local" STUN/TURN server for mediasoup, saving the overhead of using public a 3rd party STUN/TURN server for NAT traversal. +![STUNner mediasoup integration deployment architecture](../../img/stunner_mediasoup.svg) + In this tutorial we deploy a video room example using [mediasoup's demo application](https://github.com/versatica/mediasoup-demo/) with slight modifications (more on these below), the [mediasoup server](https://github.com/versatica/mediasoup/) for media exchange, a Kubernetes Ingress gateway to secure signaling connections and handle TLS, and STUNner as a media gateway to expose the mediasoup server pool to clients. ### Modifications on the mediasoup demo diff --git a/docs/img/stunner_mediasoup.svg b/docs/img/stunner_mediasoup.svg new file mode 100644 index 0000000..5949b7b --- /dev/null +++ b/docs/img/stunner_mediasoup.svg @@ -0,0 +1,4 @@ + + + +
Kubernetes  cluster
Kubernetes  cluster
HTTPS
HTTPS
Ingress
Ingress
UDP/RTP
UDP/RTP
STUN/TURN
STUN/TURN
\ No newline at end of file From 653a23b31393ba95285d6f0d0e9939c8b7d9d438 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Wed, 16 Oct 2024 23:18:56 +0200 Subject: [PATCH 22/37] docs(neko): Fix note block --- docs/examples/neko/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/neko/README.md b/docs/examples/neko/README.md index d22689e..092b5c9 100644 --- a/docs/examples/neko/README.md +++ b/docs/examples/neko/README.md @@ -39,7 +39,7 @@ kubectl get service udp-gateway -n default -o jsonpath='{.status.loadBalancer.in STUNNERIP=$(kubectl get service udp-gateway -n default -o jsonpath='{.status.loadBalancer.ingress[0].ip}') ``` -> **Note** +> [!NOTE] > This IP should be accessible from your browser. If that "public IP" is behind a NAT, you can overwrite it with the actual public IP that routes to the service by hand (e.g. `STUNNERIP=`). We need to give this public IP the Neko configuration in the `NEKO_ICESERVERS` environment variable, inside the `json` content (basically this will tell you browser to use STUNner as a STUN/TURN server). From 7389d9a3bd0705c027257f0c83a164cf770ce682 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Wed, 16 Oct 2024 23:46:02 +0200 Subject: [PATCH 23/37] docs: Add Elixir from PR #162 --- README.md | 6 + docs/README.md | 1 + docs/examples/elixir-webrtc/README.md | 211 ++++++++++++++++++ .../elixir-webrtc/nexus-call-stunner.yaml | 51 +++++ docs/examples/elixir-webrtc/nexus-server.yaml | 100 +++++++++ mkdocs.yml | 1 + 6 files changed, 370 insertions(+) create mode 100644 docs/examples/elixir-webrtc/README.md create mode 100644 docs/examples/elixir-webrtc/nexus-call-stunner.yaml create mode 100644 docs/examples/elixir-webrtc/nexus-server.yaml diff --git a/README.md b/README.md index 6ac41ec..40de34c 100644 --- a/README.md +++ b/README.md @@ -565,6 +565,12 @@ applications into Kubernetes. behind STUNner. The docs also show how to obtain a valid TLS certificate to secure your signaling connections, using [cert-manager](https://cert-manager.io), [nip.io](https://nip.io) and [Let's Encrypt](https://letsencrypt.org). +* [Video-conferencing with Elixir WebRTC](/docs/examples/elixir-webrtc/README.md): This tutorial helps + you deploy a fully fledged [Elixir WebRTC](https://elixir-webrtc.org/) video-conferencing room called + [Nexus](https://github.com/elixir-webrtc/apps/tree/master/nexus) into Kubernetes + behind STUNner. The docs also show how to obtain a valid TLS certificate to secure your signaling + connections, using [cert-manager](https://cert-manager.io), [nip.io](https://nip.io) and [Let's + Encrypt](https://letsencrypt.org). * [Video-conferencing with Jitsi](/docs/examples/jitsi/README.md): This tutorial helps you deploy a fully fledged [Jitsi](https://jitsi.org) video-conferencing service into Kubernetes behind STUNner. The docs also show how to obtain a valid TLS certificate to secure your signaling diff --git a/docs/README.md b/docs/README.md index 771ea28..14a15ce 100644 --- a/docs/README.md +++ b/docs/README.md @@ -39,6 +39,7 @@ * [Video-conferencing with LiveKit](examples/livekit/README.md) * [Video-conferencing with mediasoup](examples/mediasoup/README.md) * [Video-conferencing with Janus](examples/janus/README.md) +* [Video-conferencing with Elixir WebRTC](examples/elixir-webrtc/README.md) * [Video-conferencing with Jitsi](examples/jitsi/README.md) * [Cloud-gaming with CloudRetro](examples/cloudretro/README.md) * [Remote desktop access with Neko](examples/neko/README.md) diff --git a/docs/examples/elixir-webrtc/README.md b/docs/examples/elixir-webrtc/README.md new file mode 100644 index 0000000..2fdf4a5 --- /dev/null +++ b/docs/examples/elixir-webrtc/README.md @@ -0,0 +1,211 @@ +# STUNner demo: Video-conferencing with Nexus + +This document guides you through the installation of [Elixir WebRTC](https://elixir-webrtc.org/), called [Nexus](https://github.com/elixir-webrtc/apps/tree/master/nexus) into Kubernetes, when it is used together with the STUNner WebRTC media gateway. + +In this demo you will learn to: + +- integrate a typical WebRTC application with STUNner, +- obtain a valid TLS certificate to secure the signaling plane, +- deploy the Nexus app server into Kubernetes, and +- configure STUNner to expose Nexus to clients. + +## Prerequisites + +See prerequisites [here](../../INSTALL.md#prerequisites). + +## Installation + +> [!NOTE] +> +> Let's start with a disclaimer. The Nexus client-side application must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. In this demo, we will aim to obtain a proper CA-signed certificate (self-signed certificates haven't been tested). Obtaining a valid TLS certificate is a challenge. Thus, the majority of the below installation guide will be about securing client connections to Nexus over TLS; as it turns out, once HTTPS is correctly working integrating Nexus with STUNner is very simple. + +In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Nexus and the Ingress gateway will live in the `default` namespace. + +### TLS certificates + +As mentioned above, the Nexus WebRTC server will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't then [nip.io](https://nip.io) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for Nexus. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. + +Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of `nip.io`. + +### Ingress + +The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. + +Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. + +```console +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update +helm install ingress-nginx ingress-nginx/ingress-nginx +``` + +Wait until Kubernetes assigns an external IP to the Ingress. + +```console +until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done +``` + +Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. + +```console +kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' +export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') +``` + +### Cert manager + +We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. + +Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: + +```console +helm repo add cert-manager https://charts.jetstack.io +helm repo update +helm install cert-manager jetstack/cert-manager --namespace cert-manager \ + --create-namespace --set global.leaderElection.namespace=cert-manager \ + --set crds.enabled=true --timeout 600s +``` + +At this point we have all the necessary boilerplate set up to automate TLS issuance for Nexus. + +### STUNner + +Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](nexus-server.yaml) packaged with STUNner. + +Install the STUNner gateway operator and STUNner via [Helm](https://github.com/l7mp/stunner-helm): + +```console +helm repo add stunner https://l7mp.io/stunner +helm repo update +helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner +``` + +Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the Nexus pods. + +```console +git clone https://github.com/l7mp/stunner +cd stunner +kubectl apply -f docs/examples/elixir-webrtc/nexus-call-stunner.yaml +``` + +The relevant parts here are the STUNner [Gateway definition](../../GATEWAY.md#gateway), which exposes the STUNner STUN/TURN server over UDP:3478 to the Internet, and the [UDPRoute definition](../../GATEWAY.md#udproute), which takes care of routing media to the pods running the Nexus Gateway service. + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: udp-gateway + namespace: stunner +spec: + gatewayClassName: stunner-gatewayclass + listeners: + - name: udp-listener + port: 3478 + protocol: UDP +--- +apiVersion: stunner.l7mp.io/v1 +kind: UDPRoute +metadata: + name: nexus + namespace: stunner +spec: + parentRefs: + - name: udp-gateway + rules: + - backendRefs: + - kind: Service + name: nexus + namespace: default +``` + +Once the Gateway resource is installed into Kubernetes, STUNner will create a Kubernetes LoadBalancer for the Gateway to expose the TURN server on UDP:3478 to clients. It can take up to a minute for Kubernetes to allocate a public external IP for the service. + +Wait until Kubernetes assigns an external IP and store the external IP assigned by Kubernetes to +STUNner in an environment variable for later use. + +```console +until [ -n "$(kubectl get svc udp-gateway -n stunner -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done +export STUNNERIP=$(kubectl get service udp-gateway -n stunner -o jsonpath='{.status.loadBalancer.ingress[0].ip}') +``` +### Nexus Docker images + +The crucial step of integrating *any* WebRTC media server with STUNner is to ensure that the server instructs the clients to use STUNner as the STUN/TURN server. +Unfortunately, currently the [official Nexus Docker image](ghcr.io/elixir-webrtc/apps/nexus) does not support this configuration in runtime (by default Google's STUN server is hardcoded into it). +Therefore, we have to modify this setting to STUNner's IP and build a new Docker image. + +In order to achieve this, first clone the Elixir WebRTC sample app repository: + +```console +git clone https://github.com/elixir-webrtc/apps/ +cd apps/nexus +``` + +You have to modify the ICE config to use STUNner with the given credentials in two files: + +`assets/js/home.js`: +``` +... +# const pcConfig = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; + +# change to: + + const pcConfig = { iceServers: [{ urls: 'turn::3478?transport=udp', username: 'user-1', credential: 'pass-1',iceTransportPolicy: 'relay'}] }; +``` + +`lib/nexus/peer.ex`: +``` +... +# ice_servers: [%{urls: "stun:stun.l.google.com:19302"}], + +# change to: + + ice_servers: [%{urls: "turn::3478?transport=udp", "username": "user-1", "credential": "pass-1", "iceTransportPolicy": "relay"}], +``` + +Now rebuild the Docker image, and push it into your image repository: +``` +export MYREPO=myrepo # use your own Docker repository name! +sudo docker build -t $MYREPO/nexus . +sudo docker push $MYREPO/nexus +``` + +After uploading the image, you also have to modify the Nexus image repo location in the Kubernetes deployment file. + +```console +sed -i "s/l7mp/$MYREPO/g" docs/examples/elixir-webrtc/nexus-server.yaml +``` + +We also need the Ingress external IP address we have stored previously: this will make sure that the TLS certificate created by cert-manager will be bound to the proper `nip.io` domain and IP address. + +```console +sed -i "s/ingressserviceip/$INGRESSIP/g" docs/examples/elixir-webrtc/nexus-server.yaml +``` + +Finally, fire up Nexus. + +```console +kubectl apply -f docs/examples/elixir-webrtc/nexus-server.yaml +``` + +The demo installation bundle includes a few resources to deploy Nexus: + +- Nexus deployment and service, +- a cluster issuer for the TLS certificates, +- an Ingress resource to terminate the secure connections between your browser and the Kubernetes cluster. + +Wait until all pods become operational and jump right into testing! + +## Test + +After installing everything, execute the following command to retrieve the URL of your freshly deployed Nexus demo app: + +```console +echo INGRESSIP.nip.io +``` + +Copy the URL into your browser, and if everything is set up correctly, you should be able to connect to a video room. If you repeat the procedure in a separate browser tab you can enjoy a nice video-conferencing session with yourself, with the twist that all media between the browser tabs is flowing through STUNner and the Nexus server deployed in you Kubernetes cluster. + +# Help + +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file diff --git a/docs/examples/elixir-webrtc/nexus-call-stunner.yaml b/docs/examples/elixir-webrtc/nexus-call-stunner.yaml new file mode 100644 index 0000000..ed05217 --- /dev/null +++ b/docs/examples/elixir-webrtc/nexus-call-stunner.yaml @@ -0,0 +1,51 @@ +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: stunner-gatewayclass +spec: + controllerName: "stunner.l7mp.io/gateway-operator" + parametersRef: + group: "stunner.l7mp.io" + kind: GatewayConfig + name: stunner-gatewayconfig + namespace: stunner + description: "STUNner is a WebRTC ingress gateway for Kubernetes" + +--- +apiVersion: stunner.l7mp.io/v1 +kind: GatewayConfig +metadata: + name: stunner-gatewayconfig + namespace: stunner +spec: + realm: stunner.l7mp.io + authType: static + userName: "user-1" + password: "pass-1" + +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: udp-gateway + namespace: stunner +spec: + gatewayClassName: stunner-gatewayclass + listeners: + - name: udp-listener + port: 3478 + protocol: TURN-UDP +--- +apiVersion: stunner.l7mp.io/v1 +kind: UDPRoute +metadata: + name: nexus + namespace: stunner +spec: + parentRefs: + - name: udp-gateway + rules: + - backendRefs: + - kind: Service + name: nexus + namespace: default \ No newline at end of file diff --git a/docs/examples/elixir-webrtc/nexus-server.yaml b/docs/examples/elixir-webrtc/nexus-server.yaml new file mode 100644 index 0000000..f7a39e6 --- /dev/null +++ b/docs/examples/elixir-webrtc/nexus-server.yaml @@ -0,0 +1,100 @@ +apiVersion: v1 +kind: Service +metadata: + name: nexus + labels: + app.kubernetes.io/name: nexus +spec: + type: ClusterIP + ports: + - port: 4000 + targetPort: 4000 + protocol: TCP + name: http + selector: + app.kubernetes.io/name: nexus +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nexus + labels: + app.kubernetes.io/name: nexus +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: nexus + template: + metadata: + labels: + app.kubernetes.io/name: nexus + spec: + terminationGracePeriodSeconds: 18000 # 5 hours + containers: + - name: nexus + image: "l7mp/nexus" + imagePullPolicy: IfNotPresent + env: + - name: SECRET_KEY_BASE + value: f0e01531666a6ccd5b15879a3c00a15f8feaaea86230cf35d96fe0b8e468bc553549e47edb737a4d1530d1c56a3a7a3827443e1bd00aa46adb44dc6aa087ff9f + - name: PHX_SERVER + value: "1" + - name: PHX_HOST + value: ingressserviceip.nip.io + - name: ADMIN_USERNAME + value: admin + - name: ADMIN_PASSWORD + value: admin + - name: ICE_PORT_RANGE + value: 62000-63000 + - name: NEXUS_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + ports: + - name: http + containerPort: 4000 + protocol: TCP +--- +# Ingress for both Nexus +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: nexus + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + nginx.ingress.kubernetes.io/ssl-redirect: "true" +spec: + ingressClassName: nginx + tls: + - hosts: + - ingressserviceip.nip.io + secretName: nexus-secret-tls + rules: + - host: ingressserviceip.nip.io + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: nexus + port: + number: 4000 +--- +apiVersion: cert-manager.io/v1 +kind: ClusterIssuer +metadata: + name: letsencrypt-prod +spec: + acme: + email: info@l7mp.io + server: https://acme-v02.api.letsencrypt.org/directory + privateKeySecretRef: + name: letsencrypt-secret-prod + solvers: + - http01: + ingress: + class: nginx +--- \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index c02ee83..ff0cca1 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -24,6 +24,7 @@ nav: - 'Direct one to one call': 'examples/direct-one2one-call/README.md' - 'LiveKit': 'examples/livekit/README.md' - 'Janus': 'examples/janus/README.md' + - 'Elixir WebRTC': 'examples/elixir-webrtc/README.md' - 'Jitsi': 'examples/jitsi/README.md' - 'mediasoup': 'examples/mediasoup/README.md' - 'CloudRetro': 'examples/cloudretro/README.md' From e1d61ad1b7926328e095cd05f7d96c3f97e24ae6 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Wed, 16 Oct 2024 23:49:18 +0200 Subject: [PATCH 24/37] docs: Addresing suggested changes --- docs/examples/janus/README.md | 2 +- docs/examples/jitsi/README.md | 2 +- docs/examples/livekit/README.md | 2 +- docs/examples/mediasoup/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index dfef33e..3fb21fb 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -41,7 +41,7 @@ Janus does not come with an official Docker image; thus, we built one using a se ### Ingress and Cert manager installation -To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. +To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. ### STUNner diff --git a/docs/examples/jitsi/README.md b/docs/examples/jitsi/README.md index 887b15f..2aa9fea 100644 --- a/docs/examples/jitsi/README.md +++ b/docs/examples/jitsi/README.md @@ -37,7 +37,7 @@ In the below example, STUNner will be installed into the identically named names ### Ingress and Cert manager installation -To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. +To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. ### STUNner diff --git a/docs/examples/livekit/README.md b/docs/examples/livekit/README.md index ce04c5d..87cf337 100644 --- a/docs/examples/livekit/README.md +++ b/docs/examples/livekit/README.md @@ -37,7 +37,7 @@ In the below example, STUNner will be installed into the identically named names ### Ingress and Cert manager installation -To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. +To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. ### STUNner diff --git a/docs/examples/mediasoup/README.md b/docs/examples/mediasoup/README.md index d9815f0..eb6525e 100644 --- a/docs/examples/mediasoup/README.md +++ b/docs/examples/mediasoup/README.md @@ -58,7 +58,7 @@ In the below example, STUNner will be installed into the identically named names ### Ingress and Cert manager installation -To ingest secured traffic into the cluster, you need to install some resources. Please follow the instructions in [this section](../TLS.md#installation) to install Ingress and Cert manager. +To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. ### STUNner From 3a0fd570bf6373a29d2fb9a98db601ab9e8d2b88 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Thu, 17 Oct 2024 00:16:34 +0200 Subject: [PATCH 25/37] docs(/examples/elixir): Inititial refactor --- docs/examples/elixir-webrtc/README.md | 62 +++------------------------ 1 file changed, 6 insertions(+), 56 deletions(-) diff --git a/docs/examples/elixir-webrtc/README.md b/docs/examples/elixir-webrtc/README.md index 2fdf4a5..9b98a7d 100644 --- a/docs/examples/elixir-webrtc/README.md +++ b/docs/examples/elixir-webrtc/README.md @@ -17,69 +17,19 @@ See prerequisites [here](../../INSTALL.md#prerequisites). > [!NOTE] > -> Let's start with a disclaimer. The Nexus client-side application must work over a secure HTTPS connection, because [getUserMedia](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#browser_compatibility) is available only in secure contexts. This implies that the client-server signaling connection must be secure too. In this demo, we will aim to obtain a proper CA-signed certificate (self-signed certificates haven't been tested). Obtaining a valid TLS certificate is a challenge. Thus, the majority of the below installation guide will be about securing client connections to Nexus over TLS; as it turns out, once HTTPS is correctly working integrating Nexus with STUNner is very simple. +> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Nexus and the Ingress gateway will live in the `default` namespace. -### TLS certificates +### Ingress and Cert manager installation -As mentioned above, the Nexus WebRTC server will need a valid TLS cert, which means it must run behind an existing DNS domain name backed by a CA signed TLS certificate. This is simple if you have your own domain, but if you don't then [nip.io](https://nip.io) provides a dead simple wildcard DNS for any IP address. We will use this to "own a domain" and obtain a CA signed certificate for Nexus. This will allow us to point the domain name `client-.nip.io` to an ingress HTTP gateway in our Kubernetes cluster, which will then use some automation (namely, cert-manager) to obtain a valid CA signed cert. - -Note that public wildcard DNS domains might run into [rate limiting](https://letsencrypt.org/docs/rate-limits/) issues. If this occurs you can try [alternative services](https://moss.sh/free-wildcard-dns-services/) instead of `nip.io`. - -### Ingress - -The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. - -Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. - -```console -helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx -helm repo update -helm install ingress-nginx ingress-nginx/ingress-nginx -``` - -Wait until Kubernetes assigns an external IP to the Ingress. - -```console -until [ -n "$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}')" ]; do sleep 1; done -``` - -Store the Ingress IP address Kubernetes assigned to our Ingress; this will be needed later when we configure the validation pipeline for our TLS certs. - -```console -kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -export INGRESSIP=$(kubectl get service ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}') -export INGRESSIP=$(echo $INGRESSIP | sed 's/\./-/g') -``` - -### Cert manager - -We use the official [cert-manager](https://cert-manager.io) to automate TLS certificate management. - -Add the Helm repository, which contains the cert-manager Helm chart, and install the charts: - -```console -helm repo add cert-manager https://charts.jetstack.io -helm repo update -helm install cert-manager jetstack/cert-manager --namespace cert-manager \ - --create-namespace --set global.leaderElection.namespace=cert-manager \ - --set crds.enabled=true --timeout 600s -``` - -At this point we have all the necessary boilerplate set up to automate TLS issuance for Nexus. +To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. ### STUNner -Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](nexus-server.yaml) packaged with STUNner. +Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](livekit-server.yaml) packaged with STUNner. -Install the STUNner gateway operator and STUNner via [Helm](https://github.com/l7mp/stunner-helm): - -```console -helm repo add stunner https://l7mp.io/stunner -helm repo update -helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace --namespace=stunner -``` +To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the Nexus pods. @@ -130,7 +80,7 @@ export STUNNERIP=$(kubectl get service udp-gateway -n stunner -o jsonpath='{.sta ``` ### Nexus Docker images -The crucial step of integrating *any* WebRTC media server with STUNner is to ensure that the server instructs the clients to use STUNner as the STUN/TURN server. +The crucial step of integrating *any* WebRTC media server with STUNner is to ensure that the server instructs the clients to use STUNner as the STUN/TURN server. Unfortunately, currently the [official Nexus Docker image](ghcr.io/elixir-webrtc/apps/nexus) does not support this configuration in runtime (by default Google's STUN server is hardcoded into it). Therefore, we have to modify this setting to STUNner's IP and build a new Docker image. From b296e6a8d35b9ea335a7a888cd164c73ced7c79a Mon Sep 17 00:00:00 2001 From: Kornel David Date: Thu, 17 Oct 2024 00:56:38 +0200 Subject: [PATCH 26/37] docs(TLS.md): Minor changes --- docs/examples/TLS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md index 71e0a97..d1d9e4a 100644 --- a/docs/examples/TLS.md +++ b/docs/examples/TLS.md @@ -34,9 +34,9 @@ We use `nip.io` to "own a domain" in some examples. To replace it with your own ### Ingress -The first step of obtaining a valid cert is to install a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. +The first step of secured traffic ingestion is obtaining a valid cert by installing a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. -Install an ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. +Install an Ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. ```console helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx From 1e79d2268bc9dbb112a70771b1cccfb9cbbbcaba Mon Sep 17 00:00:00 2001 From: Kornel David Date: Thu, 17 Oct 2024 00:57:33 +0200 Subject: [PATCH 27/37] refact(/examples/livekit): Compact README --- docs/examples/livekit/README.md | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/docs/examples/livekit/README.md b/docs/examples/livekit/README.md index 87cf337..6fc81d0 100644 --- a/docs/examples/livekit/README.md +++ b/docs/examples/livekit/README.md @@ -11,11 +11,16 @@ In this demo you will learn to: ## Prerequisites -See prerequisites [here](../../INSTALL.md#prerequisites). +To run this example, you need: +* a [Kubernetes cluster](../../INSTALL.md#prerequisites), +* a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), +* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, +* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. > [!NOTE] > -> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. +> If you have your own TLS certificate, put it in a `Secret` [resource](https://kubernetes.io/docs/concepts/configuration/secret/) and deploy it into the `default` namespace under the `livekit-secret-tls` name. + ## Setup @@ -27,24 +32,11 @@ The figure below shows LiveKit deployed into regular Kubernetes pods behind STUN In this tutorial we deploy a video room example using [LiveKit's React SDK](https://github.com/livekit/livekit-react/tree/master/example), the [LiveKit server](https://github.com/livekit/livekit) for media exchange, a Kubernetes Ingress gateway to secure signaling connections and handle TLS, and STUNner as a media gateway to expose the LiveKit server pool to clients. -## Installation - -> [!NOTE] -> -> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). - -In the below example, STUNner will be installed into the identically named namespace (`stunner`), while LiveKit and the Ingress gateway will live in the `default` namespace. - -### Ingress and Cert manager installation - -To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. ### STUNner Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](livekit-server.yaml) packaged with STUNner. -To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). - Configure STUNner to act as a STUN/TURN server to clients, and route all received media to the LiveKit server pods. ```console From d0a9b5fc6f59b4364597fe319e181bf8f095b1dd Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sat, 19 Oct 2024 16:44:47 +0200 Subject: [PATCH 28/37] docs(livekit): Change section title --- docs/examples/livekit/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/livekit/README.md b/docs/examples/livekit/README.md index 6fc81d0..3855c22 100644 --- a/docs/examples/livekit/README.md +++ b/docs/examples/livekit/README.md @@ -22,7 +22,7 @@ To run this example, you need: > If you have your own TLS certificate, put it in a `Secret` [resource](https://kubernetes.io/docs/concepts/configuration/secret/) and deploy it into the `default` namespace under the `livekit-secret-tls` name. -## Setup +## Description The recommended way to install LiveKit into Kubernetes is deploying the media servers into the host-network namespace of the Kubernetes nodes (`hostNetwork: true`). This deployment model, however, comes with a set of uncanny [operational limitations and security concerns](../../WHY.md). Using STUNner, however, media servers can be deployed into ordinary Kubernetes pods and run over a private IP network, like any "normal" Kubernetes workload. From ee89aa69bddca74ac7e37c6a3586dfabbbfa6fa7 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sat, 19 Oct 2024 16:45:24 +0200 Subject: [PATCH 29/37] refact(/janus): Refactor docs once more --- docs/examples/janus/README.md | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index 3fb21fb..f8d54ad 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -11,13 +11,17 @@ In this demo you will learn to: ## Prerequisites -See prerequisites [here](../../INSTALL.md#prerequisites). +To run this example, you need: +* a [Kubernetes cluster](../../INSTALL.md#prerequisites), +* a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), +* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, +* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. > [!NOTE] > -> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. +> If you have your own TLS certificate, put it in a `Secret` [resource](https://kubernetes.io/docs/concepts/configuration/secret/) and deploy it into the `default` namespace under the `janus-web-secret-tls` name. -## Setup +## Description The recommended way (or at least the possible way, [link](https://janus.discourse.group/t/janus-with-kubernetes-demystifying-the-myths/938), [link](https://bugraoz93.medium.com/active-passive-highly-availability-janus-gateway-on-kubernetes-2189256e5525)) to install Janus into Kubernetes is deploying the media servers into the host-network namespace of the Kubernetes nodes (`hostNetwork: true`). This deployment model, however, comes with a set of uncanny [operational limitations and security concerns](../../WHY.md). Using STUNner, however, media servers can be deployed into ordinary Kubernetes pods and run over a private IP network, like any "normal" Kubernetes workload. @@ -27,22 +31,10 @@ The figure below shows Janus deployed into regular Kubernetes pods behind STUNne In this tutorial we deploy [Janus Gateway](https://github.com/meetecho/janus-gateway/tree/master) with a set of [preimplemented and packaged server plugins](https://janus.conf.meetecho.com/docs/pluginslist.html) for media exchange, a [Janus Web Demo](https://github.com/meetecho/janus-gateway/tree/master/html), a Kubernetes Ingress gateway to secure signaling connections and handle TLS, and STUNner as a media gateway to expose the Janus server pool to clients. -## Installation - -> [!NOTE] -> -> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). - -In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Janus and the Ingress gateway will live in the `default` namespace. - ### Docker images Janus does not come with an official Docker image; thus, we built one using a self-made Dockerfile based on the available documents in the official [Janus repository](https://github.com/meetecho/janus-gateway). Actually, we've made two Dockerfiles. One for the Janus Gateway server and one for the Janus Web Demos. The [Janus Gateway server Dockerfile](./DOCKERFILE-janus-gateway) should be ran in the root directory of the [Janus repository](https://github.com/meetecho/janus-gateway). The Janus Web Demos Dockerfile should be used in the `/html` directory of the [same repository](https://github.com/meetecho/janus-gateway/tree/master/html). The images (`l7mp/janus-gateway:v1.2.4` and `l7mp/janus-web:latest`) used in the following demo are hosted on Docker Hub under the L7MP organization. -### Ingress and Cert manager installation - -To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. - ### STUNner Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](janus-server.yaml) packaged with STUNner. From 6c70d2feeb74664ca901b24deb756edf4bfc8b03 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sat, 19 Oct 2024 16:54:51 +0200 Subject: [PATCH 30/37] docs(elixir): Refactor and fix image --- docs/examples/elixir-webrtc/README.md | 16 ++++++---------- docs/examples/elixir-webrtc/nexus-server.yaml | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/docs/examples/elixir-webrtc/README.md b/docs/examples/elixir-webrtc/README.md index 9b98a7d..7e6ab8b 100644 --- a/docs/examples/elixir-webrtc/README.md +++ b/docs/examples/elixir-webrtc/README.md @@ -11,19 +11,15 @@ In this demo you will learn to: ## Prerequisites -See prerequisites [here](../../INSTALL.md#prerequisites). - -## Installation +To run this example, you need: +* a [Kubernetes cluster](../../INSTALL.md#prerequisites), +* a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), +* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, +* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. > [!NOTE] > -> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). - -In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Nexus and the Ingress gateway will live in the `default` namespace. - -### Ingress and Cert manager installation - -To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. +> If you have your own TLS certificate, put it in a `Secret` [resource](https://kubernetes.io/docs/concepts/configuration/secret/) and deploy it into the `default` namespace under the `nexus-secret-tls` name. ### STUNner diff --git a/docs/examples/elixir-webrtc/nexus-server.yaml b/docs/examples/elixir-webrtc/nexus-server.yaml index f7a39e6..dd0db13 100644 --- a/docs/examples/elixir-webrtc/nexus-server.yaml +++ b/docs/examples/elixir-webrtc/nexus-server.yaml @@ -33,7 +33,7 @@ spec: terminationGracePeriodSeconds: 18000 # 5 hours containers: - name: nexus - image: "l7mp/nexus" + image: "l7mp/l7mp/elixir-webrtc-nexus" imagePullPolicy: IfNotPresent env: - name: SECRET_KEY_BASE From ecfdaff41a3bc28236844ca288954f262c10ea99 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sat, 19 Oct 2024 16:58:54 +0200 Subject: [PATCH 31/37] docs(jitsi): Refactor once more --- docs/examples/jitsi/README.md | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/docs/examples/jitsi/README.md b/docs/examples/jitsi/README.md index 2aa9fea..463a7e8 100644 --- a/docs/examples/jitsi/README.md +++ b/docs/examples/jitsi/README.md @@ -11,13 +11,17 @@ In this demo you will learn to: ## Prerequisites -See prerequisites [here](../../INSTALL.md#prerequisites). +To run this example, you need: +* a [Kubernetes cluster](../../INSTALL.md#prerequisites), +* a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), +* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, +* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. > [!NOTE] > -> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. +> If you have your own TLS certificate, put it in a `Secret` [resource](https://kubernetes.io/docs/concepts/configuration/secret/) and deploy it into the `default` namespace under the `jitsi-secret` name. -## Setup +## Description The recommended way to install Jitsi into Kubernetes is deploying the media servers into the host-network namespace of the Kubernetes nodes (`hostNetwork: true`), or using a NodePort service or a dedicated Ingress to ingest WebRTC media traffic into the network. However, these options allow only one JVB instance per Kubernetes node and the host-network deployment model also comes with a set of uncanny [operational limitations and security concerns](../../WHY.md). Using STUNner, however, media servers can be deployed into ordinary Kubernetes pods and run over a private IP network, like any "normal" Kubernetes workload. @@ -27,18 +31,6 @@ The figure below shows Jitsi deployed into regular Kubernetes pods behind STUNne In this tutorial we deploy a video room example using the [Jitsi framework](https://jitsi.github.io/handbook/docs/architecture) for media exchange, a Kubernetes Ingress gateway to secure signaling connections and handle TLS, and STUNner as a media gateway to expose the Jitsi JVB to clients. -## Installation - -> [!NOTE] -> -> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). - -In the below example, STUNner will be installed into the identically named namespace (`stunner`), while Jitsi and the Ingress gateway will live in the `default` namespace. - -### Ingress and Cert manager installation - -To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. - ### STUNner Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](jitsi-server.yaml) packaged with STUNner. From b3cc45ecb0d166e5b884aac1a3f3ba9037201f87 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sat, 19 Oct 2024 17:01:30 +0200 Subject: [PATCH 32/37] docs(mediasoup): Refactor once more --- docs/examples/mediasoup/README.md | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/docs/examples/mediasoup/README.md b/docs/examples/mediasoup/README.md index eb6525e..4dbde01 100644 --- a/docs/examples/mediasoup/README.md +++ b/docs/examples/mediasoup/README.md @@ -11,14 +11,18 @@ In this demo you will learn to: ## Prerequisites -See prerequisites [here](../../INSTALL.md#prerequisites). +To run this example, you need: +* a [Kubernetes cluster](../../INSTALL.md#prerequisites), +* a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), +* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, +* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. > [!NOTE] > -> As a regrettable exception, Minikube is unfortunately not supported for this demo. The reason is that [Let's Encrypt certificate issuance is not available with nip.io](https://medium.com/@EmiiKhaos/there-is-no-possibility-that-you-can-get-lets-encrypt-certificate-with-nip-io-7483663e0c1b); later on you will learn more about why this is crucial above. +> If you have your own TLS certificate, put it in a `Secret` [resource](https://kubernetes.io/docs/concepts/configuration/secret/) and deploy it into the `default` namespace under the `mediasoup-demo-tls` name. -## Setup +## Description The recommended way to install mediasoup ([link](https://mediasoup.discourse.group/t/server-in-kubernetes-with-turn/3434),[link](https://www.reddit.com/r/kubernetes/comments/sdkhwn/deploying_mediasoup_webrtc_sfu_in_kubernetes/)) into Kubernetes is deploying the media servers into the host-network namespace of the Kubernetes nodes (`hostNetwork: true`). This deployment model, however, comes with a set of uncanny [operational limitations and security concerns](../../WHY.md). Using STUNner, however, media servers can be deployed into ordinary Kubernetes pods and run over a private IP network, like any "normal" Kubernetes workload. @@ -48,18 +52,6 @@ with an additional environment variable we can load the pod's private IP into th - Added the parsing of url parameters to configure TURN server and a simple if/else in server/app/lib/RoomClient.js. The mediasoup clients will use the configured TURN server to gather the ICE candidates. Example: https://mediasoup-demo.example.com/?enableIceServer=yes&iceServerHost=100.100.100.100&iceServerPort=3478&iceServerProto=udp&iceServerUser=user-1&iceServerPass=pass-1 -## Installation - -> [!NOTE] -> -> Let's start with a disclaimer. Securing connection between the user and the server is a must. Read more about TLS [here](../TLS.md). - -In the below example, STUNner will be installed into the identically named namespace (`stunner`), while mediasoup and the Ingress gateway will live in the `default` namespace. - -### Ingress and Cert manager installation - -To ingest secured traffic into the cluster, you need to install additional resources. Please follow the instructions in [this section](../TLS.md#installation) to install an Ingress and the Cert manager. - ### STUNner Now comes the fun part. The simplest way to run this demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy (after some minor modifications) the [manifest](mediasoup-server.yaml) packaged with STUNner. From 3e20945995e7ecb67c473e4580efd9f3254195fc Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sat, 19 Oct 2024 17:03:36 +0200 Subject: [PATCH 33/37] docs(neko): Refactor --- docs/examples/neko/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/examples/neko/README.md b/docs/examples/neko/README.md index 092b5c9..1c049cb 100644 --- a/docs/examples/neko/README.md +++ b/docs/examples/neko/README.md @@ -15,14 +15,15 @@ In this demo you will learn the following steps to: ### Prerequisites -See prerequisites [here](../../INSTALL.md#prerequisites). +To run this example, you need: +* a [Kubernetes cluster](../../INSTALL.md#prerequisites), +* a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), +* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster. ### Quick installation The simplest way to deploy the demo is to clone the [STUNner git repository](https://github.com/l7mp/stunner) and deploy the [manifest](neko.yaml) packaged with STUNner. -To install the stable version of STUNner, please follow the instructions in [this section](../../INSTALL.md#installation-1). - Configure STUNner to act as a STUN server towards clients, and to let media reach the media server. ```console From 32b9cc2453c5f0a7906eaef538e32af3796c41a6 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Mon, 21 Oct 2024 19:38:37 +0200 Subject: [PATCH 34/37] docs(TLS): Reword ingress desc --- docs/examples/TLS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/TLS.md b/docs/examples/TLS.md index d1d9e4a..34a5502 100644 --- a/docs/examples/TLS.md +++ b/docs/examples/TLS.md @@ -36,7 +36,7 @@ We use `nip.io` to "own a domain" in some examples. To replace it with your own The first step of secured traffic ingestion is obtaining a valid cert by installing a Kubernetes Ingress: this will be used during the validation of our certificates and to terminate client TLS encrypted contexts. -Install an Ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but this is not required. +Install an Ingress controller into your cluster. We used the official [nginx ingress](https://github.com/kubernetes/ingress-nginx), but other Ingress implementations might work (check their documentation for install steps). ```console helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx From 82df6bbd2d69e6747d853f58d60c16d6b06f7eda Mon Sep 17 00:00:00 2001 From: Kornel David Date: Mon, 21 Oct 2024 19:39:32 +0200 Subject: [PATCH 35/37] docs(examples): Reword prerequisites --- docs/examples/elixir-webrtc/README.md | 2 +- docs/examples/janus/README.md | 2 +- docs/examples/jitsi/README.md | 2 +- docs/examples/livekit/README.md | 2 +- docs/examples/mediasoup/README.md | 2 +- docs/examples/neko/README.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/examples/elixir-webrtc/README.md b/docs/examples/elixir-webrtc/README.md index 7e6ab8b..38c22d9 100644 --- a/docs/examples/elixir-webrtc/README.md +++ b/docs/examples/elixir-webrtc/README.md @@ -15,7 +15,7 @@ To run this example, you need: * a [Kubernetes cluster](../../INSTALL.md#prerequisites), * a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), * an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, -* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. +* a [Cert-manager](../TLS.md#cert-manager) to automate TLS certificate management. > [!NOTE] > diff --git a/docs/examples/janus/README.md b/docs/examples/janus/README.md index f8d54ad..8a12870 100644 --- a/docs/examples/janus/README.md +++ b/docs/examples/janus/README.md @@ -15,7 +15,7 @@ To run this example, you need: * a [Kubernetes cluster](../../INSTALL.md#prerequisites), * a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), * an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, -* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. +* a [Cert-manager](../TLS.md#cert-manager) to automate TLS certificate management. > [!NOTE] > diff --git a/docs/examples/jitsi/README.md b/docs/examples/jitsi/README.md index 463a7e8..aa77973 100644 --- a/docs/examples/jitsi/README.md +++ b/docs/examples/jitsi/README.md @@ -15,7 +15,7 @@ To run this example, you need: * a [Kubernetes cluster](../../INSTALL.md#prerequisites), * a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), * an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, -* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. +* a [Cert-manager](../TLS.md#cert-manager) to automate TLS certificate management. > [!NOTE] > diff --git a/docs/examples/livekit/README.md b/docs/examples/livekit/README.md index 3855c22..99aa02c 100644 --- a/docs/examples/livekit/README.md +++ b/docs/examples/livekit/README.md @@ -15,7 +15,7 @@ To run this example, you need: * a [Kubernetes cluster](../../INSTALL.md#prerequisites), * a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), * an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, -* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. +* a [Cert-manager](../TLS.md#cert-manager) to automate TLS certificate management. > [!NOTE] > diff --git a/docs/examples/mediasoup/README.md b/docs/examples/mediasoup/README.md index 4dbde01..f3e6bcf 100644 --- a/docs/examples/mediasoup/README.md +++ b/docs/examples/mediasoup/README.md @@ -15,7 +15,7 @@ To run this example, you need: * a [Kubernetes cluster](../../INSTALL.md#prerequisites), * a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), * an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster, -* a [Cert-manager](../TLS.md#cert-manager) to secure traffic. +* a [Cert-manager](../TLS.md#cert-manager) to automate TLS certificate management. > [!NOTE] > diff --git a/docs/examples/neko/README.md b/docs/examples/neko/README.md index 1c049cb..0777cc4 100644 --- a/docs/examples/neko/README.md +++ b/docs/examples/neko/README.md @@ -18,7 +18,7 @@ In this demo you will learn the following steps to: To run this example, you need: * a [Kubernetes cluster](../../INSTALL.md#prerequisites), * a [deployed STUNner](../../INSTALL.md#installation-1) (presumably the latest stable version), -* an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster. +* optionally, an [Ingress controller](../TLS.md#ingress) to ingest traffic into the cluster. ### Quick installation From c68a4914adfec078edf73a10657ba47364bf21b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tam=C3=A1s=20L=C3=A9vai?= Date: Thu, 24 Oct 2024 09:42:09 +0200 Subject: [PATCH 36/37] doc(examples/simple-tunnel): Fix turncat links --- docs/examples/simple-tunnel/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/simple-tunnel/README.md b/docs/examples/simple-tunnel/README.md index 99de957..ffbe209 100644 --- a/docs/examples/simple-tunnel/README.md +++ b/docs/examples/simple-tunnel/README.md @@ -18,7 +18,7 @@ The tutorial assumes a fresh STUNner installation; see the [STUNner installation ### Setup -In this tutorial we perform a quick Kubernetes/STUNner benchmark: we fire up an iperf server inside the cluster and perform a speed test from the local console. We will use the [`turncat`](../../cmd/turncat) client utility to tunnel test traffic to the iperf server via STUNner acting as a STUN/TURN gateway. +In this tutorial we perform a quick Kubernetes/STUNner benchmark: we fire up an iperf server inside the cluster and perform a speed test from the local console. We will use the [`turncat`](../../cmd/turncat.md) client utility to tunnel test traffic to the iperf server via STUNner acting as a STUN/TURN gateway. ![STUNner benchmarks setup](../../img/stunner_benchmark.svg) @@ -158,7 +158,7 @@ We will need to learn the ClusterIP assigned by Kubernetes to the `iperf-server` export IPERF_ADDR=$(kubectl get svc iperf-server -o jsonpath="{.spec.clusterIP}") ``` -Next, set up `turncat` to listen on `UDP:127.0.0.1:5000` and tunnel connections from this listener via the STUNner STUN/TURN listener `udp-listener` to the iperf server. Luckily, `turncat` is clever enough to [parse the running STUNner configuration](../../cmd/turncat) from Kubernetes and set the STUN/TURN server public address/port and the authentication credentials accordingly. +Next, set up `turncat` to listen on `UDP:127.0.0.1:5000` and tunnel connections from this listener via the STUNner STUN/TURN listener `udp-listener` to the iperf server. Luckily, `turncat` is clever enough to [parse the running STUNner configuration](../../cmd/turncat.md) from Kubernetes and set the STUN/TURN server public address/port and the authentication credentials accordingly. ``` console bin/turncat --log=all:INFO udp://127.0.0.1:5000 k8s://stunner/udp-gateway:udp-listener \ @@ -218,4 +218,4 @@ kubectl delete -f docs/examples/simple-tunnel/iperf-stunner.yaml # Help -STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). \ No newline at end of file +STUNner development is coordinated in Discord, feel free to [join](https://discord.gg/DyPgEsbwzc). From 0634024d308fce6fa346218ebbcc755adb4a93f4 Mon Sep 17 00:00:00 2001 From: Kornel David Date: Sun, 27 Oct 2024 22:16:54 +0100 Subject: [PATCH 37/37] docs(install): Add skip crd install section --- docs/INSTALL.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index f6004f4..22771a9 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -63,6 +63,22 @@ helm install stunner-prod stunner/stunner --create-namespace --namespace=stunner helm install stunner-dev stunner/stunner --create-namespace --namespace=stunner-dev ``` +### Skip install CRDs + +You can install the STUNner chart without the Gateway API CRDs and STUNner CRDs with the `--skip-crds` flag. However, ensure that the CRDs are already present in the cluster, as the STUNner Gateway Operator will fail to start without them. + +```console +helm install stunner-gateway-operator stunner/stunner-gateway-operator --create-namespace \ + --namespace=stunner-system --skip-crds +``` + +To manually install the CRDs: + +```console +kubectl apply -k github.com/kubernetes-sigs/gateway-api/config/crd?ref=v1.0.0 +kubectl apply -f https://raw.githubusercontent.com/l7mp/stunner-helm/refs/heads/main/helm/stunner-gateway-operator/crds/stunner-crd.yaml +``` + ## Customization The Helm charts let you fine-tune STUNner features, including [compute resources](#resources) provisioned for `stunnerd` pods, [UDP multithreading](#udp-multithreading), and[graceful shutdown](#graceful-shutdown).