# 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='' ``` ## 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 ```