diff --git a/webtop/RESEARCH.md b/webtop/RESEARCH.md new file mode 100644 index 0000000..88da4c3 --- /dev/null +++ b/webtop/RESEARCH.md @@ -0,0 +1,26 @@ +# Remote Desktop / Browser Isolation Research: Webtop + +## Conclusion +`linuxserver/webtop` is the recommended solution for providing a persistent, lightweight Linux desktop environment accessible directly through a web browser on a Synology NAS. + +## Comparison Summary + +### 1. `linuxserver/webtop` +* **Architecture**: A Docker container that runs a full Linux desktop environment (like Ubuntu with XFCE) and streams the display to the browser using KasmVNC technology. +* **Best For**: A persistent personal cloud desktop. It acts just like a regular computer; you log in, open apps, leave them running, and come back later. +* **Resource Usage**: Very lightweight compared to a full Virtual Machine, as it shares the NAS's Linux kernel. +* **Key Features**: Pixel-perfect rendering, audio support, clipboard integration, and you can easily install standard Linux applications (LibreOffice, VS Code, Firefox) inside of it. + +### 2. Kasm Workspaces +* **Architecture**: An enterprise orchestration platform that spins up isolated Docker containers dynamically. +* **Best For**: Disposable, temporary sessions. You request a desktop, do your work securely, and when you are done, the container is destroyed entirely. +* **Pros/Cons**: Excellent for extreme security (zero-trust, anti-malware sandboxing) and multi-user scaling, but overkill for a simple personal persistent desktop. (Note: Webtop uses Kasm's display technology under the hood). + +### 3. Apache Guacamole +* **Architecture**: A clientless remote desktop gateway. +* **Best For**: Connecting to *existing* physical machines or fully-virtualized VMs (via RDP, SSH, or VNC) over the web. +* **Pros/Cons**: Guacamole is just the viewing portal; it does not contain an operating system itself. You would need to run a separate heavy VM on the Synology NAS to connect to it. Webtop incorporates the OS directly into the container. + +### 4. Standard Virtual Machines (Synology VMM) +* **Architecture**: Hardware-level virtualization allocating dedicated RAM, CPU threads, and virtual disks to a guest OS. +* **Pros/Cons**: While powerful, it requires high RAM utilization and takes minutes to boot. Webtop boots in seconds and only uses RAM when processes are actively running. diff --git a/webtop/SETUP.md b/webtop/SETUP.md new file mode 100644 index 0000000..ac8dd94 --- /dev/null +++ b/webtop/SETUP.md @@ -0,0 +1,43 @@ +# Service Setup Guide: Webtop + +Webtop provides a full Linux desktop environment (Ubuntu XFCE) directly in your web browser. + +## 1. Pre-Setup (Manual) +### Create Service User +- [ ] **Manual**: Create a local user named `svc-webtop` in Synology DSM (Control Panel > User & Group). +- [ ] **Manual**: Give this user read/write access to the `docker` shared folder. + +### Get User IDs +- [ ] **Manual**: SSH into your NAS and run `sudo synouser --get svc-webtop`. +- [ ] **Confirmed IDs**: Locate the `User ID` (PUID) and `Group ID` (PGID). +- [ ] **Action**: Open `create_webtop_folders.sh` and update the `USER_ID="[PUID]:[PGID]"` line. +- [ ] **Action**: Open `stack.env` and update the `PUID` and `PGID` variables. + +## 2. Infrastructure Setup +### Run Setup Script +- [ ] **Action**: Run the setup script in Dry-Run mode to verify changes: + ```bash + sudo bash create_webtop_folders.sh + ``` +- [ ] **Action**: Apply the folder creation and ownership settings: + ```bash + sudo bash create_webtop_folders.sh --run + ``` +- **What it does**: + - Creates `/volume1/docker/webtop/config` which acts as the persistent home directory (`/config`) for your virtual desktop. + - Sets ownership securely to the `svc-webtop` user so the container process can write to it. + +## 3. Portainer Deployment +### Environment Variables +- [ ] **Action**: Review `stack.env`. You can customize the browser tab name by editing `TITLE`. + +### Deploy Stack +- [ ] **Action**: Create a new stack named `webtop-stack`. +- [ ] **Action**: Upload or paste the environment variables from `stack.env`. +- [ ] **Action**: Paste the content of `docker-compose.portainer.yml` and deploy. +- [ ] **Verification**: Access the Webtop desktop interface at `http://[NAS_IP]:3000`. + +## 4. Post-Setup Notes +1. **Persistent Data**: Everything saved strictly within the virtual `~` or `/config` directory is retained. If you want to access your real NAS files (like your ebooks or movies) from inside this desktop, you can uncomment and map `/volume1/media` in the `docker-compose.portainer.yml` file. +2. **Security Opt**: The `seccomp:unconfined` flag is enabled. This is required to run multi-process modern browsers (like Google Chrome or Firefox) natively *inside* the container without crashing. +3. **Execution User**: Unlike some custom containers, Linuxserver.io images (like Webtop) handle user switching natively inside the container. Do not forcefully apply the `user:` directive in Docker Compose, as it will break the container's boot process which relies on root purely to set permissions before downgrading to the PUID/PGID. diff --git a/webtop/create_webtop_folders.sh b/webtop/create_webtop_folders.sh new file mode 100644 index 0000000..61eecf5 --- /dev/null +++ b/webtop/create_webtop_folders.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# Default to dry-run mode +DRY_RUN=true +if [[ "$1" == "--run" || "$1" == "-r" ]]; then DRY_RUN=false; fi + +if [ "$DRY_RUN" = "true" ]; then + echo "--- DRY RUN MODE ---" + echo "To apply changes, run: sudo bash $0 --run" + echo "--------------------" +fi + +# Configuration +BASE="/volume1/docker/webtop" +# Replace with your actual Synology PUID/PGID for the svc-webtop user +USER_ID="1046:65538" # svc-webtop + +# Helper functions +run_mkdir() { + local path=$1 + if [ -d "$path" ]; then + echo "[OK] Folder exists, no changes will be made: $path" + else + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CREATE] Folder: $path" + else + echo "[EXECUTE] Creating folder: $path" + mkdir -p "$path" + fi + fi +} + +run_chown_recursive() { + local owner=$1; local path=$2 + local uid=${owner%%:*}; local gid=${owner#*:} + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Owner to $owner upon creation: $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target ownership + if find "$path" \( ! -uid "$uid" -o ! -gid "$gid" \) | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Owner to $owner (recursive): $path" + else + echo "[EXECUTE] Setting owner to $owner (recursive): $path" + chown -R "$owner" "$path" + fi + else + echo "[OK] Owner is $owner, no changes will be made: $path" + fi +} + +run_chmod_recursive() { + local mode=$1; local path=$2 + + # Check if folder exists first + if [ ! -d "$path" ]; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL SET] Permissions to $mode upon creation: $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + return + fi + + # Check if any file/folder inside diverges from the target permissions + if find "$path" ! -perm -"$mode" | grep -q .; then + if [ "$DRY_RUN" = "true" ]; then + echo "[WILL CHANGE] Permissions to $mode (recursive): $path" + else + echo "[EXECUTE] Setting permissions to $mode (recursive): $path" + chmod -R "$mode" "$path" + fi + else + echo "[OK] Permissions are $mode, no changes will be made: $path" + fi +} + +# Run tasks +run_mkdir "${BASE}/config" +run_chown_recursive "$USER_ID" "${BASE}" +run_chmod_recursive 750 "${BASE}" + +if [ "$DRY_RUN" = "false" ]; then + echo "Done." +fi diff --git a/webtop/docker-compose.portainer.yml b/webtop/docker-compose.portainer.yml new file mode 100644 index 0000000..e0f60bb --- /dev/null +++ b/webtop/docker-compose.portainer.yml @@ -0,0 +1,29 @@ +version: '3.8' + +services: + webtop: + # Using the Ubuntu base with XFCE desktop environment for a great balance of features and low resource usage + image: lscr.io/linuxserver/webtop:ubuntu-xfce + container_name: webtop + restart: always + # Note on Root Exception: Linuxserver.io images require root privileges at boot to run s6-overlay + # initialization scripts (like setting folder permissions). They internally drop privileges + # down to the ${PUID} and ${PGID} provided in the environment section to run the actual application. + # Therefore, we do NOT use the `user:` directive here. + security_opt: + - seccomp:unconfined # Required for some internal applications (e.g. Chrome inside the container) to function properly + environment: + - PUID=${PUID} + - PGID=${PGID} + - TZ=${TZ} + - TITLE=${TITLE:-Webtop} + volumes: + # Maps the virtual desktop's /config (home directory) to persistent NAS storage + - /volume1/docker/webtop/config:/config:rw + # Optional: You can mount media folders here so you can access your NAS files from inside the virtual desktop + # - /volume1/media:/media:rw + ports: + - "3000:3000" # HTTP Access + # - "3001:3001" # HTTPS Access (Optional, usually handled by a reverse proxy instead) + # shm_size is important for web browsers (like Chrome/Firefox) running inside the container to prevent crashing + shm_size: "1gb" diff --git a/webtop/stack.env b/webtop/stack.env new file mode 100644 index 0000000..e191c27 --- /dev/null +++ b/webtop/stack.env @@ -0,0 +1,9 @@ +# Synology Execution User +# Change these to match the svc-webtop user IDs +PUID=1046 +PGID=65538 +TZ=America/Toronto + +# Webtop Customization +# The text that appears on the browser tab +TITLE=Personal Cloud Desktop