aboutsummaryrefslogtreecommitdiff
path: root/src/desktop-lite/install.sh
diff options
context:
space:
mode:
authorJosh Spicer <josh@joshspicer.com>2022-05-12 23:10:51 +0300
committerGitHub <noreply@github.com>2022-05-12 23:10:51 +0300
commit3a277ad757dbc51a43a5dd452d030c67a49d49f1 (patch)
tree7d4f27493f946d8792b2ff5b6383258cb9f03ce0 /src/desktop-lite/install.sh
parent2707a37ca0d4a45c7487f856bf95f8c5e10bce94 (diff)
restructure and update cli (#11)
* restructure and update cli * typo
Diffstat (limited to 'src/desktop-lite/install.sh')
-rw-r--r--src/desktop-lite/install.sh394
1 files changed, 394 insertions, 0 deletions
diff --git a/src/desktop-lite/install.sh b/src/desktop-lite/install.sh
new file mode 100644
index 0000000..aeddac3
--- /dev/null
+++ b/src/desktop-lite/install.sh
@@ -0,0 +1,394 @@
+#!/usr/bin/env bash
+#-------------------------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
+#-------------------------------------------------------------------------------------------------------------
+#
+# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/desktop-lite.md
+# Maintainer: The VS Code and Codespaces Teams
+#
+# Syntax: ./desktop-lite-debian.sh [non-root user] [Desktop password] [Install web client flag] [VNC port] [Web Port]
+
+USERNAME=${1:-"automatic"}
+VNC_PASSWORD=${2:-"vscode"}
+INSTALL_NOVNC=${3:-"true"}
+VNC_PORT="${4:-5901}"
+NOVNC_PORT="${5:-6080}"
+
+NOVNC_VERSION=1.2.0
+WEBSOCKETIFY_VERSION=0.10.0
+
+package_list="
+ tigervnc-standalone-server \
+ tigervnc-common \
+ fluxbox \
+ dbus-x11 \
+ x11-utils \
+ x11-xserver-utils \
+ xdg-utils \
+ fbautostart \
+ at-spi2-core \
+ xterm \
+ eterm \
+ nautilus\
+ mousepad \
+ seahorse \
+ gnome-icon-theme \
+ gnome-keyring \
+ libx11-dev \
+ libxkbfile-dev \
+ libsecret-1-dev \
+ libgbm-dev \
+ libnotify4 \
+ libnss3 \
+ libxss1 \
+ libasound2 \
+ xfonts-base \
+ xfonts-terminus \
+ fonts-noto \
+ fonts-wqy-microhei \
+ fonts-droid-fallback \
+ htop \
+ ncdu \
+ curl \
+ ca-certificates\
+ unzip \
+ nano \
+ locales"
+
+set -e
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
+ exit 1
+fi
+
+# Determine the appropriate non-root user
+if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
+ USERNAME=""
+ POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
+ for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
+ if id -u ${CURRENT_USER} > /dev/null 2>&1; then
+ USERNAME=${CURRENT_USER}
+ break
+ fi
+ done
+ if [ "${USERNAME}" = "" ]; then
+ USERNAME=root
+ fi
+elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
+ USERNAME=root
+fi
+# Add default Fluxbox config files if none are already present
+fluxbox_apps="$(cat \
+<< 'EOF'
+[transient] (role=GtkFileChooserDialog)
+ [Dimensions] {70% 70%}
+ [Position] (CENTER) {0 0}
+[end]
+EOF
+)"
+
+fluxbox_init="$(cat \
+<< 'EOF'
+session.configVersion: 13
+session.menuFile: ~/.fluxbox/menu
+session.keyFile: ~/.fluxbox/keys
+session.styleFile: /usr/share/fluxbox/styles/qnx-photon
+session.screen0.workspaces: 1
+session.screen0.workspacewarping: false
+session.screen0.toolbar.widthPercent: 100
+session.screen0.strftimeFormat: %a %l:%M %p
+session.screen0.toolbar.tools: RootMenu, clock, iconbar, systemtray
+session.screen0.workspaceNames: One,
+EOF
+)"
+
+fluxbox_menu="$(cat \
+<< 'EOF'
+[begin] ( Application Menu )
+ [exec] (File Manager) { nautilus ~ } <>
+ [exec] (Text Editor) { mousepad } <>
+ [exec] (Terminal) { tilix -w ~ -e $(readlink -f /proc/$$/exe) -il } <>
+ [exec] (Web Browser) { x-www-browser --disable-dev-shm-usage } <>
+ [submenu] (System) {}
+ [exec] (Set Resolution) { tilix -t "Set Resolution" -e bash /usr/local/bin/set-resolution } <>
+ [exec] (Edit Application Menu) { mousepad ~/.fluxbox/menu } <>
+ [exec] (Passwords and Keys) { seahorse } <>
+ [exec] (Top Processes) { tilix -t "Top" -e htop } <>
+ [exec] (Disk Utilization) { tilix -t "Disk Utilization" -e ncdu / } <>
+ [exec] (Editres) {editres} <>
+ [exec] (Xfontsel) {xfontsel} <>
+ [exec] (Xkill) {xkill} <>
+ [exec] (Xrefresh) {xrefresh} <>
+ [end]
+ [config] (Configuration)
+ [workspaces] (Workspaces)
+[end]
+EOF
+)"
+
+# Copy config files if the don't already exist
+copy_fluxbox_config() {
+ local target_dir="$1"
+ mkdir -p "${target_dir}/.fluxbox"
+ touch "${target_dir}/.Xmodmap"
+ if [ ! -e "${target_dir}/.fluxbox/apps" ]; then
+ echo "${fluxbox_apps}" > "${target_dir}/.fluxbox/apps"
+ fi
+ if [ ! -e "${target_dir}/.fluxbox/init" ]; then
+ echo "${fluxbox_init}" > "${target_dir}/.fluxbox/init"
+ fi
+ if [ ! -e "${target_dir}/.fluxbox/menu" ]; then
+ echo "${fluxbox_menu}" > "${target_dir}/.fluxbox/menu"
+ fi
+}
+
+
+# Function to run apt-get if needed
+apt_get_update_if_needed()
+{
+ if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
+ echo "Running apt-get update..."
+ apt-get update
+ else
+ echo "Skipping apt-get update."
+ fi
+}
+
+# Checks if packages are installed and installs them if not
+check_packages() {
+ if ! dpkg -s "$@" > /dev/null 2>&1; then
+ apt_get_update_if_needed
+ apt-get -y install --no-install-recommends "$@"
+ fi
+}
+
+# Ensure apt is in non-interactive to avoid prompts
+export DEBIAN_FRONTEND=noninteractive
+
+apt_get_update_if_needed
+
+# On older Ubuntu, Tilix is in a PPA. on Debian strech its in backports.
+if [[ -z $(apt-cache --names-only search ^tilix$) ]]; then
+ . /etc/os-release
+ if [ "${ID}" = "ubuntu" ]; then
+ apt-get install -y --no-install-recommends apt-transport-https software-properties-common
+ add-apt-repository -y ppa:webupd8team/terminix
+ elif [ "${VERSION_CODENAME}" = "stretch" ]; then
+ echo "deb http://deb.debian.org/debian stretch-backports main" > /etc/apt/sources.list.d/stretch-backports.list
+ fi
+ apt-get update
+ if [[ -z $(apt-cache --names-only search ^tilix$) ]]; then
+ echo "(!) WARNING: Tilix not available on ${ID} ${VERSION_CODENAME} architecture $(uname -m). Skipping."
+ else
+ package_list="${package_list} tilix"
+ fi
+else
+ package_list="${package_list} tilix"
+fi
+
+# Install X11, fluxbox and VS Code dependencies
+check_packages ${package_list}
+
+# Install Emoji font if available in distro - Available in Debian 10+, Ubuntu 18.04+
+if dpkg-query -W fonts-noto-color-emoji > /dev/null 2>&1 && ! dpkg -s fonts-noto-color-emoji > /dev/null 2>&1; then
+ apt-get -y install --no-install-recommends fonts-noto-color-emoji
+fi
+
+# Check at least one locale exists
+if ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then
+ echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
+ locale-gen
+fi
+
+# Install the Cascadia Code fonts - https://github.com/microsoft/cascadia-code
+if [ ! -d "/usr/share/fonts/truetype/cascadia" ]; then
+ curl -sSL https://github.com/microsoft/cascadia-code/releases/download/v2008.25/CascadiaCode-2008.25.zip -o /tmp/cascadia-fonts.zip
+ unzip /tmp/cascadia-fonts.zip -d /tmp/cascadia-fonts
+ mkdir -p /usr/share/fonts/truetype/cascadia
+ mv /tmp/cascadia-fonts/ttf/* /usr/share/fonts/truetype/cascadia/
+ rm -rf /tmp/cascadia-fonts.zip /tmp/cascadia-fonts
+fi
+
+# Install noVNC
+if [ "${INSTALL_NOVNC}" = "true" ] && [ ! -d "/usr/local/novnc" ]; then
+ mkdir -p /usr/local/novnc
+ curl -sSL https://github.com/novnc/noVNC/archive/v${NOVNC_VERSION}.zip -o /tmp/novnc-install.zip
+ unzip /tmp/novnc-install.zip -d /usr/local/novnc
+ cp /usr/local/novnc/noVNC-${NOVNC_VERSION}/vnc.html /usr/local/novnc/noVNC-${NOVNC_VERSION}/index.html
+ curl -sSL https://github.com/novnc/websockify/archive/v${WEBSOCKETIFY_VERSION}.zip -o /tmp/websockify-install.zip
+ unzip /tmp/websockify-install.zip -d /usr/local/novnc
+ ln -s /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION} /usr/local/novnc/noVNC-${NOVNC_VERSION}/utils/websockify
+ rm -f /tmp/websockify-install.zip /tmp/novnc-install.zip
+
+ # Install noVNC dependencies and use them.
+ if ! dpkg -s python3-minimal python3-numpy > /dev/null 2>&1; then
+ apt-get -y install --no-install-recommends python3-minimal python3-numpy
+ fi
+ sed -i -E 's/^python /python3 /' /usr/local/novnc/websockify-${WEBSOCKETIFY_VERSION}/run
+fi
+
+# Set up folders for scripts and init files
+mkdir -p /var/run/dbus /usr/local/etc/vscode-dev-containers/
+
+# Script to change resolution of desktop
+cat << EOF > /usr/local/bin/set-resolution
+#!/bin/bash
+RESOLUTION=\${1:-\${VNC_RESOLUTION:-1920x1080}}
+DPI=\${2:-\${VNC_DPI:-96}}
+IGNORE_ERROR=\${3:-"false"}
+if [ -z "\$1" ]; then
+ echo -e "**Current Settings **\n"
+ xrandr
+ echo -n -e "\nEnter new resolution (WIDTHxHEIGHT, blank for \${RESOLUTION}, Ctrl+C to abort).\n> "
+ read NEW_RES
+ if [ "\${NEW_RES}" != "" ]; then
+ RESOLUTION=\${NEW_RES}
+ fi
+ if ! echo "\${RESOLUTION}" | grep -E '[0-9]+x[0-9]+' > /dev/null; then
+ echo -e "\nInvalid resolution format!\n"
+ exit 1
+ fi
+ if [ -z "\$2" ]; then
+ echo -n -e "\nEnter new DPI (blank for \${DPI}, Ctrl+C to abort).\n> "
+ read NEW_DPI
+ if [ "\${NEW_DPI}" != "" ]; then
+ DPI=\${NEW_DPI}
+ fi
+ fi
+fi
+
+xrandr --fb \${RESOLUTION} --dpi \${DPI} > /dev/null 2>&1
+
+if [ \$? -ne 0 ] && [ "\${IGNORE_ERROR}" != "true" ]; then
+ echo -e "\nFAILED TO SET RESOLUTION!\n"
+ exit 1
+fi
+
+echo -e "\nSuccess!\n"
+EOF
+
+# Container ENTRYPOINT script
+cat << EOF > /usr/local/share/desktop-init.sh
+#!/bin/bash
+
+user_name="${USERNAME}"
+group_name="$(id -gn ${USERNAME})"
+LOG=/tmp/container-init.log
+
+export DBUS_SESSION_BUS_ADDRESS="${DBUS_SESSION_BUS_ADDRESS:-"autolaunch:"}"
+export DISPLAY="${DISPLAY:-:1}"
+export VNC_RESOLUTION="${VNC_RESOLUTION:-1440x768x16}"
+export LANG="${LANG:-"en_US.UTF-8"}"
+export LANGUAGE="${LANGUAGE:-"en_US.UTF-8"}"
+
+# Execute the command it not already running
+startInBackgroundIfNotRunning()
+{
+ log "Starting \$1."
+ echo -e "\n** \$(date) **" | sudoIf tee -a /tmp/\$1.log > /dev/null
+ if ! pidof \$1 > /dev/null; then
+ keepRunningInBackground "\$@"
+ while ! pidof \$1 > /dev/null; do
+ sleep 1
+ done
+ log "\$1 started."
+ else
+ echo "\$1 is already running." | sudoIf tee -a /tmp/\$1.log > /dev/null
+ log "\$1 is already running."
+ fi
+}
+
+# Keep command running in background
+keepRunningInBackground()
+{
+ (\$2 bash -c "while :; do echo [\\\$(date)] Process started.; \$3; echo [\\\$(date)] Process exited!; sleep 5; done 2>&1" | sudoIf tee -a /tmp/\$1.log > /dev/null & echo "\$!" | sudoIf tee /tmp/\$1.pid > /dev/null)
+}
+
+# Use sudo to run as root when required
+sudoIf()
+{
+ if [ "\$(id -u)" -ne 0 ]; then
+ sudo "\$@"
+ else
+ "\$@"
+ fi
+}
+
+# Use sudo to run as non-root user if not already running
+sudoUserIf()
+{
+ if [ "\$(id -u)" -eq 0 ] && [ "\${user_name}" != "root" ]; then
+ sudo -u \${user_name} "\$@"
+ else
+ "\$@"
+ fi
+}
+
+# Log messages
+log()
+{
+ echo -e "[\$(date)] \$@" | sudoIf tee -a \$LOG > /dev/null
+}
+
+log "** SCRIPT START **"
+
+# Start dbus.
+log 'Running "/etc/init.d/dbus start".'
+if [ -f "/var/run/dbus/pid" ] && ! pidof dbus-daemon > /dev/null; then
+ sudoIf rm -f /var/run/dbus/pid
+fi
+sudoIf /etc/init.d/dbus start 2>&1 | sudoIf tee -a /tmp/dbus-daemon-system.log > /dev/null
+while ! pidof dbus-daemon > /dev/null; do
+ sleep 1
+done
+
+# Startup tigervnc server and fluxbox
+sudo rm -rf /tmp/.X11-unix /tmp/.X*-lock
+mkdir -p /tmp/.X11-unix
+sudoIf chmod 1777 /tmp/.X11-unix
+sudoIf chown root:\${group_name} /tmp/.X11-unix
+if [ "\$(echo "\${VNC_RESOLUTION}" | tr -cd 'x' | wc -c)" = "1" ]; then VNC_RESOLUTION=\${VNC_RESOLUTION}x16; fi
+screen_geometry="\${VNC_RESOLUTION%*x*}"
+screen_depth="\${VNC_RESOLUTION##*x}"
+startInBackgroundIfNotRunning "Xtigervnc" sudoUserIf "tigervncserver \${DISPLAY} -geometry \${screen_geometry} -depth \${screen_depth} -rfbport ${VNC_PORT} -dpi \${VNC_DPI:-96} -localhost -desktop fluxbox -fg -passwd /usr/local/etc/vscode-dev-containers/vnc-passwd"
+
+# Spin up noVNC if installed and not runnning.
+if [ -d "/usr/local/novnc" ] && [ "\$(ps -ef | grep /usr/local/novnc/noVNC*/utils/launch.sh | grep -v grep)" = "" ]; then
+ keepRunningInBackground "noVNC" sudoIf "/usr/local/novnc/noVNC*/utils/launch.sh --listen ${NOVNC_PORT} --vnc localhost:${VNC_PORT}"
+ log "noVNC started."
+else
+ log "noVNC is already running or not installed."
+fi
+
+# Run whatever was passed in
+log "Executing \"\$@\"."
+exec "\$@"
+log "** SCRIPT EXIT **"
+EOF
+
+echo "${VNC_PASSWORD}" | vncpasswd -f > /usr/local/etc/vscode-dev-containers/vnc-passwd
+chmod +x /usr/local/share/desktop-init.sh /usr/local/bin/set-resolution
+
+# Set up fluxbox config
+copy_fluxbox_config "/root"
+if [ "${USERNAME}" != "root" ]; then
+ copy_fluxbox_config "/home/${USERNAME}"
+ chown -R ${USERNAME} /home/${USERNAME}/.Xmodmap /home/${USERNAME}/.fluxbox
+fi
+
+cat << EOF
+
+
+You now have a working desktop! Connect to in one of the following ways:
+
+- Forward port ${NOVNC_PORT} and use a web browser start the noVNC client (recommended)
+- Forward port ${VNC_PORT} using VS Code client and connect using a VNC Viewer
+
+In both cases, use the password "${VNC_PASSWORD}" when connecting
+
+(*) Done!
+
+EOF
+