sync: Auto-sync from acg-guru-5070 at 2026-03-19 19:25:24
Synced files: - Session log 2026-03-19 updated (autostart, ScreenConnect, Flarum forum, theme, Node.js) - docs/forum-posts/ recovered from old btrfs home (7 forum post guides) Machine: acg-guru-5070 Timestamp: 2026-03-19 19:25:24 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
100
docs/forum-posts/arch-linux-ext4-home-from-windows-drive.md
Normal file
100
docs/forum-posts/arch-linux-ext4-home-from-windows-drive.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# Guide: Repurpose Old Windows BitLocker Drive as /home on Arch Linux
|
||||
|
||||
## Environment
|
||||
- OS: CachyOS (Arch-based) with btrfs root
|
||||
- Existing /home: btrfs subvolume (@home) on OS drive
|
||||
- Secondary drive: 954GB NVMe with Windows BitLocker partition
|
||||
|
||||
## Goal
|
||||
|
||||
Wipe the old Windows drive and mount it as `/home` on ext4, giving a dedicated large partition for user data separate from the OS.
|
||||
|
||||
## Steps
|
||||
|
||||
### Step 1: Identify the Drive
|
||||
|
||||
```bash
|
||||
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,MODEL
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
nvme0n1 953.9G disk SKHynix_HFS001TEJ9X115N
|
||||
├─nvme0n1p1 4G part vfat /boot
|
||||
└─nvme0n1p2 949.9G part btrfs /root <-- OS drive
|
||||
nvme1n1 953.9G disk SKHynix_HFS001TEJ9X115N
|
||||
├─nvme1n1p1 16M part <-- Windows MSR
|
||||
└─nvme1n1p2 953.9G part BitLocker <-- Target drive
|
||||
```
|
||||
|
||||
### Step 2: Wipe and Partition
|
||||
|
||||
```bash
|
||||
# Wipe all filesystem signatures
|
||||
sudo wipefs -a /dev/nvme1n1
|
||||
|
||||
# Create GPT table with single ext4 partition
|
||||
sudo parted /dev/nvme1n1 --script mklabel gpt mkpart primary ext4 0% 100%
|
||||
|
||||
# Format with label
|
||||
sudo mkfs.ext4 -L home /dev/nvme1n1p1
|
||||
```
|
||||
|
||||
### Step 3: Copy Existing /home
|
||||
|
||||
```bash
|
||||
# Mount new partition temporarily
|
||||
sudo mount /dev/nvme1n1p1 /mnt
|
||||
|
||||
# Copy everything preserving permissions, ACLs, and extended attributes
|
||||
sudo rsync -aAXv /home/ /mnt/
|
||||
|
||||
# Verify
|
||||
ls -la /mnt/yourusername/
|
||||
du -sh /mnt/yourusername/
|
||||
|
||||
# Unmount
|
||||
sudo umount /mnt
|
||||
```
|
||||
|
||||
### Step 4: Get UUID
|
||||
|
||||
```bash
|
||||
sudo blkid /dev/nvme1n1p1
|
||||
# UUID="4143f922-455f-4154-8f87-6df123548916" TYPE="ext4"
|
||||
```
|
||||
|
||||
### Step 5: Update /etc/fstab
|
||||
|
||||
Replace the existing `/home` mount entry. If coming from a btrfs subvolume setup:
|
||||
|
||||
```bash
|
||||
# BEFORE (btrfs subvolume):
|
||||
# UUID=8a8b1d34-... /home btrfs subvol=/@home,defaults,noatime,compress=zstd:1 0 0
|
||||
|
||||
# AFTER (ext4 on new drive):
|
||||
UUID=4143f922-455f-4154-8f87-6df123548916 /home ext4 defaults,noatime 0 2
|
||||
```
|
||||
|
||||
### Step 6: Reboot
|
||||
|
||||
```bash
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
### Step 7: Verify After Reboot
|
||||
|
||||
```bash
|
||||
df -h /home
|
||||
# Should show /dev/nvme1n1p1 mounted at /home with ~938GB available
|
||||
|
||||
mount | grep home
|
||||
# /dev/nvme1n1p1 on /home type ext4 (rw,noatime)
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- The old btrfs `@home` subvolume remains on the OS drive as an automatic backup. You can delete it later with `sudo btrfs subvolume delete /path/to/@home` if you need the space.
|
||||
- ext4 was chosen over btrfs for the /home drive for simplicity and maximum compatibility. If you prefer btrfs features (snapshots, compression), use `mkfs.btrfs` instead.
|
||||
- The `noatime` mount option reduces unnecessary writes by not updating file access timestamps.
|
||||
- Pass `0 2` in fstab (not `0 0`) so fsck runs on boot if needed, but after the root filesystem (which is `0 1`).
|
||||
92
docs/forum-posts/cachyos-tailscale-fix.md
Normal file
92
docs/forum-posts/cachyos-tailscale-fix.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# Fix: Tailscale Health Warnings on CachyOS (Arch) with KDE Plasma
|
||||
|
||||
## Environment
|
||||
- OS: CachyOS (Arch-based), kernel 6.19.7-1-cachyos
|
||||
- DE: KDE Plasma 6 (Wayland)
|
||||
- Tailscale: 1.94.2
|
||||
|
||||
## Problem
|
||||
|
||||
`tailscale status` showed two health warnings:
|
||||
|
||||
```
|
||||
# Health check:
|
||||
# - systemd-resolved and NetworkManager are wired together incorrectly; MagicDNS will probably not work.
|
||||
# - Some peers are advertising routes but --accept-routes is false
|
||||
```
|
||||
|
||||
## Diagnosis
|
||||
|
||||
### Issue 1: Accept Routes
|
||||
Peers (pfSense, NAS) were advertising subnet routes but the machine wasn't accepting them:
|
||||
```bash
|
||||
tailscale status --json | python3 -c "
|
||||
import json,sys
|
||||
d=json.load(sys.stdin)
|
||||
for k,v in d.get('Peer',{}).items():
|
||||
routes = v.get('PrimaryRoutes', [])
|
||||
if routes:
|
||||
print(f\"{v['HostName']}: {routes}\")
|
||||
"
|
||||
# Output: pfSense: ['172.16.0.0/22'], D2TESTNAS: ['192.168.0.0/24']
|
||||
```
|
||||
|
||||
### Issue 2: DNS Wiring
|
||||
```bash
|
||||
resolvectl status
|
||||
# resolv.conf mode: foreign <-- WRONG, should be "stub"
|
||||
|
||||
ls -la /etc/resolv.conf
|
||||
# -rw-r--r-- 1 root root 86 ... <-- regular file, NOT a symlink
|
||||
|
||||
cat /etc/NetworkManager/NetworkManager.conf
|
||||
# Empty - no dns= directive
|
||||
```
|
||||
|
||||
NetworkManager was generating `/etc/resolv.conf` directly instead of going through systemd-resolved. Tailscale needs systemd-resolved to handle MagicDNS (.ts.net) queries.
|
||||
|
||||
## Fix
|
||||
|
||||
### Fix 1: Accept Routes
|
||||
```bash
|
||||
sudo tailscale set --accept-routes
|
||||
```
|
||||
|
||||
### Fix 2: Wire NetworkManager to systemd-resolved
|
||||
|
||||
Step 1 - Tell NetworkManager to use systemd-resolved as DNS backend:
|
||||
```bash
|
||||
sudo tee /etc/NetworkManager/conf.d/dns.conf > /dev/null << 'EOF'
|
||||
[main]
|
||||
dns=systemd-resolved
|
||||
EOF
|
||||
```
|
||||
|
||||
Step 2 - Fix the resolv.conf symlink:
|
||||
```bash
|
||||
sudo ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
|
||||
```
|
||||
|
||||
Step 3 - Restart services:
|
||||
```bash
|
||||
sudo systemctl restart NetworkManager
|
||||
sudo systemctl restart systemd-resolved
|
||||
sudo systemctl restart tailscaled
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
resolvectl status
|
||||
# resolv.conf mode: stub <-- CORRECT
|
||||
|
||||
tailscale status
|
||||
# No health warnings
|
||||
|
||||
ping d2testnas
|
||||
# PING d2testnas.tailea2889.ts.net (100.85.152.90) - MagicDNS working
|
||||
```
|
||||
|
||||
## Why This Happens
|
||||
|
||||
CachyOS (and many Arch installs) ship with both NetworkManager and systemd-resolved active, but NetworkManager isn't configured to delegate DNS to systemd-resolved. It writes `/etc/resolv.conf` directly, bypassing the resolved stub. Tailscale configures its MagicDNS via systemd-resolved's D-Bus API, so if resolved isn't actually handling queries, `.ts.net` names won't resolve.
|
||||
85
docs/forum-posts/esxi8-evaluation-license-reset.md
Normal file
85
docs/forum-posts/esxi8-evaluation-license-reset.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Fix: Reset Expired ESXi 8 Evaluation License via SSH
|
||||
|
||||
## Environment
|
||||
- VMware ESXi 8 (two hosts)
|
||||
- License: Evaluation mode (60-day trial expired)
|
||||
|
||||
## Problem
|
||||
|
||||
ESXi evaluation period expired. The web UI shows license warnings and functionality is restricted. VMs may not auto-start after host reboots.
|
||||
|
||||
```
|
||||
vim-cmd vimsvc/license --show
|
||||
# diagnostic = Evaluation period has expired, please install license.
|
||||
# expirationHours = 0
|
||||
# expirationMinutes = 0
|
||||
```
|
||||
|
||||
## Fix
|
||||
|
||||
### Step 1: Enable SSH (if not already)
|
||||
In ESXi web UI: **Host** → **Actions** → **Services** → **Enable SSH**
|
||||
|
||||
### Step 2: SSH in and Reset
|
||||
|
||||
```bash
|
||||
ssh root@<esxi-host-ip>
|
||||
|
||||
# Remove current license config and restore default
|
||||
rm -r /etc/vmware/license.cfg
|
||||
cp /etc/vmware/.#license.cfg /etc/vmware/license.cfg
|
||||
|
||||
# Restart services to pick up the change
|
||||
/etc/init.d/vpxa restart
|
||||
/etc/init.d/hostd restart
|
||||
```
|
||||
|
||||
**Note:** After restarting hostd, the web UI will be unavailable for 15-30 seconds while it comes back up.
|
||||
|
||||
### Step 3: Verify
|
||||
|
||||
Wait ~15 seconds for hostd to fully start, then:
|
||||
|
||||
```bash
|
||||
vim-cmd vimsvc/license --show
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
serial: 00000-00000-00000-00000-00000
|
||||
vmodl key: eval
|
||||
name: Evaluation Mode
|
||||
total: 1
|
||||
used: 1
|
||||
[evaluation] = License has not been set, evaluation Period in effect.
|
||||
[expirationHours] = 1440
|
||||
[expirationMinutes] = 0
|
||||
[expirationDate] = <60 days from now>
|
||||
```
|
||||
|
||||
## Automation via Expect (for remote execution)
|
||||
|
||||
If you need to script this from a Linux workstation and `sshpass` doesn't work with ESXi's keyboard-interactive auth (common issue), use `expect`:
|
||||
|
||||
```bash
|
||||
# Install expect (Arch)
|
||||
sudo pacman -S expect
|
||||
|
||||
# Run reset
|
||||
expect -c '
|
||||
spawn ssh -o StrictHostKeyChecking=no -o PubkeyAuthentication=no root@192.168.0.122 \
|
||||
"rm -r /etc/vmware/license.cfg && cp /etc/vmware/.#license.cfg /etc/vmware/license.cfg && /etc/init.d/vpxa restart && /etc/init.d/hostd restart"
|
||||
expect "Password:"
|
||||
send "your_password_here\r"
|
||||
expect eof
|
||||
'
|
||||
```
|
||||
|
||||
**Note on sshpass:** ESXi 8 uses `keyboard-interactive` authentication, not `password` auth. `sshpass` fails with exit code 5 even with correct credentials. `expect` handles keyboard-interactive properly.
|
||||
|
||||
## Important Notes
|
||||
|
||||
- This resets the 60-day evaluation timer — it does not provide a permanent license
|
||||
- The reset can be repeated when the evaluation expires again
|
||||
- VMs configured to auto-start should resume normal operation after the license is active
|
||||
- If you have a legitimate license key, apply it via the web UI instead: **Manage** → **Licensing** → **Assign license**
|
||||
142
docs/forum-posts/freepbx17-pjsip-trunk-name-reload-fix.md
Normal file
142
docs/forum-posts/freepbx17-pjsip-trunk-name-reload-fix.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Fix: FreePBX 17 "Undefined array key trunk_name" on fwconsole reload
|
||||
|
||||
## Environment
|
||||
- FreePBX 17 (Sangoma FreePBX Distro)
|
||||
- OS: Debian 12 (bookworm)
|
||||
- Asterisk: PJSIP driver
|
||||
- Trunk: Single PJSIP trunk (FirstDigital)
|
||||
|
||||
## Problem
|
||||
|
||||
`fwconsole reload` fails with:
|
||||
|
||||
```
|
||||
In PJSip.class.php line 504:
|
||||
Undefined array key "trunk_name"
|
||||
```
|
||||
|
||||
This prevents any configuration changes made in the FreePBX GUI from being applied to Asterisk. DIDs, transfers, and other call routing changes silently fail to take effect.
|
||||
|
||||
## Diagnosis
|
||||
|
||||
### The Bug
|
||||
|
||||
The `getAllTrunks()` method in `PJSip.class.php` (line ~1606) uses this SQL query:
|
||||
|
||||
```sql
|
||||
SELECT id, keyword, data FROM pjsip as tech
|
||||
LEFT OUTER JOIN trunks ON (tech.id = trunks.trunkid) OR (tech.id = trunks.trunkid)
|
||||
WHERE trunks.disabled = 'off' OR trunks.disabled IS NULL
|
||||
```
|
||||
|
||||
The `trunks.disabled IS NULL` condition catches rows from the `pjsip` table that have **no matching entry in the `trunks` table** — which includes all **extension** data (extensions 201, 202, 235, etc. are stored in the same `pjsip` table). Extensions don't have a `trunk_name` field, so line 504 crashes:
|
||||
|
||||
```php
|
||||
$tn = $trunk['trunk_name']; // line 504 - crashes for extensions
|
||||
```
|
||||
|
||||
### Additional Issue: Orphaned Trunk Data
|
||||
|
||||
We also found an orphaned trunk in the `pjsip` table:
|
||||
|
||||
```sql
|
||||
SELECT id, keyword, data FROM pjsip WHERE keyword='trunk_name';
|
||||
-- Returns:
|
||||
-- id=1, trunk_name=FirstDigital (valid - exists in trunks table)
|
||||
-- id=2, trunk_name=FirstDigital_SIP (orphan - NO matching entry in trunks table)
|
||||
```
|
||||
|
||||
This orphan was likely created by a partially-deleted trunk configuration.
|
||||
|
||||
### Side Effect: Broken Logging
|
||||
|
||||
We also discovered that `/var/log/asterisk/full` was empty — the logger had no file output configured. This masked the problem since no call errors were being recorded.
|
||||
|
||||
## Fix
|
||||
|
||||
### Step 1: Patch PJSip.class.php
|
||||
|
||||
File location:
|
||||
```
|
||||
/var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php
|
||||
```
|
||||
|
||||
Backup first:
|
||||
```bash
|
||||
cp /var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php \
|
||||
/var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php.bak
|
||||
```
|
||||
|
||||
Replace line 504:
|
||||
```php
|
||||
// BEFORE (line 504):
|
||||
$tn = $trunk['trunk_name'];
|
||||
|
||||
// AFTER:
|
||||
$tn = $trunk['trunk_name'] ?? null; if ($tn === null) { continue; }
|
||||
```
|
||||
|
||||
Using sed:
|
||||
```bash
|
||||
sed -i "504s/.*/\t\t\t\$tn = \$trunk['trunk_name'] ?? null; if (\$tn === null) { continue; }/" \
|
||||
/var/www/html/admin/modules/core/functions.inc/drivers/PJSip.class.php
|
||||
```
|
||||
|
||||
### Step 2: Clean Up Orphaned Trunk Data (if present)
|
||||
|
||||
Check for orphans:
|
||||
```sql
|
||||
-- Run in mysql:
|
||||
SELECT p.id, p.data FROM pjsip p
|
||||
WHERE p.keyword='trunk_name'
|
||||
AND p.id NOT IN (SELECT trunkid FROM trunks);
|
||||
```
|
||||
|
||||
Remove any orphans found:
|
||||
```sql
|
||||
-- Replace '2' with the orphaned ID from the query above
|
||||
DELETE FROM pjsip WHERE id='2';
|
||||
```
|
||||
|
||||
### Step 3: Restore Asterisk Logging
|
||||
|
||||
If `/var/log/asterisk/full` is empty and `logger show channels` shows no file output:
|
||||
|
||||
```bash
|
||||
echo 'full => notice,warning,error,verbose,dtmf,fax' > /etc/asterisk/logger_logfiles_custom.conf
|
||||
```
|
||||
|
||||
### Step 4: Reload
|
||||
|
||||
```bash
|
||||
fwconsole reload
|
||||
# Should output: Reload Complete (no errors)
|
||||
```
|
||||
|
||||
Verify logging:
|
||||
```bash
|
||||
asterisk -rx "logger show channels"
|
||||
# Should show: /var/log/asterisk/full File default Enabled
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
# Reload should succeed cleanly
|
||||
fwconsole reload
|
||||
# Output: Reload Started / Reload Complete
|
||||
|
||||
# Asterisk should be logging
|
||||
wc -l /var/log/asterisk/full
|
||||
# Should be non-zero and growing
|
||||
|
||||
# Trunk should be connected
|
||||
asterisk -rx "pjsip show endpoint <trunk_name>"
|
||||
# Contact status should show "Avail"
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **This patch will be overwritten on FreePBX module updates.** After running `fwconsole ma updateall` or updating the Core module, check if the fix is still in place.
|
||||
- The root cause is a bug in FreePBX's `getAllTrunks()` SQL query that doesn't properly filter extensions from trunk data. An upstream fix would modify the query to use `INNER JOIN` or add a `WHERE` clause filtering on `pjsip.keyword = 'trunk_name'`.
|
||||
- The orphaned trunk data suggests a trunk was deleted through the GUI but the `pjsip` table wasn't fully cleaned up — a separate FreePBX bug.
|
||||
73
docs/forum-posts/kde-plasma-brightness-nvidia-intel-fix.md
Normal file
73
docs/forum-posts/kde-plasma-brightness-nvidia-intel-fix.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Fix: KDE Plasma Brightness Stuck at ~20% on Intel/NVIDIA Hybrid Laptop
|
||||
|
||||
## Environment
|
||||
- OS: CachyOS (Arch-based), kernel 6.19.7-1-cachyos
|
||||
- DE: KDE Plasma 6
|
||||
- GPU: Intel Arrow Lake-S (integrated) + NVIDIA RTX 5070 Ti Mobile
|
||||
- Laptop: ASUS (model with dual NVMe)
|
||||
|
||||
## Problem
|
||||
|
||||
KDE brightness slider showed 100%, but the screen was visibly much dimmer than it should be. Adjusting brightness via hotkeys would make it even dimmer — any hotkey press reset the panel to a dim state.
|
||||
|
||||
## Diagnosis
|
||||
|
||||
Two backlight interfaces exist:
|
||||
|
||||
```bash
|
||||
ls /sys/class/backlight/
|
||||
# intel_backlight nvidia_0
|
||||
|
||||
cat /sys/class/backlight/intel_backlight/brightness
|
||||
# 100
|
||||
cat /sys/class/backlight/intel_backlight/max_brightness
|
||||
# 496
|
||||
|
||||
cat /sys/class/backlight/nvidia_0/brightness
|
||||
# 100
|
||||
cat /sys/class/backlight/nvidia_0/max_brightness
|
||||
# 100
|
||||
|
||||
cat /sys/class/backlight/intel_backlight/type
|
||||
# raw
|
||||
cat /sys/class/backlight/nvidia_0/type
|
||||
# raw
|
||||
```
|
||||
|
||||
**Root cause:** Both backlights report type `raw`, so KDE couldn't distinguish which was the "real" panel backlight. `nvidia_0` has max=100, `intel_backlight` has max=496. When KDE's brightness hotkeys set "100%" via `nvidia_0`'s scale, it wrote `100` to `intel_backlight` — which is only ~20% of its actual 496 range.
|
||||
|
||||
## Fix
|
||||
|
||||
### Immediate Fix
|
||||
Set the correct brightness:
|
||||
```bash
|
||||
sudo sh -c 'echo 496 > /sys/class/backlight/intel_backlight/brightness'
|
||||
```
|
||||
|
||||
### Permanent Fix - Hide nvidia_0 via udev
|
||||
|
||||
Create `/etc/udev/rules.d/backlight.rules`:
|
||||
```bash
|
||||
sudo tee /etc/udev/rules.d/backlight.rules > /dev/null << 'EOF'
|
||||
# Disable nvidia_0 backlight - conflicts with intel_backlight on this laptop
|
||||
# KDE picks up nvidia_0 (max=100) and maps it incorrectly to intel_backlight (max=496)
|
||||
SUBSYSTEM=="backlight", KERNEL=="nvidia_0", ATTR{brightness}="0", RUN+="/bin/chmod 000 /sys/class/backlight/nvidia_0"
|
||||
EOF
|
||||
```
|
||||
|
||||
Apply immediately (without reboot):
|
||||
```bash
|
||||
sudo chmod 000 /sys/class/backlight/nvidia_0
|
||||
sudo udevadm control --reload-rules
|
||||
systemctl --user restart plasma-powerdevil
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
After hiding `nvidia_0`, KDE only sees `intel_backlight` and maps the slider/hotkeys correctly to the 0-496 range. Full brightness is restored and hotkeys work as expected.
|
||||
|
||||
## Why This Happens
|
||||
|
||||
On Intel/NVIDIA hybrid laptops, both GPUs may expose a backlight interface. The NVIDIA driver creates `nvidia_0` even though the actual panel backlight is controlled by `intel_backlight`. Since both report type `raw`, KDE (powerdevil) can pick up the wrong one. The `nvidia_0` interface has a max of 100 — when KDE writes that value to the actual panel controller (max 496), you get ~20% brightness.
|
||||
|
||||
This is most common on newer laptops with Intel Arrow Lake + RTX 40/50 series mobile GPUs running the proprietary NVIDIA driver.
|
||||
131
docs/forum-posts/screenconnect-linux-wayland-fix.md
Normal file
131
docs/forum-posts/screenconnect-linux-wayland-fix.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Fix: ConnectWise ScreenConnect Client on Arch Linux with Wayland
|
||||
|
||||
## Environment
|
||||
- OS: CachyOS (Arch-based), kernel 6.19.x
|
||||
- DE: KDE Plasma 6 (Wayland session)
|
||||
- Java: OpenJDK 25.x
|
||||
- ScreenConnect: Access Host client (Linux .sh installer)
|
||||
|
||||
## Problem
|
||||
|
||||
The ScreenConnect `.sh` installer fails on Arch Linux because it only supports `dpkg` (Debian) and `rpm` (Red Hat) package managers. Even after getting it installed, the client connects but produces no visible window on Wayland desktops.
|
||||
|
||||
There are three separate issues that must be fixed in sequence.
|
||||
|
||||
## Issue 1: Installer Doesn't Work on Arch
|
||||
|
||||
The `ScreenConnect.ClientSetup.sh` installer checks for `dpkg` or `rpm`, neither of which exist on Arch by default. The script contains two embedded installers — "Guest" (uses package managers) and "Host" (self-contained tar.gz). The Guest installer's `exit 0` at line ~557 prevents the Host installer from running if a package manager isn't found.
|
||||
|
||||
**Fix:** Install `dpkg` so the installer's detection logic succeeds:
|
||||
```bash
|
||||
sudo pacman -S dpkg
|
||||
```
|
||||
|
||||
Then run the installer **as your regular user** (not root):
|
||||
```bash
|
||||
~/Downloads/ScreenConnect.ClientSetup.sh
|
||||
```
|
||||
|
||||
**Gotcha:** If you run with `sudo`, it installs to `/root/.local/share/applications/` instead of your home directory. To fix this:
|
||||
```bash
|
||||
sudo mv /root/.local/share/applications/connectwisecontrol-* ~/.local/share/applications/
|
||||
sudo chown -R $USER:$USER ~/.local/share/applications/connectwisecontrol-*
|
||||
```
|
||||
|
||||
The installed location is: `~/.local/share/applications/connectwisecontrol-<hash>/`
|
||||
|
||||
### Alternative: PKGBUILD Approach
|
||||
|
||||
There's a [community PKGBUILD on GitHub](https://github.com/kelderek/connectwisecontrol-arch) that repackages the `.deb` as a proper Arch package with a systemd service. This is a good option if you want pacman-managed installs and `pacman -Rs` uninstallation. However, the simpler `dpkg` approach above works well for the Access Host client.
|
||||
|
||||
## Issue 2: Java Headless — No GUI Support
|
||||
|
||||
The ScreenConnect client is a Java Swing application. CachyOS (and many Arch installs) ships `jre-openjdk-headless` by default, which lacks AWT/Swing libraries.
|
||||
|
||||
**Error in logs** (`~/.local/share/applications/connectwisecontrol-<hash>-logs`):
|
||||
```
|
||||
java.awt.HeadlessException:
|
||||
No X11 DISPLAY variable was set,
|
||||
or no headful library support was found
|
||||
```
|
||||
|
||||
**Fix:** Install the full (headful) JRE:
|
||||
```bash
|
||||
sudo pacman -S --ask 4 jre-openjdk
|
||||
# --ask 4 allows replacing the conflicting headless package
|
||||
```
|
||||
|
||||
## Issue 3: Wayland Incompatibility
|
||||
|
||||
Java AWT/Swing does not support Wayland natively. Even with the full JRE, the ScreenConnect window fails to create on a Wayland session because the Java toolkit can't open an X11 display.
|
||||
|
||||
**Error in logs:**
|
||||
```
|
||||
java.lang.NullPointerException: Cannot invoke "com.screenconnect.client.ScreenFrame.getScreenPanel()"
|
||||
because "this.screenFrame" is null
|
||||
```
|
||||
|
||||
**Fix:** Force X11 (XWayland) backend by patching the launcher script:
|
||||
```bash
|
||||
sed -i '1a export GDK_BACKEND=x11\nexport _JAVA_AWT_WM_NONREPARENTING=1' \
|
||||
~/.local/share/applications/connectwisecontrol-*/ClientLauncher.sh
|
||||
```
|
||||
|
||||
- `GDK_BACKEND=x11` forces the Java process to use XWayland instead of native Wayland
|
||||
- `_JAVA_AWT_WM_NONREPARENTING=1` is recommended by the Arch `jre-openjdk` package for tiling/non-reparenting window managers, and fixes rendering issues on KDE Plasma under Wayland
|
||||
|
||||
## Autostart on Login
|
||||
|
||||
To have ScreenConnect start automatically when you log in, copy the `.desktop` file to your autostart directory:
|
||||
```bash
|
||||
cp ~/.local/share/applications/connectwisecontrol-*.desktop ~/.config/autostart/
|
||||
```
|
||||
|
||||
## Complete Setup (TL;DR)
|
||||
|
||||
```bash
|
||||
# 1. Install dependencies
|
||||
sudo pacman -S dpkg jre-openjdk
|
||||
|
||||
# 2. Run installer as your user (NOT sudo)
|
||||
~/Downloads/ScreenConnect.ClientSetup.sh
|
||||
|
||||
# 3. Patch launcher for Wayland
|
||||
sed -i '1a export GDK_BACKEND=x11\nexport _JAVA_AWT_WM_NONREPARENTING=1' \
|
||||
~/.local/share/applications/connectwisecontrol-*/ClientLauncher.sh
|
||||
|
||||
# 4. Enable autostart
|
||||
cp ~/.local/share/applications/connectwisecontrol-*.desktop ~/.config/autostart/
|
||||
|
||||
# 5. Launch
|
||||
sh ~/.local/share/applications/connectwisecontrol-*/ClientLauncher.sh
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
Check the log file for errors:
|
||||
```bash
|
||||
cat ~/.local/share/applications/connectwisecontrol-*-logs
|
||||
```
|
||||
|
||||
A clean run should show only these non-fatal warnings:
|
||||
```
|
||||
WARNING: A restricted method in java.lang.System has been called
|
||||
WARNING: java.lang.System::loadLibrary has been called by com.screenconnect.Extensions
|
||||
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning
|
||||
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **Updates overwrite the patch.** The `ClientLauncher.sh` Wayland fix will be lost if ScreenConnect updates itself or you reinstall. Reapply the `sed` command after any update.
|
||||
- **Logs location:** `~/.local/share/applications/connectwisecontrol-<hash>-logs`
|
||||
- **Desktop entry:** `~/.local/share/applications/connectwisecontrol-<hash>.desktop`
|
||||
- **Applies to all Arch-based distros** on Wayland: CachyOS, Manjaro, EndeavourOS, etc.
|
||||
- **Applies to all Wayland compositors:** KDE Plasma, GNOME, Sway, Hyprland, etc.
|
||||
|
||||
## What Doesn't Work (Online Suggestions to Avoid)
|
||||
|
||||
- **IcedTea / Java Web Start (JNLP):** Frequently recommended in forums but broken with modern Java versions. Only works for the web viewer, not the persistent Access Host agent.
|
||||
- **Switching to X11 globally:** Works, but defeats the purpose of running Wayland. The per-app `GDK_BACKEND=x11` fix is better.
|
||||
- **Debtap:** Can convert the `.deb` but doesn't create a systemd service or handle the Wayland issue. More steps for the same result.
|
||||
116
docs/forum-posts/tailscale-missing-vlan-subnet-route.md
Normal file
116
docs/forum-posts/tailscale-missing-vlan-subnet-route.md
Normal file
@@ -0,0 +1,116 @@
|
||||
# Fix: Remote VLAN Not Reachable via Tailscale - Missing Subnet Route
|
||||
|
||||
## Environment
|
||||
- Tailscale: 1.94.2
|
||||
- Remote site: Dataforth (192.168.0.0/24 main LAN, 192.168.100.0/24 VLAN100 for phones)
|
||||
- Tailscale exit nodes advertising routes: pfSense-2 (172.16.0.0/22), D2TESTNAS (192.168.0.0/24)
|
||||
- Target: FreePBX PBX at 192.168.100.2 on VLAN100
|
||||
|
||||
## Problem
|
||||
|
||||
A FreePBX phone system at 192.168.100.2 (VLAN100) was unreachable via Tailscale from a remote workstation, even though other devices on the same site's main LAN (192.168.0.0/24) were reachable.
|
||||
|
||||
```bash
|
||||
ping 192.168.0.6 # Works - on main LAN, routed via D2TESTNAS
|
||||
ping 192.168.100.2 # Fails - 100% packet loss
|
||||
```
|
||||
|
||||
## Diagnosis
|
||||
|
||||
Check what subnet routes Tailscale peers are advertising:
|
||||
|
||||
```bash
|
||||
tailscale status --json | python3 -c "
|
||||
import json,sys
|
||||
d=json.load(sys.stdin)
|
||||
for k,v in d.get('Peer',{}).items():
|
||||
routes = v.get('PrimaryRoutes', [])
|
||||
if routes:
|
||||
print(f\"{v['HostName']}: {routes}\")
|
||||
"
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
pfSense-2: ['172.16.0.0/22']
|
||||
D2TESTNAS: ['192.168.0.0/24']
|
||||
```
|
||||
|
||||
**192.168.100.0/24 (VLAN100) is not being advertised by any Tailscale node.** The PBX is on a separate VLAN that no Tailscale peer is routing.
|
||||
|
||||
Also verify the local machine is accepting routes:
|
||||
```bash
|
||||
# Check if --accept-routes is enabled
|
||||
tailscale status
|
||||
# Look for health warning: "Some peers are advertising routes but --accept-routes is false"
|
||||
|
||||
# If present, enable it:
|
||||
sudo tailscale set --accept-routes
|
||||
```
|
||||
|
||||
Check local routing table:
|
||||
```bash
|
||||
ip route | grep 192.168.100
|
||||
# Empty - no route exists
|
||||
```
|
||||
|
||||
## Fix
|
||||
|
||||
The VLAN subnet needs to be advertised by a Tailscale node that has a leg on that network. Two options:
|
||||
|
||||
### Option A: Add Route to Existing Tailscale Node (Recommended)
|
||||
|
||||
On the pfSense or gateway that bridges VLAN100, update the Tailscale advertised routes to include the phone VLAN:
|
||||
|
||||
```bash
|
||||
# On pfSense-2 (or whichever node routes VLAN100):
|
||||
tailscale set --advertise-routes=172.16.0.0/22,192.168.100.0/24
|
||||
```
|
||||
|
||||
Then approve the new route in the Tailscale admin console (if using ACLs) or it auto-approves if `--advertise-routes` auto-approval is enabled.
|
||||
|
||||
### Option B: Add Route to D2TESTNAS (if it has VLAN access)
|
||||
|
||||
If the NAS has a trunk port or tagged VLAN interface for VLAN100:
|
||||
|
||||
```bash
|
||||
# On D2TESTNAS:
|
||||
tailscale set --advertise-routes=192.168.0.0/24,192.168.100.0/24
|
||||
```
|
||||
|
||||
### Option C: Connect Directly to Site WiFi (Workaround)
|
||||
|
||||
If you're physically at the site, connect to the local WiFi network that has routing to VLAN100. This bypasses the need for Tailscale routing entirely.
|
||||
|
||||
```bash
|
||||
# After connecting to Dataforth WiFi:
|
||||
ping 192.168.100.2
|
||||
# Works - local routing handles the VLAN
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
After adding the route:
|
||||
|
||||
```bash
|
||||
# Check the route appears
|
||||
tailscale status --json | python3 -c "
|
||||
import json,sys
|
||||
d=json.load(sys.stdin)
|
||||
for k,v in d.get('Peer',{}).items():
|
||||
routes = v.get('PrimaryRoutes', [])
|
||||
if routes:
|
||||
print(f\"{v['HostName']}: {routes}\")
|
||||
"
|
||||
# Should now show: pfSense-2: ['172.16.0.0/22', '192.168.100.0/24']
|
||||
|
||||
# Test connectivity
|
||||
ping 192.168.100.2
|
||||
# Should respond
|
||||
```
|
||||
|
||||
## Why This Happens
|
||||
|
||||
Tailscale subnet routing is explicit — each subnet that should be reachable via the mesh must be advertised by a node on that network. VLANs are separate broadcast domains, so even though 192.168.0.0/24 and 192.168.100.0/24 are at the same physical site, they require separate route advertisements.
|
||||
|
||||
This is easy to miss when a site has multiple VLANs — the main LAN works fine via Tailscale, but phone VLANs, management VLANs, IoT VLANs, etc. are silently unreachable until explicitly advertised.
|
||||
Reference in New Issue
Block a user