A fresh system (e.g. Ubuntu after apt install flatpak) has no Flathub remote, so installing from the .flatpakrepo could not find the freedesktop 25.08 runtime. Found in the HeiniRemote VM test 2026-10-13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
heiniremote-flatpak
Flatpak packaging for the HeiniRemote
customer agent (de.pc_heini.HeiniRemoteAgent) — an additional distribution
channel next to the plain release binary, with all dependencies (GStreamer,
libnice, wl-clipboard, …) pinned inside the freedesktop 25.08 runtime (24.08 ships libpipewire 1.2,
whose buffer negotiation fails against KWin 6.7 / PipeWire 1.6 hosts).
Same setup as o3de-flatpak:
a Gitea Action builds the Flatpak without flatpak-builder (no bubblewrap
needed in CI), exports it into an OSTree repo and force-pushes that to the
pages branch. The difference: the agent is compiled from upstream source
(newest v* tag, falling back to main while no release exists) instead of
repackaging a prebuilt archive.
Install
Note: this repository must stay public. Flatpak fetches the OSTree repo from the raw
pagesbranch without any credentials — with the repo set to private,flatpak remote-add/flatpak installfail with a 404. (The agent's source lives in the private HeiniRemote repo; only the built binary is published here.)
From the Flatpak remote (gets updates via flatpak update):
flatpak remote-add --if-not-exists heiniremote \
https://git.pc-heini.de/pc-heini/HeiniRemote-AgentFlatpak/raw/branch/pages/heiniremote.flatpakrepo
flatpak install heiniremote de.pc_heini.HeiniRemoteAgent
Or as a single-file bundle (attached to each release of this repo, no remote needed, but no auto-updates either):
flatpak install ./heiniremote-agent-<version>.flatpak
Configure
The agent needs a server URL and device token. Inside the sandbox the config path is:
~/.var/app/de.pc_heini.HeiniRemoteAgent/config/heiniremote/agent.toml
If a native install already left a config at ~/.config/heiniremote/agent.toml,
the wrapper picks it up automatically (read-only). HEINIREMOTE_SERVER_URL /
HEINIREMOTE_TOKEN env overrides work as usual:
flatpak run --env=HEINIREMOTE_SERVER_URL=wss://… de.pc_heini.HeiniRemoteAgent
Autostart
The native install runs as a systemd user service; the Flatpak equivalent is a
user unit wrapping flatpak run:
# ~/.config/systemd/user/heiniremote-agent.service
[Unit]
Description=PC-Heini Fernwartung (HeiniRemote Agent, Flatpak)
After=graphical-session.target
[Service]
ExecStart=flatpak run de.pc_heini.HeiniRemoteAgent
Restart=on-failure
[Install]
WantedBy=graphical-session.target
How the sandbox is punched
Screen capture and input injection go through xdg-desktop-portal (ScreenCast + RemoteDesktop) — that is the normal, fully sandboxed path and needs no special permission. Two things do:
--talk-name=org.freedesktop.Flatpak— the PTY rescue console must show the host, not the sandbox. The wrapper setsSHELL=/app/bin/host-shell, which execs the user's real login shell viaflatpak-spawn --host. This is a deliberate sandbox escape; for a remote maintenance tool the sandbox is packaging, not a security boundary.--filesystem=xdg-config/heiniremote:ro— adopt a native install'sagent.toml(see above).
Everything else is standard: network (signaling + WebRTC/TURN), wayland
(bundled wl-copy/wl-paste), dri (dmabuf screencast buffers), and the
StatusNotifier names for the tray icon.
Repo layout
| File | Role |
|---|---|
.gitea/workflows/build-flatpak.yml |
CI: resolve upstream version → cargo build → assemble → publish pages + release bundle. Daily schedule picks up new upstream versions. |
scripts/get-latest-version.sh |
Newest upstream v* tag, else main HEAD (0.0.0-git.<date>.<sha>). |
scripts/make-flatpak.sh |
bwrap-free assembly: build-init → copy files → build-finish → build-export. |
heiniremote-wrapper.sh |
Entry point: host-shell $SHELL override + config adoption. |
host-shell.sh |
flatpak-spawn --host bridge for the PTY console. |
de.pc_heini.HeiniRemoteAgent.* |
Desktop file, AppStream metainfo (version stamped by CI), icon. |
Builds track the newest upstream main commit. To rebuild before the nightly check, push a change to a packaging file (README, docs, LICENSE and .gitignore are ignored by the workflow) or run the workflow manually via workflow_dispatch.