Posts in category “Tutorial”

Apache Guacamole + PopOS RDP 搭建教程

使用 Apache Guacamole 和 PopOS 搭建基于网页浏览器的无客户端远程桌面访问系统的完整指南。

概述

  • Guacamole: 基于 Web 的远程桌面网关(HTML5,无需安装客户端软件)
  • 目标系统: PopOS 配置 xrdp 服务器
  • 访问方式: 任何设备通过浏览器访问
  • 支持协议: RDP、VNC、SSH、Telnet、Kubernetes 连接

1. PopOS RDP 服务器配置

安装和配置 xrdp

# 安装 xrdp(比 GNOME 自带的远程桌面更稳定)
sudo apt update
sudo apt install xrdp

# 启动并设置开机自启
sudo systemctl enable xrdp
sudo systemctl start xrdp

# 验证服务状态
sudo systemctl status xrdp

解决 PolicyKit 权限问题

创建文件 /etc/polkit-1/localauthority/50-local.d/45-allow-colord.pkla

[Allow Colord All Users]
Identity=unix-user:*
Action=org.freedesktop.color-manager.*
ResultAny=no
ResultInactive=no
ResultActive=yes

[Allow PackageKit All Users]
Identity=unix-user:*
Action=org.freedesktop.packagekit.*
ResultAny=no
ResultInactive=no
ResultActive=yes

可选:防火墙配置

# 如果使用 Docker 和局域网 IP,通常不需要开放端口
# 只有需要外部访问时才开放
sudo ufw allow 3389

2. Guacamole Docker 配置

更新的 Docker Compose 配置

services:
  guacdb:
    container_name: guacamoledb
    image: mariadb:10.11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'MariaDBRootPass2024'
      MYSQL_DATABASE: 'guacamole_db'
      MYSQL_USER: 'guacamole_user'
      MYSQL_PASSWORD: 'MariaDBUserPass2024'
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - guacamole-network

  guacd:
    container_name: guacd
    image: guacamole/guacd:1.6.0
    restart: unless-stopped
    devices:
      - /dev/snd:/dev/snd # 映射声音设备
    networks:
      - guacamole-network

  guacamole:
    container_name: guacamole
    image: guacamole/guacamole:1.6.0
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      GUAC_AUDIO: "audio/L16"  # 改用更好的音频格式
      GUAC_AUDIO_RATE: "44100"  # 设置音频采样率
      GUACD_HOSTNAME: "guacd"
      MYSQL_HOSTNAME: "guacdb"
      MYSQL_DATABASE: "guacamole_db"
      MYSQL_USER: "guacamole_user"
      MYSQL_PASSWORD: "MariaDBUserPass2024"
      TOTP_ENABLED: "true"
      WEBAPP_CONTEXT: "ROOT"  # 允许直接通过 http://localhost:8080 访问
    depends_on:
      - guacdb
      - guacd
    networks:
      - guacamole-network

networks:
  guacamole-network:
    driver: bridge

volumes:
  db-data:

数据库初始化

# 1. 创建目录并设置
mkdir guacamole
cd guacamole

# 2. 生成数据库初始化文件
docker run --rm guacamole/guacamole:1.6.0 /opt/guacamole/bin/initdb.sh --mysql > initdb.sql

# 3. 启动服务
docker-compose up -d

# 4. 等待数据库准备就绪
sleep 30

# 5. 导入数据库架构
docker exec -i guacamoledb mysql -u root -pMariaDBRootPass2024 guacamole_db < initdb.sql

# 6. 验证表已创建
docker exec -it guacamoledb mysql -u root -pMariaDBRootPass2024 -e "USE guacamole_db; SHOW TABLES;"

3. Guacamole 配置

初始设置

  1. 访问 Guacamole:http://localhost:8080(注意:没有 /guacamole 后缀!)
  2. 默认登录:guacadmin / guacadmin
  3. 重要:立即更改默认密码

创建 RDP 连接

  1. 前往 设置连接新建连接

  2. 编辑连接

    • 名称:PopOS 桌面(或任意名称)
    • 协议:RDP
  3. 参数

    • 主机名:使用实际局域网 IP(例如:192.168.1.100
    • 端口:3389
    • 用户名:你的 PopOS 用户名
    • 密码:你的 PopOS 密码
  4. 可选设置

    • 安全模式:anyrdp
    • 忽略服务器证书:✓(勾选)
    • 禁用身份验证:✓(如果需要)

Guacamole 代理参数

  • 通常保持空白(主机名、端口、加密字段)
  • 只有在 guacd 运行在不同服务器时才需要配置

4. 关键网络配置说明

⚠️ Docker 网络注意事项

  • 在连接主机名中使用 IP 地址,不要用域名
  • 如果使用 Tailscale/VPN:使用物理网络 IP,不要用 VPN IP
  • 容器 DNS 解析可能指向无法访问的网络
  • Docker 可以通过局域网 IP 访问主机端口,无需防火墙规则

IP 地址查找示例

# 查找你的 PopOS IP
ip addr show | grep "inet 192"
# 在 Guacamole 连接中使用这个 IP,不要用 localhost 或域名

5. 测试

验证 RDP 服务

# 在 PopOS 上测试本地 RDP
telnet localhost 3389

测试 Guacamole 连接

  1. 登录 Guacamole Web 界面
  2. 点击你的连接
  3. 应该能在浏览器中看到 PopOS 桌面

故障排除

常见问题

  • PolicyKit 密码提示:添加上述 polkit 配置
  • 黑屏:在本地popOS上退出登录

调试命令

# 检查 xrdp 状态
sudo systemctl status xrdp

# 检查端口监听
sudo netstat -tlnp | grep 3389

# 检查 Guacamole 日志
docker logs guacamole
docker logs guacd

# 重启 PolicyKit(如果需要)
sudo systemctl restart polkitd
# 或者简单重启
sudo reboot

生产环境增强

Nginx 反向代理(可选)

添加 HTTPS 和自定义域名访问,支持 WebSocket:

server {
    listen 443 ssl;
    server_name your-domain.com;
    
    location / {
        proxy_pass http://localhost:8080;
        proxy_buffering off;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $http_connection;
        access_log off;
    }
}

性能说明

  • 优秀适用场景:办公工作、编程、系统管理
  • 良好适用场景:局域网内一般桌面使用
  • 不适合场景:高帧率游戏、视频播放
  • 最佳环境:低延迟的本地网络

支持的协议

  • RDP:Windows/Linux 远程桌面
  • VNC:跨平台图形界面访问
  • SSH:终端访问和文件传输
  • Telnet:传统终端协议
  • Kubernetes:容器编排访问

安全考虑

  • 更改 Guacamole 默认密码 (问题不大,有二次验证)
  • 使用 HTTPS(添加反向代理)

实用价值

通过这个配置,你可以:

  • 在任何地方用任何设备(手机、平板、电脑)通过浏览器访问你的桌面
  • 统一的 Web 入口管理所有远程连接
  • 无需在每个设备安装各种客户端软件
  • 搭建个人的"云工作台"

本配置已经在 PopOS 22.04 上通过测试

主要参考来源:

Apache Guacamole + PopOS RDP Setup Tutorial

A quick guide to set up clientless remote desktop access via web browser using Apache Guacamole and PopOS.

Overview

  • Guacamole: Web-based remote desktop gateway (HTML5, no client software needed)
  • Target: PopOS with xrdp server
  • Access: Any device with a web browser
  • Supports: RDP, VNC, SSH, Telnet, Kubernetes connections

1. PopOS RDP Server Setup

Install and Configure xrdp

# Install xrdp (more reliable than GNOME Remote Desktop)
sudo apt update
sudo apt install xrdp

# Start and enable service
sudo systemctl enable xrdp
sudo systemctl start xrdp

# Verify service
sudo systemctl status xrdp
sudo netstat -tlnp | grep 3389

Fix PolicyKit Permission Issues

Create /etc/polkit-1/localauthority/50-local.d/45-allow-colord.pkla:

[Allow Colord All Users]
Identity=unix-user:*
Action=org.freedesktop.color-manager.*
ResultAny=no
ResultInactive=no
ResultActive=yes

[Allow PackageKit All Users]
Identity=unix-user:*
Action=org.freedesktop.packagekit.*
ResultAny=no
ResultInactive=no
ResultActive=yes

Optional: Firewall Configuration

# Usually NOT needed if using Docker with LAN IP
# Only open if external access required
sudo ufw allow 3389

2. Guacamole Docker Setup

Updated Docker Compose Configuration

services:
  guacdb:
    container_name: guacamoledb
    image: mariadb:10.11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: 'MariaDBRootPass2024'
      MYSQL_DATABASE: 'guacamole_db'
      MYSQL_USER: 'guacamole_user'
      MYSQL_PASSWORD: 'MariaDBUserPass2024'
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - guacamole-network

  guacd:
    container_name: guacd
    image: guacamole/guacd:1.6.0
    restart: unless-stopped
    networks:
      - guacamole-network

  guacamole:
    container_name: guacamole
    image: guacamole/guacamole:1.6.0
    restart: unless-stopped
    ports:
      - "8080:8080"
    environment:
      GUACD_HOSTNAME: "guacd"
      MYSQL_HOSTNAME: "guacdb"
      MYSQL_DATABASE: "guacamole_db"
      MYSQL_USER: "guacamole_user"
      MYSQL_PASSWORD: "MariaDBUserPass2024"
      TOTP_ENABLED: "true"
      WEBAPP_CONTEXT: "ROOT"  # Access via http://localhost:8080
    depends_on:
      - guacdb
      - guacd
    networks:
      - guacamole-network

networks:
  guacamole-network:
    driver: bridge

volumes:
  db-data:

Database Initialization (Correct Method)

# 1. Create directory and setup
mkdir guacamole
cd guacamole

# 2. Generate database initialization file
docker run --rm guacamole/guacamole:1.6.0 /opt/guacamole/bin/initdb.sh --mysql > initdb.sql

# 3. Start services
docker-compose up -d

# 4. Wait for database to be ready
sleep 30

# 5. Import database schema (no docker cp needed!)
docker exec -i guacamoledb mysql -u root -pMariaDBRootPass2024 guacamole_db < initdb.sql

# 6. Verify tables created
docker exec -it guacamoledb mysql -u root -pMariaDBRootPass2024 -e "USE guacamole_db; SHOW TABLES;"

3. Guacamole Configuration

Initial Setup

  1. Access Guacamole: http://localhost:8080 (note: no /guacamole suffix!)
  2. Default login: guacadmin / guacadmin
  3. Important: Change default password immediately

Create RDP Connection

  1. Go to SettingsConnectionsNew Connection

  2. Edit Connection:

    • Name: PopOS Desktop (or any name)
    • Protocol: RDP
  3. Parameters:

    • Hostname: Use actual LAN IP (e.g., 192.168.1.100)
    • Port: 3389
    • Username: Your PopOS username
    • Password: Your PopOS password
  4. Optional Settings:

    • Security mode: any or rdp
    • Ignore server certificate: ✓ (check)
    • Disable authentication: ✓ (if needed)

Guacamole Proxy Parameters

  • Usually leave empty (Hostname, Port, Encryption fields)
  • Only configure if guacd runs on different server

4. Critical Network Configuration Notes

⚠️ Docker Networking Gotchas

  • Use IP addresses, not domain names in connection hostname
  • If using Tailscale/VPN: Use physical network IP, not VPN IP
  • Container DNS resolution may point to unreachable networks
  • Docker can access host ports via LAN IP without firewall rules

Example IP Discovery

# Find your PopOS IP
ip addr show | grep "inet 192"
# Use this IP in Guacamole connection, not localhost or domain names

5. Testing

Verify RDP Service

# On PopOS, test local RDP
telnet localhost 3389

Test Guacamole Connection

  1. Login to Guacamole web interface
  2. Click your connection
  3. Should see PopOS desktop in browser

Troubleshooting

Common Issues

  • "Non-numeric character in element length": Version mismatch or network issue
  • "Connection refused": Check xrdp service and firewall
  • PolicyKit password prompts: Add polkit configuration above
  • Black screen: Try different security mode settings
  • Slow performance: Normal on high-latency networks, excellent on LAN

Debug Commands

# Check xrdp status
sudo systemctl status xrdp

# Check port listening
sudo netstat -tlnp | grep 3389

# Check Guacamole logs
docker logs guacamole
docker logs guacd

# Restart PolicyKit (if needed)
sudo systemctl restart polkitd
# Or simply reboot
sudo reboot

Production Enhancements

Nginx Reverse Proxy (Optional)

Add HTTPS and custom domain access:

server {
    listen 443 ssl;
    server_name your-domain.com;
    
    location / {
        proxy_pass http://localhost:8080;
		proxy_buffering off;
		proxy_http_version 1.1;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection $http_connection;
		access_log off;
    }
}

Performance Notes

  • Excellent for: Office work, programming, system administration
  • Good for: General desktop use on LAN
  • Not ideal for: High-framerate gaming, video streaming
  • Best on: Local network with low latency

Supported Protocols

  • RDP: Windows/Linux remote desktop
  • VNC: Cross-platform graphical access
  • SSH: Terminal access with file transfer
  • Telnet: Legacy terminal protocol
  • Kubernetes: Container orchestration access

Security Considerations

  • Change default Guacamole passwords
  • Use HTTPS in production (add reverse proxy)
  • Consider VPN access for external connections
  • Regularly update Docker images
  • PolicyKit configuration limits privilege escalation

Setup tested on PopOS 22.04 with Guacamole 1.6.0 via Docker

Key Sources:

指南:添加 HappyNotes web到手机桌面

很多人不喜欢web app是因为要先打开浏览器再输入相应的网址,然而这一繁琐步骤是可以免去的,你完全可以像使用原生app一样使用web app。 我个人更喜欢web app,因此特意在这里告诉潜在的HappyNotes用户,只需几秒钟,你就能将它固定在手机桌面上,不论看起来还是用起来都像一个真正的移动App。

为什么 Webapp 如此棒

在介绍安装步骤前,我先啰嗦几句为什么 webapp 很酷:

  • 你永远在使用最新版本,无需手动更新
  • 体积小得令人惊讶
  • 跨设备使用,随时随地
  • 不受应用商店审核限制

iPhone 用户安装指南 📱

  1. 在 Safari 浏览器中打开 HappyNotes, 网址 https://happynotes.shukebeta.com
  2. 点击分享按钮(带箭头的方形图标)
  3. 向下滚动,选择"添加到主屏幕"
  4. 给它起个喜欢的名字(比如"HappyNotes")
  5. 点击"添加" - 大功告成!

Android 用户安装指南 🤖

  1. 打开 Chrome 浏览器,进入 HappyNotes, 网址 https://happynotes.shukebeta.com
  2. 点击菜单(三个点)或查找"+"图标
  3. 选择"添加到主屏幕"
  4. 为快捷方式命名
  5. 点击"添加" - 搞定!

现在,你可以直接从主屏幕点击 HappyNotes。随时随地,记你想记!

Howto: Add HappyNotes web to your phone's home screen

Ever wanted to use HappyNotes but thought it seemed complicated? This guide helps you add this webapp to your phone's home screen in just a few seconds, making it feel just like a native app!

Why Webapps Are Actually Amazing

Before we dive into installation, let me share why webapps like HappyNotes are fantastic:

  • Always use the latest version automatically
  • Zero download size (no massive app store downloads!)
  • Work across all devices

For iPhone Users 📱

  1. Open HappyNotes in Safari
  2. Tap the share button (square with an arrow pointing up)
  3. Scroll and select "Add to Home Screen"
  4. Name it as you like (e.g., "HappyNotes")
  5. Tap "Add" - done!

For Android Users 🤖

  1. Open Chrome and navigate to HappyNotes
  2. Tap the menu (three dots) or look for a "+" icon
  3. Choose "Add to Home Screen"
  4. Name your shortcut
  5. Tap "Add" - you're all set!

Pro tip: The icon will look just like a regular app icon. Your friends won't even know the difference! 😉

Now you can tap HappyNotes directly from your home screen, just like any other app. Enjoy seamless, always-updated note-taking wherever you go!

移动介质上的Linux:使用 tmpfs、关闭 atime 以延长 SD 卡或优盘的使用寿命

我有一台老旧的 Asus C100P Chromebook,Google早在几年前就停止了对它的支持。它是32位ARM CPU,因此我没法替它更换BIOS,但我可以在developer mode下启用优盘启动,这样我就能够在优盘或者sd卡运行Linux。

然而,在使用 SD 卡或其他闪存设备作为操作系统存储时,合理管理写入操作至关重要。本文将介绍如何通过使用 tmpfs 文件系统、关闭 atime 来延长设备的使用寿命。

1. 使用 tmpfs

什么是 tmpfs?

tmpfs 是一种基于内存的临时文件系统,具有以下优点:

  • 高速存储: 数据存储在内存中,读写速度极快。
  • 动态大小: 根据实际使用情况动态分配内存,不会固定占用资源。
  • 减少写入: 适合存储临时文件和日志,显著减少对闪存的写入操作。

如何配置 tmpfs

1.1 编辑 /etc/fstab 文件

打开终端并输入:

sudo nano /etc/fstab

添加以下行以创建 tmpfs 挂载点:

tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
tmpfs /var/log tmpfs defaults,noatime,mode=0755 0 0

1.2 挂载 tmpfs

保存文件后,运行以下命令使更改生效:

sudo mount -a

1.3 验证挂载

使用以下命令确认 tmpfs 是否成功挂载:

df -h

您应该能看到类似于 /tmp/var/log 的 tmpfs 挂载点。

1.4 设置自动复制日志到 tmpfs

为了在系统启动时自动将日志复制到 tmpfs,我们需要修改 /etc/rc.local 文件:

a. 创建一个目录来存储持久化的日志:

sudo mkdir -p /var/log.hdd
sudo cp -a /var/log/* /var/log.hdd/

b. 编辑 /etc/rc.local 文件:

sudo nano /etc/rc.local

c. 在文件中添加以下内容:

#!/bin/sh -e
# 复制日志文件到 tmpfs
cp -a /var/log.hdd/* /var/log/
exit 0

d. 确保 rc.local 文件具有执行权限:

sudo chmod +x /etc/rc.local

2. 关闭 atime

atime (访问时间) 是文件系统的一个属性,每次访问文件时都会更新。关闭 atime 可以减少不必要的写入操作,从而延长 SD 卡的寿命。

如何关闭 atime

2.1 编辑 /etc/fstab 文件

打开 /etc/fstab 文件:

sudo nano /etc/fstab

2.2 修改挂载选项

找到 SD 卡对应的挂载项(通常是根分区 /),在挂载选项中添加 noatime:

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx / ext4 defaults,noatime 0 1

2.3 重新挂载文件系统

保存文件后,使用以下命令重新挂载文件系统:

sudo mount -o remount /

请记住,虽然这些方法可以有效延长 SD 卡的使用寿命,但仍然建议定期备份重要数据,以防意外发生。毕竟备份不做,十恶不赦!

又:

mode=1777 中的 1 表示设置了"粘滞位"(sticky bit)。具体含义如下:

  1. 777 部分:

    • 7: 所有者(owner)有读、写、执行权限
    • 7: 用户组(group)有读、写、执行权限
    • 7: 其他用户(others)有读、写、执行权限
  2. 前面的 1:

    • 表示设置了粘滞位(sticky bit)

粘滞位的作用:

  • 对于目录,当设置了粘滞位时,只有文件的所有者、目录的所有者或 root 用户才能删除或重命名该目录中的文件。
  • 这通常用于像 /tmp 这样的公共目录,允许所有用户创建文件,但防止用户删除或修改其他用户的文件。

所以 mode=1777 的含义是:

  • 所有用户都可以在该目录中创建、读取和执行文件(777)
  • 但只有文件所有者和目录所有者可以删除或重命名文件(1)

这种权限设置既保证了目录的共享性,又提供了一定的安全保护,防止用户互相干扰。