Signed .deb packages for every Glyndor product.
amd64 and arm64, rebuilt daily, nothing unverified ever served
curl -fsSL https://apt.glyndor.net/install/podup | sudo shIt adds the archive, installs the signing key after checking its fingerprint,
installs the package, and reports whether automatic security upgrades are on.
It does not change that setting itself; if the unattended-upgrades package is
missing it installs it. Anything but Keyring installed after the fingerprint
and signature lines means it refused: it exits before dpkg -i, so no script from
the downloaded package ran.
Swap podup for any package marked served below.
| Package | What it is | In the archive |
|---|---|---|
podup |
Docker-compose translator and runner for rootless Podman | served |
epistle |
Self-hosted headless mail server: SMTP, IMAP | served |
helmly-agent |
Hardened server agent for the Glyndor panel: signed commands over WireGuard and mTLS | not packaged |
apt list '?origin(Glyndor)' # everything currently served
The floor is podman. podup depends on podman 5, and epistle needs podup
to run the mail stack, so this archive installs on the Debian and Ubuntu
releases that ship podman 5 or newer from their own repositories, and refuses
on the ones that do not. The refusal names it:
podman (>= 5.0) but it is not going to be installed.
The distribution floor workflow runs the install line above in fresh containers every week and asserts exactly this:
| Image | Expected |
|---|---|
debian:trixie |
installs |
ubuntu:26.04 |
installs |
ubuntu:22.04 |
refused, naming podman |
A release missing from that table has not been measured. The check reads what the release serves from its own repositories; a podman added from elsewhere is not what the floor is about.
The signing key ships as a package, so apt owns it. The same package installs
glyndor-upgrade.timer, which runs daily and upgrades the packages from this archive
(plus any dependency a new release needs), including products published later,
and leaves every other package alone. Nothing to re-run, no expiry
to diarise.
The timer does not depend on the machine's own unattended-upgrades schedule and
does not change it. To opt out, run sudo systemctl disable --now glyndor-upgrade.timer;
that choice survives upgrades of the package. It needs systemd and the
unattended-upgrades engine, which the install command above puts on the machine
if it is missing.
flowchart LR
P["Product release<br/>.deb + .sig"] -->|daily pull| V["verify-debs.sh<br/>release key"]
V -->|admitted| R["reprepro<br/>signs the index<br/>archive key"]
R --> S["apt.glyndor.net<br/>R2 + Cloudflare"]
S -->|apt update| C["Client<br/>glyndor-archive-keyring"]
V -.->|bad signature| X["publish fails, nothing served"]
Two keys, two jobs. The release key proves a package is the one its product published; the archive key proves the index is the one this repository built. You check the second, this repository checks the first.
Rebuilt from scratch every run, so the failure mode is an archive that does not update, never one that serves something unverified.
This is the archive key, the one apt uses to check the index. The installer compares it for you; repeat it by hand to confirm a key already installed, or if you would rather not pipe a network response into a shell.
curl -fsSLO https://apt.glyndor.net/glyndor-archive-keyring.deb curl -fsSLO https://apt.glyndor.net/glyndor-archive-keyring.deb.asc dpkg-deb -x glyndor-archive-keyring.deb keyring-check gpg --show-keys keyring-check/usr/share/keyrings/glyndor.gpg
Nothing from the package runs. It must print exactly:
9ADF 04EA 8C31 39CD B673 03CF A670 5C2E A153 F3D6
Published here, not on apt.glyndor.net. A tampered archive cannot vouch for
itself. Same value for a copy already installed, at
/usr/share/keyrings/glyndor.gpg.
Caution
dpkg -i runs maintainer scripts as root. If it does not match, delete the
download and report it via the Security tab. dpkg -r does not undo
what a maintainer script already did.
The fingerprint authenticates the key, not the package that carried it: a
substituted .deb can ship the genuine key next to a hostile maintainer
script. So also check the detached signature over the whole package with that
key, which must exit 0 (the keyring path has to be absolute):
GNUPGHOME="$(mktemp -d)" gpg --no-default-keyring \ --keyring "$PWD/keyring-check/usr/share/keyrings/glyndor.gpg" \ --verify glyndor-archive-keyring.deb.asc glyndor-archive-keyring.deb
Only once both pass:
sudo dpkg -i glyndor-archive-keyring.deb
Warning
Do not stop here and install the package with apt. The keyring switches the
upgrade timer on, but the timer runs the unattended-upgrades engine, and
only the script installs that when it is missing. Run the install command at
the top instead.
See CONTRIBUTING.md. The tests are the specification; the threat model says what they specify against.