Skip to content

Commit c1f3467

Browse files
committed
Release abstractgateway 0.2.24
1 parent bc3ba8c commit c1f3467

23 files changed

Lines changed: 486 additions & 133 deletions

.github/workflows/publish-ghcr.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish GHCR Server Image
1+
name: Publish GHCR Gateway Images
22

33
on:
44
workflow_dispatch:
@@ -18,7 +18,7 @@ concurrency:
1818

1919
jobs:
2020
publish:
21-
name: Publish server image
21+
name: Publish Gateway images
2222
runs-on: ubuntu-latest
2323
steps:
2424
- uses: actions/checkout@v4
@@ -85,9 +85,11 @@ jobs:
8585
provenance: false
8686
push: true
8787
build-args: |
88-
ABSTRACTGATEWAY_INSTALL_MODE=local
88+
ABSTRACTGATEWAY_INSTALL_MODE=pypi
8989
ABSTRACTGATEWAY_VERSION=${{ steps.meta.outputs.version }}
9090
tags: |
91+
ghcr.io/${{ github.repository_owner }}/abstractgateway:${{ steps.meta.outputs.version }}
92+
ghcr.io/${{ github.repository_owner }}/abstractgateway:latest
9193
ghcr.io/${{ github.repository_owner }}/abstractgateway-server:${{ steps.meta.outputs.version }}
9294
ghcr.io/${{ github.repository_owner }}/abstractgateway-server:latest
9395
- name: Attempt experimental NVIDIA full server image
@@ -100,9 +102,11 @@ jobs:
100102
provenance: false
101103
push: true
102104
build-args: |
103-
ABSTRACTGATEWAY_INSTALL_MODE=local
105+
ABSTRACTGATEWAY_INSTALL_MODE=pypi
104106
ABSTRACTGATEWAY_VERSION=${{ steps.meta.outputs.version }}
105107
ABSTRACTGATEWAY_EXTRAS=gpu
106108
tags: |
109+
ghcr.io/${{ github.repository_owner }}/abstractgateway:${{ steps.meta.outputs.version }}-gpu
110+
ghcr.io/${{ github.repository_owner }}/abstractgateway:gpu-latest
107111
ghcr.io/${{ github.repository_owner }}/abstractgateway-server-nvidia:${{ steps.meta.outputs.version }}
108112
ghcr.io/${{ github.repository_owner }}/abstractgateway-server-nvidia:latest

.github/workflows/release.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ jobs:
198198
- uses: pypa/gh-action-pypi-publish@release/v1
199199

200200
publish-ghcr:
201-
name: Publish GHCR server image
201+
name: Publish GHCR Gateway images
202202
runs-on: ubuntu-latest
203203
needs: [build, ensure-tag, publish-pypi]
204204
permissions:
@@ -244,9 +244,11 @@ jobs:
244244
provenance: false
245245
push: true
246246
build-args: |
247-
ABSTRACTGATEWAY_INSTALL_MODE=local
247+
ABSTRACTGATEWAY_INSTALL_MODE=pypi
248248
ABSTRACTGATEWAY_VERSION=${{ needs.build.outputs.version }}
249249
tags: |
250+
ghcr.io/${{ github.repository_owner }}/abstractgateway:${{ needs.build.outputs.version }}
251+
ghcr.io/${{ github.repository_owner }}/abstractgateway:latest
250252
ghcr.io/${{ github.repository_owner }}/abstractgateway-server:${{ needs.build.outputs.version }}
251253
ghcr.io/${{ github.repository_owner }}/abstractgateway-server:latest
252254
- name: Attempt experimental NVIDIA full server image
@@ -259,10 +261,12 @@ jobs:
259261
provenance: false
260262
push: true
261263
build-args: |
262-
ABSTRACTGATEWAY_INSTALL_MODE=local
264+
ABSTRACTGATEWAY_INSTALL_MODE=pypi
263265
ABSTRACTGATEWAY_VERSION=${{ needs.build.outputs.version }}
264266
ABSTRACTGATEWAY_EXTRAS=gpu
265267
tags: |
268+
ghcr.io/${{ github.repository_owner }}/abstractgateway:${{ needs.build.outputs.version }}-gpu
269+
ghcr.io/${{ github.repository_owner }}/abstractgateway:gpu-latest
266270
ghcr.io/${{ github.repository_owner }}/abstractgateway-server-nvidia:${{ needs.build.outputs.version }}
267271
ghcr.io/${{ github.repository_owner }}/abstractgateway-server-nvidia:latest
268272

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.2.24] - 2026-05-31
11+
12+
### Added
13+
- Added `abstractgateway-config bootstrap-admin` to create or recover a file-backed `default/admin` Gateway user for hosted/container user-auth deployments.
14+
- Added a Gateway Docker entrypoint that bootstraps the admin user token into `/data/auth/bootstrap-admin-token` before starting the server.
15+
- Added first-class GHCR tags for `ghcr.io/lpalbou/abstractgateway:<version>`, `latest`, `<version>-gpu`, and `gpu-latest`, while preserving the legacy `abstractgateway-server` tags during transition.
16+
17+
### Changed
18+
- Gateway Docker and Compose defaults now use `/data`, enable hosted user auth, and build release images from the just-published PyPI wheel instead of local source.
19+
- Gateway startup now accepts hosted user-auth deployments without the legacy shared `ABSTRACTGATEWAY_AUTH_TOKEN`.
20+
21+
### Fixed
22+
- Fixed the PyPI/GHCR release path so container images can start cleanly from the published Gateway wheel and still provide an initial admin login token.
23+
1024
## [0.2.23] - 2026-05-31
1125

1226
### Fixed

README.md

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -95,17 +95,21 @@ Release images are published to GHCR. The default image is the light,
9595
portable server image:
9696

9797
```bash
98-
docker pull ghcr.io/lpalbou/abstractgateway-server:0.2.23
98+
docker pull ghcr.io/lpalbou/abstractgateway:0.2.24
9999
```
100100

101101
NVIDIA hosts can try the experimental full GPU image when local
102102
vLLM/HuggingFace/Diffusers engines are wanted. This image is published
103103
best-effort until it has a real CUDA build and smoke gate:
104104

105105
```bash
106-
docker pull ghcr.io/lpalbou/abstractgateway-server-nvidia:0.2.23
106+
docker pull ghcr.io/lpalbou/abstractgateway:0.2.24-gpu
107107
```
108108

109+
Legacy `abstractgateway-server` and `abstractgateway-server-nvidia` GHCR aliases
110+
are still published for existing deployments; new deployments should use
111+
`abstractgateway`.
112+
109113
The image installs the base `abstractgateway` package: HTTP server,
110114
`AbstractRuntime`, Runtime-owned provider/tool and
111115
multimodal facades, OpenAI-compatible text/media providers,
@@ -121,21 +125,23 @@ AbstractFlow note:
121125
- You do **not** need the `abstractflow` Python package to run `.flow` bundles (bundle mode). You only need it to author bundles. VisualFlow directory mode was intentionally removed from the gateway to keep the dependency direction clean.
122126

123127
```bash
124-
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
125-
126-
docker run --rm --name abstractgateway-server \
127-
-p 127.0.0.1:8080:8080 \
128-
-e ABSTRACTGATEWAY_AUTH_TOKEN="$ABSTRACTGATEWAY_AUTH_TOKEN" \
128+
docker run --rm --name abstractgateway \
129+
-p 8080:8080 \
130+
-e ABSTRACTGATEWAY_DATA_DIR=/data \
131+
-e ABSTRACTGATEWAY_USER_AUTH=1 \
129132
-e OPENAI_COMPATIBLE_BASE_URL="http://host.docker.internal:1234/v1" \
130-
-v "$PWD/runtime/gateway:/data/gateway" \
131-
-v "$PWD/flows/bundles:/data/flows:ro" \
132-
ghcr.io/lpalbou/abstractgateway-server:0.2.23
133+
-v "$PWD/runtime:/data" \
134+
ghcr.io/lpalbou/abstractgateway:latest
133135
```
134136

137+
On first start, the container creates `default/admin` and writes the admin user
138+
token to `runtime/auth/bootstrap-admin-token`. Use that token in `/console`,
139+
then rotate it or create named users from the console.
140+
135141
Configure framework model defaults through execution-host capability routes:
136142

137143
```bash
138-
abstractgateway-config set-default output.text \
144+
docker exec abstractgateway abstractgateway-config set-default output.text \
139145
--provider openai-compatible \
140146
--model your-model \
141147
--base-url http://host.docker.internal:1234/v1

docker/abstractgateway-server/.env.example

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
1-
# Required gateway auth token. Generate with:
2-
# python -c 'import secrets; print(secrets.token_urlsafe(32))'
3-
ABSTRACTGATEWAY_AUTH_TOKEN=replace-with-a-gateway-token
1+
# Gateway user-auth is the default container mode. On first start the
2+
# entrypoint creates default/admin and writes its token to:
3+
# <mounted runtime>/auth/bootstrap-admin-token
4+
ABSTRACTGATEWAY_USER_AUTH=1
5+
ABSTRACTGATEWAY_BOOTSTRAP_ADMIN=1
6+
# Set to 1 for local demos only; production logs should not contain raw tokens.
7+
ABSTRACTGATEWAY_BOOTSTRAP_PRINT_TOKEN=0
8+
# Optional fixed bootstrap token. Leave empty to generate one.
9+
ABSTRACTGATEWAY_BOOTSTRAP_ADMIN_TOKEN=
10+
11+
# Optional legacy shared Gateway admin token for compatibility/bootstrap APIs.
12+
# Browser apps should sign in with a Gateway user token instead.
13+
ABSTRACTGATEWAY_AUTH_TOKEN=
414

515
# Local bind. Keep loopback unless a reverse proxy/TLS layer handles public access.
616
ABSTRACTGATEWAY_PORT=8080
@@ -70,12 +80,13 @@ ABSTRACTVOICE_REMOTE_TIMEOUT_S=
7080

7181
# Local-source builds for unreleased checkouts:
7282
# ABSTRACTGATEWAY_INSTALL_MODE=local
73-
# ABSTRACTGATEWAY_VERSION=0.2.4
74-
# ABSTRACTGATEWAY_IMAGE_TAG=0.2.4-local
75-
# ABSTRACTGATEWAY_EXTRAS=server,memory
83+
# ABSTRACTGATEWAY_VERSION=0.2.23
84+
# ABSTRACTGATEWAY_IMAGE_TAG=0.2.23-local
85+
# ABSTRACTGATEWAY_EXTRAS=
7686

7787
# NVIDIA full image/local build overlay:
78-
# ABSTRACTGATEWAY_EXTRAS=server-nvidia
88+
# ABSTRACTGATEWAY_NVIDIA_IMAGE_TAG=0.2.23-gpu
89+
# ABSTRACTGATEWAY_EXTRAS=gpu
7990
# ABSTRACTVISION_BACKEND=diffusers
8091
# ABSTRACTVISION_DIFFUSERS_DEVICE=cuda
8192
# ABSTRACTVISION_DIFFUSERS_ALLOW_DOWNLOAD=0

docker/abstractgateway-server/Dockerfile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,21 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
1010
PIP_NO_CACHE_DIR=1 \
1111
HOST=0.0.0.0 \
1212
PORT=8080 \
13-
ABSTRACTGATEWAY_DATA_DIR=/data/gateway \
14-
ABSTRACTGATEWAY_FLOWS_DIR=/data/flows \
13+
ABSTRACTGATEWAY_DATA_DIR=/data \
14+
ABSTRACTGATEWAY_USER_AUTH=1 \
1515
ABSTRACTGATEWAY_WORKFLOW_SOURCE=bundle \
1616
ABSTRACTGATEWAY_STORE_BACKEND=file \
1717
ABSTRACTGATEWAY_ALLOWED_ORIGINS=http://localhost:*,http://127.0.0.1:*
1818

1919
RUN addgroup --system abstractgateway \
2020
&& adduser --system --ingroup abstractgateway --home /home/abstractgateway abstractgateway \
21-
&& mkdir -p /data/gateway /data/flows /workspace \
21+
&& mkdir -p /data /data/flows /workspace \
2222
&& chown -R abstractgateway:abstractgateway /data /workspace
2323

2424
COPY pyproject.toml README.md CHANGELOG.md /tmp/abstractgateway-src/
2525
COPY src /tmp/abstractgateway-src/src
2626
COPY flows/bundles/basic-agent.flow flows/bundles/basic-agent@0.0.1.flow /tmp/abstractgateway-src/flows/bundles/
27+
COPY docker/abstractgateway-server/entrypoint.sh /usr/local/bin/abstractgateway-docker-entrypoint
2728

2829
RUN apt-get update \
2930
&& apt-get install -y --no-install-recommends build-essential libmagic1 \
@@ -50,14 +51,17 @@ RUN apt-get update \
5051
fi; \
5152
fi \
5253
&& apt-get purge -y --auto-remove build-essential \
54+
&& chmod +x /usr/local/bin/abstractgateway-docker-entrypoint \
5355
&& rm -rf /var/lib/apt/lists/* /tmp/abstractgateway-src
5456

5557
USER abstractgateway
5658
WORKDIR /home/abstractgateway
5759

5860
EXPOSE 8080
61+
VOLUME ["/data"]
5962

6063
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
6164
CMD python -c "import os, urllib.request; urllib.request.urlopen(f'http://127.0.0.1:{os.getenv(\"PORT\", \"8080\")}/api/health', timeout=3).read()" || exit 1
6265

66+
ENTRYPOINT ["abstractgateway-docker-entrypoint"]
6367
CMD ["sh", "-c", "abstractgateway serve --host \"${HOST:-0.0.0.0}\" --port \"${PORT:-8080}\""]

docker/abstractgateway-server/Dockerfile.nvidia

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
1111
PIP_NO_CACHE_DIR=1 \
1212
HOST=0.0.0.0 \
1313
PORT=8080 \
14-
ABSTRACTGATEWAY_DATA_DIR=/data/gateway \
15-
ABSTRACTGATEWAY_FLOWS_DIR=/data/flows \
14+
ABSTRACTGATEWAY_DATA_DIR=/data \
15+
ABSTRACTGATEWAY_USER_AUTH=1 \
1616
ABSTRACTGATEWAY_WORKFLOW_SOURCE=bundle \
1717
ABSTRACTGATEWAY_STORE_BACKEND=file \
1818
ABSTRACTGATEWAY_ALLOWED_ORIGINS=http://localhost:*,http://127.0.0.1:* \
@@ -28,12 +28,13 @@ RUN apt-get update \
2828
libsndfile1 \
2929
&& addgroup --system abstractgateway \
3030
&& adduser --system --ingroup abstractgateway --home /home/abstractgateway abstractgateway \
31-
&& mkdir -p /data/gateway /data/flows /workspace \
31+
&& mkdir -p /data /data/flows /workspace \
3232
&& chown -R abstractgateway:abstractgateway /data /workspace /home/abstractgateway
3333

3434
COPY pyproject.toml README.md CHANGELOG.md /tmp/abstractgateway-src/
3535
COPY src /tmp/abstractgateway-src/src
3636
COPY flows/bundles/basic-agent.flow flows/bundles/basic-agent@0.0.1.flow /tmp/abstractgateway-src/flows/bundles/
37+
COPY docker/abstractgateway-server/entrypoint.sh /usr/local/bin/abstractgateway-docker-entrypoint
3738

3839
RUN python -m pip install --upgrade pip \
3940
&& if [ "$ABSTRACTGATEWAY_INSTALL_MODE" = "local" ]; then \
@@ -57,14 +58,17 @@ RUN python -m pip install --upgrade pip \
5758
fi; \
5859
fi; \
5960
fi \
61+
&& chmod +x /usr/local/bin/abstractgateway-docker-entrypoint \
6062
&& rm -rf /tmp/abstractgateway-src
6163

6264
USER abstractgateway
6365
WORKDIR /home/abstractgateway
6466

6567
EXPOSE 8080
68+
VOLUME ["/data"]
6669

6770
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
6871
CMD python -c "import os, urllib.request; urllib.request.urlopen(f'http://127.0.0.1:{os.getenv(\"PORT\", \"8080\")}/api/health', timeout=3).read()" || exit 1
6972

73+
ENTRYPOINT ["abstractgateway-docker-entrypoint"]
7074
CMD ["sh", "-c", "abstractgateway serve --host \"${HOST:-0.0.0.0}\" --port \"${PORT:-8080}\""]

docker/abstractgateway-server/README.md

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ This image packages the AbstractGateway HTTP/SSE server for durable
44
AbstractRuntime runs:
55

66
```bash
7-
ghcr.io/lpalbou/abstractgateway-server:0.2.15
7+
ghcr.io/lpalbou/abstractgateway:0.2.24
88
```
99

1010
Release images are published for `linux/amd64` and `linux/arm64`.
1111
A separate experimental full NVIDIA image is published best-effort for
1212
`linux/amd64`:
1313

1414
```bash
15-
ghcr.io/lpalbou/abstractgateway-server-nvidia:0.2.15
15+
ghcr.io/lpalbou/abstractgateway:0.2.24-gpu
1616
```
1717

18+
Legacy aliases `ghcr.io/lpalbou/abstractgateway-server:*` and
19+
`ghcr.io/lpalbou/abstractgateway-server-nvidia:*` are still published for a
20+
transition period. New deployments should use `abstractgateway`.
21+
1822
The image installs:
1923

2024
```bash
@@ -50,7 +54,12 @@ that route through its native MLX runner.
5054
Keep secrets in an uncommitted env file:
5155

5256
```bash
53-
ABSTRACTGATEWAY_AUTH_TOKEN=replace-with-a-gateway-token
57+
ABSTRACTGATEWAY_USER_AUTH=1
58+
ABSTRACTGATEWAY_BOOTSTRAP_ADMIN=1
59+
ABSTRACTGATEWAY_BOOTSTRAP_PRINT_TOKEN=0
60+
ABSTRACTGATEWAY_BOOTSTRAP_ADMIN_TOKEN=
61+
# Optional legacy shared admin token; browser apps should use Gateway user tokens.
62+
ABSTRACTGATEWAY_AUTH_TOKEN=
5463
ABSTRACTGATEWAY_PROVIDER=openai-compatible
5564
ABSTRACTGATEWAY_MODEL=your-model
5665
OPENAI_API_KEY=sk-...
@@ -72,32 +81,35 @@ ABSTRACTVOICE_REMOTE_API_KEY=
7281
Then run:
7382

7483
```bash
75-
docker run --rm --name abstractgateway-server \
76-
-p 127.0.0.1:8080:8080 \
84+
docker run --rm --name abstractgateway \
85+
-p 8080:8080 \
7786
--env-file .env \
78-
-v "$PWD/runtime/gateway:/data/gateway" \
79-
-v "$PWD/flows/bundles:/data/flows:ro" \
87+
-v "$PWD/runtime:/data" \
8088
-v "$PWD/workspace:/workspace" \
81-
ghcr.io/lpalbou/abstractgateway-server:0.2.15
89+
ghcr.io/lpalbou/abstractgateway:latest
8290
```
8391

84-
`ABSTRACTGATEWAY_AUTH_TOKEN` is the gateway bearer token. Clients send it as
85-
`Authorization: Bearer <token>`, including from Swagger UI's `Authorize`
86-
button. Provider keys stay inside the container.
92+
The container uses Gateway user auth by default. On first start the entrypoint
93+
creates the `default/admin` user and writes the raw token once to
94+
`runtime/auth/bootstrap-admin-token` inside the mounted data directory. Use that
95+
token in `/console` and then create/rotate/manage users from the Gateway
96+
Console. Set `ABSTRACTGATEWAY_BOOTSTRAP_PRINT_TOKEN=1` only for local demos
97+
where Docker logs are private. Provider keys stay inside the container.
8798

8899
For local OpenAI-compatible text endpoints such as Docker Model Runner, LM
89100
Studio, `mlx_lm.server`, or Ollama's `/v1` server, point the container at a URL
90101
reachable from Docker:
91102

92103
```bash
93-
docker run --rm --name abstractgateway-server \
94-
-p 127.0.0.1:8080:8080 \
95-
-e ABSTRACTGATEWAY_AUTH_TOKEN="$ABSTRACTGATEWAY_AUTH_TOKEN" \
104+
docker run --rm --name abstractgateway \
105+
-p 8080:8080 \
106+
-e ABSTRACTGATEWAY_USER_AUTH=1 \
96107
-e ABSTRACTGATEWAY_PROVIDER="openai-compatible" \
97108
-e ABSTRACTGATEWAY_MODEL="your-model" \
98109
-e OPENAI_COMPATIBLE_BASE_URL="http://host.docker.internal:1234/v1" \
99110
-e OPENAI_COMPATIBLE_API_KEY="$OPENAI_COMPATIBLE_API_KEY" \
100-
ghcr.io/lpalbou/abstractgateway-server:0.2.15
111+
-v "$PWD/runtime:/data" \
112+
ghcr.io/lpalbou/abstractgateway:latest
101113
```
102114

103115
Use `http://model-runner.docker.internal/engines/v1` for Docker Model Runner,
@@ -134,6 +146,8 @@ Useful compose variables:
134146
- `embedding.text` capability default: configure through `abstractgateway-config set-default embedding.text ...`; remote/provider-backed embeddings work in the default image, local HuggingFace/sentence-transformer embeddings require an image built with `abstractgateway[embeddings]`
135147
- `ABSTRACTVISION_*`: AbstractVision image backend or OpenAI-compatible image endpoint
136148
- `ABSTRACTVOICE_*`: AbstractVoice TTS/STT backend, local/remote engine, and model controls
149+
- `ABSTRACTGATEWAY_USER_AUTH`: `1` for per-user Gateway tokens and browser sessions
150+
- `ABSTRACTGATEWAY_BOOTSTRAP_ADMIN`: `1` to ensure `default/admin` exists at container start
137151
- `ABSTRACTGATEWAY_EXTRAS`: build-time install extra for local image builds (empty for the default image, `gpu` for NVIDIA)
138152

139153
Release scope: TTS, STT, and generated images are direct Gateway endpoints.
@@ -144,7 +158,7 @@ For unreleased local checkouts, build the image from this repository:
144158

145159
```bash
146160
ABSTRACTGATEWAY_INSTALL_MODE=local \
147-
ABSTRACTGATEWAY_IMAGE_TAG=0.2.15-local \
161+
ABSTRACTGATEWAY_IMAGE_TAG=0.2.24-local \
148162
docker compose -f docker/abstractgateway-server/compose.yml up -d --build
149163
```
150164

@@ -153,6 +167,7 @@ docker compose -f docker/abstractgateway-server/compose.yml up -d --build
153167
```bash
154168
curl http://localhost:8080/api/health
155169

156-
curl -H "Authorization: Bearer $ABSTRACTGATEWAY_AUTH_TOKEN" \
157-
http://localhost:8080/api/gateway/bundles
170+
ADMIN_TOKEN="$(docker exec abstractgateway cat /data/auth/bootstrap-admin-token)"
171+
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
172+
http://localhost:8080/api/gateway/me
158173
```

0 commit comments

Comments
 (0)