From 8a692654c3d4428edca5ac64d0f313d13f203c07 Mon Sep 17 00:00:00 2001 From: Seungmin Kim <8457324+ehfd@users.noreply.github.com> Date: Mon, 24 Jun 2024 09:23:11 -0700 Subject: [PATCH] Introduce NGINX --- Dockerfile | 3 + entrypoint.sh | 22 -------- kasmvnc-entrypoint.sh | 74 +++++++++++++++++++++++++ selkies-gstreamer-entrypoint.sh | 97 ++++++++++++++++++++++++++++++++- supervisord.conf | 22 ++++++++ 5 files changed, 195 insertions(+), 23 deletions(-) create mode 100644 kasmvnc-entrypoint.sh diff --git a/Dockerfile b/Dockerfile index 7b54340..0db32f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -50,6 +50,7 @@ RUN apt-get update && apt-get install --no-install-recommends -y \ software-properties-common \ build-essential \ ca-certificates \ + nginx \ cups-browsed \ cups-bsd \ cups-common \ @@ -568,6 +569,8 @@ COPY --chown=1000:1000 entrypoint.sh /etc/entrypoint.sh RUN chmod 755 /etc/entrypoint.sh COPY --chown=1000:1000 selkies-gstreamer-entrypoint.sh /etc/selkies-gstreamer-entrypoint.sh RUN chmod 755 /etc/selkies-gstreamer-entrypoint.sh +COPY --chown=1000:1000 kasmvnc-entrypoint.sh /etc/kasmvnc-entrypoint.sh +RUN chmod 755 /etc/kasmvnc-entrypoint.sh COPY --chown=1000:1000 supervisord.conf /etc/supervisord.conf RUN chmod 755 /etc/supervisord.conf diff --git a/entrypoint.sh b/entrypoint.sh index b30d3f0..597c658 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -86,28 +86,6 @@ echo 'Waiting for X Socket' && until [ -S "/tmp/.X11-unix/X${DISPLAY#*:}" ]; do # Resize the screen to the provided size /usr/local/bin/selkies-gstreamer-resize "${DISPLAY_SIZEW}x${DISPLAY_SIZEH}" -# Run the KasmVNC fallback web interface if enabled -if [ "$(echo ${KASMVNC_ENABLE} | tr '[:upper:]' '[:lower:]')" = "true" ]; then - export KASM_DISPLAY=":50" - yq -i " - .command_line.prompt = false | - .desktop.allow_resize = $(echo ${SELKIES_ENABLE_RESIZE-false} | tr '[:upper:]' '[:lower:]') | - .network.interface = \"0.0.0.0\" | - .network.websocket_port = 8080 | - .network.ssl.require_ssl = $(echo ${SELKIES_ENABLE_HTTPS-false} | tr '[:upper:]' '[:lower:]') | - .encoding.max_frame_rate = ${DISPLAY_REFRESH} - " /etc/kasmvnc/kasmvnc.yaml - if [ -n "${SELKIES_HTTPS_CERT}" ]; then yq -i ".network.ssl.pem_certificate = \"${SELKIES_HTTPS_CERT-/etc/ssl/certs/ssl-cert-snakeoil.pem}\"" /etc/kasmvnc/kasmvnc.yaml; fi - if [ -n "${SELKIES_HTTPS_KEY}" ]; then yq -i ".network.ssl.pem_key = \"${SELKIES_HTTPS_KEY-/etc/ssl/private/ssl-cert-snakeoil.key}\"" /etc/kasmvnc/kasmvnc.yaml; fi - if [ "$(echo ${SELKIES_ENABLE_RESIZE} | tr '[:upper:]' '[:lower:]')" = "true" ]; then export KASM_RESIZE_FLAG="-r"; fi - (echo "${SELKIES_BASIC_AUTH_PASSWORD:-${PASSWD}}"; echo "${SELKIES_BASIC_AUTH_PASSWORD:-${PASSWD}}";) | kasmvncpasswd -u "${SELKIES_BASIC_AUTH_USER:-${USER}}" -o - if [ "$(echo ${SELKIES_ENABLE_BASIC_AUTH} | tr '[:upper:]' '[:lower:]')" = "false" ]; then export NO_KASM_AUTH_FLAG="-disableBasicAuth"; fi - if [ -n "${KASMVNC_VIEWPASS}" ]; then (echo "${KASMVNC_VIEWPASS}"; echo "${KASMVNC_VIEWPASS}";) | kasmvncpasswd -u "view"; fi - kasmvncserver "${KASM_DISPLAY}" -geometry "${DISPLAY_SIZEW}x${DISPLAY_SIZEH}" -depth "${DISPLAY_CDEPTH}" -noxstartup -FrameRate "${DISPLAY_REFRESH}" -websocketPort 8080 -AlwaysShared -BlacklistTimeout 0 ${NO_KASM_AUTH_FLAG} - until [ -S "/tmp/.X11-unix/X${KASM_DISPLAY#*:}" ]; do sleep 0.5; done; - kasmxproxy -a "${DISPLAY}" -v "${KASM_DISPLAY}" -f "${DISPLAY_REFRESH}" ${KASM_RESIZE_FLAG} & -fi - # Use VirtualGL to run the KDE desktop environment with OpenGL if the GPU is available, otherwise use OpenGL with llvmpipe export XDG_SESSION_ID="${DISPLAY#*:}" export QT_LOGGING_RULES='*.debug=false;qt.qpa.*=false' diff --git a/kasmvnc-entrypoint.sh b/kasmvnc-entrypoint.sh new file mode 100644 index 0000000..cdc7343 --- /dev/null +++ b/kasmvnc-entrypoint.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. + +set -e + +# Set password for basic authentication +if [ "$(echo ${SELKIES_ENABLE_BASIC_AUTH} | tr '[:upper:]' '[:lower:]')" = "true" ] && [ -z "${SELKIES_BASIC_AUTH_PASSWORD}" ]; then export SELKIES_BASIC_AUTH_PASSWORD="${PASSWD}"; fi + +# Set default display +export DISPLAY="${DISPLAY:-:0}" +# PipeWire-Pulse server socket path +export PIPEWIRE_LATENCY="32/48000" +export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp}" +export PIPEWIRE_RUNTIME_DIR="${PIPEWIRE_RUNTIME_DIR:-${XDG_RUNTIME_DIR:-/tmp}}" +export PULSE_RUNTIME_PATH="${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR:-/tmp}/pulse}" +export PULSE_SERVER="${PULSE_SERVER:-unix:${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR:-/tmp}/pulse}/native}" + +# Configure NGINX +echo "# Selkies KasmVNC NGINX Configuration +server { + listen 8080 $(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"ssl\"; fi); + listen [::]:8080 $(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"ssl\"; fi); + ssl_certificate ${SELKIES_HTTPS_CERT-/etc/ssl/certs/ssl-cert-snakeoil.pem}; + ssl_certificate_key ${SELKIES_HTTPS_KEY-/etc/ssl/private/ssl-cert-snakeoil.key}; + + location / { + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + + proxy_http_version 1.1; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + proxy_connect_timeout 1800s; + proxy_buffering off; + + client_max_body_size 10M; + + proxy_pass http$(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"s\"; fi)://localhost:8081; + } +}" | tee /etc/nginx/sites-available/default > /dev/null + +# Configure KasmVNC +export KASM_DISPLAY=":50" +yq -i " +.command_line.prompt = false | +.network.interface = \"0.0.0.0\" | +.network.websocket_port = 8081 | +.network.ssl.require_ssl = $(echo ${SELKIES_ENABLE_HTTPS-false} | tr '[:upper:]' '[:lower:]') | +.encoding.max_frame_rate = ${DISPLAY_REFRESH} +" /etc/kasmvnc/kasmvnc.yaml + +if [ -n "${SELKIES_HTTPS_CERT}" ]; then yq -i ".network.ssl.pem_certificate = \"${SELKIES_HTTPS_CERT-/etc/ssl/certs/ssl-cert-snakeoil.pem}\"" /etc/kasmvnc/kasmvnc.yaml; fi +if [ -n "${SELKIES_HTTPS_KEY}" ]; then yq -i ".network.ssl.pem_key = \"${SELKIES_HTTPS_KEY-/etc/ssl/private/ssl-cert-snakeoil.key}\"" /etc/kasmvnc/kasmvnc.yaml; fi + +if [ "$(echo ${SELKIES_ENABLE_RESIZE} | tr '[:upper:]' '[:lower:]')" = "true" ]; then export KASM_RESIZE_FLAG="-r"; fi + +(echo "${SELKIES_BASIC_AUTH_PASSWORD:-${PASSWD}}"; echo "${SELKIES_BASIC_AUTH_PASSWORD:-${PASSWD}}";) | kasmvncpasswd -u "${SELKIES_BASIC_AUTH_USER:-${USER}}" -ow +if [ "$(echo ${SELKIES_ENABLE_BASIC_AUTH} | tr '[:upper:]' '[:lower:]')" = "false" ]; then export NO_KASM_AUTH_FLAG="-disableBasicAuth"; fi +if [ -n "${KASMVNC_VIEWPASS}" ]; then (echo "${KASMVNC_VIEWPASS}"; echo "${KASMVNC_VIEWPASS}";) | kasmvncpasswd -u "view"; fi + +# Run KasmVNC +kasmvncserver "${KASM_DISPLAY}" -geometry "${DISPLAY_SIZEW}x${DISPLAY_SIZEH}" -depth "${DISPLAY_CDEPTH}" -noxstartup -FrameRate "${DISPLAY_REFRESH}" -websocketPort 8081 -AlwaysShared -BlacklistTimeout 0 ${NO_KASM_AUTH_FLAG} + +until [ -S "/tmp/.X11-unix/X${KASM_DISPLAY#*:}" ]; do sleep 0.5; done; + +kasmxproxy -a "${DISPLAY}" -v "${KASM_DISPLAY}" -f "${DISPLAY_REFRESH}" ${KASM_RESIZE_FLAG} & diff --git a/selkies-gstreamer-entrypoint.sh b/selkies-gstreamer-entrypoint.sh index 2493803..3fe2631 100755 --- a/selkies-gstreamer-entrypoint.sh +++ b/selkies-gstreamer-entrypoint.sh @@ -18,6 +18,101 @@ export PIPEWIRE_RUNTIME_DIR="${PIPEWIRE_RUNTIME_DIR:-${XDG_RUNTIME_DIR:-/tmp}}" export PULSE_RUNTIME_PATH="${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR:-/tmp}/pulse}" export PULSE_SERVER="${PULSE_SERVER:-unix:${PULSE_RUNTIME_PATH:-${XDG_RUNTIME_DIR:-/tmp}/pulse}/native}" +# Configure NGINX +echo "# Selkies-GStreamer NGINX Configuration +server { + listen 8080 $(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"ssl\"; fi); + listen [::]:8080 $(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"ssl\"; fi); + ssl_certificate ${SELKIES_HTTPS_CERT-/etc/ssl/certs/ssl-cert-snakeoil.pem}; + ssl_certificate_key ${SELKIES_HTTPS_KEY-/etc/ssl/private/ssl-cert-snakeoil.key}; + + location / { + alias /opt/gst-web; + index index.html index.htm; + } + + location /health { + proxy_http_version 1.1; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + proxy_connect_timeout 1800s; + proxy_buffering off; + + client_max_body_size 10M; + + proxy_pass http$(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"s\"; fi)://localhost:8081; + } + + location /turn { + proxy_http_version 1.1; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + proxy_connect_timeout 1800s; + proxy_buffering off; + + client_max_body_size 10M; + + proxy_pass http$(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"s\"; fi)://localhost:8081; + } + + location /ws { + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + + proxy_http_version 1.1; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + proxy_connect_timeout 1800s; + proxy_buffering off; + + client_max_body_size 10M; + + proxy_pass http$(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"s\"; fi)://localhost:8081; + } + + location /webrtc/signalling { + proxy_set_header Upgrade \$http_upgrade; + proxy_set_header Connection \"upgrade\"; + + proxy_set_header Host \$host; + proxy_set_header X-Real-IP \$remote_addr; + proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto \$scheme; + + proxy_http_version 1.1; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + proxy_connect_timeout 1800s; + proxy_buffering off; + + client_max_body_size 10M; + + proxy_pass http$(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"s\"; fi)://localhost:8081; + } + + location /metrics { + proxy_http_version 1.1; + proxy_read_timeout 1800s; + proxy_send_timeout 1800s; + proxy_connect_timeout 1800s; + proxy_buffering off; + + client_max_body_size 10M; + + proxy_pass http$(if [ \"$(echo ${SELKIES_ENABLE_HTTPS} | tr '[:upper:]' '[:lower:]')\" = \"true\" ]; then printf \"s\"; fi)://localhost:8081; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + alias /opt/gst-web; + } +}" | tee /etc/nginx/sites-available/default > /dev/null + # Export environment variables required for Selkies-GStreamer export GST_DEBUG="${GST_DEBUG:-*:2}" export GSTREAMER_PATH=/opt/gstreamer @@ -46,5 +141,5 @@ rm -rf "${HOME}/.cache/gstreamer-1.0" # Start the Selkies-GStreamer WebRTC HTML5 remote desktop application selkies-gstreamer \ --addr="0.0.0.0" \ - --port="8080" \ + --port="8081" \ $@ diff --git a/supervisord.conf b/supervisord.conf index 0a116a7..d599793 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -46,6 +46,28 @@ autostart=true autorestart=true priority=20 +[program:kasmvnc] +command=bash -c "if [ $(echo %(ENV_KASMVNC_ENABLE)s | tr '[:upper:]' '[:lower:]') = true ]; then /etc/kasmvnc-entrypoint.sh; else sleep infinity; fi" +stdout_logfile=/tmp/kasmvnc-entrypoint.log +stdout_logfile_backups=0 +redirect_stderr=true +stopasgroup=true +stopsignal=INT +autostart=true +autorestart=true +priority=20 + +[program:nginx] +command=bash -c "until head -n 1 /etc/nginx/sites-available/default | grep -q 'Selkies'; do sleep 0.5; done; /usr/sbin/nginx -g \"daemon off;\"" +stdout_logfile=/tmp/nginx.log +stdout_logfile_backups=0 +redirect_stderr=true +stopasgroup=true +stopsignal=INT +autostart=true +autorestart=true +priority=30 + [group:pipewire-group] program=pipewire,wireplumber,pipewire-pulse priority=10