Repository access views
As part of adding repository hosting to Debusine, it needs to be able to serve repositories from debian:archive collections in an apt-compatible format.
Domains
Since Debusine’s Set-Cookie
header doesn’t include a Domain
attribute, its cookies are not available to subdomains. It should therefore
be safe to run repositories from a subdomain of DEBUSINE_FQDN
: content
served from that subdomain will not be able to run session fixation attacks
on its parent domain.
A reasonable default would be deb.{DEBUSINE_FQDN}
: shorter than
repositories
, not protocol-specific like ftp
, and familiar from
deb.debian.org
. However, we can include a setting such as
DEBUSINE_DEBIAN_ARCHIVE_FQDN
to allow instances to override this.
Repositories will normally be served over HTTPS, but public repositories may also be served over HTTP. This is sometimes useful for bootstrapping minimal environments that lack certificates.
URL paths
The basic path to a repository is /{scope}/{workspace}
, relying on the
fact that archive collections are singletons.
Suites in the archive are mapped onto subdirectories of dists/
as usual.
Todo
In future, we might also provide the ability to map particular repositories onto different URLs.
by-hash
paths are handled specially: they are translated into a search for a
repository index in the correct suite with the correct path and checksum.
That repository index need not be the active index for its path in the
suite; it can be served as long as the suite’s
full_history_retention_period
has not expired.
/{scope}/{workspace}/{timestamp}
, where timestamp
has the format
YYYYMMDDTHHMMSSZ
, e.g. 20250529T133100Z
for 13:31 UTC on 29 May
2025, addresses the state of the repository as it existed at timestamp
.
This is done by looking up collection items that have created_at
and
removed_at
fields bracketing the given timestamp, rather than just those
that are active (with removed_at
unset), and can be done as long as the
suite’s full_history_retention_period
has not expired. This URL format
is compatible with snapshot.debian.org and snapshot.ubuntu.com; like those
services, a user can request any timestamp as a snapshot ID, and the server
will provide the indexes and other files that were current at that point in
time.
Todo
Add a Snapshots field to
generated Release
files, pointing to the corresponding URL format.
Todo
Once we’ve defined how repository signing works, we should also publish each repository’s public keys in some standard location.
Cache control
Responses to different URLs in a repository should be cached in different
ways, and Debusine sends the Cache-Control
response header to inform
HTTP caches of this.
by-hash
files under dists/
, and all files resulting from a
timestamp-specific query are immutable: they may be removed, but they won’t
be replaced with different contents at the same URL. This is also true for
files under pool/
in archives where may_reuse_versions
is false.
For these files, Debusine sends Cache-Control: max-age=31536000
(i.e.
365 days, an arbitrary long period).
For other files, Debusine sends Cache-Control: max-age=1800,
proxy-revalidate
to indicate that shared caches should revalidate
responses before reuse if they are older than half an hour. (This period is
also arbitrary, but should be a good starting point.)
Debusine also sends Vary: Authorization
for all responses to repository
URLs, since its responses depend on whether the requester has the “viewer”
role on the workspace.
Examples
If we were to create an archive collection in debian/base
on
debusine.debian.net and generate indexes for its suites, then APT
configuration for it might look something like this:
Types: deb deb-src
URIs: https://deb.debusine.debian.net/debian/base
Suites: bookworm
Components: main contrib non-free non-free-firmware
A snapshot of it from the start of May 2025 might be as follows (in this
case we have to add the snapshot ID to the URL, as we don’t control the
Release
file and can’t add a Snapshots
field to it):
Types: deb deb-src
URIs: https://deb.debusine.debian.net/debian/base/20250501T000000Z
Suites: bookworm
Components: main contrib non-free non-free-firmware
An experiment workspace based on debian/developers
might look like
this:
Types: deb deb-src
URIs: https://deb.debusine.debian.net/debian/developers-test
Suites: sid
Components: main
Or a snapshot, once Debusine’s generated Release
files gain a
Snapshots
field:
Types: deb deb-src
URIs: https://deb.debusine.debian.net/debian/developers-test
Snapshot: 20250501T000000Z
Suites: sid
Components: main