How to add the myguard APT repository to Debian and Ubuntu

This guide adds deb.myguard.nl to your server so you can install our packages with apt like any other software. There are two ways to do it. The manual setup is the primary, recommended method, you can see exactly what every command does, and it is the right way to add any third-party APT repository in 2026. If you just want it done in one line, there is also a lazy way at the bottom using a bootstrap package.

New to APT repositories? An APT repository is just a web server that publishes signed .deb packages plus an index your machine trusts. Once added, apt update and apt install work exactly as they do for the official Debian or Ubuntu packages.

Manual setup (recommended)

The recommended way to add the myguard APT repository on Debian or Ubuntu: import the signing key into its own keyring, register the source with signed-by, and install your first package, fully transparent and verifiable. Five short steps.

Step 1, Install the prerequisites

You need curl to download the signing key, ca-certificates so HTTPS is trusted, and lsb-release to detect your distribution codename automatically. Most systems already have these.

apt-get update
apt-get -y install lsb-release ca-certificates curl

Step 2, Install the repository keyring

Create a dedicated keyrings directory and drop our signing key into its own file there. This is the modern approach: the key is scoped to this one repository via signed-by below, so it can never be used to validate packages from anywhere else on your system. Our key is published ready-to-use (already de-armoured), so you just save it, no gpg --dearmor step needed.

sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://deb.myguard.nl/deb.myguard.nl.gpg \
  | sudo tee /etc/apt/keyrings/deb.myguard.nl.gpg >/dev/null

Step 3, Add the repository source

Register the repository, tied to the keyring from the previous step via signed-by. The codename (for example bookworm or noble) is detected automatically, so this same command works on every supported release. This points at the full per-distribution tree under /apt/dists/, everything we build for your release, in one source line. (Prefer just one package? See the repository layout below.)

CODENAME=$(lsb_release -cs)
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/deb.myguard.nl.gpg] https://deb.myguard.nl/apt/dists/$CODENAME $CODENAME main" \
  | sudo tee /etc/apt/sources.list.d/deb.myguard.nl.list

Step 4, Update the package index

Refresh APT so it reads the new repository. If the signature check passes, you are ready to install, if you see a NO_PUBKEY or signature error, re-run step 2.

sudo apt-get update

Step 5, Install any package

Install NGINX, Angie, or anything else from the repository with apt-get install.

# Web server with HTTP/3
sudo apt-get install nginx

# NGINX alternative with built-in ACME/Let's Encrypt
sudo apt-get install angie

# Mail stack
sudo apt-get install postfix dovecot-core rspamd

# WAF for NGINX
sudo apt-get install libnginx-mod-http-modsecurity libmodsecurity3 modsecurity-crs

Verify the signing key (recommended)

Before trusting any third-party repository, confirm the key fingerprint matches what we publish. Run:

gpg --no-default-keyring --keyring /etc/apt/keyrings/deb.myguard.nl.gpg --fingerprint

The fingerprint must be exactly:

D18B 8E5A DF7D 55CE 2A00  D581 67F9 C3D8 456D 7F62
Thijs Eilander <eilander@myguard.nl>

It is an RSA 4096-bit key (valid through May 2028). If your output does not match this fingerprint character-for-character, stop, do not run apt update, and re-download the key from https://deb.myguard.nl/deb.myguard.nl.gpg over a trusted connection.

Repository layout, pick what you pull in

The repository is published in three layouts so you can be as broad or as surgical as you like. The signing key and codename are identical for all three, only the URL in your source line changes. Pick one (or mix and match):

LayoutURL patternWhat you get
Full per-distribution (recommended)/apt/dists/<codename>Everything we build for your release in one source line. This is what the setup above uses.
Single package/apt/<package>/<codename>Just one package plus its dependencies, nothing else. Ideal if you only want, say, our NGINX and don’t want the rest in your apt index.
Legacy mixed (being retired)/ <codename> (site root)The old flat layout where every release shared one tree. Still live so existing setups keep working, please migrate to one of the above when convenient.

The <package> trees currently published are: nginx, angie, postfix, dovecot, rspamd, mariadb and openssh.

See all the options: browse the live repository at deb.myguard.nl/apt to see every full-distribution and per-package tree currently available, and pick the exact URL for your source line.

Curious why the repository is split up this way, and how it works under the hood? Read The New deb.myguard.nl Repository Layout: Per-Package APT Trees Explained, the full story, from scratch.

Add a single package only

Want just one package, for example our NGINX, without adding the whole distribution? Point the source line at that package’s own tree under /apt/<package>/<codename>. The keyring and key from the steps above are reused unchanged; only the path differs.

CODENAME=$(lsb_release -cs)

# Example: only our NGINX (and its dependencies)
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/deb.myguard.nl.gpg] https://deb.myguard.nl/apt/nginx/$CODENAME $CODENAME main" \
  | sudo tee /etc/apt/sources.list.d/deb.myguard.nl-nginx.list

sudo apt-get update
sudo apt-get install nginx

Swap nginx for any published package name to add only that one. You can add several single-package source lines side by side, give each its own file in /etc/apt/sources.list.d/ (for example deb.myguard.nl-postfix.list) so they are easy to manage and remove later. Note that mariadb is built for trixie and resolute only, and openssh is published per release as builds land.

Supported distributions

The repository publishes a separate suite per distribution codename. Use the codename of your release (the manual setup above detects it for you with lsb_release -cs):

  • Debian: 11 (bullseye), 12 (bookworm), 13 (trixie)
  • Ubuntu: 20.04 (focal), 22.04 (jammy), 24.04 (noble), 26.04 (resolute)

Component is main; architectures published are amd64, i386 and all. On an arm64 box, the repository’s architecture-independent packages still install, just adjust arch= in the sources line as needed.

APT pinning (optional)

Pinning lets packages from this repository take priority over the versions in the default Debian/Ubuntu archive, useful when our build is newer or specifically optimised. Pin by your release codename so it always targets the right suite:

CODENAME=$(lsb_release -cs)
sudo tee /etc/apt/preferences.d/99-deb-myguard-nl >/dev/null <<EOF
Package: *
Pin: release n=$CODENAME
Pin-Priority: 501
EOF

A priority of 501 beats the default archive (500) without overriding held or manually pinned packages. Remove the file to undo pinning. Skip this section entirely if you only want the occasional package and prefer your distro’s versions everywhere else.

The lazy way, the myguard.deb bootstrap

Short on time? The myguard.deb bootstrap package does steps 1–4 of the manual setup for you: it installs the signing key into its own keyring, writes the signed-by source for your codename, and sets up pinning. Use this if you trust the project and just want it working now.

# Prerequisites (HTTPS download + codename detection)
apt-get update
apt-get -y install lsb-release ca-certificates curl

# Fetch and install the bootstrap package
curl -fsSLO https://deb.myguard.nl/myguard.deb
sudo dpkg -i myguard.deb
sudo apt-get update

That’s it, jump straight to installing packages. The trade-off versus the manual setup: you are running our packaging script instead of typing the commands yourself, so you don’t see each step happen. The end state is identical to the manual method, including key isolation and the signed-by source. If you want to audit it first, the package is just a normal .deb, inspect it with dpkg-deb -e myguard.deb and read the maintainer scripts before installing.

What to install next

Troubleshooting

  • Wrong codename / 404 on update: run lsb_release -cs and confirm it matches a codename in the supported list above. Re-run step 3 with the correct one.
  • NO_PUBKEY or signature errors: the keyring is missing or corrupt. Re-run step 2, then check the fingerprint as shown in the verify section.
  • Package not found after update: the source line may be pointing at the wrong codename, or the package name differs: run apt-cache search <name>.
  • Package conflicts with distro versions: enable pinning (see above) so myguard packages take priority.
  • arm64 / other architectures: change arch=amd64 to arch=arm64 in /etc/apt/sources.list.d/deb.myguard.nl.list, then sudo apt-get update.
  • TLS, proxy or firewall problems on the main host: use the backup mirror on port 8888 (see below): it serves the exact same packages over plain HTTP from a separate web server.

Backup mirror on port 8888

If the main HTTPS endpoint is misbehaving, a corporate proxy mangling TLS, an old client that chokes on the certificate, or the front-end being down, the repository is also published by a separate web server on port 8888 over plain HTTP. It serves byte-for-byte the same signed packages, so it is a safe fallback: APT verifies every package against the GPG key regardless of transport, so HTTP here costs you nothing in integrity.

Just swap the host in your sources line for http://deb.myguard.nl:8888 (the same /apt/dists/<codename> path applies):

CODENAME=$(lsb_release -cs)
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/deb.myguard.nl.gpg] http://deb.myguard.nl:8888/apt/dists/$CODENAME $CODENAME main" \
  | sudo tee /etc/apt/sources.list.d/deb.myguard.nl.list
sudo apt-get update

The signing key, codenames, components and package set are identical, only the host and port differ. Switch back to https://deb.myguard.nl once the main endpoint is healthy again.

Still stuck? Report problems at github.com/eilandert/deb.myguard.nl.

Related guides