aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--README.md28
-rw-r--r--meta/flatpak.txt1
-rw-r--r--meta/mail.txt5
-rw-r--r--run_onchange_after_deploy-pteid-pkcs11.sh.tmpl61
-rw-r--r--run_onchange_after_deploy-tb-eer.sh.tmpl77
-rw-r--r--run_onchange_after_deploy-thunderbird.sh.tmpl2
6 files changed, 134 insertions, 40 deletions
diff --git a/README.md b/README.md
index b9496c1..906dd71 100644
--- a/README.md
+++ b/README.md
@@ -29,8 +29,8 @@ My Arch Linux configuration, managed with [chezmoi](https://www.chezmoi.io/).
| Bar / launcher | [waybar](https://github.com/Alexays/Waybar), [fuzzel](https://codeberg.org/dnkl/fuzzel) |
| Notifications | [mako](https://github.com/emersion/mako) |
| Lock screen | [swaylock](https://github.com/swaywm/swaylock) |
-| Browser | [LibreWolf](https://librewolf.net/) (Flathub `io.gitlab.librewolf-community` for bubblewrap host-isolation), hardened via `user-overrides.js` + `userChrome.css` (kept under `firefox/` by name for recognizability) |
-| Mail | [Thunderbird](https://www.thunderbird.net/) against [ProtonMail Bridge](https://proton.me/mail/bridge) + Radicale (CalDAV/CardDAV); non-private prefs tracked under `thunderbird/` |
+| Browser | [LibreWolf](https://librewolf.net/) (Flathub `io.gitlab.librewolf-community` for bubblewrap host-isolation), hardened via `user-overrides.js` + `userChrome.css` (kept under `firefox/` by name for recognizability) |
+| Mail | [Thunderbird](https://www.thunderbird.net/) (Flathub `org.mozilla.Thunderbird`) against [ProtonMail Bridge](https://proton.me/mail/bridge) + Radicale (CalDAV/CardDAV); non-private prefs tracked under `thunderbird/` |
| Secrets & identity | [GPG](https://gnupg.org/) (commit signing + SSH auth via gpg-agent), [pass](https://www.passwordstore.org/) |
| Media & viewers | [mpv](https://mpv.io/), [zathura](https://pwmt.org/projects/zathura/), [yazi](https://yazi-rs.github.io/) |
| Code quality | stylua + [selene](https://github.com/Kampfkarren/selene), [shfmt](https://github.com/mvdan/sh) + [shellcheck](https://www.shellcheck.net/), [ruff](https://github.com/astral-sh/ruff), [taplo](https://taplo.tamasfe.dev/), [prettier](https://prettier.io/) — all wired through `just check` |
@@ -75,14 +75,15 @@ chezmoi apply -v
Everything is driven by [just](https://just.systems/) recipes against four parallel models:
-| Directory | Managed by | Purpose |
-| ----------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `dot_*`, `private_dot_*` | chezmoi | Dotfiles deployed to `$HOME`. Prefixes: `dot_` → `.`, `private_` → `0600`, `executable_` → `+x`. |
-| `meta/*.txt` | `just pkg-apply`, `just pkg-status` | Plain-text package lists (one per line, `#` comments). Groups: `base`, `dev`, `wayland`, etc. |
-| `systemd-units/{system,user}/*.txt` | `just unit-apply`, `just unit-status` | Units to enable, split by scope. `system/` files pair by name with `meta/` groups (`system/base.txt` ↔ `meta/base.txt`); `user/` files are standalone. Recipe group token: `<name>` / `system:<name>` / `user:<name>`. |
-| `etc/` | `run_onchange_after_deploy-etc.sh.tmpl` | System-level configs deployed to `/etc/` via a chezmoi onchange hook. |
-| `firefox/` | `run_onchange_after_deploy-firefox.sh.tmpl` | LibreWolf `user-overrides.js` + `userChrome.css` (kept under the familiar `firefox/` name). |
-| (cartão de cidadão) | `run_onchange_after_deploy-pteid-pkcs11.sh.tmpl` | Bridges the `pt.gov.autenticacao` flatpak's PKCS#11 module into the LibreWolf flatpak's NSS DB (filesystem + `--socket=pcsc` override + `modutil -add`). No-op unless both flatpaks are installed. |
+| Directory | Managed by | Purpose |
+| ----------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `dot_*`, `private_dot_*` | chezmoi | Dotfiles deployed to `$HOME`. Prefixes: `dot_` → `.`, `private_` → `0600`, `executable_` → `+x`. |
+| `meta/*.txt` | `just pkg-apply`, `just pkg-status` | Plain-text package lists (one per line, `#` comments). Groups: `base`, `dev`, `wayland`, etc. |
+| `systemd-units/{system,user}/*.txt` | `just unit-apply`, `just unit-status` | Units to enable, split by scope. `system/` files pair by name with `meta/` groups (`system/base.txt` ↔ `meta/base.txt`); `user/` files are standalone. Recipe group token: `<name>` / `system:<name>` / `user:<name>`. |
+| `etc/` | `run_onchange_after_deploy-etc.sh.tmpl` | System-level configs deployed to `/etc/` via a chezmoi onchange hook. |
+| `firefox/` | `run_onchange_after_deploy-firefox.sh.tmpl` | LibreWolf `user-overrides.js` + `userChrome.css` (kept under the familiar `firefox/` name). |
+| (cartão de cidadão) | `run_onchange_after_deploy-pteid-pkcs11.sh.tmpl` | Bridges the `pt.gov.autenticacao` flatpak's PKCS#11 module into the NSS DB of every Mozilla-family flatpak we use (LibreWolf, Thunderbird) — `--filesystem` + `--socket=pcsc` override + `modutil -add` per profile. No-op unless `pt.gov.autenticacao` is installed. |
+| (Thunderbird native editor) | `run_onchange_after_deploy-tb-eer.sh.tmpl` | Bridges `external-editor-revived` (host pacman package) into the Thunderbird flatpak: deploys a `flatpak-spawn --host` wrapper into the sandbox's `~/.mozilla/native-messaging-hosts/` and rewrites the manifest `path` to point at it. No-op unless TB flatpak + EER host package are both installed. |
## Recipes at a glance
@@ -145,5 +146,10 @@ The repo is enough to rebuild a machine's tooling and configuration, but not its
- `~/.password-store/` — the `pass` store that feeds API keys/tokens into the shell at login.
- SSH private keys under `~/.ssh/id_*` (only `.pub` / config is in the repo).
- LibreWolf profile data (bookmarks, history, extension state) at `~/.var/app/io.gitlab.librewolf-community/.librewolf/` — only the hardening policy lives in `firefox/`.
+- Thunderbird profile data (accounts, calendars, OpenPGP keys) at `~/.var/app/org.mozilla.Thunderbird/.thunderbird/` — only non-private prefs live in `thunderbird/`.
-Recovery on a fresh install: run `bootstrap.sh`, then `gpg --import` + `pass init <KEYID>`, restore `~/.password-store/`, drop SSH private keys into `~/.ssh/`, and restore the LibreWolf profile.
+Recovery on a fresh install: run `bootstrap.sh`, then `gpg --import` + `pass init <KEYID>`, restore `~/.password-store/`, drop SSH private keys into `~/.ssh/`, restore the LibreWolf and Thunderbird profiles, and run once:
+
+```sh
+xdg-mime default org.mozilla.Thunderbird.desktop x-scheme-handler/mailto
+```
diff --git a/meta/flatpak.txt b/meta/flatpak.txt
index 5fdd5ec..c76b100 100644
--- a/meta/flatpak.txt
+++ b/meta/flatpak.txt
@@ -12,6 +12,7 @@ io.gitlab.librewolf-community
org.chromium.Chromium
org.kde.okular
org.libreoffice.LibreOffice
+org.mozilla.Thunderbird
org.torproject.torbrowser-launcher
# Portuguese Citizen Card (eID) middleware + GUI. Not on Flathub; ships
diff --git a/meta/mail.txt b/meta/mail.txt
index 1e65dca..74f6214 100644
--- a/meta/mail.txt
+++ b/meta/mail.txt
@@ -1,8 +1,9 @@
+# Host-side bits the org.mozilla.Thunderbird flatpak depends on.
protonmail-bridge-core
-thunderbird
# git send-email Perl prereqs (SMTP via local Bridge on 127.0.0.1:1025)
perl-authen-sasl
perl-mime-tools
perl-net-smtp-ssl
-# Edit messages in nvim (kernel-style inline patch review without TB mangling)
+# Native messaging host binary for External Editor Revived; bridged into the
+# TB flatpak by run_onchange_after_deploy-tb-eer.sh.tmpl.
external-editor-revived
diff --git a/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl b/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl
index b6c3b6c..6046bec 100644
--- a/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl
+++ b/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl
@@ -1,7 +1,7 @@
#!/bin/sh
-# Bridge the pt.gov.autenticacao flatpak's PKCS#11 module into the LibreWolf
-# flatpak's NSS database so cartão de cidadão authentication works in the
-# browser despite the cross-sandbox isolation.
+# Bridge the pt.gov.autenticacao flatpak's PKCS#11 module into the NSS
+# database of every Mozilla-family flatpak we use, so cartão de cidadão
+# authentication / S/MIME signing works despite cross-sandbox isolation.
#
# Idempotent. Re-runs whenever this script or the pt.gov.autenticacao entry
# in meta/flatpak.txt changes.
@@ -10,11 +10,9 @@
set -eu
PTEID_APP=pt.gov.autenticacao
-BROWSER_APP=io.gitlab.librewolf-community
MODULE_NAME=pteid-mw
flatpak info --user "$PTEID_APP" >/dev/null 2>&1 || exit 0
-flatpak info --user "$BROWSER_APP" >/dev/null 2>&1 || exit 0
PTEID_LOC=$(flatpak info --user --show-location "$PTEID_APP" 2>/dev/null)
[ -d "$PTEID_LOC/files" ] || exit 0
@@ -27,36 +25,47 @@ SO_DIR=$(dirname "$SO")
SO_IN_SANDBOX="/run/host$SO"
SO_DIR_IN_SANDBOX="/run/host$SO_DIR"
-flatpak override --user \
+if ! command -v modutil >/dev/null 2>&1; then
+ echo "pteid-pkcs11: modutil not found (install nss); skipping NSS registration." >&2
+ exit 0
+fi
+
+# Each line: <flatpak_app_id> <profile_subdir> <process_name>
+# - profile_subdir is the directory under ~/.var/app/<id>/ that holds the
+# per-profile NSS DBs (cert9.db lives in each <profile>/ underneath it)
+# - process_name is the binary name to grep for to detect a running instance
+APPS="\
+io.gitlab.librewolf-community .librewolf librewolf
+org.mozilla.Thunderbird .thunderbird thunderbird"
+
+echo "$APPS" | while IFS=' ' read -r app profile_subdir proc_name; do
+ [ -n "$app" ] || continue
+ flatpak info --user "$app" >/dev/null 2>&1 || continue
+
+ flatpak override --user \
--filesystem="$PTEID_LOC/files:ro" \
--socket=pcsc \
--env="LD_LIBRARY_PATH=$SO_DIR_IN_SANDBOX" \
- "$BROWSER_APP"
+ "$app"
-command -v modutil >/dev/null 2>&1 || {
- echo "pteid-pkcs11: modutil not found (install nss); skipping NSS registration." >&2
- exit 0
-}
+ profiles_dir="$HOME/.var/app/$app/$profile_subdir"
+ [ -d "$profiles_dir" ] || continue
-PROFILES_DIR="$HOME/.var/app/$BROWSER_APP/.librewolf"
-[ -d "$PROFILES_DIR" ] || exit 0
-
-registered=0
-skipped=0
-for prof in "$PROFILES_DIR"/*/; do
+ registered=0
+ for prof in "$profiles_dir"/*/; do
[ -f "$prof/cert9.db" ] || continue
if modutil -list -dbdir "sql:$prof" 2>/dev/null | grep -q "^[[:space:]]*Name:[[:space:]]*$MODULE_NAME$"; then
- skipped=$((skipped + 1))
- continue
+ continue
fi
- if pgrep -u "$(id -u)" -x librewolf >/dev/null 2>&1; then
- echo "pteid-pkcs11: LibreWolf is running; close it and re-run 'chezmoi apply' to register the PKCS#11 module." >&2
- exit 0
+ if pgrep -u "$(id -u)" -x "$proc_name" >/dev/null 2>&1; then
+ echo "pteid-pkcs11: $proc_name is running; close it and re-run 'chezmoi apply' to register the PKCS#11 module." >&2
+ continue
fi
modutil -add "$MODULE_NAME" -libfile "$SO_IN_SANDBOX" -dbdir "sql:$prof" -force >/dev/null
registered=$((registered + 1))
-done
+ done
-if [ "$registered" -gt 0 ]; then
- echo "pteid-pkcs11: registered $MODULE_NAME in $registered LibreWolf profile(s)."
-fi
+ if [ "$registered" -gt 0 ]; then
+ echo "pteid-pkcs11: registered $MODULE_NAME in $registered $proc_name profile(s)."
+ fi
+done
diff --git a/run_onchange_after_deploy-tb-eer.sh.tmpl b/run_onchange_after_deploy-tb-eer.sh.tmpl
new file mode 100644
index 0000000..3622e67
--- /dev/null
+++ b/run_onchange_after_deploy-tb-eer.sh.tmpl
@@ -0,0 +1,77 @@
+#!/bin/sh
+# Bridge the External Editor Revived native messaging host into the
+# org.mozilla.Thunderbird flatpak. The host binary stays installed via
+# pacman (`external-editor-revived`); we relocate the manifest into the
+# sandbox and replace its binary path with a wrapper that re-enters the
+# host via flatpak-spawn.
+#
+# Idempotent. Re-runs on script changes or whenever the host-side manifest
+# content changes.
+#
+# host manifest hash: {{ output "sh" "-c" "for p in /usr/lib/mozilla/native-messaging-hosts/external_editor_revived.json /usr/lib/thunderbird/native-messaging-hosts/external_editor_revived.json; do [ -f \"$p\" ] && sha256sum \"$p\" && break; done; true" | sha256sum }}
+set -eu
+
+TB_APP=org.mozilla.Thunderbird
+MANIFEST_NAME=external_editor_revived.json
+WRAPPER_NAME=external_editor_revived.sh
+HOST_BINARY=/usr/lib/external-editor-revived/external-editor-revived
+
+flatpak info --user "$TB_APP" >/dev/null 2>&1 || exit 0
+
+# Locate the host-side manifest. Different PKGBUILDs have used different
+# install dirs; prefer the canonical mozilla path, fall back to TB-specific.
+HOST_MANIFEST=
+for candidate in \
+ /usr/lib/mozilla/native-messaging-hosts/$MANIFEST_NAME \
+ /usr/lib/thunderbird/native-messaging-hosts/$MANIFEST_NAME \
+ /usr/lib64/mozilla/native-messaging-hosts/$MANIFEST_NAME; do
+ if [ -f "$candidate" ]; then
+ HOST_MANIFEST=$candidate
+ break
+ fi
+done
+[ -n "$HOST_MANIFEST" ] || {
+ echo "tb-eer: external-editor-revived manifest not found on host; install the package or skip TB native editor." >&2
+ exit 0
+}
+
+[ -x "$HOST_BINARY" ] || {
+ echo "tb-eer: $HOST_BINARY not executable on host; skipping." >&2
+ exit 0
+}
+
+# Allow flatpak-spawn --host from inside the sandbox.
+flatpak override --user --talk-name=org.freedesktop.Flatpak "$TB_APP"
+
+# In-sandbox path the manifest will reference. TB looks for user manifests
+# at $HOME/.mozilla/native-messaging-hosts/ from inside its sandbox; from
+# outside that maps to ~/.var/app/$TB_APP/.mozilla/native-messaging-hosts/.
+SANDBOX_NMH_DIR="$HOME/.mozilla/native-messaging-hosts"
+HOST_NMH_DIR="$HOME/.var/app/$TB_APP/.mozilla/native-messaging-hosts"
+mkdir -p "$HOST_NMH_DIR"
+
+# Wrapper that re-enters the host to invoke the real binary.
+WRAPPER_HOST_PATH="$HOST_NMH_DIR/$WRAPPER_NAME"
+WRAPPER_SANDBOX_PATH="$SANDBOX_NMH_DIR/$WRAPPER_NAME"
+cat >"$WRAPPER_HOST_PATH" <<EOF
+#!/bin/sh
+exec flatpak-spawn --host "$HOST_BINARY" "\$@"
+EOF
+chmod +x "$WRAPPER_HOST_PATH"
+
+# Rewrite the manifest's "path" field to point at the wrapper as seen from
+# inside the sandbox.
+TARGET_MANIFEST="$HOST_NMH_DIR/$MANIFEST_NAME"
+if command -v jq >/dev/null 2>&1; then
+ jq --arg p "$WRAPPER_SANDBOX_PATH" '.path = $p' "$HOST_MANIFEST" >"$TARGET_MANIFEST.tmp"
+ mv "$TARGET_MANIFEST.tmp" "$TARGET_MANIFEST"
+else
+ # Fallback: simple sed on the "path": "..." line. Brittle if the file
+ # ever becomes minified or contains escaped quotes — jq is preferred.
+ escaped=$(printf '%s' "$WRAPPER_SANDBOX_PATH" | sed 's/[\/&]/\\&/g')
+ sed -E "s|(\"path\"[[:space:]]*:[[:space:]]*\")[^\"]*(\")|\1$escaped\2|" \
+ "$HOST_MANIFEST" >"$TARGET_MANIFEST.tmp"
+ mv "$TARGET_MANIFEST.tmp" "$TARGET_MANIFEST"
+fi
+
+echo "tb-eer: External Editor Revived bridged into $TB_APP."
diff --git a/run_onchange_after_deploy-thunderbird.sh.tmpl b/run_onchange_after_deploy-thunderbird.sh.tmpl
index f19eae0..2b86f49 100644
--- a/run_onchange_after_deploy-thunderbird.sh.tmpl
+++ b/run_onchange_after_deploy-thunderbird.sh.tmpl
@@ -4,7 +4,7 @@
# thunderbird/ content hash: {{ output "sh" "-c" (printf "cd %q && find thunderbird -type f -exec sha256sum {} + | LC_ALL=C sort" .chezmoi.sourceDir) | sha256sum }}
set -eu
-PROFILES_DIR="$HOME/.thunderbird"
+PROFILES_DIR="$HOME/.var/app/org.mozilla.Thunderbird/.thunderbird"
[ -d "$PROFILES_DIR" ] || exit 0
PROFILE=$(find "$PROFILES_DIR" -maxdepth 1 -mindepth 1 -type d -name '*.default-default' | head -1)