mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:46 +01:00
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:
1 parent
30cb22500f
commit
ccffddc864
14 files changed
+49
-220
No files matched your search
+13
-13
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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
@@ -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.
|
||||
@@ -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; };
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 ];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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"
|
||||
])
|
||||
++ [
|
||||
{
|
||||
|
||||
@@ -24,7 +24,6 @@ let
|
||||
"hosts/idols-${name}"
|
||||
# nixos hardening
|
||||
"hardening/nixpaks"
|
||||
"hardening/bwraps"
|
||||
])
|
||||
++ [
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user