GHCR images
Signing in to the registry, which images exist, how they are tagged, and how to pin one.
Every NuFi image is on the GitHub Container Registry under
ghcr.io/dudaji-vn. They are
private: every machine that pulls one signs in first.
One-time sign-in, on every host
- Create a personal access token at
github.com/settings/tokens/new
with the single scope
read:packages. - Sign in:
echo ghp_xxxxxxxxxxxxxxxxxxxx | docker login ghcr.io -u <your-github-username> --password-stdin - The credential stays in
~/.docker/config.jsonuntil you rotate the token.
denied: denied on a pull means the sign-in expired or the token lacks the
scope. Sign in again.
The images
| Image | What it is | Built by |
|---|---|---|
ghcr.io/dudaji-vn/nufichat | the NuFi app | chat-release.yml |
ghcr.io/dudaji-vn/nufi-console | NuFi Console | console-image.yml |
ghcr.io/dudaji-vn/nufichat-admin-panel | NuFi Admin Panel | admin-panel-image.yml |
ghcr.io/dudaji-vn/nufi-studio | NuFi Studio | nufi-agent-image.yml |
ghcr.io/dudaji-vn/nufi-works | NuFi Works | agents-image.yml |
The gateway (nufi/litellm:local) and the injection scanner
(nufi/scanner:local) are not published; the compose stack builds them on
the host from deploy/platform/litellm/ and deploy/platform/scanner/.
All five published images are linux/amd64 only. On an arm64 host (Apple
Silicon, Graviton) Docker refuses to pull them until the service carries
platform: linux/amd64, and then runs them under emulation. See
Run the stack locally for the
override file.
Tags
Every image carries the same set:
| Tag | Made by | Use |
|---|---|---|
vX.Y.Z | a release tag on main (nufi-vX.Y.Z for the app, nufi-console-vX.Y.Z, nufi-admin-vX.Y.Z, nufi-studio-vX.Y.Z, nufi-works-vX.Y.Z); the prefix is dropped from the image tag | production |
latest | the same release tag | never in a deployment; it moves |
main | every push to main that touches the app | development and staging |
sha-<short> | every push to main | pinning a specific build without cutting a release |
The release tag on the repository and the tag on the image differ by the
prefix: nufi-v0.1.12 on the repository is nufichat:v0.1.12 on the
registry. The latest at the time of writing: nufichat:v0.1.12,
nufi-console:v0.1.7, nufichat-admin-panel:v0.0.5; Studio and Works have
shipped from main so far. See Release and deploy
for how a tag becomes an image.
Pinning
Production pins a version and moves it on purpose. In deploy/platform:
# .env
NUFI_CONSOLE_TAG=v0.1.7The compose file reads ${NUFI_CONSOLE_TAG:-main}. The app has no such
variable there; change the image: line on the librechat service from
nufichat:main to nufichat:v0.1.12. In deploy/railway, IMAGE_TAG in
.env pins the app the same way.
Apply a new pin:
docker compose pull librechat console
docker compose up -d librechat consoleBoth are no-ops when nothing changed.
When a pull fails
| Message | Meaning |
|---|---|
denied: denied | not signed in, or the token lacks read:packages |
manifest unknown | the tag does not exist; check the spelling, then the Actions run that should have published it |
no matching manifest for linux/arm64/v8 | arm64 host without the platform override |
TLS handshake timeout | the registry is throttling you; wait a minute |
Offline hosts
Mirror the images into your own registry and change the image: lines:
docker pull ghcr.io/dudaji-vn/nufichat:v0.1.12
docker tag ghcr.io/dudaji-vn/nufichat:v0.1.12 registry.example.com/nufichat:v0.1.12
docker push registry.example.com/nufichat:v0.1.12The two locally built images need the build context (litellm/, scanner/)
on the host, or a mirror of the image you built elsewhere with the same
docker tag and push.
Untagged images stay on GHCR for 90 days; tagged ones until someone deletes them. Nothing prunes the package list automatically.