Users in HUB_DATA/users.json with scrypt hashes and roles (viewer, operator, apps-admin, admin), managed by hub/users-cli.ts; HUB_USER/HUB_PASSWORD remain a bootstrap admin while the file does not exist. Five failed logins in 15 minutes lock the address or the name for 15 minutes. Logins, logouts and every refused request go to a JSON Lines audit log that admins read through hub/audit/list. Endpoints are listed in routes.ts with their kind and capability; writes stay refused for now. Optional <ID>_ADMIN_TOKEN is read for the coming write stages. The management plan is in docs/hub-management-plan.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.5 KiB
Docker
35 lines
1.5 KiB
Docker
# The hub image built by Gitea CI (git.shx.one): one small container that serves the
|
|
# console and a read-only, Technitium-compatible API over several real servers.
|
|
# See hub/README.md. Self-contained: it does not use the console image.
|
|
#
|
|
# docker run --rm -p 8080:8080 -e HUB_SERVERS=dns=https://dns.example.net \
|
|
# -e DNS_TOKEN=... -e HUB_USER=admin -e HUB_PASSWORD=... -v hub-data:/data \
|
|
# git.shx.one/denozord/technitium-hub:latest
|
|
FROM node:22-alpine AS build
|
|
WORKDIR /src
|
|
COPY package.json package-lock.json ./
|
|
RUN npm ci
|
|
COPY . .
|
|
RUN npm run build
|
|
# What the hub runs: its sources without the tests, and a package.json that makes the
|
|
# .ts files ECMAScript modules. It imports only node: built-ins, so there is no node_modules.
|
|
RUN mkdir -p /out/hub \
|
|
&& cp hub/*.ts /out/hub/ \
|
|
&& rm /out/hub/*.test.ts \
|
|
&& echo '{"type":"module"}' > /out/package.json
|
|
|
|
FROM node:22-alpine
|
|
WORKDIR /app
|
|
COPY --from=build /out/ ./
|
|
COPY --from=build /src/dist ./dist
|
|
ENV HUB_STATIC=/app/dist HUB_PORT=8080 HUB_DATA=/data NODE_ENV=production
|
|
# The users file and the audit log live here: mount a volume on it.
|
|
RUN mkdir -p /data && chown node:node /data
|
|
VOLUME /data
|
|
USER node
|
|
EXPOSE 8080
|
|
# No curl in alpine: node asks the hub's public endpoint itself.
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
CMD ["node", "-e", "fetch('http://127.0.0.1:'+(process.env.HUB_PORT||8080)+'/api/status').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"]
|
|
CMD ["node", "--experimental-strip-types", "--no-warnings", "/app/hub/server.ts"]
|