This repository has been archived on 2026-10-18. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Miles WardandClaude Fable 5.1 04a86ead95 v0.2: covered codes, service marks, and an audit log
Codes are covered until revealed. A reveal is a server-side, per-session
window (60 s, two periods): POST /api/accounts/{id}/reveal opens it and
returns the code, GET /api/codes only ever returns codes for accounts in
that window, and /hide closes it early. The browser therefore never holds
a code it has not asked for by name, which is what makes the log honest.

Settings -> Log is an audit trail in the style of Daito: one line per
event with who, how long ago and from which address. It records what the
server observed - sign-ins and failed attempts (under the name tried),
reveals, accounts added / renamed / removed, delivery and credential
changes, test messages. Entries are JSON lines in audit.jsonl (owner-only,
newest 5,000 kept, compacted at twice that). The address comes from
X-Forwarded-For / X-Real-IP when parseable, else the TCP peer via
ConnectInfo; in Docker bridge networking that peer is the gateway, which
the README and template now say.

The account list shows each service's mark instead of an initial. The
pack (crates/webui/src/icons.js, generated by scripts/fetch-icons.py) is
~175 marks from Simple Icons (CC0) plus Font Awesome Free brands (CC BY
4.0) for Amazon, AWS, Microsoft, LinkedIn, Slack, Xbox, Salesforce and
Yahoo, which Simple Icons no longer carries. Matching is by issuer name,
then shorter word prefixes, then the label's mail domain; unmatched
accounts keep the initial tile. Marks that would vanish against a theme's
tile fall back to ink for that theme only.

The setup and Delivery platform pickers are plain text; the coloured dots
are gone.

Router tests cover the reveal window, session scoping, 401s, and the
forwarded address landing in the log.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-09 02:08:47 -04:00

107 lines
3.8 KiB
Markdown

# Publishing to Gitea
Releases are cut by hand. Each one needs a Gitea **personal access token**
with the `write:repository` and `write:package` scopes, which is why none of
this is automated: the token should only ever exist in your own shell or
keychain.
On a Mac that has pushed before, git already holds the token in the login
keychain and nothing needs exporting. Elsewhere, create one at **Gitea →
Settings → Applications → Generate New Token** and export it once per shell
session:
```bash
export GITEA_TOKEN='<paste-your-token>'
```
## 1. Cut the version
Bump `version` in the workspace `Cargo.toml`, update the `IMAGE_TAG` and
`GIT_REF` defaults in `scripts/build-and-publish-unraid.sh`, add a line to the
README changelog, and commit. Then tag:
```bash
git tag -a v0.2 -m "OpenMFA v0.2"
```
Tags are `vMAJOR.MINOR[.PATCH]` — `v0.1`, `v0.2`, … — and the image carries
the same number without the `v` (`0.1`, `0.1.1`, `0.2`) plus a moving `latest`.
## 2. Push the code and the tag
```bash
git push origin main --follow-tags
```
With a token in the environment rather than the keychain, prefix the command
with `git -c "http.extraHeader=Authorization: token $GITEA_TOKEN"`.
## 3. Build the image
The Dockerfile cross-compiles to `x86_64-unknown-linux-musl` from whatever
architecture the builder runs on, so this is fast on Apple Silicon — no QEMU.
`--provenance=false --sbom=false` matters: Unraid's Docker cannot load the
attestation manifests BuildKit attaches by default.
```bash
docker build --pull --platform linux/amd64 --provenance=false --sbom=false -f deploy/docker/Dockerfile -t gitea.milesward.dev/mward4/openmfa:0.2 -t gitea.milesward.dev/mward4/openmfa:latest .
```
## 4. Push the image
**Never run `docker login` or `docker logout` for `gitea.milesward.dev` on a
Mac where git keeps the token in the keychain.** Docker's `osxkeychain`
credential helper maps to the same keychain item as git's: `login` fails with
"The specified item already exists in the keychain (-25299)", and `logout`
silently deletes the credential git was using, so the next `git push` fails
with a bare 401. Write the auth into a throwaway config instead — a config
that already contains an `auths` entry makes the CLI skip the helper:
```bash
export DOCKER_CONFIG="$(mktemp -d)" && printf '{"auths":{"gitea.milesward.dev":{"auth":"%s"}}}' "$(printf 'mward4:%s' "$GITEA_TOKEN" | base64 | tr -d '\n')" > "$DOCKER_CONFIG/config.json" && docker push gitea.milesward.dev/mward4/openmfa:0.2 && docker push gitea.milesward.dev/mward4/openmfa:latest; rm -rf "$DOCKER_CONFIG"; unset DOCKER_CONFIG
```
On a Colima host, `export DOCKER_HOST="unix://$HOME/.colima/default/docker.sock"`
first: an isolated `DOCKER_CONFIG` has no `currentContext`, and the CLI would
otherwise look for `/var/run/docker.sock`.
On a fresh machine, `scripts/build-and-publish-unraid.sh` does the clone,
build and push in one pass using that same private-config approach:
```bash
GITEA_TOKEN="$GITEA_TOKEN" ./scripts/build-and-publish-unraid.sh
```
## 5. Verify the pull
The repo is public, so this needs no credentials — which is exactly how Unraid
will fetch it:
```bash
docker pull gitea.milesward.dev/mward4/openmfa:0.2
```
## 6. Deploy on Unraid
Add a container with Repository set to:
```
gitea.milesward.dev/mward4/openmfa:0.2
```
(or `:latest`). Map `/var/lib/openmfa` to `/mnt/user/appdata/openmfa`,
publish port `8720`, and leave networking on bridge. Or import
`deploy/unraid/openmfa.xml` into
`/boot/config/plugins/dockerMan/templates-user/` to get all of that prefilled.
To upgrade an existing container, change the tag and apply. The vault, key,
settings and admin account all live in the appdata mount and carry over.
## Afterwards
If a token was exported, make sure it is not left in the shell:
```bash
unset GITEA_TOKEN
```