|
|
1 hafta önce | |
|---|---|---|
| src | 1 hafta önce | |
| usm-scripts | 1 hafta önce | |
| .gitignore | 1 hafta önce | |
| .usmignore | 1 hafta önce | |
| MANIFEST.usm | 1 hafta önce | |
| README.md | 1 hafta önce | |
| meson.build | 1 hafta önce |
A Statum + Spry application that browses and serves any number of USM
repositories: human-facing pages for exploring packages (an all-repository
overview plus per-repository browse views), plus the exact HTTP endpoints a
real USM client (usm repository list / verify / install) expects to
fetch from a repository host.
| Endpoint | Purpose |
|---|---|
GET / |
Overview: every repository (name, summary, package count, total size), per-repo add-repository instructions (sudo usm add-repo <repo.usmr URL>), the global install-USM block, and a combined package table with repo badges + server-side search across all repositories |
GET /repo/{name} |
Single-repo browse: that repository's overview card, instructions and package table, search scoped to it |
GET /repo/{name}/package/{file} |
Package detail: manifest fields read out of the .usmc (licences, flags, provides/depends tables), sha512, on-disk size/mtime, download button |
GET /repo/{name}/PACKAGES.usml |
That repository's listing streamed verbatim (application/json) |
GET /repo/{name}/repo.usmr |
A rewritten copy of the .usmr with its embedded url replaced by the derived base + repo/{name}/ — the URL sudo usm add-repo consumes |
GET /repo/{name}/{file}.usmc |
Package archives streamed from that repository's public/ (application/octet-stream, exact content-length) |
GET /install-usm.sh |
The configured installer script (installer.path mode only), served by the root-level catch-all |
The derived base is base_url from the config when set, else
X-Forwarded-Proto/X-Forwarded-Host, else the request's own scheme/host —
so clients behind a reverse proxy resolve against the public name. Each
repository is addressed by the name in its .usmr, which is also its
routing segment.
web-config.json (in the app's working directory, or ASTRALIS_CONFIG_PATH)
carries the static Statum keys plus an optional "usm-web" section:
{
"statum": { "…": "static keys from spry keys / statum-genkeys" },
"usm-web": {
"repo": "/repo",
"repositories": ["web-stack", "extra"],
"installer": { "path": "install-usm.sh" },
"base_url": "https://repo.example.com/",
"name": "My repositories"
}
}
| Key | Meaning |
|---|---|
repo |
The parent directory holding the repositories (each a subdirectory with a .usmr and public/); relative paths resolve against the config file's directory |
repositories |
Optional explicit list of repository subdirectories to serve (in that order); when absent or empty every subdirectory containing a .usmr is discovered by scanning |
installer.url |
External installer location; the homepage links out and shows curl -fsSL <url> \| sh |
installer.path |
Installer script this app serves at /install-usm.sh; relative paths resolve against the config file's directory |
base_url |
Optional override of the request-derived repository base (normalised to a trailing slash) |
name |
Optional overview-title override |
installer takes exactly one of url/path; providing both (or neither,
when the block should appear) is a configuration error. Omit the section
entirely to hide the install-USM card.
The repository parent is selected by (in order) the --repo <dir> argument,
the USM_WEB_REPO_DIR environment variable, the config's repo key, or the
/repo default, and is expected to look like:
/repo
├── web-stack/
│ ├── web-stack.usmr
│ ├── keys/ (not used by usm-web; signing is upstream)
│ └── public/
│ ├── PACKAGES.usml
│ └── <name>-<version>.usmc
└── extra/
└── …
A legacy single-repository layout with the .usmr directly inside the
configured directory is still served as one repository. Discovery re-runs on
every request, so repositories added or removed on disk are picked up without
a restart, and each repository's .usmr and PACKAGES.usml re-read when
their mtimes change — one repository can be rebuilt without disturbing the
others. There is no database and no authentication; all Statum state is
stateless PAGE slots.
spry dev
Builds, runs the app on port 8080 (--port N to change) and watches
src/, meson.build and web-config.json: saving a file rebuilds
incrementally — page HTML and resources recompile via the meson codegen
targets — and restarts the app when the build succeeds.
The environment below is required for the underlying meson builds (the
spry dev child processes set it for you; export it in shells where you
build or run manually):
export WS_PREFIX="$HOME/.local"
export PKG_CONFIG_PATH="$WS_PREFIX/lib64/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
export XDG_DATA_DIRS="$WS_PREFIX/share${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"
export LD_LIBRARY_PATH="$WS_PREFIX/lib64${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
meson setup builddir
ninja -C builddir
./builddir/usm-web 8080 --repo ../repos
--repo points at the parent directory holding the repositories (see the
layout above). Repo parsing uses libusm (Usm.Repository,
Usm.RepositoryListing, Usm.Manifest.from_package) — no hand-rolled
usml/usmr mappers.
| Path | Purpose |
|---|---|
src/main.vala |
application wiring: modules, config, pages, action, endpoints |
src/UsmWebConfig.vala |
the "usm-web" config section (repo parent, repositories, installer url|path, base_url, name) |
src/RepositoryService.vala |
multi-repository discovery + libusm-backed read side with per-repo mtime reload |
src/DerivedBase.vala |
base-URI derivation from config/forwarded headers |
src/PackagesState.vala |
shared packages slot-state builder (overview + repo-scoped) and size/fingerprint formatting |
src/entrypoints/ |
HomeEntrypoint (/), RepoBrowseEntrypoint (/repo/{name}) and PackageDetailEntrypoint (/repo/{name}/package/{file}) |
src/actions/ |
SearchPackagesAction — server-side table filtering (all repositories or one) |
src/endpoints/ |
the USM-facing endpoints listed above |
src/pages/*.html |
Statum pages, compiled by statum-mkpstm at build time |
src/Static/main.css |
stylesheet embedded by statum-mkres |
MANIFEST.usm |
USM package manifest: provides bin:usm-web, build/runtime/manage deps |
usm-scripts/ |
USM build + install scripts (meson staging) |
web-config.json |
static keys and the usm-web section (gitignored, 0600) |
Registrations live between // spry:*-begin/end markers in src/main.vala,
# spry:*-begin/end markers in meson.build and <!-- spry:nav-begin/end -->
markers in src/pages/main.html; the spry add commands edit only those
blocks and are idempotent.
USM itself installs from the canonical installer URL
(https://packages.astrologue.nz/install-usm.sh); pass
--installer-url file://… to carry a locally built installer into the
image instead.
spry deploy --verbose \
--repository ../web-stack-repo/web-stack.usmr
--system {fedora,debian,ubuntu,alpine,gentoo} is shorthand for the
matching base image plus system package manager (mutually exclusive with
--spm/--base); with no flags the fedora equivalent applies, so the
command above is unchanged. Alpine images build the stack natively on
musl; gentoo stage3 compiles the platform from source — allow an hour or
more for the image build.
This packages the application and builds a single-stage container image
through USM (usm manifest deploy): the MANIFEST.usm + usm-scripts/
drive the in-container build and install, the Web-Stack resolves from the
given repository (including the usm package that provides the libusm
pc:/vapi: refs this app builds against), and the system package manager
provides the platform libraries. The result is
usm-web-<version>.image.tar.xz, loadable with podman load -i.
web-config.json is never packaged (.usmignore), so keys are never baked
into the image. Bind-mount the repository read-only at /repo and, when you
want stable keys or an installer section, mount a config:
podman load -i usm-web-0.1.image.tar.xz
podman run -d -p 8080:8080 \
-v /path/to/repos-parent:/repo:ro,Z \
-v $PWD/web-config.json:/run/web-config.json:ro \
-e ASTRALIS_CONFIG_PATH=/run/web-config.json \
localhost/usm-web:0.1
/repo inside the container is the repositories parent directory: every
subdirectory holding a .usmr is served at /repo/<name>/….