Adds a Render Blueprint (render.yaml) and supporting pieces so nanobot can
be deployed to Render in one click, with persistent memory across deploys.
- render.yaml: web service + 1GB persistent disk mounted at
/home/nanobot/.nanobot. Prompts for ANTHROPIC_API_KEY and
NANOBOT_WEB_TOKEN at deploy time (sync: false).
- render-config.json: committed gateway config that wires secrets via
${VAR} placeholders (resolved at runtime). Nothing secret is committed.
- entrypoint.sh: adds a branch gated on RENDER=true that copies the config
onto the mounted disk, chowns the root-owned mount, and drops to the
non-root nanobot user via setpriv. Local (non-Render) path is unchanged.
- Dockerfile: COPY render-config.json; USER nanobot -> USER root so the
entrypoint can chown the freshly-mounted disk before dropping privileges;
add PYTHONUNBUFFERED/PYTHONFAULTHANDLER for diagnosable crash output.
- README.md: Deploy to Render button + section.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
59 lines
2.2 KiB
Docker
59 lines
2.2 KiB
Docker
FROM node:24-bookworm-slim AS webui-builder
|
|
|
|
WORKDIR /app
|
|
COPY webui/package.json webui/package-lock.json ./webui/
|
|
WORKDIR /app/webui
|
|
RUN npm ci
|
|
COPY webui/ ./
|
|
RUN mkdir -p /app/nanobot/web && npm run build
|
|
|
|
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim
|
|
|
|
RUN apt-get update && \
|
|
apt-get install -y --no-install-recommends ca-certificates git bubblewrap openssh-client libmagic1 && \
|
|
rm -rf /var/lib/apt/lists/*
|
|
|
|
WORKDIR /app
|
|
|
|
# Install Python dependencies first (cached layer). Hatch reads the custom build
|
|
# hook from hatch_build.py even for this metadata-only install.
|
|
ARG NANOBOT_EXTRAS=whatsapp
|
|
COPY pyproject.toml README.md LICENSE THIRD_PARTY_NOTICES.md hatch_build.py ./
|
|
RUN mkdir -p nanobot && touch nanobot/__init__.py && \
|
|
NANOBOT_SKIP_WEBUI_BUILD=1 uv pip install --system --no-cache ".[$NANOBOT_EXTRAS]" && \
|
|
rm -rf nanobot
|
|
|
|
# Copy the full source and install
|
|
COPY nanobot/ nanobot/
|
|
COPY --from=webui-builder /app/nanobot/web/dist/ nanobot/web/dist/
|
|
RUN NANOBOT_SKIP_WEBUI_BUILD=1 uv pip install --system --no-cache ".[$NANOBOT_EXTRAS]"
|
|
|
|
# Render deploy template (see render.yaml): committed gateway config that wires
|
|
# secrets through ${ANTHROPIC_API_KEY} / ${NANOBOT_WEB_TOKEN} env vars (resolved
|
|
# at startup). Lives in the code dir (/app), not the data dir, so a mounted disk
|
|
# won't shadow it. Only used when RENDER=true; ignored by local runs.
|
|
COPY render-config.json ./
|
|
|
|
# Create non-root user and config directory
|
|
RUN useradd -m -u 1000 -s /bin/bash nanobot && \
|
|
mkdir -p /home/nanobot/.nanobot && \
|
|
chown -R nanobot:nanobot /home/nanobot /app
|
|
|
|
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
RUN sed -i 's/\r$//' /usr/local/bin/entrypoint.sh && chmod +x /usr/local/bin/entrypoint.sh
|
|
|
|
# Start as root so the Render entrypoint can chown the freshly-mounted
|
|
# (root-owned) persistent disk, then drop to the non-root nanobot user via
|
|
# setpriv (see entrypoint.sh). Local runs without a disk are unaffected.
|
|
USER root
|
|
ENV HOME=/home/nanobot
|
|
# Ensure crash output reaches Render logs (app output is otherwise swallowed on
|
|
# non-graceful exit).
|
|
ENV PYTHONUNBUFFERED=1 PYTHONFAULTHANDLER=1
|
|
|
|
# Gateway health endpoint and optional WebUI/WebSocket channel ports
|
|
EXPOSE 18790 8765
|
|
|
|
ENTRYPOINT ["entrypoint.sh"]
|
|
CMD ["status"]
|