Compare commits
10 Commits
1d7df93a94
...
e297e99eb1
| Author | SHA1 | Date | |
|---|---|---|---|
| e297e99eb1 | |||
| 9ce0dd31f3 | |||
| 6e7baa8fd8 | |||
| 7e3f381087 | |||
| 505cd353c8 | |||
| da3ef5d20e | |||
| 901a3b6073 | |||
| 7c0816019b | |||
| d802c80053 | |||
| c5d557ba2d |
42
gitea/SETUP.md
Normal file
42
gitea/SETUP.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Service Setup Guide: Gitea
|
||||
|
||||
Gitea is a painless self-hosted Git service covering the entire software development lifecycle.
|
||||
|
||||
## 1. Pre-Setup (Manual)
|
||||
### Create Service User
|
||||
- [ ] **Manual**: Create a local user named `svc-gitea` 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-gitea`.
|
||||
- [ ] **Confirmed IDs**: Locate the `User ID` (PUID) and `Group ID` (PGID).
|
||||
- [ ] **Action**: Open `create_gitea_folders.sh` and update the `USER_ID="[PUID]:[PGID]"` line.
|
||||
- [ ] **Action**: Open `stack.env` and update the `USER_UID` and `USER_GID` variables.
|
||||
|
||||
## 2. Infrastructure Setup
|
||||
### Run Setup Script
|
||||
- [ ] **Action**: Run the setup script in Dry-Run mode to verify changes:
|
||||
```bash
|
||||
sudo bash create_gitea_folders.sh
|
||||
```
|
||||
- [ ] **Action**: Apply the folder creation and ownership settings:
|
||||
```bash
|
||||
sudo bash create_gitea_folders.sh --run
|
||||
```
|
||||
|
||||
## 3. Portainer Deployment
|
||||
### Environment Variables
|
||||
- [ ] **Action**: Review `stack.env`. Ensure `DOMAIN` and `ROOT_URL` exactly match the Cloudflare configuration (e.g., `gitea.chengs.uk`) to prevent the mismatch security error.
|
||||
|
||||
### Deploy Stack
|
||||
- [ ] **Action**: Create a new stack named `gitea-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 Gitea web interface at `http://[NAS_IP]:3001` (or whatever HTTP port you defined).
|
||||
|
||||
## 4. Troubleshooting
|
||||
### ROOT_URL Error Mismatch
|
||||
If you ever see the error:
|
||||
`Your ROOT_URL in app.ini is "http://...", it's unlikely matching the site you are visiting.`
|
||||
|
||||
This means Gitea's security system noticed you are accessing it from a different URL than it was configured for. Ensure the `GITEA__server__DOMAIN` and `GITEA__server__ROOT_URL` environment variables exactly match the public address you use (like a Cloudflare Tunnel domain). This is already permanently fixed via the environment variables in the provided `docker-compose.portainer.yml` file.
|
||||
96
gitea/create_gitea_folders.sh
Normal file
96
gitea/create_gitea_folders.sh
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/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/gitea"
|
||||
# Replace with your actual Synology PUID/PGID for the svc-gitea user
|
||||
# Using 1033 as requested by user
|
||||
USER_ID="1033:65538" # svc-gitea
|
||||
|
||||
# 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}/data"
|
||||
run_mkdir "${BASE}/config"
|
||||
run_chown_recursive "$USER_ID" "${BASE}"
|
||||
run_chmod_recursive 750 "${BASE}"
|
||||
|
||||
if [ "$DRY_RUN" = "false" ]; then
|
||||
echo "Done."
|
||||
fi
|
||||
42
gitea/docker-compose.portainer.yml
Normal file
42
gitea/docker-compose.portainer.yml
Normal file
@@ -0,0 +1,42 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
server:
|
||||
image: docker.gitea.com/gitea:1.25.4-rootless
|
||||
container_name: gitea
|
||||
user: ${USER_UID}
|
||||
environment:
|
||||
- PUID=${USER_UID}
|
||||
- PGID=${USER_GID}
|
||||
- TZ=${TZ}
|
||||
|
||||
# Database Configuration
|
||||
- GITEA__database__DB_TYPE=postgres
|
||||
- GITEA__database__HOST=postgres:5432
|
||||
- GITEA__database__NAME=gitea
|
||||
- GITEA__database__USER=gitea
|
||||
- GITEA__database__PASSWD=0VWXASPz6HaIelby1lWRQ0rJr7gCo14FoHbjSUWxgV
|
||||
|
||||
# Fix for ROOT_URL Domain Check Error
|
||||
- GITEA__server__DOMAIN=${DOMAIN}
|
||||
- GITEA__server__ROOT_URL=${ROOT_URL}
|
||||
- GITEA__server__SSH_PORT=${SSH_PORT}
|
||||
- GITEA__server__HTTP_PORT=3000
|
||||
restart: always
|
||||
networks:
|
||||
- backend-net
|
||||
- frontend-net
|
||||
volumes:
|
||||
- /volume1/docker/gitea/data:/var/lib/gitea:rw
|
||||
- /volume1/docker/gitea/config:/etc/gitea:rw
|
||||
|
||||
ports:
|
||||
# Map the local NAS port to the container's internal 3000 port
|
||||
- "${HTTP_PORT}:3000"
|
||||
- "${SSH_PORT}:22"
|
||||
|
||||
networks:
|
||||
backend-net:
|
||||
external: true
|
||||
frontend-net:
|
||||
external: true
|
||||
15
gitea/stack.env
Normal file
15
gitea/stack.env
Normal file
@@ -0,0 +1,15 @@
|
||||
# Synology Execution User
|
||||
# Change these to match the svc-gitea user IDs
|
||||
USER_UID=1033
|
||||
USER_GID=65538
|
||||
TZ=America/Toronto
|
||||
|
||||
# Gitea Configuration
|
||||
# Ensure this matches your exact Cloudflare tunnel URL
|
||||
DOMAIN=gitea.chengs.uk
|
||||
ROOT_URL=https://gitea.chengs.uk/
|
||||
|
||||
# Local NAS Ports
|
||||
# Set the HTTP port (e.g. 3001 if that's what you were using before)
|
||||
HTTP_PORT=3001
|
||||
SSH_PORT=2222
|
||||
76
vaultwarden/SMTP_PROPOSAL.md
Normal file
76
vaultwarden/SMTP_PROPOSAL.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Vaultwarden SMTP Configuration Proposal
|
||||
**Objective**: Configure Vaultwarden to send transactional emails (invites, 2FA, verifications) using a combination of Cloudflare (for the custom domain `chengs.uk`) and Gmail (as the outbound SMTP provider).
|
||||
|
||||
## Approach Overview
|
||||
Cloudflare provides **Email Routing** (inbound forwarding) but does *not* provide an outbound SMTP service. To send emails using your Gmail account while appearing to come from your custom domain (e.g., `vault@chengs.uk`), we must combine Cloudflare's inbound routing with Gmail's "Send mail as" alias feature and App Passwords.
|
||||
|
||||
Here is the proposed architecture:
|
||||
1. **Cloudflare**: Routes incoming emails for `vault@chengs.uk` to your personal Gmail account.
|
||||
2. **Gmail**: Configured with an "App Password" to allow Vaultwarden to securely authenticate. Gmail is also configured to allow sending *as* `vault@chengs.uk`.
|
||||
3. **Vaultwarden**: Connects to `smtp.gmail.com`, authenticating with your base Gmail credentials, but sending emails from the custom alias.
|
||||
|
||||
---
|
||||
|
||||
## Detailed Manual Steps
|
||||
|
||||
### Phase 1: Cloudflare Setup (Email Routing)
|
||||
*Note: This is required if you want emails to come from `@chengs.uk`. If you simply want them to come from your `@gmail.com` address, you can skip to Phase 2.*
|
||||
1. Log into your **Cloudflare Dashboard** and select your domain (`chengs.uk`).
|
||||
2. Go to **Email** -> **Email Routing** on the left sidebar.
|
||||
3. Click **Get Started** and navigate to the **Routes** tab.
|
||||
4. Create a **Custom Address**:
|
||||
- **Custom address**: `vault` (so the email is `vault@chengs.uk`)
|
||||
- **Action**: `Send to`
|
||||
- **Destination address**: `your-personal-email@gmail.com`
|
||||
5. Cloudflare will send a verification email to your Gmail. Open it and verify the routing.
|
||||
6. Once verified, ensure the Email Routing status shows as active. Cloudflare will automatically add the necessary MX and TXT (SPF) records to your DNS.
|
||||
|
||||
### Phase 2: Gmail Setup (App Password & Alias)
|
||||
Vaultwarden requires a secure way to authenticate with Gmail without using your primary password or requiring web-based 2FA prompts.
|
||||
|
||||
#### Step A: Generate an App Password
|
||||
1. Go to your Google Account management page: [myaccount.google.com](https://myaccount.google.com/).
|
||||
2. Navigate to the **Security** tab.
|
||||
3. Ensure **2-Step Verification** is turned ON (this is a strict requirement for App Passwords).
|
||||
4. Under 2-Step Verification, search for or find the **App passwords** section.
|
||||
5. Provide an App name (e.g., "Vaultwarden NAS") and click **Create**.
|
||||
6. **Save the 16-character password**. You will not see this again. This will be your `SMTP_PASSWORD` for Vaultwarden.
|
||||
|
||||
#### Step B: Add Custom Domain Alias (Optional, for @chengs.uk)
|
||||
If you set up Cloudflare in Phase 1 and want Vaultwarden to send emails *as* `vault@chengs.uk`, you must authorize Gmail to send from this alias:
|
||||
1. Open Gmail on the web and click the **Gear Icon** -> **See all settings**.
|
||||
2. Go to the **Accounts and Import** tab.
|
||||
3. Under "Send mail as", click **Add another email address**.
|
||||
4. Enter the Name (e.g., "Vaultwarden Admin") and Email address (`vault@chengs.uk`). Check "Treat as an alias".
|
||||
5. In the next SMTP step, Google will ask for SMTP details to send *as* this user. Use Gmail's own SMTP servers!
|
||||
- **SMTP Server**: `smtp.gmail.com`
|
||||
- **Port**: `587`
|
||||
- **Username**: `your-personal-email@gmail.com`
|
||||
- **Password**: The **16-character App Password** you generated in Step A.
|
||||
- Select **Secured connection using TLS**.
|
||||
6. Google will send a verification code to `vault@chengs.uk` (which Cloudflare will forward to your Gmail). Enter the code to verify.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Vaultwarden Configuration (`stack.env`)
|
||||
Once the manual steps above are complete, you will update your Vaultwarden `stack.env` file with the following variables so the container can connect to Gmail:
|
||||
|
||||
```env
|
||||
# Vaultwarden Domain (Must exactly match your Cloudflare Tunnel URL)
|
||||
DOMAIN=https://vault.chengs.uk
|
||||
|
||||
# SMTP Configuration
|
||||
SMTP_HOST=smtp.gmail.com
|
||||
SMTP_PORT=587
|
||||
SMTP_SECURITY=starttls
|
||||
SMTP_USERNAME=your-personal-email@gmail.com
|
||||
SMTP_PASSWORD=your-16-character-app-password
|
||||
|
||||
# The From address.
|
||||
# If you completed Phase 1 & 2B, use: vault@chengs.uk
|
||||
# If you skipped them, use: your-personal-email@gmail.com
|
||||
SMTP_FROM=vault@chengs.uk
|
||||
SMTP_FROM_NAME=Vaultwarden Admin
|
||||
```
|
||||
|
||||
After updating these values, you simply re-deploy the Portainer stack to apply the changes.
|
||||
@@ -15,6 +15,7 @@ services:
|
||||
# Email (Optional but recommended for invitations & 2FA)
|
||||
- SMTP_HOST=${SMTP_HOST}
|
||||
- SMTP_FROM=${SMTP_FROM}
|
||||
- SMTP_FROM_NAME=${SMTP_FROM_NAME}
|
||||
- SMTP_SECURITY=${SMTP_SECURITY:-starttls}
|
||||
- SMTP_PORT=${SMTP_PORT:-587}
|
||||
- SMTP_USERNAME=${SMTP_USERNAME}
|
||||
|
||||
@@ -5,18 +5,19 @@ TZ=America/Toronto
|
||||
|
||||
# Vaultwarden Configuration
|
||||
# Replace with your actual NAS IP/domain and https
|
||||
DOMAIN=https://vaultwarden.yourdomain.com
|
||||
DOMAIN=https://vault.chengs.uk
|
||||
|
||||
# SECURITY: Enable signups to create your initial account, then set this to 'false' inside Portainer
|
||||
SIGNUPS_ALLOWED=true
|
||||
|
||||
# Email Configuration (Optional)
|
||||
SMTP_HOST=smtp.yourdomain.com
|
||||
SMTP_HOST=smtp.gmail.com
|
||||
SMTP_FROM=vaultwarden@yourdomain.com
|
||||
SMTP_FROM_NAME=Vaultwarden Admin
|
||||
SMTP_SECURITY=starttls
|
||||
SMTP_PORT=587
|
||||
SMTP_USERNAME=your_username
|
||||
SMTP_PASSWORD=your_password
|
||||
SMTP_USERNAME=jeffcheng.home@gmail.com
|
||||
SMTP_PASSWORD=irlxlnvdpwxdhrex
|
||||
|
||||
# Admin Panel Token (Optional)
|
||||
# IMPORTANT: Do not use plain text! Generate a secure hash by running this command via SSH on your NAS:
|
||||
|
||||
26
webtop/RESEARCH.md
Normal file
26
webtop/RESEARCH.md
Normal file
@@ -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.
|
||||
80
webtop/SETUP.md
Normal file
80
webtop/SETUP.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# 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]:3030`.
|
||||
|
||||
## 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.
|
||||
|
||||
## 5. Security: Cloudflare Zero Trust (Required for Internet Exposure)
|
||||
> [!CAUTION]
|
||||
> The Webtop container gives anyone who accesses it a passwordless root terminal (`sudo`) *within* the container. You **must not** expose this to the public internet (e.g., via Cloudflare Tunnel) without an authentication layer in front of it.
|
||||
|
||||
If you are routing `webtop.chengs.uk` through a Cloudflare Tunnel, follow these steps to secure it with Cloudflare Access. **CRITICAL: Do this BEFORE adding the public hostname to your Cloudflare Tunnel to ensure zero exposure time.**
|
||||
|
||||
1. Go to your **Cloudflare Zero Trust** Dashboard (`one.dash.cloudflare.com`).
|
||||
2. Navigate to **Access** -> **Applications** and click **Add an Application**.
|
||||
3. Choose **Self-hosted**.
|
||||
4. **Application Configuration**:
|
||||
- **Application Name**: Webtop NAS
|
||||
- **Subdomain**: `webtop`
|
||||
- **Domain**: `chengs.uk`
|
||||
5. **Add a Policy**:
|
||||
- **Policy Name**: Allow Admin Only
|
||||
- **Action**: Allow
|
||||
- **Include**: Select **Emails** and type your personal email address (e.g., `your-email@gmail.com`).
|
||||
6. Save the application.
|
||||
|
||||
Now, when you visit `webtop.chengs.uk`, you will be intercepted by a Cloudflare login screen. Cloudflare will email you a one-time pin, verifying your identity before you are allowed to reach the Webtop desktop.
|
||||
|
||||
## 6. Access: Connect the Cloudflare Tunnel
|
||||
Now that the door is locked via the Access Policy, you can safely create the DNS record and route traffic to your NAS.
|
||||
|
||||
1. In the **Cloudflare Zero Trust** Dashboard, go to **Networks** -> **Tunnels**.
|
||||
2. Click on your active NAS tunnel (e.g., `nas-tunnel`) and select **Configure**.
|
||||
3. Go to the **Public Hostname** tab.
|
||||
4. Click **Add a public hostname**.
|
||||
5. **Configuration**:
|
||||
- **Subdomain**: `webtop`
|
||||
- **Domain**: `chengs.uk`
|
||||
- **Service Type**: `HTTP` (The Cloudflare daemon handles the external HTTPS encryption).
|
||||
- **Service URL**: `[YOUR_NAS_LOCAL_IP]:3030` (e.g., `192.168.1.100:3030`).
|
||||
6. Click **Save hostname**.
|
||||
|
||||
Cloudflare will automatically create the DNS record for `webtop.chengs.uk`. You can now navigate to that URL from anywhere in the world to securely access your personal cloud desktop!
|
||||
94
webtop/create_webtop_folders.sh
Normal file
94
webtop/create_webtop_folders.sh
Normal file
@@ -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="1045: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
|
||||
29
webtop/docker-compose.portainer.yml
Normal file
29
webtop/docker-compose.portainer.yml
Normal file
@@ -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:
|
||||
- "3030: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"
|
||||
9
webtop/stack.env
Normal file
9
webtop/stack.env
Normal file
@@ -0,0 +1,9 @@
|
||||
# Synology Execution User
|
||||
# Change these to match the svc-webtop user IDs
|
||||
PUID=1045
|
||||
PGID=65538
|
||||
TZ=America/Toronto
|
||||
|
||||
# Webtop Customization
|
||||
# The text that appears on the browser tab
|
||||
TITLE=Personal Cloud Desktop
|
||||
Reference in New Issue
Block a user