-
Notifications
You must be signed in to change notification settings - Fork 0
docs: per-purpose inference env vars #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| # Neo4j Auth Runbook (Environment-Agnostic) | ||
|
|
||
| ## Goals | ||
| - Keep a single source of truth in `.env` | ||
| - Prevent auth drift between compose config and Neo4j persisted auth state | ||
| - Provide deterministic preflight and rotation helpers | ||
|
|
||
| ## Files | ||
| - `scripts/lib/common.sh` | ||
| - `scripts/neo4j-auth-preflight.sh` | ||
| - `scripts/neo4j-auth-rotate.sh` | ||
|
|
||
| ## Required env contract | ||
| In `.env`: | ||
| - `NEO4J_PASSWORD=<secret>` | ||
| - `NEO4J_AUTH=neo4j/${NEO4J_PASSWORD}` | ||
|
|
||
| ## Preflight check | ||
| ```bash | ||
| scripts/neo4j-auth-preflight.sh | ||
| ``` | ||
| Expected output: `NEO4J_AUTH_OK` | ||
|
|
||
| ## Rotate password safely | ||
| ```bash | ||
| scripts/neo4j-auth-rotate.sh --new-pass 'your-new-strong-password' | ||
| ``` | ||
| Expected output: | ||
| - `NEO4J_AUTH_OK` | ||
| - `NEO4J_PASSWORD_ROTATED_OK` | ||
|
|
||
| ## Notes | ||
| - These scripts avoid hardcoded host paths by deriving compose/env paths from script location, with overrides via `PROJECT_DIR`, `COMPOSE_FILE`, and `ENV_FILE`. | ||
| - If your container names differ, set `NEO4J_CONTAINER` before running. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| PROJECT_DIR_DEFAULT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" | ||
| PROJECT_DIR="${PROJECT_DIR:-$PROJECT_DIR_DEFAULT}" | ||
| COMPOSE_FILE="${COMPOSE_FILE:-$PROJECT_DIR/compose.graph.yml}" | ||
| ENV_FILE="${ENV_FILE:-$PROJECT_DIR/.env}" | ||
| SERVICE_NEO4J="${SERVICE_NEO4J:-neo4j}" | ||
| SERVICE_STORE="${SERVICE_STORE:-store}" | ||
|
|
||
| require_cmd() { command -v "$1" >/dev/null 2>&1 || { echo "missing command: $1" >&2; exit 1; }; } | ||
|
|
||
| require_env() { | ||
| local k="$1" | ||
| if ! grep -q "^${k}=" "$ENV_FILE"; then | ||
| echo "missing required env var in $ENV_FILE: $k" >&2 | ||
| exit 1 | ||
| fi | ||
| } | ||
|
|
||
| env_get() { | ||
| local k="$1" | ||
| grep -E "^${k}=" "$ENV_FILE" | tail -n1 | cut -d= -f2- | ||
| } | ||
|
|
||
| compose() { | ||
| docker compose -f "$COMPOSE_FILE" "$@" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| source "$(dirname "$0")/lib/common.sh" | ||
|
|
||
| require_cmd docker | ||
| require_env NEO4J_PASSWORD | ||
| PASS="$(env_get NEO4J_PASSWORD)" | ||
| CONTAINER="${NEO4J_CONTAINER:-foxmemory-neo4j}" | ||
|
|
||
| echo "[preflight] checking neo4j auth via cypher-shell..." | ||
| if docker exec "$CONTAINER" cypher-shell -u neo4j -p "$PASS" "RETURN 1 as ok;" >/tmp/neo4j-preflight.out 2>&1; then | ||
| echo "NEO4J_AUTH_OK" | ||
| else | ||
| echo "NEO4J_AUTH_FAIL" | ||
| tail -n 20 /tmp/neo4j-preflight.out || true | ||
| exit 1 | ||
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
| source "$(dirname "$0")/lib/common.sh" | ||
|
|
||
| usage() { | ||
| cat <<USAGE | ||
| Usage: $0 --new-pass '<password>' [--no-restart] | ||
|
|
||
| Rotates Neo4j password using compose/.env contract, then verifies login. | ||
| USAGE | ||
| } | ||
|
|
||
| NEW_PASS="" | ||
| RESTART=1 | ||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --new-pass) NEW_PASS="$2"; shift 2;; | ||
| --no-restart) RESTART=0; shift;; | ||
| -h|--help) usage; exit 0;; | ||
| *) echo "unknown arg: $1"; usage; exit 1;; | ||
| esac | ||
| done | ||
|
|
||
| [[ -n "$NEW_PASS" ]] || { echo "--new-pass is required"; usage; exit 1; } | ||
| require_cmd docker | ||
| require_env NEO4J_PASSWORD | ||
|
|
||
| # Update .env source-of-truth | ||
| if grep -q '^NEO4J_PASSWORD=' "$ENV_FILE"; then | ||
| sed -i.bak "s#^NEO4J_PASSWORD=.*#NEO4J_PASSWORD=${NEW_PASS}#" "$ENV_FILE" | ||
| else | ||
| echo "NEO4J_PASSWORD=${NEW_PASS}" >> "$ENV_FILE" | ||
| fi | ||
| if grep -q '^NEO4J_AUTH=' "$ENV_FILE"; then | ||
| sed -i.bak "s#^NEO4J_AUTH=.*#NEO4J_AUTH=neo4j/${NEW_PASS}#" "$ENV_FILE" | ||
| else | ||
| echo "NEO4J_AUTH=neo4j/${NEW_PASS}" >> "$ENV_FILE" | ||
| fi | ||
|
|
||
| echo "[rotate] updated $ENV_FILE" | ||
|
|
||
| if [[ "$RESTART" -eq 1 ]]; then | ||
| compose stop "$SERVICE_STORE" || true | ||
|
|
||
| # Temporarily disable auth, set password, restore auth contract | ||
| python3 - <<PY | ||
| from pathlib import Path | ||
| p=Path("$COMPOSE_FILE") | ||
| s=p.read_text() | ||
| s=s.replace('NEO4J_AUTH: neo4j/${NEO4J_PASSWORD}','NEO4J_AUTH: none') | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The auth toggle targets Useful? React with 👍 / 👎. |
||
| p.write_text(s) | ||
| PY | ||
|
|
||
| compose up -d "$SERVICE_NEO4J" | ||
| sleep 10 | ||
|
|
||
| CONTAINER="${NEO4J_CONTAINER:-foxmemory-neo4j}" | ||
| docker exec "$CONTAINER" cypher-shell "ALTER USER neo4j SET PASSWORD '$NEW_PASS' CHANGE NOT REQUIRED;" >/tmp/neo4j-rotate.out 2>&1 || { | ||
| echo "[rotate] failed to set password"; tail -n 30 /tmp/neo4j-rotate.out; exit 1; | ||
| } | ||
|
|
||
| python3 - <<PY | ||
| from pathlib import Path | ||
| p=Path("$COMPOSE_FILE") | ||
| s=p.read_text() | ||
| s=s.replace('NEO4J_AUTH: none','NEO4J_AUTH: neo4j/${NEO4J_PASSWORD}') | ||
| p.write_text(s) | ||
| PY | ||
|
|
||
| compose up -d "$SERVICE_NEO4J" "$SERVICE_STORE" | ||
| sleep 10 | ||
| fi | ||
|
|
||
| "$(dirname "$0")/neo4j-auth-preflight.sh" | ||
| echo "NEO4J_PASSWORD_ROTATED_OK" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This script rewrites
NEO4J_PASSWORDin.envbefore attempting any restart or password change in Neo4j. If a later step fails (container name mismatch, startup timing, cypher error), the file now contains a password that was never applied, causing auth drift and breaking subsequent preflight/restart flows until someone manually repairs.env.Useful? React with 👍 / 👎.