Configuration
config.LoadEnv() reads .env from the process working directory. An explicit filename is supported; a missing implicit .env is allowed, while a missing explicit file or invalid file returns an error. Process variables override file values, including empty values; unset values use defaults. The loader does not modify process environment variables.
| Variable | Default | Use |
|---|---|---|
ENV | development | CLI/environment selection |
PORT | 8080 | API listener |
DATABASE_URL | empty | Required PostgreSQL URL; API startup pings it |
RABBITMQ_URL | amqp://guest:guest@localhost:5672/ | API connects before serving |
JWT_SECRET | empty | Required signing secret of at least 32 bytes |
JWT_EXPIRATION_HOURS | 24 | Integer, 1–24 hours validated by identity |
REFRESH_TOKEN_EXPIRATION_DAYS | 7 | Integer, 1–365 days validated by identity |
REDIS_HOST | localhost | Future Redis initialization |
REDIS_PORT | 6379 | Future Redis initialization |
REDIS_PASSWORD | empty | Future Redis initialization |
CORS_ORIGINS | * | Request middleware's comma-separated origin configuration |
CORS configuration is read separately by middleware, not stored in config.Env. Redis values exist in configuration and Compose, but the current API startup does not require a live Redis connection.
The legacy GetEnv helpers fall back for empty values and invalid conversions. That differs from LoadEnv's precedence and error behavior; application startup uses LoadEnv. See the config package.
go
package config_test
import (
"fmt"
"os"
"github.com/prescriptoo/prescriptoo-api/pkg/config"
)
// LoadEnv accepts an explicit file, so tools can choose configuration without
// depending on the process working directory. Environment values take priority.
func ExampleLoadEnv() {
// Fix values used by this example, restoring the caller's environment after it.
for key, value := range map[string]string{
"PORT": "9090", "JWT_EXPIRATION_HOURS": "1", "REFRESH_TOKEN_EXPIRATION_DAYS": "7",
} {
previous, exists := os.LookupEnv(key)
defer func() {
if exists {
_ = os.Setenv(key, previous)
} else {
_ = os.Unsetenv(key)
}
}()
if err := os.Setenv(key, value); err != nil {
panic(err)
}
}
file, err := os.CreateTemp("", "prescriptoo-config-*.env")
if err != nil {
panic(err)
}
defer func() {
if err := os.Remove(file.Name()); err != nil {
panic(err)
}
}()
if _, err := file.WriteString("DATABASE_URL=postgres://localhost/example\nPORT=8088\n"); err != nil {
panic(err)
}
if err := file.Close(); err != nil {
panic(err)
}
env, err := config.LoadEnv(file.Name())
if err != nil {
panic(err)
}
fmt.Println("Port:", env.Port)
fmt.Println("Access lifetime:", env.JWTExpirationHours)
// Output:
// Port: 9090
// Access lifetime: 1
}