Skip to content

Commit 62d43d1

Browse files
committed
Document runtime configuration and secrets
1 parent 31bff5c commit 62d43d1

5 files changed

Lines changed: 123 additions & 20 deletions

File tree

.env.example

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copy this file to .env for local Docker Compose use.
2+
# This file contains demo values only. Never put real credentials here.
3+
4+
POSTGRES_DB=factoryvision
5+
POSTGRES_USER=factoryvision
6+
POSTGRES_PASSWORD=factoryvision
7+
8+
# Compose service names are used inside the Docker network.
9+
FACTORYVISION_DATABASE_URL=postgresql+psycopg://factoryvision:factoryvision@postgres:5432/factoryvision
10+
FACTORYVISION_ONNX_MODEL=/app/artifacts/models/factoryvision-segmentation.onnx
11+
FACTORYVISION_MODEL_NAME=factoryvision-segmentation
12+
FACTORYVISION_MODEL_ALIAS=candidate
13+
FACTORYVISION_THRESHOLD=0.5
14+
FACTORYVISION_MAX_UPLOAD_BYTES=10000000
15+
FACTORYVISION_BATCH_IMAGE_DIR=/app/data/batch/incoming
16+
FACTORYVISION_BATCH_ARTIFACT_DIR=/app/artifacts/batch
17+
FACTORYVISION_BATCH_MAX_IMAGES=
18+
19+
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS=airflow:admin
20+
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE=/opt/airflow/simple_auth_manager_passwords.json
21+
MLFLOW_BACKEND_STORE_URI=postgresql://factoryvision:factoryvision@postgres:5432/mlflow
22+
23+
GRAFANA_ADMIN_USER=admin
24+
GRAFANA_ADMIN_PASSWORD=factoryvision

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Local learning instructions; keep them out of the public repository.
22
instructions.md
33
factoryvision-notion.md
4+
.env
5+
.env.*
6+
!.env.example
47
.venv/
58
__pycache__/
69
*.py[cod]

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,8 @@ The ONNX model is intentionally not stored in Git because it is a generated arti
510510
.venv\Scripts\python.exe scripts\export_onnx.py
511511
```
512512

513+
Configuration is documented in [`docs/configuration.md`](docs/configuration.md), with a safe [`.env.example`](.env.example) template. Copy it to `.env` for local overrides; `.env` is ignored by Git and must never contain committed credentials.
514+
513515
Then build and start the stack:
514516

515517
```powershell

docker-compose.yml

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ services:
22
postgres:
33
image: postgres:16
44
environment:
5-
POSTGRES_DB: factoryvision
6-
POSTGRES_USER: factoryvision
7-
POSTGRES_PASSWORD: factoryvision
5+
POSTGRES_DB: ${POSTGRES_DB:-factoryvision}
6+
POSTGRES_USER: ${POSTGRES_USER:-factoryvision}
7+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-factoryvision}
88
ports:
99
- "5432:5432"
1010
volumes:
1111
- postgres_data:/var/lib/postgresql/data
1212
healthcheck:
13-
test: ["CMD-SHELL", "pg_isready -U factoryvision -d factoryvision"]
13+
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER:-factoryvision} -d $${POSTGRES_DB:-factoryvision}"]
1414
interval: 5s
1515
timeout: 5s
1616
retries: 10
@@ -20,8 +20,12 @@ services:
2020
context: .
2121
dockerfile: Dockerfile
2222
environment:
23-
FACTORYVISION_DATABASE_URL: postgresql+psycopg://factoryvision:factoryvision@postgres:5432/factoryvision
24-
FACTORYVISION_ONNX_MODEL: /app/artifacts/models/factoryvision-segmentation.onnx
23+
FACTORYVISION_DATABASE_URL: ${FACTORYVISION_DATABASE_URL:-postgresql+psycopg://factoryvision:factoryvision@postgres:5432/factoryvision}
24+
FACTORYVISION_ONNX_MODEL: ${FACTORYVISION_ONNX_MODEL:-/app/artifacts/models/factoryvision-segmentation.onnx}
25+
FACTORYVISION_MODEL_NAME: ${FACTORYVISION_MODEL_NAME:-factoryvision-segmentation}
26+
FACTORYVISION_MODEL_ALIAS: ${FACTORYVISION_MODEL_ALIAS:-candidate}
27+
FACTORYVISION_THRESHOLD: ${FACTORYVISION_THRESHOLD:-0.5}
28+
FACTORYVISION_MAX_UPLOAD_BYTES: ${FACTORYVISION_MAX_UPLOAD_BYTES:-10000000}
2529
ports:
2630
- "8000:8000"
2731
volumes:
@@ -38,13 +42,15 @@ services:
3842
postgres-init:
3943
image: postgres:16
4044
environment:
41-
PGPASSWORD: factoryvision
45+
PGPASSWORD: ${POSTGRES_PASSWORD:-factoryvision}
46+
PGUSER: ${POSTGRES_USER:-factoryvision}
47+
PGDATABASE: ${POSTGRES_DB:-factoryvision}
4248
entrypoint: ["/bin/sh", "-c"]
4349
command:
4450
- >-
45-
until pg_isready -h postgres -U factoryvision -d factoryvision; do sleep 1; done;
46-
psql -h postgres -U factoryvision -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='mlflow'" | grep -q 1 ||
47-
psql -h postgres -U factoryvision -d postgres -c "CREATE DATABASE mlflow"
51+
until pg_isready -h postgres -U $${POSTGRES_USER:-factoryvision} -d $${POSTGRES_DB:-factoryvision}; do sleep 1; done;
52+
psql -h postgres -U $${POSTGRES_USER:-factoryvision} -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='mlflow'" | grep -q 1 ||
53+
psql -h postgres -U $${POSTGRES_USER:-factoryvision} -d postgres -c "CREATE DATABASE mlflow"
4854
depends_on:
4955
postgres:
5056
condition: service_healthy
@@ -55,16 +61,17 @@ services:
5561
dockerfile: docker/Dockerfile.airflow
5662
environment: &airflow-environment
5763
AIRFLOW__CORE__EXECUTOR: LocalExecutor
58-
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://factoryvision:factoryvision@postgres:5432/factoryvision
64+
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: ${AIRFLOW__DATABASE__SQL_ALCHEMY_CONN:-postgresql+psycopg2://factoryvision:factoryvision@postgres:5432/factoryvision}
5965
AIRFLOW__CORE__LOAD_EXAMPLES: "false"
6066
AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: "true"
6167
AIRFLOW__CORE__AUTH_MANAGER: airflow.api_fastapi.auth.managers.simple.simple_auth_manager.SimpleAuthManager
62-
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: airflow:admin
63-
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE: /opt/airflow/simple_auth_manager_passwords.json
64-
FACTORYVISION_DATABASE_URL: postgresql+psycopg://factoryvision:factoryvision@postgres:5432/factoryvision
65-
FACTORYVISION_ONNX_MODEL: /app/artifacts/models/factoryvision-segmentation.onnx
66-
FACTORYVISION_BATCH_IMAGE_DIR: /app/data/batch/incoming
67-
FACTORYVISION_BATCH_ARTIFACT_DIR: /app/artifacts/batch
68+
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS: ${AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS:-airflow:admin}
69+
AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE: ${AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE:-/opt/airflow/simple_auth_manager_passwords.json}
70+
FACTORYVISION_DATABASE_URL: ${FACTORYVISION_DATABASE_URL:-postgresql+psycopg://factoryvision:factoryvision@postgres:5432/factoryvision}
71+
FACTORYVISION_ONNX_MODEL: ${FACTORYVISION_ONNX_MODEL:-/app/artifacts/models/factoryvision-segmentation.onnx}
72+
FACTORYVISION_BATCH_IMAGE_DIR: ${FACTORYVISION_BATCH_IMAGE_DIR:-/app/data/batch/incoming}
73+
FACTORYVISION_BATCH_ARTIFACT_DIR: ${FACTORYVISION_BATCH_ARTIFACT_DIR:-/app/artifacts/batch}
74+
FACTORYVISION_BATCH_MAX_IMAGES: ${FACTORYVISION_BATCH_MAX_IMAGES:-}
6875
volumes: &airflow-volumes
6976
- airflow_home:/opt/airflow
7077
- ./airflow/dags:/opt/airflow/dags
@@ -125,7 +132,7 @@ services:
125132
- --port
126133
- "5000"
127134
- --backend-store-uri
128-
- postgresql://factoryvision:factoryvision@postgres:5432/mlflow
135+
- ${MLFLOW_BACKEND_STORE_URI:-postgresql://factoryvision:factoryvision@postgres:5432/mlflow}
129136
- --artifacts-destination
130137
- /mlartifacts
131138
- --serve-artifacts
@@ -160,8 +167,8 @@ services:
160167
grafana:
161168
image: grafana/grafana:11.1.0
162169
environment:
163-
GF_SECURITY_ADMIN_USER: admin
164-
GF_SECURITY_ADMIN_PASSWORD: factoryvision
170+
GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
171+
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:-factoryvision}
165172
GF_USERS_ALLOW_SIGN_UP: "false"
166173
ports:
167174
- "3000:3000"

docs/configuration.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Configuration and secrets
2+
3+
FactoryVision reads runtime configuration from environment variables. The
4+
repository includes [`.env.example`](../.env.example) as a safe template for
5+
local Docker Compose use. Copy it to `.env` and edit the values locally:
6+
7+
```powershell
8+
Copy-Item .env.example .env
9+
docker compose --env-file .env up -d
10+
```
11+
12+
The real `.env` file is ignored by Git. The example file contains only local
13+
demo values and is safe to publish; replace those values before using a real
14+
database or monitoring system.
15+
16+
## Application variables
17+
18+
| Variable | Purpose | Example or default |
19+
| --- | --- | --- |
20+
| `FACTORYVISION_DATABASE_URL` | SQLAlchemy connection string used for prediction storage | Compose: `postgresql+psycopg://...@postgres:5432/factoryvision` |
21+
| `FACTORYVISION_ONNX_MODEL` | Path to the ONNX model inside the running environment | `/app/artifacts/models/factoryvision-segmentation.onnx` |
22+
| `FACTORYVISION_MODEL_NAME` | Logical model name stored in predictions and metrics | `factoryvision-segmentation` |
23+
| `FACTORYVISION_MODEL_ALIAS` | Serving alias, such as `candidate` or `production` | `candidate` |
24+
| `FACTORYVISION_THRESHOLD` | Probability threshold used to turn pixels into defect/not-defect | `0.5` |
25+
| `FACTORYVISION_MAX_UPLOAD_BYTES` | Maximum accepted upload size | `10000000` |
26+
| `FACTORYVISION_BATCH_IMAGE_DIR` | Directory scanned by batch inference | `/app/data/batch/incoming` in Compose |
27+
| `FACTORYVISION_BATCH_ARTIFACT_DIR` | Directory for batch hand-off and summary artifacts | `/app/artifacts/batch` in Compose |
28+
| `FACTORYVISION_BATCH_MAX_IMAGES` | Optional limit for one batch run | Empty means no limit |
29+
30+
For direct local API execution, use host paths and `localhost` in the database
31+
URL. For Docker Compose, use container paths and the service name `postgres`.
32+
The same distinction applies to Kubernetes, where paths must exist inside the
33+
pod and the database hostname must be a Kubernetes Service.
34+
35+
## Service configuration
36+
37+
| Variable | Used by | Sensitive? |
38+
| --- | --- | --- |
39+
| `POSTGRES_DB` | PostgreSQL container | No, but database details should still be environment-specific |
40+
| `POSTGRES_USER` | PostgreSQL and clients | No for the local demo |
41+
| `POSTGRES_PASSWORD` | PostgreSQL initialization | Yes outside local development |
42+
| `MLFLOW_BACKEND_STORE_URI` | MLflow metadata database | Contains credentials when using authenticated SQL |
43+
| `GRAFANA_ADMIN_USER` | Grafana login | No for the username |
44+
| `GRAFANA_ADMIN_PASSWORD` | Grafana login | Yes outside local development |
45+
| `AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_USERS` | Local Airflow demo login | Contains a demo credential |
46+
| `AIRFLOW__CORE__SIMPLE_AUTH_MANAGER_PASSWORDS_FILE` | Airflow password-file location | No; the generated file is runtime state |
47+
48+
Compose reads `.env` automatically; `docker-compose.yml` also supplies local
49+
defaults when a variable is absent. Use `docker compose config` to inspect the
50+
resolved configuration, but do not paste resolved output into a public issue
51+
or commit it because it may contain passwords.
52+
53+
## Where secrets belong
54+
55+
- Local development: `.env`, kept outside Git.
56+
- GitHub Actions: the automatically provided `GITHUB_TOKEN` is used for GHCR;
57+
do not create a password line in `.env` for it.
58+
- Kubernetes: use a Kubernetes `Secret` for database URLs, passwords, and
59+
registry credentials. Keep ordinary model and threshold settings in a
60+
`ConfigMap`. The current local manifests use demo values and document where
61+
a Secret should replace them.
62+
- Cloud deployment: use the cloud provider's secret store or managed
63+
environment-variable mechanism rather than committing credentials.
64+
65+
Never commit `.env`, access tokens, database passwords, private keys, or
66+
resolved deployment output. If a credential is exposed, rotate it rather than
67+
only deleting it from the working tree.

0 commit comments

Comments
 (0)