diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9bb6a9a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.git +.venv +.pytest_cache +.ruff_cache +*.egg-info +__pycache__ +*.pyc +.env + +frontend/node_modules +frontend/dist + +var diff --git a/.env.example b/.env.example index 964b0da..bbcc9a1 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,14 @@ -GNEXUS_CREDS_ENV=development -GNEXUS_CREDS_DATABASE_URL=postgresql+psycopg://gnexus_creds:gnexus_creds@localhost:5432/gnexus_creds -GNEXUS_CREDS_MASTER_KEY=change-me-to-a-32-byte-url-safe-key -GNEXUS_CREDS_SESSION_SECRET=change-me -GNEXUS_AUTH_BASE_URL=http://gnexus-auth.local -GNEXUS_AUTH_CLIENT_ID=gnexus-creds -GNEXUS_AUTH_CLIENT_SECRET=change-me -GNEXUS_AUTH_REDIRECT_URI=http://localhost:8000/auth/callback -GNEXUS_AUTH_WEBHOOK_SECRET=change-me +GNEXUS_CREDS_ENV=production +GNEXUS_CREDS_DATABASE_URL=postgresql+psycopg://gnexus_creds:change-me@postgres:5432/gnexus_creds +GNEXUS_CREDS_MASTER_KEY=replace-with-a-long-random-master-key +GNEXUS_CREDS_SESSION_SECRET=replace-with-a-long-random-session-secret +GNEXUS_CREDS_SESSION_COOKIE_NAME=gnexus_creds_session + +GNEXUS_AUTH_BASE_URL=https://auth.gnexus.space +GNEXUS_AUTH_CLIENT_ID=replace-with-client-id +GNEXUS_AUTH_CLIENT_SECRET=replace-with-client-secret +GNEXUS_AUTH_REDIRECT_URI=https://creds.gnexus.space/auth/callback +GNEXUS_AUTH_WEBHOOK_SECRET=replace-with-webhook-secret + +GNEXUS_CREDS_RATE_LIMIT_WINDOW_SECONDS=60 +GNEXUS_CREDS_RATE_LIMIT_MAX_SENSITIVE_REQUESTS=120 diff --git a/Dockerfile b/Dockerfile index b3c5a8c..47410c9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,18 @@ +FROM node:22-bookworm-slim AS frontend + +WORKDIR /app/frontend + +RUN apt-get update \ + && apt-get install -y --no-install-recommends ca-certificates git \ + && rm -rf /var/lib/apt/lists/* + +COPY frontend/package*.json ./ +RUN npm ci + +COPY frontend ./ +RUN npm run build + + FROM python:3.13-slim AS runtime ENV PYTHONDONTWRITEBYTECODE=1 \ @@ -6,7 +21,7 @@ WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends git \ + && apt-get install -y --no-install-recommends ca-certificates git \ && rm -rf /var/lib/apt/lists/* COPY pyproject.toml README.md ./ @@ -16,6 +31,9 @@ RUN pip install --no-cache-dir . +COPY --from=frontend /app/frontend/dist ./frontend/dist +COPY --from=frontend /app/frontend/node_modules/gnexus-ui-kit/dist/assets/fonts ./frontend/node_modules/gnexus-ui-kit/dist/assets/fonts + EXPOSE 8000 CMD ["uvicorn", "gnexus_creds.main:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md index 2422e18..ab14750 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,12 @@ uv run uvicorn gnexus_creds.main:app --reload ``` +For local PostgreSQL development: + +```env +GNEXUS_CREDS_DATABASE_URL=postgresql+psycopg://gnexus_creds:gnexus_creds@127.0.0.1:5432/gnexus_creds +``` + Health endpoints: ```text @@ -62,7 +68,32 @@ ## Docker +Prepare a production env file from `.env.example`, then build the image: + ```bash docker build -t gnexus-creds . +``` + +Apply migrations: + +```bash +docker run --rm --env-file .env gnexus-creds alembic upgrade head +``` + +Start the app: + +```bash docker run --env-file .env -p 8000:8000 gnexus-creds ``` + +Local compose stack with PostgreSQL: + +```bash +docker compose up -d postgres +docker compose run --rm app alembic upgrade head +docker compose up -d app +``` + +The image includes the built Vue UI and serves it from FastAPI. The container +does not run migrations automatically; run `alembic upgrade head` explicitly +during deploy. diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1f49d6e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,27 @@ +services: + postgres: + image: postgres:18 + environment: + POSTGRES_DB: gnexus_creds + POSTGRES_USER: gnexus_creds + POSTGRES_PASSWORD: gnexus_creds + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U gnexus_creds -d gnexus_creds"] + interval: 5s + timeout: 3s + retries: 20 + + app: + build: . + depends_on: + postgres: + condition: service_healthy + env_file: + - .env + ports: + - "8000:8000" + +volumes: + postgres-data: diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 2efd4d1..893668a 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -1,5 +1,5 @@