Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .agents/skills/dmf-platform-umbrella-conventions/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
name: dmf-platform-umbrella-conventions
description: DMF Platform umbrella workspace conventions, boot ritual, and cross-repo state rules
description: dmfdeploy platform umbrella workspace conventions, boot ritual, and cross-repo state rules
source: auto-skill
extracted_at: '2026-06-10T13:00:00.000Z'
---

# DMF Platform Umbrella Conventions
# dmfdeploy platform Umbrella Conventions

## Context

This repo (`dmf-init`) is a component of the **DMF Platform**, an umbrella workspace with multiple component repos checked out alongside it. Operators set `$DMFDEPLOY_UMBRELLA` to its local path.
This repo (`dmf-init`) is a component of the **dmfdeploy platform**, an umbrella workspace with multiple component repos checked out alongside it. Operators set `$DMFDEPLOY_UMBRELLA` to its local path.

## Before any non-trivial change

Expand All @@ -23,7 +23,7 @@ Then read in order:
1. `dmfdeploy/STATUS.md` — what's happening across all repos right now
2. `dmfdeploy/QWEN.md` — full boot ritual + skills index + Qwen-specific rules
3. `dmfdeploy/docs/decisions/INDEX.md` — ADRs applicable to your task
4. The most recent file under `dmfdeploy/docs/handoffs/`
4. The comments on your tracking issue (the old [handoff notes](https://github.com/dmfdeploy/dmfdeploy/tree/22f351cd1cf4b16a391a013861015666b065e55c/docs/handoffs) were removed from the umbrella tree)

## Cross-repo state

Expand Down
2 changes: 1 addition & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# .githooks/pre-commit — secret scan via gitleaks.
#
# Mirrors the umbrella DMF Platform pre-commit hook for sub-repos.
# Mirrors the umbrella dmfdeploy platform pre-commit hook for sub-repos.
# Refuses any commit whose staged changes match a gitleaks rule from
# the .gitleaks.toml at the repo root.
#
Expand Down
6 changes: 3 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# === DMF Platform .gitignore ===
# === dmfdeploy platform .gitignore ===
# Repo-specific rules go above the baseline block at the bottom.

# Python (FastAPI backend)
Expand Down Expand Up @@ -55,8 +55,8 @@ __MACOSX/
*.swo
*~

# === Secrets-prevention baseline (DMF Platform 2026-05-07) ===
# Patterns that should never be committed across any DMF Platform repo.
# === Secrets-prevention baseline (dmfdeploy platform 2026-05-07) ===
# Patterns that should never be committed across any dmfdeploy platform repo.
# Repo-specific rules belong above this block; add new shared rules here.

# Kubeconfigs
Expand Down
2 changes: 1 addition & 1 deletion .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# DMF Platform — sub-repo gitleaks config
# dmfdeploy platform — sub-repo gitleaks config
#
# Mirrors the public-safe subset of the umbrella's .gitleaks.toml so each
# public repo's local pre-commit catches the same leak categories:
Expand Down
7 changes: 2 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

The Day-0 stateless init/bootstrap container (React + FastAPI) that wraps the dmf-env wizard + toolchain behind a localhost web UI.

This repo is part of the **DMF Platform**. GitHub is the canonical home and the
This repo is part of the **dmfdeploy platform**. GitHub is the canonical home and the
single source of truth: all changes land via **Pull Request** against `main`.
(The full pre-publish history lives in a LAN-only `dmf-init-archive` Forgejo
repo, reachable as a read-only `archive` git remote — it is **not** an upstream
and is never a contribution path.)

## Quick start

1. Read the platform overview in the [dmfdeploy/dmfdeploy](https://github.com/dmfdeploy/dmfdeploy) umbrella repo
(`docs/architecture/DMF Platform Plan.md`) and apply any relevant ADRs from
(`docs/architecture/dmfdeploy-platform-plan.md`) and apply any relevant ADRs from
`docs/decisions/INDEX.md`.
2. Fork or branch, make your change on a topic branch, open a PR against `main`.
3. Ensure CI is green and your commits are **signed off** (see DCO below).
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2026 DMF Platform contributors
Copyright 2026 dmfdeploy platform contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 3 additions & 3 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
DMF Platform — dmf-init (Day-0 stateless init/bootstrap container)
Copyright 2026 DMF Platform contributors
dmfdeploy platform — dmf-init (Day-0 stateless init/bootstrap container)
Copyright 2026 dmfdeploy platform contributors
Licensed under the Apache License, Version 2.0 (see LICENSE).

This product packages, but does not vendor, the DMF Platform env tooling
This product packages, but does not vendor, the dmfdeploy platform env tooling
(dmf-env), generic playbooks/roles (dmf-infra), and AWX launcher runbooks
(dmf-runbooks). Those are pulled at image-build time from their own
repositories; each is governed by its own LICENSE. The container image
Expand Down
91 changes: 52 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

[![CI](https://github.com/dmfdeploy/dmf-init/actions/workflows/ci.yml/badge.svg)](https://github.com/dmfdeploy/dmf-init/actions/workflows/ci.yml)

**Day-0 self-contained init & bootstrap container** for the DMF Platform.
**Day-0 installer container** that commissions a dmfdeploy platform cluster on a node you bring, through a localhost-only web UI.

Part of [dmfdeploy](https://github.com/dmfdeploy/dmfdeploy), an independent open prototype that explores the ideas of the EBU Dynamic Media Facility on commodity infrastructure. Status: prototype, single-node sandbox.

> **New to the project vocabulary?** See the [DMF Glossary](https://github.com/dmfdeploy/dmfdeploy/blob/main/docs/GLOSSARY.md) for project-coined terms (appliance, checkpoint, age key, answers-file, …).

A single container that puts a friendly, localhost-only web UI on the existing
[`dmf-env`](https://github.com/dmfdeploy/dmf-env) env-creation + `bin/`
bootstrap toolchain, drives a cluster from zero to verified, and offers a
**passphrase-wrapped backup as a browser download** at each checkpoint — so the
operator can commission a cluster, save the backup wherever they choose, and
then delete the container with nothing left behind.
A single container puts a friendly, localhost-only web UI on the existing
[`dmf-env`](https://github.com/dmfdeploy/dmf-env) env-creation and `bin/`
bootstrap toolchain. It drives a cluster from zero to verified. At each
checkpoint it offers a **passphrase-wrapped backup as a browser download**. You
can commission a cluster, save the backup wherever you choose, and then delete
the container with nothing left behind.
Reached as `http://localhost`, which is a browser **secure context** (clipboard
+ WebAuthn work) with no certificate warning; HTTPS is opt-in for non-localhost
access.
Expand All @@ -23,7 +25,7 @@ what it does and does not show, is on the

> **What you get (the deliverable):** a **commissioned, verified cluster** plus
> one or more **passphrase-wrapped encrypted backups** (browser downloads). The
> container is **disposable / run-once** — delete it when you're done and the
> container is **disposable / run-once**; delete it when you're done and the
> backups + your passphrase are all that remain. It does **not** build or emit a
> deployable image; it *commissions a cluster*.

Expand All @@ -34,12 +36,12 @@ Architecture orientation: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).
| Mode | Purpose |
|---|---|
| **Create new** | Collect inputs, render the env bundle, seal a downloadable passphrase-wrapped backup (checkpoint #1), then orchestrate the full sandbox bootstrap (pre-seed → seed → post-seed → configure → verify) with live logs and per-checkpoint downloads. |
| **Manage** | Restore an env by uploading a previously downloaded encrypted backup (passphrase-unwrapped), then re-run playbooks, upgrade, rotate, or tear down — offering a fresh downloadable backup on any change. |
| **Manage** | Restore an env by uploading a previously downloaded encrypted backup (passphrase-unwrapped), then re-run playbooks, upgrade, rotate, or tear down, offering a fresh downloadable backup on any change. |

## Design principles

- **Stateless.** All env state lives in a tmpfs scratch root; nothing durable is
written to the host. After commissioning, the downloaded encrypted backup(s) +
written to the host. After commissioning, the downloaded encrypted backups and
the operator passphrase are the only artifacts that matter.
- **Passphrase wraps the age key.** The age private key rides inside the backup;
the backup is encrypted by an operator passphrase (the single human-held
Expand All @@ -54,22 +56,25 @@ Architecture orientation: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).

### Quick start (launcher)

If you just want to get going, the `dmf-init` launcher wraps Docker for you — it
To get started, the `dmf-init` launcher wraps Docker for you; it
starts the container with the correct flags, waits until it's ready, extracts the
one-time launch link, and opens your browser. No clone required:

Read the launcher before you run it. Download it, read it, then run it:

```bash
curl -fsSL https://raw.githubusercontent.com/dmfdeploy/dmf-init/main/bin/dmf-init | bash -s -- up
curl -fsSL https://raw.githubusercontent.com/dmfdeploy/dmf-init/main/bin/dmf-init -o dmf-init
less dmf-init
bash dmf-init up
```

> Piping a script into your shell runs remote code — if you'd rather read it
> first (recommended), download then run:
> ```bash
> curl -fsSL https://raw.githubusercontent.com/dmfdeploy/dmf-init/main/bin/dmf-init -o dmf-init
> less dmf-init && bash dmf-init up
> ```
If you trust the source, you can pipe the launcher into your shell instead. This runs remote code without a chance to read it first:

```bash
curl -fsSL https://raw.githubusercontent.com/dmfdeploy/dmf-init/main/bin/dmf-init | bash -s -- up
```

From a clone, it's just `bin/dmf-init`:
From a clone, run `bin/dmf-init`:

```bash
bin/dmf-init up # start + open the browser (prints the link too)
Expand All @@ -80,13 +85,13 @@ bin/dmf-init down # stop and remove the container

Options for `up`: `--port N` (default 8000), `--tls` (HTTPS), `--image REF`,
`--repo-base-url URL` (private mirror). Run `bin/dmf-init --help` for details. The
launcher never weakens the security posture — it always publishes on `127.0.0.1`
launcher never weakens the security posture; it always publishes on `127.0.0.1`
only and mounts the tmpfs data root. The explicit `docker run` invocations below
remain the advanced/reference path (and are what the launcher runs under the hood).

### Prerequisites

A **BuildKit-capable Docker** is mandatory — the `Dockerfile` pins
A **BuildKit-capable Docker** is mandatory; the `Dockerfile` pins
`# syntax=docker/dockerfile:1.7` and `bin/build-bundle.sh` forces
`DOCKER_BUILDKIT=1`, so classic builders will fail. **Docker 23.0+** is a
sensible minimum.
Expand All @@ -101,7 +106,7 @@ Pick based on whether the host has **runtime network access**:
| **Image** | `ghcr.io/dmfdeploy/dmf-init:latest` | `dmf-init:bundle` |
| **Repos** | Fetched at startup | Baked into the tarball |

**Networked** (canonical ghcr image — simplest path):
**Networked** (canonical ghcr image: simplest path):

```bash
docker run --rm -p 127.0.0.1:8000:8000 \
Expand All @@ -120,7 +125,7 @@ docker run --rm -p 127.0.0.1:8000:8000 \
> `-e DMF_ALLOW_NON_TMPFS_DATA_ROOT=true` (dev/test only). `docker rm` stays
> safe because nothing durable is written to host disk.

Repos are fetched from the public org `https://github.com/dmfdeploy` by default —
Repos are fetched from the public org `https://github.com/dmfdeploy` by default;
no extra env needed. To pull from a private mirror, override the base URL (and
optionally supply credentials):

Expand All @@ -134,7 +139,7 @@ docker run --rm -p 127.0.0.1:8000:8000 \
Multi-arch (amd64 + arm64), published by
[`.github/workflows/publish-image.yml`](.github/workflows/publish-image.yml).

**Air-gapped** (bundle — repos baked in via `bin/build-bundle.sh`):
**Air-gapped** (bundle: repos baked in via `bin/build-bundle.sh`):

```bash
# on a machine with Docker + the umbrella checked out:
Expand All @@ -152,7 +157,7 @@ it by a non-localhost address.

**Lost your session / launch link?** The session refreshes while you're active
and lasts well beyond a single run idle, but if it lapses (or you closed the tab)
the one-time launch link is spent. You don't need to restart — re-mint a fresh
the one-time launch link is spent. You don't need to restart; re-mint a fresh
link on the *running* container (preserving the in-progress run) by sending it
`SIGHUP`, then open the new link printed in the logs:

Expand All @@ -166,18 +171,22 @@ Canonical spec:

### Target node

The installer provisions a **node you bring** — an SSH-reachable **Debian 12 or
13, ARM64** host (a cloud VM, a spare box, a Raspberry Pi). Other distros and
architectures are untested for now. Your own workstation OS doesn't matter; the
installer runs in a browser. On the wizard's *Target node* step you supply:

- **Node IP** — an address reachable *from this installer container*. Not
`localhost` / `127.0.0.1`: that resolves to the container itself, not your node.
- **Ansible user** — the SSH login on that node (`root`, or the image's default
The installer provisions a **node you bring**: an SSH-reachable **Debian, ARM64**
host (a cloud VM, a spare box, a Raspberry Pi). The installer does not check the
Debian version itself. The running v0.1 sandbox is a Debian 13 (Trixie) ARM64
node with 4 vCPU, 16 GB RAM and a 60 GB disk, and the full stack uses about 7 GB
RAM and 30 GB disk at idle. Treat that as the minimum. The
[`dmf-infra`](https://github.com/dmfdeploy/dmf-infra) baseline playbook also
handles Debian 12 (Bookworm). Other distros and architectures are untested for
now. Your own workstation OS doesn't matter; the installer runs in a browser. On the wizard's *Target node* step you supply:

- **Node IP**: an address reachable *from this installer container*. Do not use
`localhost` or `127.0.0.1`, which resolve to the container itself.
- **Ansible user**: the SSH login on that node (`root`, or the image's default
user such as `debian`).
- **Interface** — the node's primary network interface (`eth0`, `ens3`, …).
- **Interface**: the node's primary network interface (`eth0`, `ens3`, …).

These fields are intentionally blank by default — fill them for *your* node.
These fields are intentionally blank by default; fill them for *your* node.

> **macOS convenience (not the paved path):** `dmf-env/bin/recreate-sandbox-vm.sh`
> spins up a local Lima VM (whose user / interface are `lima` / `lima0`). It
Expand All @@ -186,11 +195,15 @@ These fields are intentionally blank by default — fill them for *your* node.

## Dependencies

- [`dmf-env`](https://github.com/dmfdeploy/dmf-env) — env tooling (`init-wizard.sh`, `bin/` scripts) the container wraps.
- [`dmf-infra`](https://github.com/dmfdeploy/dmf-infra) — generic bootstrap playbooks/roles.
- [`dmf-runbooks`](https://github.com/dmfdeploy/dmf-runbooks) — catalog launcher (post-seed).
- [`dmf-env`](https://github.com/dmfdeploy/dmf-env): env tooling (`init-wizard.sh`, `bin/` scripts) the container wraps.
- [`dmf-infra`](https://github.com/dmfdeploy/dmf-infra): generic bootstrap playbooks/roles.
- [`dmf-runbooks`](https://github.com/dmfdeploy/dmf-runbooks): catalog launcher (post-seed).

## For contributors

`AGENTS.md`, `CLAUDE.md` and `QWEN.md` hold instructions for AI coding agents that help maintain this repository. Human contributors can skip them and start with [CONTRIBUTING.md](CONTRIBUTING.md).

## License

Apache License, Version 2.0 — see [LICENSE](LICENSE).
Apache License, Version 2.0. See [LICENSE](LICENSE).
Third-party components are listed in [NOTICE](NOTICE).
Loading