Start with a concrete task

From a tested DEB to your Debian fleet.

Separate builds, approval and signing. Then use APT, SSH and systemd through your existing rollout policy.

Read the reference

Install TPA

The published source is https://tpa.run/r/tparun/bootstrap/ (browse packages). The deb822 source file below contains an embedded PUBLIC signing key, not a private key or account credential.

curl -fsSL https://tpa.run/tparun.sources -o /tmp/tpa-bootstrap.sources
cat /tmp/tpa-bootstrap.sources
# Extract and inspect the embedded public key:
sed -n '/^ -----BEGIN PGP PUBLIC KEY BLOCK-----/,/^ -----END PGP PUBLIC KEY BLOCK-----/p' /tmp/tpa-bootstrap.sources \
  | sed 's/^ //; s/^\.$//' > /tmp/tpa-bootstrap.asc
gpg --show-keys --with-fingerprint /tmp/tpa-bootstrap.asc

# ONLY after independently confirming the publisher fingerprint:
sudo install -m 0644 /tmp/tpa-bootstrap.sources \
  /etc/apt/sources.list.d/tpa-bootstrap.sources
sudo apt update
sudo apt install tpa=0.8.0
tpa version

Expected bootstrap fingerprint: EDCEE63AA803737C8ABBC1E4A34190A2829D5E54. On arm64 or riscv64, change the source's Architectures: field to the output of dpkg --print-architecture before installation. Never use trusted=yes or disable HTTPS/signature verification.

Inspect a repository first

Inspection is read-only and does not configure APT or create an account. Review package identity, provenance, sizes and hashes; verification is a separate trust decision.

tpa inspect -json https://tpa.run/r/tparun/bootstrap/
tpa verify --require-signed -keyring ./trusted-public.gpg \
  -fingerprint FULL_FINGERPRINT https://tpa.run/r/tparun/bootstrap/

Use the independently trusted public key for the expected publisher, not an arbitrary key merely downloaded from an untrusted repository.

Install from a source you chose

After reviewing its source configuration and signing key, add the repository's deb822 source and use normal APT. Do not disable signature or TLS checking. Public consumers do not need a TPA.run account.

sudo apt update
sudo apt install tpa=0.8.0
tpa version

Publish with SSH-CAS

Build and sign a complete repository on your own machine with TPA. TPA.run receives, verifies, stores and serves the original bytes, including index.html and repository.json. It does not build packages or sign on your behalf.

Before publishing, complete SSH identity registration and confirmation, obtain repository ownership and a publishing entitlement from your operator, and authorize your owner's public APT signing certificate. Pin the server SSH host key in your SSH configuration. An operator browser session alone does not grant publishing authority.

# Owner-side preparation; replace OWNER_FINGERPRINT with your signing identity.
tpa pack -in ./artifacts -out ./finished -gpg OWNER_FINGERPRINT
gpg --export OWNER_FINGERPRINT > owner-public.gpg

# Replace HOST, PORT and REPOSITORY_ID with your provisioned destination.
tpa publish -in ./finished \
  --output=tparun+ssh://tparun@HOST:PORT/REPOSITORY_ID \
  -ssh-config ./ssh-config -keyring ./owner-public.gpg \
  -fingerprint OWNER_FINGERPRINT -json

For an update, add -parent-generation CURRENT_GENERATION using the current active generation. After an interrupted or uncertain activation, inspect the active generation before retrying. Never send your private signing key to the hosting server.

Canonical receive-only hosting does not accept the legacy tparun stage / tparun publish package-ingestion workflow. Use a qualified TPA client with tpa publish. TPA is available from the canonical tparun/bootstrap repository; the backend package is a separate release.

An identical completed repository can reuse every existing chunk. Receipt payload, control traffic, logical size and physical storage are different metrics. Inspect the current active generation after an uncertain transfer before retrying.

Upload on one device. Sign on another.

This workflow uses the published TPA 0.8.0 client, including stage and owner-side sign. See availability.

On the build device or in CI, use the already-tested DEBs and their original release manifest. Set an explicit destination, a 32-hex stage ID and your pinned SSH configuration.

tpa stage create --output="$DESTINATION" \
  -stage="$STAGE_ID" -manifest=release-manifest.json \
  -ssh-config=publisher-ssh.conf

tpa stage upload --output="$DESTINATION" \
  -stage="$STAGE_ID" -in=example_1.4.0_amd64.deb \
  -ssh-config=publisher-ssh.conf

On the signing device, review the complete stage inventory and compare its manifest digest with the original manifest from the trusted build record. Approve the package identities and hashes, not just a stage name or a server's success message.

tpa stage inspect --output="$DESTINATION" \
  -stage="$STAGE_ID" -ssh-config=owner-ssh.conf

tpa sign --output="$DESTINATION" \
  -stage="$STAGE_ID" -manifest=release-manifest.json \
  -gpg="$OWNER_FINGERPRINT" -fingerprint="$OWNER_FINGERPRINT" \
  -keyring=owner-public.gpg -ssh-config=owner-ssh.conf \
  -origin="$EXISTING_ORIGIN" -label="$EXISTING_LABEL"

TPA retrieves the artifacts, verifies their identities and exact hashes against that manifest, then derives and signs APT metadata locally. It does not rebuild the DEBs. The owner key stays on the signing device; the host receives only finished content. Preserve the existing repository's Origin and Label. A stage describes a complete next snapshot: include other packages that must remain available.

Roll out approved versions with native tools

Choose a canary using your existing inventory or configuration-management system. Configure the reviewed deb822 source and publisher public key on that host first. Private sources also need repository-scoped APT reader credentials.

# Illustrative package and service; choose your approved version.
ssh canary-01 'apt-cache policy example'

# On the selected host, using its normal administrative policy:
sudo apt-get --simulate install example=1.4.0
sudo apt-get install example=1.4.0
systemctl status example.service

Check the application as well as the package version. Expand to the next host group only after your canary checks pass. Pin the intended version and use your existing automation; TPA.run does not maintain a host inventory, execute these commands, or reconcile machine state.

Plan recovery before rollout

Keep any required previous DEBs in the repository snapshot, and retain compatible configuration and application-data backups. A package downgrade is not whole-system rollback; maintainer scripts and data migrations can require separate recovery steps. Publishing a generation does not install it anywhere, enable automatic updates, or grant host privileges.

Use an ordinary SSH/web server

This strategy needs no TPA.run account, special receiver, CAS or remote signing key. The destination must be new; configure your normal web server to serve it unchanged.

tpa pack -in ./artifacts \
  --output=ssh://publisher@HOST/absolute/new-repository \
  -ssh-config ./ssh-config -gpg OWNER_FINGERPRINT

Use a private repository

Ask its publisher for repository-scoped reader credentials and source instructions. They authorize only that repository's downloads, not publishing or administration. Keep credentials in restricted APT authentication configuration, never in shared command history or public URLs.

The hosting core still checks visibility and authorization independently of the website. An account workspace is not a private-reader bypass.

Manage keys and permissions

Open your workspace to inspect public-key fingerprints and capabilities. Register only a public key. Keep CI publishing credentials separate from personal Browser Login keys.

Use the existing registered passkey at operator sign-in for administrative policy. SSH sessions never upgrade to operator authority.

Check production versus development features