Compare commits

...

11 Commits

Author SHA1 Message Date
Muhammad Atif Ali
92097e398d Update KasmVNC user group and config settings
- Use `usermod` to add user to ssl-cert group for compatibility.
- Simplify KasmVNC config with protocol and SSL parameters.
- Ensure UDP communication is confined to localhost for security.
2024-10-24 19:49:11 +05:00
Muhammad Atif Ali
e4a57f4a6a Update KasmVNC with custom image config steps
Add instructions for extending kasmtech custom images and modify the
run script to attempt system-wide config creation, ensuring flexibility
for environments without sudo access.
2024-10-24 12:58:20 +05:00
Muhammad Atif Ali
66b0bf6d27 Fix user group command in KasmVNC installation script 2024-10-24 12:00:48 +05:00
Muhammad Atif Ali
f6ebe73aea Simplify VNC server installation and config setup
- Streamlined the installation script's messaging for clarity.
- Added default SSL certificate path in the config.
2024-10-24 10:20:07 +05:00
Muhammad Atif Ali
2e0f3eddc0 Simplify config file creation in kasmvnc script 2024-10-23 21:18:56 +05:00
Muhammad Atif Ali
f63b460971 Enhance kasmvnc to simplify user permissions management 2024-10-23 21:07:33 +05:00
Muhammad Atif Ali
df507ca559 feat(kasmvnc): support images without sudo access
- Allow KasmVNC to be installed and run on systems where `sudo` is not available.
- Automatically adjust config file location and server start method based on `sudo` availability.
- Enhance portability for broader usage across various environments.
2024-10-23 20:12:08 +05:00
Steven Masley
ce5a5b383a feat(vscode-web): support hosting on a subpath with subdomain=false (#288)
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
Co-authored-by: Muhammad Atif Ali <me@matifali.dev>
2024-10-21 13:46:19 +05:00
framctr
1b147ae90d feat(jupyterlab): add support for subdomain=false (#316)
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
Co-authored-by: Asher <ash@coder.com>
2024-10-21 12:06:10 +05:00
djarbz
7992d9d265 fix(kasmVNC): fix debian installation and improve logging (#326) 2024-10-21 08:04:59 +05:00
Yves ANDOLFATTO
20d97a25dd fix(filebrowser): support custom base_url in case of custom db path (#320)
Co-authored-by: Muhammad Atif Ali <atif@coder.com>
Co-authored-by: Muhammad Atif Ali <me@matifali.dev>
2024-10-18 17:21:36 +05:00
11 changed files with 142 additions and 58 deletions

View File

@@ -47,6 +47,7 @@ You can test a module locally by updating the source as follows
```tf ```tf
module "example" { module "example" {
source = "git::https://github.com/<USERNAME>/<REPO>.git//<MODULE-NAME>?ref=<BRANCH-NAME>" source = "git::https://github.com/<USERNAME>/<REPO>.git//<MODULE-NAME>?ref=<BRANCH-NAME>"
# You may need to remove the 'version' field, it is incompatible with some sources.
} }
``` ```

View File

@@ -14,7 +14,7 @@ A file browser for your workspace.
```tf ```tf
module "filebrowser" { module "filebrowser" {
source = "registry.coder.com/modules/filebrowser/coder" source = "registry.coder.com/modules/filebrowser/coder"
version = "1.0.19" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
} }
``` ```
@@ -28,7 +28,7 @@ module "filebrowser" {
```tf ```tf
module "filebrowser" { module "filebrowser" {
source = "registry.coder.com/modules/filebrowser/coder" source = "registry.coder.com/modules/filebrowser/coder"
version = "1.0.19" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
folder = "/home/coder/project" folder = "/home/coder/project"
} }
@@ -39,7 +39,7 @@ module "filebrowser" {
```tf ```tf
module "filebrowser" { module "filebrowser" {
source = "registry.coder.com/modules/filebrowser/coder" source = "registry.coder.com/modules/filebrowser/coder"
version = "1.0.19" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
database_path = ".config/filebrowser.db" database_path = ".config/filebrowser.db"
} }

View File

@@ -18,7 +18,7 @@ if [ "${DB_PATH}" != "filebrowser.db" ]; then
fi fi
# set baseurl to be able to run if sudomain=false; if subdomain=true the SERVER_BASE_PATH value will be "" # set baseurl to be able to run if sudomain=false; if subdomain=true the SERVER_BASE_PATH value will be ""
filebrowser config set --baseurl "${SERVER_BASE_PATH}" > ${LOG_PATH} 2>&1 filebrowser config set --baseurl "${SERVER_BASE_PATH}"$${DB_FLAG} > ${LOG_PATH} 2>&1
printf "📂 Serving $${ROOT_DIR} at http://localhost:${PORT} \n\n" printf "📂 Serving $${ROOT_DIR} at http://localhost:${PORT} \n\n"

View File

@@ -16,7 +16,7 @@ A module that adds JupyterLab in your Coder template.
```tf ```tf
module "jupyterlab" { module "jupyterlab" {
source = "registry.coder.com/modules/jupyterlab/coder" source = "registry.coder.com/modules/jupyterlab/coder"
version = "1.0.19" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
} }
``` ```

View File

@@ -9,6 +9,9 @@ terraform {
} }
} }
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}
# Add required variables for your modules and remove any unneeded variables # Add required variables for your modules and remove any unneeded variables
variable "agent_id" { variable "agent_id" {
type = string type = string
@@ -36,6 +39,12 @@ variable "share" {
} }
} }
variable "subdomain" {
type = bool
description = "Determines whether JupyterLab will be accessed via its own subdomain or whether it will be accessed via a path on Coder."
default = true
}
variable "order" { variable "order" {
type = number type = number
description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)." description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)."
@@ -49,17 +58,18 @@ resource "coder_script" "jupyterlab" {
script = templatefile("${path.module}/run.sh", { script = templatefile("${path.module}/run.sh", {
LOG_PATH : var.log_path, LOG_PATH : var.log_path,
PORT : var.port PORT : var.port
BASE_URL : var.subdomain ? "" : "/@${data.coder_workspace_owner.me.name}/${data.coder_workspace.me.name}/apps/jupyterlab"
}) })
run_on_start = true run_on_start = true
} }
resource "coder_app" "jupyterlab" { resource "coder_app" "jupyterlab" {
agent_id = var.agent_id agent_id = var.agent_id
slug = "jupyterlab" slug = "jupyterlab" # sync with the usage in URL
display_name = "JupyterLab" display_name = "JupyterLab"
url = "http://localhost:${var.port}" url = var.subdomain ? "http://localhost:${var.port}" : "http://localhost:${var.port}/@${data.coder_workspace_owner.me.name}/${data.coder_workspace.me.name}/apps/jupyterlab"
icon = "/icon/jupyter.svg" icon = "/icon/jupyter.svg"
subdomain = true subdomain = var.subdomain
share = var.share share = var.share
order = var.order order = var.order
} }

View File

@@ -1,5 +1,9 @@
#!/usr/bin/env sh #!/usr/bin/env sh
if [ -n "${BASE_URL}" ]; then
BASE_URL_FLAG="--ServerApp.base_url=${BASE_URL}"
fi
BOLD='\033[0;1m' BOLD='\033[0;1m'
printf "$${BOLD}Installing jupyterlab!\n" printf "$${BOLD}Installing jupyterlab!\n"
@@ -15,11 +19,17 @@ if ! command -v jupyterlab > /dev/null 2>&1; then
fi fi
# install jupyterlab # install jupyterlab
pipx install -q jupyterlab pipx install -q jupyterlab
echo "🥳 jupyterlab has been installed\n\n" printf "%s\n\n" "🥳 jupyterlab has been installed"
else else
echo "🥳 jupyterlab is already installed\n\n" printf "%s\n\n" "🥳 jupyterlab is already installed"
fi fi
echo "👷 Starting jupyterlab in background..." printf "👷 Starting jupyterlab in background..."
echo "check logs at ${LOG_PATH}" printf "check logs at ${LOG_PATH}"
$HOME/.local/bin/jupyter-lab --ServerApp.ip='0.0.0.0' --ServerApp.port=${PORT} --no-browser --ServerApp.token='' --ServerApp.password='' > ${LOG_PATH} 2>&1 & $HOME/.local/bin/jupyter-lab --no-browser \
"$BASE_URL_FLAG" \
--ServerApp.ip='*' \
--ServerApp.port="${PORT}" \
--ServerApp.token='' \
--ServerApp.password='' \
> "${LOG_PATH}" 2>&1 &

View File

@@ -14,10 +14,29 @@ Automatically install [KasmVNC](https://kasmweb.com/kasmvnc) in a workspace, and
```tf ```tf
module "kasmvnc" { module "kasmvnc" {
source = "registry.coder.com/modules/kasmvnc/coder" source = "registry.coder.com/modules/kasmvnc/coder"
version = "1.0.21" version = "1.0.23"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
desktop_environment = "xfce" desktop_environment = "xfce"
} }
``` ```
> **Note:** This module only works on workspaces with a pre-installed desktop environment. As an example base image you can use `codercom/enterprise-desktop` image. > **Note:** This module only works on workspaces with a pre-installed desktop environment. As an example base image you can use `codercom/enterprise-desktop` image.
> **Note:** You can also use the kasmtech [custom images](https://kasmweb.com/docs/latest/guide/custom_images.html) by extending them as following:
```Dockerfile
FROM kasmweb/postman:1.16.0
ARG USER=kasm-user
USER root
# Overwrite the existing config file to disable ssl
RUN cat <<EOF > /etc/kasmvnc/kasmvnc.yaml
network:
protocol: http
ssl:
require_ssl: false
udp:
public_ip: 127.0.0.1
EOF
RUN addgroup $USER ssl-cert
USER $USER
```

View File

@@ -5,7 +5,7 @@
# Function to check if vncserver is already installed # Function to check if vncserver is already installed
check_installed() { check_installed() {
if command -v vncserver &> /dev/null; then if command -v vncserver &> /dev/null; then
echo "vncserver is already installed." echo "A binary with name vncserver already installed."
return 0 # Don't exit, just indicate it's installed return 0 # Don't exit, just indicate it's installed
else else
return 1 # Indicates not installed return 1 # Indicates not installed
@@ -19,7 +19,7 @@ download_file() {
if command -v wget &> /dev/null; then if command -v wget &> /dev/null; then
wget $url -O $output wget $url -O $output
elif command -v curl &> /dev/null; then elif command -v curl &> /dev/null; then
curl -L $url -o $output curl -fsSL $url -o $output
elif command -v busybox &> /dev/null; then elif command -v busybox &> /dev/null; then
busybox wget -O $output $url busybox wget -O $output $url
else else
@@ -32,8 +32,9 @@ download_file() {
install_deb() { install_deb() {
local url=$1 local url=$1
download_file $url /tmp/kasmvncserver.deb download_file $url /tmp/kasmvncserver.deb
sudo apt-get install --yes --no-install-recommends --no-install-suggests /tmp/kasmvncserver.deb sudo apt-get update
sudo adduser $USER ssl-cert DEBIAN_FRONTEND=noninteractive sudo apt-get install --yes -qq --no-install-recommends --no-install-suggests /tmp/kasmvncserver.deb
sudo usermod -aG ssl-cert $USER
rm /tmp/kasmvncserver.deb rm /tmp/kasmvncserver.deb
} }
@@ -74,6 +75,8 @@ install_alpine() {
rm /tmp/kasmvncserver.tgz rm /tmp/kasmvncserver.tgz
} }
# Check if vncserver is installed, and install if not
if ! check_installed; then
# Detect system information # Detect system information
distro=$(grep "^ID=" /etc/os-release | awk -F= '{print $2}') distro=$(grep "^ID=" /etc/os-release | awk -F= '{print $2}')
version=$(grep "^VERSION_ID=" /etc/os-release | awk -F= '{print $2}' | tr -d '"') version=$(grep "^VERSION_ID=" /etc/os-release | awk -F= '{print $2}' | tr -d '"')
@@ -101,8 +104,7 @@ else
exit 1 exit 1
fi fi
# Check if vncserver is installed, and install if not echo "Installing KASM version: ${VERSION}"
if ! check_installed; then
case $distro in case $distro in
ubuntu | debian | kali) ubuntu | debian | kali)
case $version in case $version in
@@ -153,10 +155,12 @@ if ! check_installed; then
;; ;;
esac esac
else else
echo "vncserver already installed. Skipping installation." echo "Skipping installation."
fi fi
# Coder port-forwarding from dashboard only supports HTTP # Try to create /etc/kasmvnc/kasmvnc.yaml system-wide
# we don't fail as some images might be missing sudo permissions
sudo mkdir -p /etc/kasmvnc || true
sudo bash -c "cat > /etc/kasmvnc/kasmvnc.yaml <<EOF sudo bash -c "cat > /etc/kasmvnc/kasmvnc.yaml <<EOF
network: network:
protocol: http protocol: http
@@ -165,7 +169,22 @@ network:
require_ssl: false require_ssl: false
udp: udp:
public_ip: 127.0.0.1 public_ip: 127.0.0.1
EOF" EOF" || true
# There could already be a config file in the image at /etc/kasmvnc/kasmvnc.yaml, but we need to set the websocket port
mkdir -p "$HOME/.vnc"
cat > "$HOME/.vnc/kasmvnc.yaml" <<EOF
network:
protocol: http
websocket_port: ${PORT}
ssl:
require_ssl: false
pem_certificate:
pem_key:
udp:
public_ip: 127.0.0.1
EOF
# This password is not used since we start the server without auth. # This password is not used since we start the server without auth.
# The server is protected via the Coder session token / tunnel # The server is protected via the Coder session token / tunnel
@@ -174,4 +193,4 @@ echo -e "password\npassword\n" | vncpasswd -wo -u $USER
# Start the server # Start the server
printf "🚀 Starting KasmVNC server...\n" printf "🚀 Starting KasmVNC server...\n"
sudo -u $USER bash -c "vncserver -select-de ${DESKTOP_ENVIRONMENT} -disableBasicAuth" > /tmp/kasmvncserver.log 2>&1 & vncserver -select-de ${DESKTOP_ENVIRONMENT} -disableBasicAuth > /tmp/kasmvncserver.log 2>&1 &

View File

@@ -14,7 +14,7 @@ Automatically install [Visual Studio Code Server](https://code.visualstudio.com/
```tf ```tf
module "vscode-web" { module "vscode-web" {
source = "registry.coder.com/modules/vscode-web/coder" source = "registry.coder.com/modules/vscode-web/coder"
version = "1.0.20" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
accept_license = true accept_license = true
} }
@@ -29,7 +29,7 @@ module "vscode-web" {
```tf ```tf
module "vscode-web" { module "vscode-web" {
source = "registry.coder.com/modules/vscode-web/coder" source = "registry.coder.com/modules/vscode-web/coder"
version = "1.0.20" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
install_prefix = "/home/coder/.vscode-web" install_prefix = "/home/coder/.vscode-web"
folder = "/home/coder" folder = "/home/coder"
@@ -42,7 +42,7 @@ module "vscode-web" {
```tf ```tf
module "vscode-web" { module "vscode-web" {
source = "registry.coder.com/modules/vscode-web/coder" source = "registry.coder.com/modules/vscode-web/coder"
version = "1.0.20" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
extensions = ["github.copilot", "ms-python.python", "ms-toolsai.jupyter"] extensions = ["github.copilot", "ms-python.python", "ms-toolsai.jupyter"]
accept_license = true accept_license = true
@@ -56,7 +56,7 @@ Configure VS Code's [settings.json](https://code.visualstudio.com/docs/getstarte
```tf ```tf
module "vscode-web" { module "vscode-web" {
source = "registry.coder.com/modules/vscode-web/coder" source = "registry.coder.com/modules/vscode-web/coder"
version = "1.0.20" version = "1.0.22"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
extensions = ["dracula-theme.theme-dracula"] extensions = ["dracula-theme.theme-dracula"]
settings = { settings = {

View File

@@ -121,6 +121,18 @@ variable "auto_install_extensions" {
default = false default = false
} }
variable "subdomain" {
type = bool
description = <<-EOT
Determines whether the app will be accessed via it's own subdomain or whether it will be accessed via a path on Coder.
If wildcards have not been setup by the administrator then apps with "subdomain" set to true will not be accessible.
EOT
default = true
}
data "coder_workspace_owner" "me" {}
data "coder_workspace" "me" {}
resource "coder_script" "vscode-web" { resource "coder_script" "vscode-web" {
agent_id = var.agent_id agent_id = var.agent_id
display_name = "VS Code Web" display_name = "VS Code Web"
@@ -138,6 +150,7 @@ resource "coder_script" "vscode-web" {
EXTENSIONS_DIR : var.extensions_dir, EXTENSIONS_DIR : var.extensions_dir,
FOLDER : var.folder, FOLDER : var.folder,
AUTO_INSTALL_EXTENSIONS : var.auto_install_extensions, AUTO_INSTALL_EXTENSIONS : var.auto_install_extensions,
SERVER_BASE_PATH : local.server_base_path,
}) })
run_on_start = true run_on_start = true
@@ -158,15 +171,21 @@ resource "coder_app" "vscode-web" {
agent_id = var.agent_id agent_id = var.agent_id
slug = var.slug slug = var.slug
display_name = var.display_name display_name = var.display_name
url = var.folder == "" ? "http://localhost:${var.port}" : "http://localhost:${var.port}?folder=${var.folder}" url = local.url
icon = "/icon/code.svg" icon = "/icon/code.svg"
subdomain = true subdomain = var.subdomain
share = var.share share = var.share
order = var.order order = var.order
healthcheck { healthcheck {
url = "http://localhost:${var.port}/healthz" url = local.healthcheck_url
interval = 5 interval = 5
threshold = 6 threshold = 6
} }
} }
locals {
server_base_path = var.subdomain ? "" : format("/@%s/%s/apps/%s/", data.coder_workspace_owner.me.name, data.coder_workspace.me.name, var.slug)
url = var.folder == "" ? "http://localhost:${var.port}${local.server_base_path}" : "http://localhost:${var.port}${local.server_base_path}?folder=${var.folder}"
healthcheck_url = var.subdomain ? "http://localhost:${var.port}/healthz" : "http://localhost:${var.port}${local.server_base_path}/healthz"
}

View File

@@ -10,10 +10,16 @@ if [ -n "${EXTENSIONS_DIR}" ]; then
EXTENSION_ARG="--extensions-dir=${EXTENSIONS_DIR}" EXTENSION_ARG="--extensions-dir=${EXTENSIONS_DIR}"
fi fi
# Set extension directory
SERVER_BASE_PATH_ARG=""
if [ -n "${SERVER_BASE_PATH}" ]; then
SERVER_BASE_PATH_ARG="--server-base-path=${SERVER_BASE_PATH}"
fi
run_vscode_web() { run_vscode_web() {
echo "👷 Running $VSCODE_WEB serve-local $EXTENSION_ARG --port ${PORT} --host 127.0.0.1 --accept-server-license-terms --without-connection-token --telemetry-level ${TELEMETRY_LEVEL} in the background..." echo "👷 Running $VSCODE_WEB serve-local $EXTENSION_ARG $SERVER_BASE_PATH_ARG --port ${PORT} --host 127.0.0.1 --accept-server-license-terms --without-connection-token --telemetry-level ${TELEMETRY_LEVEL} in the background..."
echo "Check logs at ${LOG_PATH}!" echo "Check logs at ${LOG_PATH}!"
"$VSCODE_WEB" serve-local "$EXTENSION_ARG" --port "${PORT}" --host 127.0.0.1 --accept-server-license-terms --without-connection-token --telemetry-level "${TELEMETRY_LEVEL}" > "${LOG_PATH}" 2>&1 & "$VSCODE_WEB" serve-local "$EXTENSION_ARG" "$SERVER_BASE_PATH_ARG" --port "${PORT}" --host 127.0.0.1 --accept-server-license-terms --without-connection-token --telemetry-level "${TELEMETRY_LEVEL}" > "${LOG_PATH}" 2>&1 &
} }
# Check if the settings file exists... # Check if the settings file exists...