-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
lagodev reads two distinct configuration sources:
| Source | What it controls |
|---|---|
.env files |
Runtime database connection, logging, app environment |
lago.json |
Directory layout the CLI uses for generators |
These never overlap — .env is about what the running program does,
lago.json is about where files land on disk when generators run.
Generate a starter file:
lago env:init # writes ./.env# .env
APP_ENV=local
APP_DEBUG=true
APP_NAME=app
# Driver: postgres | mysql | sqlite
DB_CONNECTION=postgres
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USERNAME=postgres
DB_PASSWORD=secret
DB_DATABASE=app
DB_SCHEMA=public
DB_SSL_MODE=disable
DB_TIMEZONE=Asia/Tashkent
# Pool tuning (optional)
DB_MAX_OPEN=25
DB_MAX_IDLE=5
DB_CONN_MAX_LIFETIME=1h
DB_CONN_MAX_IDLE_TIME=10m
# Logging (optional)
DB_LOG_QUERIES=true
DB_SLOW_QUERY=200msThe CLI loads .env files in this order — later files overlay
earlier ones:
-
.env— shared / committed -
.env.local— developer overrides (gitignored) -
.env.$APP_ENV— environment-specific (.env.production,.env.testing, …)
os.Getenv always wins over .env files — the process environment is
the final source of truth. This means CI / production secrets injected
through your platform of choice (Kubernetes secrets, Docker env, AWS
Parameter Store, etc.) override anything checked into the repo.
import "github.com/devituz/lagodev/config"
func init() { _ = config.LoadEnv() }
cfg := config.FromEnv() // builds a database.Config
debug := config.Bool("APP_DEBUG", false)
host := config.String("REDIS_HOST", "localhost")
ttl := config.Duration("CACHE_TTL", 5*time.Minute)
port := config.Int("APP_PORT", 8080)config.LoadEnv() is safe to call from init() — it's idempotent and
returns nil if no .env files exist.
lago env # password/secret/key/token redacted
lago env --show-secrets # full output| Variable | Type | Default | Notes |
|---|---|---|---|
APP_ENV |
string | "" |
Selects the third .env.$APP_ENV overlay; lagodev also reads it to hide error details when =production
|
APP_DEBUG |
bool | false |
Free for your app to read |
APP_NAME |
string | "" |
Free for your app to read |
APP_KEY |
string | "" |
AES-256 key (base64). Generated by lago key:generate
|
DB_CONNECTION |
string | sqlite |
postgres, mysql, sqlite
|
DB_DSN |
string | "" |
Overrides the structured fields below |
DB_HOST / DB_PORT
|
string/int | (driver default) | |
DB_USERNAME / DB_PASSWORD
|
string | "" |
|
DB_DATABASE / DB_SCHEMA
|
string | "" |
|
DB_SSL_MODE |
string | "" |
Postgres: disable, require, verify-ca, … |
DB_TIMEZONE |
string | UTC |
IANA name (Asia/Tashkent); also accepts Local
|
DB_MAX_OPEN |
int | (driver default) | Pool tuning |
DB_MAX_IDLE |
int | (driver default) | |
DB_CONN_MAX_LIFETIME |
duration | 0 |
1h, 30m, etc. |
DB_CONN_MAX_IDLE_TIME |
duration | 0 |
|
DB_LOG_QUERIES |
bool | false |
Log every SQL call |
DB_SLOW_QUERY |
duration | 0 |
Log queries slower than this |
LAGO_CONFIG |
path | lago.json |
Override the per-project config path |
Each project decides where models, migrations, factories, seeders, and tests live. Generate the file:
lago init # writes ./lago.json with the default layout{
"paths": {
"models": "models",
"migrations": "migrations",
"factories": "factories",
"seeders": "seeders",
"tests": "tests"
}
}Want everything under internal/?
{
"paths": {
"models": "internal/domain",
"migrations": "internal/db/migrations",
"factories": "internal/testdata/factories",
"seeders": "internal/testdata/seeders",
"tests": "internal/db/tests"
}
}The make:* commands honor these paths automatically; pass --dir
to override on a per-command basis.
- The path in
$LAGO_CONFIG(if set) -
lago.jsonin the current working directory - Built-in defaults (the table above)
A malformed lago.json falls back to defaults with a warning on
stderr — so a typo can't take your generators offline.
Set DB_TIMEZONE (or Config.TimeZone) to an IANA name and lagodev:
- adds
_loc=...to the SQLite DSN so timestamps round-trip in your zone, - adds
loc=...to the MySQL DSN, - adds
timezone=...to the Postgres DSN session, - uses
time.Now().In(loc)forCreatedAt/UpdatedAt.
conn.Location() // *time.Location
conn.Now() // time.Now().In(conn.Location())The default is UTC. Most production deployments should stay on
UTC and display in the user's zone at the edge — but lagodev gives
you the lever when you need it (e.g. legacy DBs storing local time).
When APP_ENV=production, the web framework's InternalError /
Error helpers strip the underlying err.Error() from the response
body and return a generic "internal server error" payload. The raw
error still hits the Recovery middleware's log so you can debug it
— it just doesn't leak DB internals to clients.
See Web-Framework for the full secure-by-default story.
-
CLI-Reference —
lago env,lago env:init,lago key:generate. -
Web-Framework —
APP_ENV=productionsemantics. - Architecture — how the connection / manager / executor pieces fit.
lagodev on GitHub · MIT-licensed — see LICENSE.