Skip to content

Commit

Permalink
feat(desktop-lite): add desktop-lite feature
Browse files Browse the repository at this point in the history
  • Loading branch information
sjinks committed Aug 12, 2024
1 parent 1678172 commit 892ec2a
Show file tree
Hide file tree
Showing 15 changed files with 393 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/test-features.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
- base
- cron
- cron-control-runner
- desktop-lite
- dev-tools
- elasticsearch
- entrypoints
Expand All @@ -47,6 +48,9 @@ jobs:
- vip-go-mu-plugins
- wp-cli
- wptl
exclude:
- feature: desktop-lite
baseImage: mcr.microsoft.com/devcontainers/base:alpine
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
Expand All @@ -68,6 +72,7 @@ jobs:
test:
- feature: cron
- feature: cron-control-runner
- feature: desktop-lite
- feature: elasticsearch
filter: alpine-base-persist
- feature: elasticsearch
Expand Down
44 changes: 44 additions & 0 deletions features/src/desktop-lite/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"id": "desktop-lite",
"name": "Desktop Lite",
"description": "A lightweight desktop environment for development.",
"version": "1.0.0",
"documentationURL": "https://github.com/Automattic/vip-codespaces/tree/trunk/features/src/desktop-lite",
"containerEnv": {
"DISPLAY": "127.0.0.1:0"
},
"customizations": {
"vscode": {
"settings": {
"playwright.env": {
"DISPLAY": "127.0.0.1:0"
}
}
}
},
"options": {
"enabled": {
"type": "boolean",
"default": true,
"description": "Enable the Desktop Lite feature."
},
"vnc_geometry": {
"type": "string",
"default": "1280x800",
"description": "The geometry of the VNC server."
},
"vnc_password": {
"type": "string",
"default": "vscode",
"description": "The password for the VNC server. The password must be at least six characters long, and only the first eight characters are significant."
},
"install-runit-service": {
"type": "boolean",
"default": true,
"description": "Whether to install a runit service for the Desktop Lite feature."
}
},
"installsAfter": [
"ghcr.io/automattic/vip-codespaces/entrypoints"
]
}
19 changes: 19 additions & 0 deletions features/src/desktop-lite/entrypoint.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin

set -eu

# shellcheck disable=SC2154
HOME_DIR="$(getent passwd "${_REMOTE_USER}" | cut -d: -f6)"
if [ -f "${HOME_DIR}/.vnc/passwd" ]; then
AUTH_OPTS="-rfbauth ${HOME_DIR}/.vnc/passwd"
else
AUTH_OPTS="-SecurityTypes None"
fi

# shellcheck disable=SC2154,SC2086
setpriv --reuid="${_REMOTE_USER}" --regid="${_REMOTE_USER}" --inh-caps=-all --init-groups \
/usr/bin/Xtigervnc -geometry "${VNC_GEOMETRY}" -listen tcp -ac ${AUTH_OPTS} -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -SendCutText -AcceptCutText :0 &
DISPLAY=:0 setpriv --reuid="${_REMOTE_USER}" --regid="${_REMOTE_USER}" --inh-caps=-all --init-groups /usr/bin/openbox &
setpriv --reuid="${_REMOTE_USER}" --regid="${_REMOTE_USER}" --inh-caps=-all --init-groups /usr/local/bin/easy-novnc -a :5800 -h 127.0.0.1 --no-url-password &
129 changes: 129 additions & 0 deletions features/src/desktop-lite/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/bin/sh

set -e

PATH=/usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin

if [ "$(id -u || true)" -ne 0 ]; then
echo 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi

: "${_REMOTE_USER:?"_REMOTE_USER is required"}"
: "${ENABLED:=}"
: "${VNC_GEOMETRY:="1280x800"}"
: "${VNC_PASSWORD:=""}"
: "${INSTALL_RUNIT_SERVICE:=true}"

if [ "${ENABLED}" = "true" ]; then
echo '(*) Installing Lightweight Desktop...'

# shellcheck source=/dev/null
. /etc/os-release

: "${ID:=}"
: "${ID_LIKE:=${ID}}"

case "${ID_LIKE}" in
"debian")
export DEBIAN_FRONTEND=noninteractive
PACKAGES=""

if ! hash curl >/dev/null 2>&1; then
PACKAGES="${PACKAGES} curl"
fi

if ! hash update-ca-certificates >/dev/null 2>&1; then
PACKAGES="${PACKAGES} ca-certificates"
fi

if ! hash openbox >/dev/null 2>&1; then
PACKAGES="${PACKAGES} openbox"
fi

if ! hash obconf >/dev/null 2>&1; then
PACKAGES="${PACKAGES} obconf"
fi

if ! hash Xtigervnc >/dev/null 2>&1; then
PACKAGES="${PACKAGES} tigervnc-standalone-server"
fi

if ! hash tigervncpasswd >/dev/null 2>&1; then
PACKAGES="${PACKAGES} tigervnc-tools"
fi

if ! hash envsubst >/dev/null 2>&1; then
PACKAGES="${PACKAGES} gettext"
fi

if [ -n "${PACKAGES}" ]; then
apt-get update
# shellcheck disable=SC2086
apt-get install -y --no-install-recommends ${PACKAGES}
apt-get clean
rm -rf /var/lib/apt/lists/*

update-rc.d -f dbus remove
fi
;;

*)
echo "(!) Unsupported distribution: ${ID}"
exit 1
;;
esac

HOME_DIR="$(getent passwd "${_REMOTE_USER}" | cut -d: -f6)"
install -d -m 0755 -o "${_REMOTE_USER}" -g "${_REMOTE_USER}" "${HOME_DIR}/.config"
install -d -m 0755 -o "${_REMOTE_USER}" -g "${_REMOTE_USER}" "${HOME_DIR}/.config/openbox"
install -m 0644 -o "${_REMOTE_USER}" -g "${_REMOTE_USER}" menu.xml "${HOME_DIR}/.config/openbox/menu.xml"
install -d -m 0755 -o "${_REMOTE_USER}" -g "${_REMOTE_USER}" "${HOME_DIR}/.vnc"

ARCH="$(arch)"
if [ "${ARCH}" = "arm64" ] || [ "${ARCH}" = "aarch64" ]; then
ARCH="arm"
elif [ "${ARCH}" = "x86_64" ] || [ "${ARCH}" = "amd64" ]; then
ARCH="64bit"
else
echo "(!) Unsupported architecture: ${ARCH}"
exit 1
fi

curl -SL "https://github.com/pgaskin/easy-novnc/releases/download/v1.1.0/easy-novnc_linux-64bit" -o /usr/local/bin/easy-novnc
chmod 0755 /usr/local/bin/easy-novnc

if [ -n "${VNC_PASSWORD}" ]; then
echo "${VNC_PASSWORD}" | tigervncpasswd -f > "${HOME_DIR}/.vnc/passwd"
chmod 0600 "${HOME_DIR}/.vnc/passwd"
chown "${_REMOTE_USER}:${_REMOTE_USER}" "${HOME_DIR}/.vnc/passwd"
fi

if [ -d /var/lib/entrypoint.d ]; then
export VNC_GEOMETRY
# shellcheck disable=SC2016
envsubst '$VNC_GEOMETRY $_REMOTE_USER' < entrypoint.tpl > /var/lib/entrypoint.d/50-desktop-lite
chmod 0755 /var/lib/entrypoint.d/50-desktop-lite
fi

if [ "${INSTALL_RUNIT_SERVICE}" = 'true' ] && [ -d /etc/sv ]; then
install -D -d -m 0755 -o root -g root /etc/service /etc/sv/openbox /etc/sv/novnc /etc/sv/tigervnc
export VNC_GEOMETRY
# shellcheck disable=SC2016
envsubst '$VNC_GEOMETRY $_REMOTE_USER' < service-run.tigervnc.tpl > /etc/sv/tigervnc/run

# shellcheck disable=SC2016
envsubst '$_REMOTE_USER' < service-run.openbox.tpl > /etc/sv/openbox/run

# shellcheck disable=SC2016
envsubst '$_REMOTE_USER' < service-run.novnc.tpl > /etc/sv/novnc/run

chmod 0755 /etc/sv/tigervnc/run /etc/sv/openbox/run /etc/sv/novnc/run

ln -sf /etc/sv/tigervnc /etc/service/tigervnc
ln -sf /etc/sv/openbox /etc/service/openbox
ln -sf /etc/sv/novnc /etc/service/novnc
fi

echo "Done!"
fi
14 changes: 14 additions & 0 deletions features/src/desktop-lite/menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<openbox_menu xmlns="http://openbox.org/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://openbox.org/ file:///usr/share/openbox/menu.xsd">
<menu id="root-menu" label="Openbox 3">
<item label="ObConf">
<action name="Execute"><execute>obconf</execute></action>
</item>
<item label="Reconfigure">
<action name="Reconfigure"/>
</item>
<item label="Restart">
<action name="Restart"/>
</item>
</menu>
</openbox_menu>
10 changes: 10 additions & 0 deletions features/src/desktop-lite/service-run.novnc.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin

set -eu
exec 2>&1

# shellcheck disable=SC2154
exec chpst -u "${_REMOTE_USER}:${_REMOTE_USER}" \
/usr/local/bin/easy-novnc -a :5800 -h 127.0.0.1 --no-url-password
12 changes: 12 additions & 0 deletions features/src/desktop-lite/service-run.openbox.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin

set -eu
exec 2>&1

sv start tigervnc || true

export DISPLAY=:0
# shellcheck disable=SC2154
exec chpst -u "${_REMOTE_USER}:${_REMOTE_USER}" /usr/bin/openbox
18 changes: 18 additions & 0 deletions features/src/desktop-lite/service-run.tigervnc.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

PATH=/bin:/sbin:/usr/bin:/usr/sbin

set -eu
exec 2>&1

# shellcheck disable=SC2154
HOME_DIR="$(getent passwd "${_REMOTE_USER}" | cut -d: -f6)"
if [ -f "${HOME_DIR}/.vnc/passwd" ]; then
AUTH_OPTS="-rfbauth ${HOME_DIR}/.vnc/passwd"
else
AUTH_OPTS="-SecurityTypes None"
fi

# shellcheck disable=SC2154,SC2086
exec chpst -u "${_REMOTE_USER}:${_REMOTE_USER}" \
/usr/bin/Xtigervnc -geometry "${VNC_GEOMETRY}" -listen tcp -ac ${AUTH_OPTS} -AlwaysShared -AcceptKeyEvents -AcceptPointerEvents -SendCutText -AcceptCutText :0
18 changes: 15 additions & 3 deletions features/test/_global/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,9 @@
"wptl": {
"enabled": true,
"version": "latest"
},
"desktop-lite": {
"enabled": true
}
},
"overrideFeatureInstallOrder": [
Expand All @@ -345,7 +348,8 @@
"./phpmyadmin",
"./vip-go-mu-plugins",
"./xdebug",
"./dev-tools"
"./dev-tools",
"./desktop-lite"
]
},
"php82-ubuntu-base": {
Expand Down Expand Up @@ -415,6 +419,9 @@
"wptl": {
"enabled": true,
"version": "latest"
},
"desktop-lite": {
"enabled": true
}
},
"overrideFeatureInstallOrder": [
Expand All @@ -435,7 +442,8 @@
"./vip-go-mu-plugins",
"./xdebug",
"./dev-tools",
"./playwright"
"./playwright",
"./desktop-lite"
]
},
"php83-ubuntu-base": {
Expand Down Expand Up @@ -505,6 +513,9 @@
"wptl": {
"enabled": true,
"version": "latest"
},
"desktop-lite": {
"enabled": true
}
},
"overrideFeatureInstallOrder": [
Expand All @@ -525,7 +536,8 @@
"./vip-go-mu-plugins",
"./xdebug",
"./dev-tools",
"./playwright"
"./playwright",
"./desktop-lite"
]
}
}
37 changes: 37 additions & 0 deletions features/test/desktop-lite/checks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

if hash sv >/dev/null 2>&1; then
check "tigervnc is running" sudo sh -c 'sv status tigervnc | grep -E ^run:'
sudo sv stop tigervnc
check "tigervnc is stopped" sudo sh -c 'sv status tigervnc | grep -E ^down:'
sudo sv start tigervnc
check "tigervnc is running" sudo sh -c 'sv status tigervnc | grep -E ^run:'

check "openbox is running" sudo sh -c 'sv status openbox | grep -E ^run:'
sudo sv stop openbox
check "openbox is stopped" sudo sh -c 'sv status openbox | grep -E ^down:'
sudo sv start openbox
check "openbox is running" sudo sh -c 'sv status openbox | grep -E ^run:'

check "novnc is running" sudo sh -c 'sv status novnc | grep -E ^run:'
sudo sv stop novnc
check "novnc is stopped" sudo sh -c 'sv status novnc | grep -E ^down:'
sudo sv start novnc
check "novnc is running" sudo sh -c 'sv status novnc | grep -E ^run:'
else
check "tigervnc is running" pgrep Xtigervnc
check "openbox is running" pgrep openbox
check "novnc is running" pgrep easy-novnc
fi

if hash netstat >/dev/null 2>&1; then
check "Port 5800 is open" sh -c 'netstat -lnt | grep :5800'
check "Port 5900 is open" sh -c 'netstat -lnt | grep :5900'
check "Port 6000 is open" sh -c 'netstat -lnt | grep :6000'
fi

# Microsoft's base images contain zsh. We don't want to run this check for MS images because we have no control over the installed services.
if test -d /etc/rc2.d && ! test -e /usr/bin/zsh; then
dir="$(ls -1 /etc/rc2.d)"
check "/etc/rc2.d is empty" test -z "${dir}"
fi
1 change: 1 addition & 0 deletions features/test/desktop-lite/debian-latest.sh
Loading

0 comments on commit 892ec2a

Please sign in to comment.