4.2 KiB
Configuration
All configuration lives in src/main/resources/application.properties. Values fall
into two groups:
- Non-secret defaults — model names, timeouts, retry policy, RSS URLs, log levels. These are literal values in the properties file and are safe to read in a review.
- Secrets and environment-specific endpoints — resolved from environment variables
via
${VAR}placeholders.
.env.example is the authoritative list of every variable, marked
REQUIRED or OPTIONAL.
Secret handling
No credential is ever committed. Required secrets are declared without a fallback:
openai.api.key=${OPENAI_API_KEY}
If the variable is absent, Spring throws
IllegalArgumentException: Could not resolve placeholder 'OPENAI_API_KEY' and the
application refuses to start.
This is intentional. The alternative — an empty default — produces a service that
boots happily and then fails every downstream call with an opaque 401, usually in
production, usually at 3am. A startup failure names the missing variable immediately.
Optional values keep a default after the colon:
minio.bucket-name=${MINIO_BUCKET_NAME:konturai}
Adding a new configuration value
- If it is a credential, endpoint, or anything that differs per environment, use a
${VAR}placeholder — no default for required secrets. - Add it to
.env.examplewith aREQUIRED/OPTIONALmarker and a one-line comment. - Add it to
.env.productionon the server before merging.
Never write a real value into application.properties, a test's
@TestPropertySource, a shell script, or documentation.
The Google service-account key
NanoBananaImageGenerationService and GeminiVideoGenerationService authenticate to
Vertex AI by loading keys/google-key.json from the classpath:
ClassPathResource resource = new ClassPathResource("keys/google-key.json");
The file must exist at src/main/resources/keys/google-key.json at build time, so
it is baked into the jar. It is gitignored and must be supplied out of band:
cp /secure/path/google-key.json src/main/resources/keys/google-key.json
On the deployment host the file must be present in the checkout before the Docker
image is built, since the Dockerfile uses COPY . ..
If the file is missing the application still starts — image and video generation log
an error and return null, while every other feature keeps working.
Local development
cp .env.example .env
$EDITOR .env
set -a && source .env && set +a
./mvnw spring-boot:run
For a fully local setup you need MongoDB on localhost:27017. Point MINIO_ENDPOINT
at a local MinIO container, or leave the storage-backed endpoints unused.
An alternative to .env is src/main/resources/application-local.properties (also
gitignored), activated with --spring.profiles.active=local.
Configuration reference by area
| Area | Prefix | Notes |
|---|---|---|
| MongoDB | spring.data.mongodb.* |
30s connect/socket/server-selection timeouts |
| Object storage | minio.* |
Stores generated reports and images |
| Security | security.jwt.*, encryption.* |
JWT secret must match the issuing auth service |
| OpenAI | openai.* |
gpt-4o for text, gpt-4o-mini for cheaper calls; retry with exponential backoff, max 3 concurrent requests |
| Ollama | ollama.* |
Self-hosted; very long timeouts (5h) for large generations |
| Vertex AI | google.* |
Imagen 3 for images, Veo 3 for video; 20s rate-limit spacing |
| Serper | serper.* |
Google search results for research reports |
facebook.* |
Posting, plus the hot-leads collector and call-centre sync | |
| RSS | rss.* |
Five sources — see rss-parsers.md |
| Schedulers | parser.scheduler.enabled, posting.scheduler.enabled |
Parser scheduler is off by default |
| CORS | cors.* |
Bound by CorsProperties, applied in WebCorsConfig |
Rotating a credential
- Issue the new credential with the provider.
- Update
.env.productionon the deployment host. - Restart the container (
docker compose up -d— see deployment.md). - Revoke the old credential.
Because secrets are never baked into the image, rotation requires no rebuild.