Stop, keep data
Stop and remove containers while retaining the artifact-data volume and your local .env.
docker compose down
Self-host · source build · v1.2.0
This localhost path takes you from a versioned source checkout to one private Markdown artifact. Docker binds the service to 127.0.0.1, and sharing stays disabled by default.
About 10 minutes after prerequisites · macOS or Linux host · no public server required
01 / Build and start
Run these commands in a terminal. The bootstrap step asks for a viewer password of at least 12 characters without echoing it and writes generated credentials to a mode-0600 .env file.
The release tag makes this guide reproducible instead of following a moving branch.
git clone https://github.com/eloktev/artifact-relay.git cd artifact-relay git checkout v1.2.0
The supported default path builds the selected source checkout locally.
docker build -t artifact-relay:1.2.0 .
Choose the password you will use in the browser. The script separately generates the API token and session signing key; it never stores the plaintext viewer password.
./scripts/bootstrap.sh
A successful health request returns a small JSON response without secret data.
docker compose up -d docker compose ps curl -fsS http://localhost:8000/api/health
02 / First value
This snippet creates a temporary file, loads the generated environment without printing it, sends the token only in the authorization header, extracts the returned opaque URL, and opens it.
Your viewer password creates a browser session for the private library. The generated API token authorizes publishing and API reads or deletes. Do not paste either credential into an artifact, chat, command output, or source control.
SAMPLE_FILE="$(mktemp)"
trap 'rm -f "$SAMPLE_FILE"' EXIT
printf '# First relay\n\nPublished from my self-hosted Artifact Relay.\n' > "$SAMPLE_FILE"
set -a
. ./.env
set +a
RESPONSE="$(curl -fsS -X POST http://localhost:8000/api/artifacts \
-H "Authorization: Bearer ${ARTIFACT_API_TOKEN}" \
-F 'title=First relay' \
-F 'summary=Local installation check' \
-F 'format=markdown' \
-F 'expires_in_days=30' \
-F "content=@${SAMPLE_FILE};filename=first-relay.md;type=text/markdown")"
unset ARTIFACT_API_TOKEN SESSION_SECRET_KEY VIEW_PASSWORD_HASH
ARTIFACT_URL="$(printf '%s' "$RESPONSE" | \
python3 -c 'import json,sys; print(json.load(sys.stdin)["url"])')"
printf 'Published: %s\n' "$ARTIFACT_URL"
if command -v open >/dev/null; then
open "$ARTIFACT_URL"
else
xdg-open "$ARTIFACT_URL"
fiThe artifact page asks for the viewer password you chose during bootstrap. Its path contains an opaque artifact ID, but the page remains private until you log in.
03 / Stop or continue
Stopping containers preserves artifacts in the named Docker volume. Deleting the volume is irreversible.
Stop and remove containers while retaining the artifact-data volume and your local .env.
docker compose down
Only when you no longer need any artifacts, remove containers and the persistent volume, then remove the credential file.
docker compose down --volumes rm .env
Prefer not to operate it?
Hermes can connect an isolated instance hosted and maintained for you. Self-hosting remains fully supported when you want to own the runtime and data.