Authenticated Web VSCode Server

Authenticated web vscode server with Pritunl Zero and VS Code Server

This script will create an authenticated Visual Studio code web server with Pritunl Zero allowing for secure access to a vscode editor running in the browser. It can be used on any RHEL9 distribution such as AlmaLinux 9 or Oracle Linux 9 . For other distributions the commands will need to be adjusted. The Visual Studio Code Server provides a server to run vscode in the web browser. This script will run this server on the localhost then install and configure Pritunl Zero to provided secure and authenticated access to the web vscode. Additional users can be added to provide a self hosted vscode server for collaborating or sharing code between systems.

First create a server with either a public IPv4 or IPv6 address. If the server is only running on a private network refer to the next section on how to create the Lets Encrypt certificate using DNS CNAME verification. This script will use HTTP verification on port 80 on both the domains configured below.

Before starting the installation configure two domains the ZERO_DOMAIN for the Pritunl Zero administrator console and the VSCODE_DOMAIN for the web vscode domain. Both of these domains should have A or AAAA records for the IPv4 and IPv6 address of the Pritunl Zero server. The ROOT_DOMAIN is used if WebAuthn tokens are configured, this domain controls the scope of those token validations, it's best to use the highest level domain to allow the tokens to function across multiple sub-domains. A DNS record does not need to be created or modified for the ROOT_DOMAIN.

This script will store all data in the persistent paths /var/lib/mongo and /var/lib/vscode. These are the only two paths that need to be maintained when re-initializing the system.

Once the script is completed it will display the default password. This can then be used to login to the admin domain or vscode domain. Open the /logout path in the vscode domain from the browser URL input to logout.

Below is also a settings.json file, this should be updated with any vscode settings to apply to the web vscode. When using to share code or text between multiple users it's recommended to use a very low files.autoSaveDelay to quickly sync the changes between users.

#!/bin/bash
# persistent paths: /var/lib/mongo /var/lib/vscode
set -e

ROOT_DOMAIN="pritunl.demo"
ZERO_DOMAIN="zero.pritunl.demo"
VSCODE_DOMAIN="vscode.pritunl.demo"

get_node_id() {
  if [ $# -eq 0 ]; then
    echo "Error: File path is required" >&2
    echo "Usage: get_node_id <node_id_file_path>" >&2
    return 1
  fi
  local node_id_file="$1"
  local node_id
  sudo mkdir -p "$(dirname "$node_id_file")"
  if [ -f "$node_id_file" ]; then
    node_id=$(cat "$node_id_file")
  else
    node_id=$(echo -n $(printf "%08x" $(date +%s))$(hexdump -n 8 -e '4/4 "%08x" 1 "\n"' /dev/urandom))
    echo "$node_id" | sudo tee "$node_id_file" > /dev/null
    sudo chmod 444 "$node_id_file"
  fi
  echo "$node_id"
}

sudo dnf -y update

sudo dnf -y install dnf-automatic
sudo sed -i 's/^upgrade_type =.*/upgrade_type = default/g' /etc/dnf/automatic.conf
sudo sed -i 's/^download_updates =.*/download_updates = yes/g' /etc/dnf/automatic.conf
sudo sed -i 's/^apply_updates =.*/apply_updates = yes/g' /etc/dnf/automatic.conf
sudo systemctl enable --now dnf-automatic.timer

sudo systemctl disable --now firewalld.service

sudo tee /etc/yum.repos.d/pritunl.repo << EOF
[pritunl]
name=Pritunl Repository
baseurl=https://repo.pritunl.com/stable/yum/oraclelinux/9/
gpgcheck=1
enabled=1
gpgkey=https://raw.githubusercontent.com/pritunl/pgp/master/pritunl_repo_pub.asc
EOF

sudo tee /etc/yum.repos.d/mongodb-org.repo << EOF
[mongodb-org]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://pgp.mongodb.com/server-8.0.asc
EOF

sudo tee /etc/yum.repos.d/code.repo << EOF
[code]
name=Visual Studio Code
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
EOF

sudo dnf -y install pritunl-zero mongodb-org code

sudo systemctl enable --now mongod

NODE_ID=$(get_node_id "/var/lib/mongo/node_id")

sudo tee /etc/pritunl-zero.json << EOF
{
    "mongo_uri": "mongodb://localhost:27017/pritunl-zero",
    "node_id": "$NODE_ID"
}
EOF
sudo chmod 600 /etc/pritunl-zero.json

sudo useradd -r -s /sbin/nologin vscode
sudo mkdir -p /home/vscode
sudo chown vscode:vscode /home/vscode
sudo chmod 700 /home/vscode

sudo mkdir -p /var/lib/vscode
sudo chown vscode:vscode /var/lib/vscode
sudo chmod 700 /var/lib/vscode

sudo mkdir -p /var/lib/vscode/.vscode
sudo chown vscode:vscode /var/lib/vscode/.vscode
sudo chmod 700 /var/lib/vscode/.vscode

sudo mkdir -p /var/lib/vscode/data
sudo chown vscode:vscode /var/lib/vscode/data
sudo ln -snf /var/lib/vscode/data /home/vscode/data
sudo chown vscode:vscode /home/vscode/data

sudo mkdir /var/lib/vscode/.vscode/data
sudo chown vscode:vscode /var/lib/vscode/.vscode/data
sudo chmod 700 /var/lib/vscode/.vscode/data
sudo mkdir /var/lib/vscode/.vscode/data/Machine
sudo chown vscode:vscode /var/lib/vscode/.vscode/data/Machine
sudo chmod 700 /var/lib/vscode/.vscode/data/Machine

sudo tee /var/lib/vscode/.vscode/data/Machine/settings.json << 'EOF'
{
    "editor.fontSize": 14,
    "files.autoSave": "afterDelay",
    "files.autoSaveDelay": 200,
}
EOF
sudo chown vscode:vscode /var/lib/vscode/.vscode/data/Machine/settings.json
sudo chmod 644 /var/lib/vscode/.vscode/data/Machine/settings.json

sudo tee /etc/systemd/system/vscode.service << EOF
[Unit]
Description=VS Code web server

[Service]
Type=exec
User=vscode
Group=vscode
WorkingDirectory=/home/vscode
Restart=on-failure
RestartSec=5s
ExecStart=/usr/bin/code serve-web --host 0.0.0.0 --port 8000 --server-data-dir=/var/lib/vscode/.vscode --without-connection-token --accept-server-license-terms
TimeoutStopSec=5s
LimitNOFILE=500000
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
ProtectHostname=true
ProtectKernelTunables=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now pritunl-zero
sudo systemctl enable --now vscode

sudo pritunl-zero upsert service --name=vscode --type=http --role=vscode --domain="$VSCODE_DOMAIN" --server="http://127.0.0.1:8000" --share-session=true --websockets=true --logout-path="/logout"
sudo pritunl-zero upsert certificate --name=pritunl-cert --type=lets_encrypt --acme-domain=$ZERO_DOMAIN --acme-domain=$VSCODE_DOMAIN --acme-type=http
sudo pritunl-zero upsert node --name=self --management=true --proxy=true --management-domain=$ZERO_DOMAIN --webauthn-domain=$ROOT_DOMAIN --add-certificate=pritunl-cert --add-service=vscode
sudo pritunl-zero upsert policy --name=pritunl-zero --role=vscode --add-service=vscode
sudo pritunl-zero upsert user --name=pritunl --role=vscode
sudo pritunl-zero default-password

DNS CNAME Verification

Lets Encrypt DNS CNAME verification can be used if the server is going to run on a private network or is configured so that the Lets Encrypt servers are unable to access port 80 on the Pritunl Zero server. To do this replace the last section of the script above with the commands below. This example uses Cloudflare but AWS Router 53 and Oracle Cloud DNS are also supported. Set CLOUDFLARE_SECRET to the Cloudflare token to access the DNS API for that domain zone. This will allow the Pritunl Zero server to create CNAME records to complete the Lets Encrypt certificate verification.

VS Code Web

Open the $VSCODE_DOMAIN and login with the default password shown in the previous step. Then click open folder and select the /home/vscode/data directory. This then provides a web based vscode with authentication.

Last updated