Files
Anand 9b3d093eb8 Expand Needle 2 tool catalog, fix diagnostics, and publish Docker images to GHCR
- Add 48 new MCP/AI-assistant tools covering guest lifecycle, node
  operations, firewall/security, and backup/replication/HA/storage/SDN
  management. Every mutating tool is admin-gated the same way
  guest_power_action already is; migrate/resize/move-disk, node
  reboot/shutdown, disk wipe, cert revocation, and cluster-node removal are
  deliberately left out as being as destructive as a delete.
- ai_chat.go: when a provider (chiefly Needle, a pure tool-router with no
  narrative output of its own) finishes calling tools but returns nothing to
  say, render the tool results themselves as the answer instead of the
  misleading "ran out of tool calls" message.
- needle.go: serialize every request against the shared Needle subprocess
  (it handles one request at a time) to stop concurrent callers from racing
  it, and surface the subprocess's captured output when a request fails
  because it died mid-response, instead of a bare network error.
- Dockerfile: switch the final stage from distroless "static" to "base" —
  the bundled Needle CLI is a dynamically-linked glibc binary and cannot run
  in an image with no libc at all.
- .github/workflows/release.yml: build and push a multi-arch (amd64/arm64)
  Docker image to ghcr.io on every version tag, tagged with the version and
  "latest".
- Dockerfile/README: add OCI image labels and document the published GHCR
  image as the primary Docker install path.
2026-09-09 23:03:54 +05:30

39 lines
1.4 KiB
Docker

# syntax=docker/dockerfile:1
FROM node:22-alpine AS web-build
WORKDIR /web
COPY web/package.json web/package-lock.json* ./
RUN npm ci
COPY web/ ./
RUN npm run build
FROM golang:1.26-alpine AS go-build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
COPY --from=web-build /web/dist ./web/dist
ARG TARGETOS
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -trimpath -ldflags="-s -w" -o /out/ferrum ./cmd/ferrum
# "base" (not "static"): Ferrum's own binary is CGO_ENABLED=0/static and
# would run fine on "static", but the bundled Needle 2 CLI (internal/needle)
# is a dynamically-linked glibc binary (needs libc.so.6/libm.so.6/
# libpthread.so.0/libdl.so.2 and the glibc dynamic linker) — "static" ships
# no libc at all, so spawning that subprocess fails outright in this image.
# "base" includes glibc, fixing that, while still carrying no shell/package
# manager.
FROM gcr.io/distroless/base-debian12
LABEL org.opencontainers.image.source="https://github.com/anand34577/ferrum" \
org.opencontainers.image.description="Ferrum — a fleet-control UI for Proxmox VE" \
org.opencontainers.image.licenses="MIT"
WORKDIR /app
COPY --from=go-build /out/ferrum /app/ferrum
COPY config.example.yaml /app/config.example.yaml
VOLUME ["/app/data"]
EXPOSE 8080
USER nonroot:nonroot
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s CMD ["/app/ferrum", "-healthcheck"]
ENTRYPOINT ["/app/ferrum"]