OpenSSL's module builds with --openssldir=/app/ssl, but nothing populates
/app/ssl/certs, so SSL_CTX_set_default_verify_paths() always fails to find
any CA. Point SSL_CERT_FILE at the runtime's real bundle (/etc/ssl/cert.pem)
via finish-args instead. Verified with --headless=text against example.com,
news.ycombinator.com, and google.com.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Found and fixed, in order, while actually trying to run the built
app (not just build it):
1. Fontconfig loads its config after the sandbox restricts filesystem
access, so it fails (upstream #11775, open, filed against NixOS
but general to any Linux sandbox). Adapted the issue's own
suggested fix to this checkout's current GlobalFontConfig::get().
2. WebContent crash-loops with "Landlock must be applied before the
process starts a second thread" -- a check that, per git log,
didn't exist before commit 3fea952607 (11 days before our pin),
added while fixing an analogous bug in Compositor (GPU driver
threads starting before Landlock). That fix reordered Compositor's
startup; WebContent has the same problem and was never updated to
match. Root-caused via temporary /proc/self/task diagnostics: the
second thread is OpenSSL's thread pool and SDL's gamepad hotplug
thread, both started before the sandbox. Fixed by moving both
after RendererSandbox::apply_sandbox(), mirroring the precedent.
3. Moving SDL's init that late surfaced a third issue: its libusb
backend's event thread hits a seccomp violation (sendmmsg on a
netlink socket) the policy doesn't grant. SDL_HINT_HIDAPI_LIBUSB=0
didn't avoid it in testing. Rather than widen the seccomp policy
for a feature most pages never use, skip gamepad init entirely
while sandboxed (--disable-sandbox still gets it) -- a real,
documented tradeoff, not a hidden one.
All three are packaged as patches/sandbox-fixes.patch, applied
automatically by task clone/update/apply-patches (none of this is
upstreamed yet, and git reset/clone would otherwise silently wipe
working-tree-only edits). Confirmed working end to end: a real
`flatpak run org.ladybird.Ladybird`, no flags, starts RequestServer,
Compositor, and two WebContent processes, all stay up, pages load,
no crash loop.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Build succeeds and installs cleanly, but the app doesn't run with
Linux sandboxing enabled at today's pinned commit:
1. Fontconfig loads after the sandbox restricts filesystem access
(tracked upstream as #11775, filed against NixOS but general to any
Linux sandbox -- Flatpak's own restrictions trigger the identical
failure). Applied the issue's suggested fix locally (uncommitted,
in ladybird/ -- the manifest's Ladybird module sources from the
working directory, so this is picked up automatically), adapted to
this checkout's current GlobalFontConfig::get() accessor. Confirmed
fixed: the "Fontconfig error: Cannot load default config file" line
is gone from a rebuild.
2. A second, separate, not-yet-reported-anywhere-findable bug: even
with that fix, WebContent crash-loops immediately with "Landlock
must be applied before the process starts a second thread" --
present from the very first run, before the fontconfig patch, so
not caused by it. Isolated cleanly to Ladybird's own sandbox code
by confirming --disable-sandbox (an existing, real flag, plumbed
through every helper process) eliminates the crash loop entirely.
task run now passes --disable-sandbox by default as the practical
workaround, with a new task clean-runtime for the stale single-
instance lock a crashed session leaves behind (manifests as
"connect: Connection refused" on the next launch -- hit this
repeatedly while testing).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
task build needed one fix: --install-deps-from=flathub. Without it,
flatpak-builder fails immediately requesting
org.freedesktop.Sdk.Extension.llvm20/x86_64/6.10, which is never
published under a "6.10" branch on Flathub (confirmed directly against
the remote) -- a naive pre-installed runtime doesn't satisfy the SDK's
declared extension points the way --install-deps-from's proper
resolution does. Upstream's CI never hits this because its container
image already has the extensions deployed.
With that fix, a real local build compiled every dependency module
(angle, skia, openssl, ffmpeg, mimalloc, wuffs, pdfjs, etc.) and the
main Ladybird module itself end to end, installed cleanly, and
`flatpak run org.ladybird.Ladybird` launches with no errors -- also
incidentally resolving the vcpkg-approach branch's open "where does Qt
come from" question: this manifest links against the KDE runtime's own
Qt6 directly.
No InsecureRootCapabilities-equivalent grant was needed for
flatpak-builder's bubblewrap sandbox in the distrobox, unlike the
vcpkg-approach branch's Dagger container.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
LadybirdBrowser/ladybird already maintains a complete, actively
CI-tested flatpak manifest at Meta/CMake/flatpak/org.ladybird.Ladybird.json,
built and tested on every commit/PR via their own
.github/workflows/flatpak.yml (x86_64 + aarch64, currently green
across the 10 most recent runs). It takes a fundamentally different
approach than the manifest this repo had been building independently:
every dependency is its own plain Flatpak module with a git-tag
source, entirely bypassing vcpkg -- sidestepping essentially every
problem the independent attempt spent this session working through
(vcpkg bootstrap, googlesource archive non-reproducibility, build-time
network deps, etc).
Discovered while fixing the very last vendoring gap in the
independent manifest (a real CI run had just compiled 68 of 69 vcpkg
ports successfully). Maintaining a second, independent manifest
against a fast-moving browser codebase when a first-party one already
exists and stays in lockstep with the code by construction isn't a
good use of ongoing effort.
The independent vcpkg-based manifest and everything learned building
it is preserved on the `vcpkg-approach` branch, not deleted.
This repo now just clones LadybirdBrowser/ladybird and builds their
manifest locally (Taskfile.yml: clone, build, run), rather than
maintaining any manifest of its own. No Flathub submission for
org.ladybird.Ladybird was found anywhere (flathub/flathub, the
flathub org) as of this commit -- since upstream owns the manifest,
they're the natural ones to submit it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A real GitHub Actions run of this module (.github/workflows/build.yml)
got through source fetching, vcpkg bootstrap, and 68 of 69 vcpkg
ports -- including compiling skia -- in ~52 minutes, before failing
cleanly on the last one: the top-level `wuffs` port (distinct from
skia's bundled `wuffs-mirror-release-c` external already fixed)
downloads google-wuffs-mirror-release-c-v0.3.4.tar.gz, which every
local exploration run had also hit, via a transient DNS failure each
time, without anyone noticing the gap since it never actually
succeeded locally either. Fetched it directly and added it as a
normal vendored file source.
This also confirms, via the same CI run, that several earlier fixes
hold end to end: the 3 googlesource git+tar externals, angle's
pip install ply vendoring (plus its separate WebKit CMakeLists.txt
fetch and git zlib external), and the Nix/runtime-install/
InsecureRootCapabilities Dagger fixes all worked together to get this
far without any other network errors.
Not yet re-verified after this specific fix -- next CI run is the
test. README.md rewritten around current, CI-verified reality instead
of local-only exploration.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Third real CI failure: got through all source fetching (~7 min) and
failed immediately on the first actual build step with "bwrap: No
permissions to create a new namespace, likely because the kernel does
not allow non-privileged user namespaces." flatpak-builder creates a
fresh bubblewrap sandbox per build step, which needs to create a
Linux user namespace -- not permitted by default inside a Dagger
container. dagger.ContainerWithExecOpts{InsecureRootCapabilities:
true} on that WithExec grants it (Docker --privileged equivalent).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
GitHub's archive-by-commit endpoint wraps content in an extra
"<repo>-<commit>/" directory, which skia's ninja build doesn't expect
-- confirmed by a real sandboxed build reaching skia's actual compile
step (package 65/69) and failing with a confusing "missing file"
error, not a hash mismatch. Switched wuffs-mirror-release-c to the
same git+tar mechanism already used for the three googlesource
externals (libyuv, piex, angle's zlib fork), which produces the
correct unwrapped layout regardless of the reproducibility issue that
originally forced git+tar for those three.
Also fixes the Dagger module's second real CI failure: a fresh
container has no Flatpak runtimes installed at all. Build() now adds
the flathub remote and installs org.freedesktop.Platform/Sdk//26.08
and the rust-stable extension first (mirroring `task install-tools`),
cached across Dagger runs via a cache volume at
~/.local/share/flatpak.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
First real CI run failed immediately: "nix: executable file not found
in $PATH" despite the container being built FROM nixos/nix. Root
cause: WithMountedCache at /nix/store mounts an initially-empty
volume AT that exact path, replacing rather than merging with
whatever the base image already has there -- which for nixos/nix is
the nix binary and its entire dependency closure. Removed both the
/nix/store and /nix/var/nix/db cache mounts; losing package-download
caching across Dagger runs is an acceptable tradeoff for correctness,
dwarfed by the actual multi-hour build time regardless.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
angle's portfile turned out to have its own googlesource-hosted git
external (chromium's zlib fork) with the same +archive
non-reproducibility problem already worked around for skia's
libyuv/piex -- same git+tar fix applied here. Also excludes
parsetab.py/__pycache__ from the vcpkg-sources harvester (build
artifacts that land in downloads/ as a side effect of running ply,
not real downloads).
A real sandboxed `task build` run with all of this in place gets
angle's pip install, its WebKit CMakeLists.txt fetch, and this new
git external all working, and continues compiling further packages
with no new network errors -- vendoring is holding up.
Adds .github/workflows/build.yml, following the same
install-dagger-then-`dagger call`-directly pattern used in
quine-global/quintodrome's ci.yml (no third-party GitHub Action).
Calls the Dagger module's Build function (updated to produce an
actual .flatpak bundle via `flatpak build-bundle`, with vcpkg's binary
cache and ccache mounted as Dagger cache volumes so repeat runs don't
recompile everything) and uploads/releases the result. flake.nix
gains the native build tools vcpkg's ports needed when this was
worked out by hand in a distrobox (gcc, perl, nasm, autotools,
ncurses, etc), so the Dagger container has them too.
Still UNTESTED end to end: the local Dagger engine is unusable (see
earlier commit), so this workflow's first real run is in CI itself.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds tools/generate-vcpkg-sources.py and sources/vcpkg-sources.json,
vendoring offline sources for all 69 vcpkg ports Ladybird depends on
(64 as plain flatpak file sources hashed from a real `vcpkg install
--only-downloads` run, plus 2 googlesource-hosted git externals
handled as hash-pinned git sources + a local tar step, since
googlesource's +archive endpoint is confirmed non-reproducible across
requests -- verified by fetching the same commit twice and getting two
different sha256 hashes).
manifest-template.json also gains the vcpkg-tool bootstrap binary
(vcpkg-glibc/vcpkg-glibc-arm64, matching vcpkg/scripts/vcpkg-tool-
metadata.txt) pre-placed at vcpkg/vcpkg so vcpkg.cmake's bootstrap
check is satisfied without a network fetch.
A real task build run now gets through all source fetching and starts
compiling real vcpkg packages (reached 7/69 before hitting a new kind
of problem: `pip install ply` needed at build time by the angle port,
not just at source-fetch time -- not yet solved, see README.md).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Real flatpak-builder run (via distrobox) surfaced two real, non-obvious
bugs and one dead end, all now fixed/documented from empirical evidence
rather than guesswork:
- org.kde.Platform//6.10 can never pair with
org.freedesktop.Sdk.Extension.rust-stable: sdk-extensions always
branch-match runtime-version, and rust-stable is only published under
freedesktop-sdk's own branch numbers, never KDE's. Since Ladybird
builds its own Qt 6.10.0 via vcpkg regardless of the runtime, there
was no reason to use the KDE runtime in the first place. Switched to
org.freedesktop.Platform/Sdk//26.08, which also happens to ship
rust-stable 1.98.0, an exact match for rust-toolchain.toml.
- Ladybird's Meta/CMake/environment.cmake force-overrides
CMAKE_TOOLCHAIN_FILE from the VCPKG_ROOT env var whenever
LADYBIRD_VCPKG_TYPE is set, silently discarding any -D value passed
on the command line. Set VCPKG_ROOT via build-options.env instead.
- flatpak-builder needs --disable-rofiles-fuse inside a distrobox
(no FUSE available in the container).
With these fixes, task build now gets all the way through source
fetching (all 347 cargo sources verified), SDK/extension resolution,
and CMake configure, failing exactly where expected: vcpkg's own
bootstrap script has no network access to download its tool binary.
README.md's vcpkg section is rewritten around this precise, verified
failure point instead of the earlier general "vcpkg needs network"
description.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
flatpak-builder has no Homebrew formula and doesn't fit a Nix devShell
well on this immutable/atomic host either (deep ostree/bubblewrap/
polkit integration), so task install-tools/build now use a Fedora
distrobox instead. The box shares ~/.local/share/flatpak with the
host, so builds done inside it are runnable directly via the host
flatpak (task run needs no container).
Also commits a hand-written, UNRUN Dagger Go module (dagger.json,
.dagger/main.go) plus flake.nix. The local Dagger engine (a podman
container) got stuck in an unkillable kernel D-state mid-session with
no working engine available to run dagger init/develop against, so
this wasn't generated or validated -- it's a starting point to finish
wiring up in GitHub Actions (or against Dagger Cloud's hosted engines)
rather than something that works today. See README.md for the full
breakdown of what's real vs. aspirational here.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Splits the manifest into manifest-template.json (hand-edited) plus
generated source fragments under sources/, assembled into
org.ladybird.Ladybird.json by tools/generate-manifest.py. Vendors
flatpak-cargo-generator.py from flatpak/flatpak-builder-tools and runs
it against Ladybird's pinned Cargo.lock to produce
sources/cargo-sources.json (347 offline sources for all Rust deps).
Adds a Taskfile.yml (install-tools, generate-cargo-sources,
generate-manifest, update-sources, build, run, clean) so the whole
pipeline is one command away instead of manual steps.
vcpkg vendoring is still unresolved (documented in README.md) and is
the remaining blocker before a real flatpak-builder run can succeed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Modeled on Flathub's org.kde.kget manifest structure, targeting the KDE
6.10 runtime. Non-vcpkg parts are wired up (app-id, finish-args, install
flags, source pinning to current master since Ladybird has no tagged
releases). Offline vendoring of vcpkg's ~40 C++ ports and Cargo deps is
not yet solved and is documented as the next work item in README.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>