feat(wechat): native nixpkgs package with app-scoped data (#492)

Switch to the native deb package from nixpkgs-patched (#560225), remove the AppImage/FHS bwrap layer, and enable native Wayland while keeping the X11 fallback.

Keep only WeChat state under one app-scoped HOME and bind the host Documents and Downloads directories like the other desktop apps. User-selected files also go through the XDG FileChooser portal. Remove the launcher, activation script, and compatibility symlinks.

Assisted-by: DeepSeek Harness (deepseek-flash)
This commit is contained in:
ryan4yin | 二花 authored and GitHub committed 2026-11-01 00:09:27 +08:00
1 parent 30cb22500f
commit ccffddc864
14 files changed
+49 -220

No files matched your search

+13 -13
View File
@@ -16,17 +16,17 @@ obsolete workarounds get rolled back instead of lingering.
A version or revision pinned for a reason that can go away.
| ID | What & where | Why | Removal condition | Added | Revisit | Status |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------- | -------------------------- | ------ |
| WA-001 | smartctl_exporter pinned to upstream `6274decc`, which carries PR [#329](https://github.com/prometheus-community/smartctl_exporter/pull/329) — `overlays/smartctl-exporter/` | `/metrics` returns HTTP 500 once a device becomes readable after startup ([#305](https://github.com/prometheus-community/smartctl_exporter/issues/305), [#326](https://github.com/prometheus-community/smartctl_exporter/issues/326)) | Drop once nixpkgs provides a version containing the #329 fix | 2026-10-03 | next nixpkgs bump | active |
| WA-004 | `catppuccin` on `main` — `flake.nix` | `main` carries the nodejs→nodejs-slim deprecation fix, which is not in a release | Switch to a release tag once it includes the fix | 2026-09-25 | on catppuccin release | active |
| WA-005 | `tuios` input — `flake.nix`; `home/base/tui/tuios/` | nixpkgs lags behind upstream | Use nixpkgs' `tuios` once it is recent enough | 2026-10-03 | on nixpkgs bump | active |
| WA-006 | `nixpkgs-blender` — `flake.nix` | Blender 5.2 LTS + CUDA/OptiX pin; keeps `just up` from triggering a full source rebuild | Bump deliberately when needed; drop the pin if the current nixpkgs build is acceptable | 2026-07-24 | deliberate | active |
| WA-007 | WeChat from `nixpkgs-master` — `hardening/bwraps/default.nix` | newest builds; the pinned channel lags | Fall back to the stable channel once it has a good build | 2026-10-03 | on nixpkgs bump | active |
| WA-020 | `fcitx5-vinput` pinned to release tag `v2.4.2` — `flake.nix`; consumer `home/linux/gui/base/vinput/default.nix` | Tracks a release tag instead of a branch, so `just up` stays on that release | Bump to a newer release tag when its changes are wanted | 2026-10-04 | on vinput release | active |
| WA-021 | `nix-x86-on-aarch64` input — our fork of rowanG077's patched FEX + muvm runtime — `flake.nix`; `hosts/12kingdoms-shoukei/game/` | FEX does not support 16K pages, so x86/x86_64 apps and games on shoukei need this pinned flake's 4K-page microVM runtime; our fork lets upstream changes be reviewed before use | Drop once FEX supports 16K pages directly, or nixpkgs/nixos-apple-silicon ships an equivalent runtime | 2026-10-07 | on FEX/nixpkgs/muvm update | active |
| WA-023 | `nix.package = pkgs.nixVersions.latest` — `modules/nixos/base/nix.nix` | NixOS is opted into Nix 2.35 (2.35.2), which nixpkgs ships as `nixVersions.latest`, while `nixVersions.stable` is still 2.34 | Drop the override and fall back to the default `pkgs.nix` once `nixVersions.stable` is 2.35 or newer | 2026-10-07 | next nixpkgs bump | active |
| WA-037 | `nixpkgs-npu` input pinned to `2ddccb854d89` — the `openvino-npu-compiler` branch of `ryan4yin/nixpkgs`, carrying [NixOS/nixpkgs#570230](https://github.com/NixOS/nixpkgs/pull/570230) — `flake.nix`; consumer `pkgs-npu` in `outputs/default.nix`, `hosts/idols-aquamarine/asr.nix` | The Intel NPU compiler, and the driver change that loads it, are unmerged, so the NPU driver the Whisper service needs comes from that branch | Drop the input and load `intel-npu-driver` from `nixos-unstable` once #570230 merges | 2026-10-17 | when #570230 merges | active |
| ID | What & where | Why | Removal condition | Added | Revisit | Status |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------- | ------ |
| WA-001 | smartctl_exporter pinned to upstream `6274decc`, which carries PR [#329](https://github.com/prometheus-community/smartctl_exporter/pull/329) — `overlays/smartctl-exporter/` | `/metrics` returns HTTP 500 once a device becomes readable after startup ([#305](https://github.com/prometheus-community/smartctl_exporter/issues/305), [#326](https://github.com/prometheus-community/smartctl_exporter/issues/326)) | Drop once nixpkgs provides a version containing the #329 fix | 2026-10-03 | next nixpkgs bump | active |
| WA-004 | `catppuccin` on `main` — `flake.nix` | `main` carries the nodejs→nodejs-slim deprecation fix, which is not in a release | Switch to a release tag once it includes the fix | 2026-09-25 | on catppuccin release | active |
| WA-005 | `tuios` input — `flake.nix`; `home/base/tui/tuios/` | nixpkgs lags behind upstream | Use nixpkgs' `tuios` once it is recent enough | 2026-10-03 | on nixpkgs bump | active |
| WA-006 | `nixpkgs-blender` — `flake.nix` | Blender 5.2 LTS + CUDA/OptiX pin; keeps `just up` from triggering a full source rebuild | Bump deliberately when needed; drop the pin if the current nixpkgs build is acceptable | 2026-07-24 | deliberate | active |
| WA-047 | WeChat from `nixpkgs-patched` carrying [NixOS/nixpkgs#560225](https://github.com/NixOS/nixpkgs/pull/560225) — `flake.nix`, `hardening/nixpaks/default.nix` | the PR switches WeChat from the AppImage/FHS wrapper to a native deb package and adds native Wayland support | Drop once #560225 merges (and use the normal nixpkgs package) | 2026-10-31 | on nixpkgs-patched or upstream merges | active |
| WA-020 | `fcitx5-vinput` pinned to release tag `v2.4.2` — `flake.nix`; consumer `home/linux/gui/base/vinput/default.nix` | Tracks a release tag instead of a branch, so `just up` stays on that release | Bump to a newer release tag when its changes are wanted | 2026-10-04 | on vinput release | active |
| WA-021 | `nix-x86-on-aarch64` input — our fork of rowanG077's patched FEX + muvm runtime — `flake.nix`; `hosts/12kingdoms-shoukei/game/` | FEX does not support 16K pages, so x86/x86_64 apps and games on shoukei need this pinned flake's 4K-page microVM runtime; our fork lets upstream changes be reviewed before use | Drop once FEX supports 16K pages directly, or nixpkgs/nixos-apple-silicon ships an equivalent runtime | 2026-10-07 | on FEX/nixpkgs/muvm update | active |
| WA-023 | `nix.package = pkgs.nixVersions.latest` — `modules/nixos/base/nix.nix` | NixOS is opted into Nix 2.35 (2.35.2), which nixpkgs ships as `nixVersions.latest`, while `nixVersions.stable` is still 2.34 | Drop the override and fall back to the default `pkgs.nix` once `nixVersions.stable` is 2.35 or newer | 2026-10-07 | next nixpkgs bump | active |
| WA-037 | `nixpkgs-npu` input pinned to `2ddccb854d89` — the `openvino-npu-compiler` branch of `ryan4yin/nixpkgs`, carrying [NixOS/nixpkgs#570230](https://github.com/NixOS/nixpkgs/pull/570230) — `flake.nix`; consumer `pkgs-npu` in `outputs/default.nix`, `hosts/idols-aquamarine/asr.nix` | The Intel NPU compiler, and the driver change that loads it, are unmerged, so the NPU driver the Whisper service needs comes from that branch | Drop the input and load `intel-npu-driver` from `nixos-unstable` once #570230 merges | 2026-10-17 | when #570230 merges | active |
## Workarounds
@@ -94,7 +94,7 @@ An unfinished feature or gap.
- Security architecture, threat model and audit status: [SECURITY.md](./SECURITY.md).
- Unmerged **nixpkgs** PRs are carried via the `nixpkgs-patched` input and the
[`.agents/skills/nixpkgs-patched`](./.agents/skills/nixpkgs-patched/SKILL.md) workflow (that input
currently carries nothing; package-level carries are recorded under `Pins`).
[`.agents/skills/nixpkgs-patched`](./.agents/skills/nixpkgs-patched/SKILL.md) workflow (currently
WA-047).
- Routine version pins (colmena, agenix, disko, lanzaboote, haumea, home-manager, `nixpkgs-stable`,
`nixpkgs-darwin`, …) are the versions in use, not workarounds, so they are not listed here.
Generated
+3 -3
View File
@@ -939,11 +939,11 @@
},
"nixpkgs-patched": {
"locked": {
"lastModified": 1791048980,
"narHash": "sha256-KgItSKML8Xvte0B7/uGnBDsYzSnnKHcOaiUbgWBXLXw=",
"lastModified": 1793459509,
"narHash": "sha256-S1TWTifxgaWpjRxLGOvHslwFuul3z2SYycgzUmuKSks=",
"owner": "ryan4yin",
"repo": "nixpkgs",
"rev": "a7868a727837f3c09cee2ce0ca671c76b1589fed",
"rev": "30ed98991ef49fd51239d9edbd0602ddddd1936d",
"type": "github"
},
"original": {
+3 -3
View File
@@ -28,9 +28,9 @@
};
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-26.05";
# ryan4yin/nixpkgs fork for the `.agents/skills/nixpkgs-patched` workflow. It
# currently carries no patches (see WORKAROUNDS.md), but `pkgs-patched` is
# wired in outputs/default.nix so a temporary carry needs no flake edit.
# ryan4yin/nixpkgs fork for the `.agents/skills/nixpkgs-patched` workflow.
# Carries NixOS/nixpkgs#560225 (WeChat native deb + Wayland support) until
# the PR merges; see WORKAROUNDS.md.
nixpkgs-patched.url = "github:ryan4yin/nixpkgs/nixos-unstable-patched";
# get some latest packages from the master branch
nixpkgs-master.url = "github:nixos/nixpkgs/master";
+7 -6
View File
@@ -27,7 +27,7 @@ explicitly; other files use the document portal. Every app also has private writ
| QQ | Isolated | Personal files, private app state | Media, notifications, tray, MPRIS, idle, accessibility |
| Telegram | Isolated | Personal files, private app state | Media, notifications, tray, MPRIS, idle, accessibility, Ayatana indicators |
| Zoom | Isolated | `~/.zoom`, `zoomus.conf`, `zoom.conf`, Downloads, `Documents/Zoom`, private app state | Media, X11/XWayland, FHS, SNI tray, idle, `/dev/video0-1`, read-only `/sys/class/drm` |
| WeChat | Isolated | `Documents/WeChat_Data`, its HOME mapping and `xwechat_files` link, private app state | Media, X11/xcb, FHS, SNI tray |
| WeChat | Isolated | Documents, Downloads, app-scoped `wechat` data, private app state | Media, Wayland, X11 fallback, SNI tray, file chooser portal |
All browsers get read-only NSS certificates, printing, native notifications and accessibility.
@@ -55,15 +55,16 @@ All browsers get read-only NSS certificates, printing, native notifications and
## Validation
- Passed: `just fmt`, `just test`, `ai-niri` build and `shoukei-niri` eval.
- Deployed on `ai`; interactive startup and tray checks passed for Chrome, Firefox, QQ, Telegram,
Zoom and WeChat.
- Deployed on `ai`; interactive startup and tray checks passed for Chrome, Firefox, QQ, Telegram and
Zoom.
- WeChat uses the native deb package from nixpkgs-patched, with nixpak as the only bwrap layer. The
build passes; interactive Wayland validation is pending.
- Chromium/Chrome: renderer sandbox, mounts, rendering and disposable-profile persistence passed.
Chromium reaches host loopback; Chrome cannot.
- Firefox: disposable headless screenshot passed.
- Brave/Edge: renderer and permission checks passed; headless page export timed out.
- Evidence: [browsers](tests/browser-runtime.md),
[Firefox/QQ/Telegram](tests/unified-app-runtime.md), [Zoom](tests/zoom-runtime.md),
[WeChat](tests/wechat-runtime.md).
[Firefox/QQ/Telegram](tests/unified-app-runtime.md), [Zoom](tests/zoom-runtime.md).
## Code map
@@ -74,6 +75,6 @@ All browsers get read-only NSS certificates, printing, native notifications and
grants.
- [browser-permissions.nix](nixpaks/modules/browser-permissions.nix),
[chromium-browser.nix](nixpaks/modules/chromium-browser.nix): browser scopes and launcher.
- [bwraps/wechat.nix](bwraps/wechat.nix): WeChat FHS and data setup.
- [nixpaks/wechat.nix](nixpaks/wechat.nix): WeChat package and data setup.
- [kernel-hardening.nix](kernel-hardening.nix), [apparmor/](apparmor/): kernel sysctl and AppArmor
profiles.
-11
View File
@@ -1,11 +0,0 @@
{ pkgs-master, ... }:
{
nixpkgs.overlays = [
(_: super: {
bwraps = {
# Track WeChat from nixpkgs-master, which carries the newest builds.
wechat = super.callPackage ./wechat.nix { wechat = pkgs-master.wechat; };
};
})
];
}
-81
View File
@@ -1,81 +0,0 @@
# - wechat's flatpak manifest: https://github.com/flathub/com.tencent.WeChat/blob/master/com.tencent.WeChat.yaml
# Refer:
# - Flatpak manifest's docs:
# - https://docs.flatpak.org/en/latest/manifests.html
# - https://docs.flatpak.org/en/latest/sandbox-permissions.html
#
# We repack WeChat ourselves because nixpkgs' `wechat` package hardcodes its
# AppImage wrapper args and does not expose them for `.override`, so there is no
# way to add our bubblewrap sandbox (bind mounts, tmpfs /home, IME env) through
# it. We reuse its already-extracted, libtiff-patched AppImage (`wechat.src`),
# so the version and source hash stay maintained by nixpkgs.
# Upstream override support: https://github.com/NixOS/nixpkgs/pull/358977
{
appimageTools,
wechat,
}:
let
pname = "wechat";
# nixpkgs' wechat package already extracted the AppImage and applied the
# libtiff.so.5 fix; reuse it so version/hash stay maintained upstream.
# https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/we/wechat/linux.nix
appimageContents = wechat.src;
in
appimageTools.wrapAppImage {
inherit pname;
inherit (wechat) version;
src = appimageContents;
extraInstallCommands = ''
mkdir -p $out/share/applications
cp ${appimageContents}/wechat.desktop $out/share/applications/
mkdir -p $out/share/pixmaps
cp ${appimageContents}/wechat.png $out/share/pixmaps/
substituteInPlace $out/share/applications/wechat.desktop --replace-fail AppRun wechat
'';
# Prepare the WeChat data dirs before the sandbox starts. The isolation itself
# is the `--tmpfs /home` / `--tmpfs /root` in `extraBwrapArgs` below.
# Adapted from https://aur.archlinux.org/cgit/aur.git/tree/wechat-universal.sh?h=wechat-universal-bwrap
extraPreBwrapCmds = ''
XDG_DOCUMENTS_DIR="''${XDG_DOCUMENTS_DIR:-$(xdg-user-dir DOCUMENTS)}"
if [[ -z "''${XDG_DOCUMENTS_DIR}" ]]; then
echo 'Error: Failed to get XDG_DOCUMENTS_DIR, refuse to continue'
exit 1
fi
WECHAT_DATA_DIR="''${XDG_DOCUMENTS_DIR}/WeChat_Data"
# Using ''${WECHAT_DATA_DIR} as Wechat Data folder
WECHAT_HOME_DIR="''${WECHAT_DATA_DIR}/home"
WECHAT_FILES_DIR="''${WECHAT_DATA_DIR}/xwechat_files"
mkdir -p "''${WECHAT_FILES_DIR}"
mkdir -p "''${WECHAT_HOME_DIR}"
ln -snf "''${WECHAT_FILES_DIR}" "''${WECHAT_HOME_DIR}/xwechat_files"
'';
extraBwrapArgs = [
"--tmpfs /home"
"--tmpfs /root"
# format: --bind <host-path> <sandbox-path>
"--bind \${WECHAT_HOME_DIR} \${HOME}"
"--bind \${WECHAT_FILES_DIR} \${WECHAT_FILES_DIR}"
"--chdir \${HOME}"
# wechat-universal only supports xcb
"--setenv QT_QPA_PLATFORM xcb"
"--setenv QT_AUTO_SCREEN_SCALE_FACTOR 1"
# use fcitx as IME
"--setenv QT_IM_MODULE fcitx"
"--setenv GTK_IM_MODULE fcitx"
];
chdirToPwd = false;
# WeChat needs outbound network; everything else is unshared
unshareNet = false;
unshareIpc = true;
unsharePid = true;
unshareUts = true;
unshareCgroup = true;
privateTmp = true;
}
+2 -1
View File
@@ -1,6 +1,7 @@
{
pkgs,
pkgs-master,
pkgs-patched,
nixpak,
...
}:
@@ -26,7 +27,7 @@ in
brave-origin = wrapper super ./brave-origin.nix;
microsoft-edge = wrapper super ./microsoft-edge.nix;
zoom = wrapper super ./zoom.nix;
wechat = wrapper super ./wechat.nix;
wechat = wrapper pkgs-patched ./wechat.nix;
};
})
];
@@ -27,14 +27,15 @@ in
"org.freedesktop.DBus" = "talk";
"org.kde.StatusNotifierWatcher" = "talk";
}
# SNI name is <pid>-<Qt tray instance ID>; WeChat 4.1.13 uses <pid>-2.
# SNI name is <pid>-<Qt tray instance ID>. The PID is from the nixpak
# namespace and varies with the inner AppImage/FHS startup chain.
// builtins.listToAttrs (
lib.concatMap (
id:
map (
instance: lib.nameValuePair "org.kde.StatusNotifierItem-${toString id}-${toString instance}" "own"
) (lib.range 1 5)
) (lib.range 2 5)
) (lib.range 1 10)
) (lib.range 2 30)
);
})
(lib.mkIf cfg.mpris {
+8 -10
View File
@@ -1,4 +1,4 @@
# The existing FHS layer owns WeChat's HOME remapping and xwechat_files link.
# WeChat data and its sandbox boundary are owned by nixpak.
{
config,
lib,
@@ -34,20 +34,18 @@
"/etc/machine-id"
]
];
# The inner FHS /home reset replaces base XDG mounts with this backing tree.
bind.rw = lib.mkForce [
(sloth.mkdir (sloth.concat' sloth.xdgDocumentsDir "/WeChat_Data"))
(sloth.concat' sloth.runtimeDir "/doc")
[
(sloth.mkdir (sloth.concat' sloth.runtimeDir "/nixpak-${config.flatpak.appId}-tmp"))
"/tmp"
]
bind.rw = [
sloth.xdgDocumentsDir
sloth.xdgDownloadDir
];
env = {
# WeChat keeps .xwechat and xwechat_files under HOME. User-selected
# files also go through the XDG file chooser portal where available.
HOME = lib.mkForce (sloth.concat' sloth.xdgDataHome "/wechat");
DISPLAY = sloth.envOr "DISPLAY" "";
XAUTHORITY = sloth.envOr "XAUTHORITY" (sloth.concat' sloth.homeDir "/.Xauthority");
XDG_DOCUMENTS_DIR = sloth.xdgDocumentsDir;
# The existing pre-FHS script uses mkdir/ln before /usr/bin exists.
XDG_DOWNLOAD_DIR = sloth.xdgDownloadDir;
PATH = lib.makeBinPath [ pkgs.coreutils ];
};
};
+5 -25
View File
@@ -1,6 +1,6 @@
{
lib,
bwraps,
wechat,
mkNixPak,
buildEnv,
makeDesktopItem,
@@ -9,32 +9,12 @@
}:
let
appId = "com.tencent.WeChat";
# As with Zoom, preserve the outer metadata file across the inner FHS layer.
# Keep the existing AppImage runtime and WeChat_Data layout unchanged.
package = bwraps.wechat.overrideAttrs (old: {
# Refuse unexpected layouts before the existing ln -snf can modify them.
extraPreBwrapCmds = ''
wechat_link="''${XDG_DOCUMENTS_DIR}/WeChat_Data/home/xwechat_files"
wechat_files="''${XDG_DOCUMENTS_DIR}/WeChat_Data/xwechat_files"
if [[ -e "$wechat_link" || -L "$wechat_link" ]]; then
if [[ ! -L "$wechat_link" || "$(readlink "$wechat_link")" != "$wechat_files" ]]; then
echo 'WeChat: unexpected xwechat_files layout; refusing to change existing data.' >&2
exit 1
fi
fi
''
+ (old.extraPreBwrapCmds or "");
extraBwrapArgs = (old.extraBwrapArgs or [ ]) ++ [
"--ro-bind /.flatpak-info /.flatpak-info"
# The inner /home reset must not hide an Xauthority file stored there.
''--ro-bind-try "''${XAUTHORITY}" "''${XAUTHORITY}"''
];
});
wrapped = mkNixPak {
config = {
imports = [ ./modules/wechat-policy.nix ];
app = {
inherit package;
package = wechat;
binPath = "bin/wechat";
};
flatpak = { inherit appId; };
@@ -43,7 +23,7 @@ let
exe = lib.getExe wrapped.config.script;
assets = runCommandLocal "wechat-desktop-assets" { } ''
mkdir -p $out/share
ln -s ${package}/share/pixmaps $out/share/pixmaps
ln -s ${wechat}/share/icons $out/share/icons
'';
in
buildEnv {
@@ -58,7 +38,7 @@ buildEnv {
name = "wechat";
desktopName = "WeChat";
exec = "${exe} %U";
icon = "wechat";
icon = "${wechat}/share/icons/hicolor/256x256/apps/wechat.png";
terminal = false;
startupWMClass = "wechat";
categories = [
-58
View File
@@ -1,58 +0,0 @@
# WeChat nested runtime verification
WeChat 4.1.13.26 built and opened a `Weixin` X11 window with a disposable profile. The final
candidate was `/nix/store/6wr94i7da0674k9hzs23fk2nr1ih4i3f-nixpak-wechat-4.1.13.26`. The existing
AppImage extraction, FHS runtime, X11 and fcitx settings remain in `hardening/bwraps/wechat.nix`;
the new nixpak wrapper adds an outer boundary.
The live extracted WeChat binary had three PID namespace identifiers, `NoNewPrivs: 1`, `Seccomp: 0`,
a network namespace different from the host, and `/.flatpak-info` identifying `com.tencent.WeChat`.
Its device view contained standard synthetic devices, `dri`, and the four explicit NVIDIA nodes; no
raw camera, USB or block devices. This smoke test does not establish an internal renderer sandbox
guarantee.
A sentinel in the disposable `Documents/WeChat_Data/home` was readable at WeChat's remapped HOME.
Its `xwechat_files` link retained the absolute target `Documents/WeChat_Data/xwechat_files`, which
remains bound inside both layers. The final launcher also rejected a separate disposable layout
containing a real `home/xwechat_files` directory, exited 1, and preserved its sentinel and contents.
It will not silently migrate an unexpected existing layout.
## Compatibility changes
As with Zoom, the wrapper preserves the outer `/.flatpak-info` file explicitly: the FHS automatic
root mount loop only propagates directories. The inner `--dev-bind /dev /dev` inherits the outer
filtered devices. The original inner network setting inherits pasta's isolated outer namespace,
including its private loopback.
The original inner `/home` reset hides the shared desktop base's XDG mounts. WeChat therefore
exposes its existing backing tree to the outer sandbox and keeps the original FHS HOME mapping. It
supplies `XDG_DOCUMENTS_DIR` and a coreutils-only PATH for the pre-FHS mkdir/link commands.
Xauthority is rebound after the inner HOME reset when present.
The first run aborted in libdbus because no machine ID was available. The WeChat policy supplies a
synthetic app-specific ID rather than the host ID. Login/device identity continuity with an existing
account remains untested. No credentials or real profile were used for this test.
## Historical constraint
Commit `0c7e43a2` removed `nixpaks/wechat-uos.nix`. Its previous TODO said the FHS runtime was
problematic inside another sandbox, but supplied no failure log. That old module also disabled X11
and set `QT_QPA_PLATFORM=kcb`, despite its xcb-only comment. Commit `28dee277` subsequently changed
the AppImage wrapper from Wayland to xcb and added fcitx environment settings. These records do not
prove the original failure's cause. Current runtime testing establishes that retaining FHS inside
nixpak is feasible with the explicit compatibility changes above.
## Repeat safely
Use the same disposable-home command as [Zoom](zoom-runtime.md), with WeChat's output and
executable, and additionally set `XDG_DOCUMENTS_DIR="$wechat_probe_dir/Documents"`. Prepare
`Documents/WeChat_Data/home` and `Documents/WeChat_Data/xwechat_files` beneath that disposable home
before launching. The smoke test stops before QR login and uses no account. Inspect the exact test
PID through `/proc` while the timeout is active; verify that its window and processes disappear
after timeout.
Pending manual checks: existing account persistence, QR/login, fcitx input, notifications/tray,
portal file chooser and selected-file access, downloads, voice/video calls, camera/screencast portal
support and clipboard workflows. Camera and ScreenCast methods are explicit grants; raw capture
devices and the host PipeWire socket are not exposed. X11 retains its display trust limitations, so
portal permission does not imply all capture requires portal consent.
@@ -64,8 +64,8 @@ still reaches the core.
The gateway (`suzi`, not a host in this flake) runs the same config with a fixed set of deltas --
`gateway-config.nu` renders it from the same `sources.yaml` and `policy.yaml`. The gateway uses
nftables TProxy, disables the desktop TUN auto-route, and uses `fake-ip` DNS with `dns.ipv6: false`:
LAN clients receive fake A mappings so mihomo retains the domain for routing and sniffing while their
traffic uses the working IPv4 TProxy path. The gateway withholds AAAA records because LAN IPv6
LAN clients receive fake A mappings so mihomo retains the domain for routing and sniffing while
their traffic uses the working IPv4 TProxy path. The gateway withholds AAAA records because LAN IPv6
transparent handling is unreliable on this gateway. Its output carries the subscriptions and the
private domains, so never commit it; the secret is filled in on the box, not here. Its binary is a
static release build under `/usr/local/bin`, not a package: update it by hand, validate the live
@@ -118,8 +118,8 @@ targets instead of writing a config the core rejects.
- WeChat resolves for itself, but its queries still cross the TUN, so `dns-hijack: any:53` catches
them and the fake-ip table hands the name back to the rules: `mmbiz.qpic.cn` measured DIRECT.
`multimedia.nt.qq.com.cn` stays in `fake-ip-filter` for the same reason. The exclude-process fix
that won clash-verge-rev#1762 is not available here: `hardening/bwraps/wechat.nix` sets
`unsharePid = true` and the sandbox reports uid 0, so no process name resolves.
that won clash-verge-rev#1762 is not available here: nixpak unshares the PID namespace and the
sandbox reports uid 0, so no process name resolves.
- `find-process-mode: off` unless `PROCESS-*` rules or `tun_exclude_process` need it.
- `tun_exclude_address`: a destination that can never be a proxy target should not pay a fake-ip
round trip -- RFC1918, RFC 6598's `100.64.0.0/10` (where Tailscale addresses come from),
@@ -23,7 +23,6 @@ let
"hosts/12kingdoms-${name}"
# nixos hardening
"hardening/nixpaks"
"hardening/bwraps"
])
++ [
{
-1
View File
@@ -24,7 +24,6 @@ let
"hosts/idols-${name}"
# nixos hardening
"hardening/nixpaks"
"hardening/bwraps"
])
++ [
{