Configuration

Kashvi reads configuration from two sources, merged in order:

  1. config/app.json — committed defaults
  2. .env — local overrides (never commit this)

.env values always win over config/app.json.

All Environment Variables

Application

VariableDefaultDescription
APP_ENVlocallocal / production / prod
APP_PORT8080HTTP server port
JWT_SECRET(insecure default)Must be changed in production
MAX_BODY_BYTES4194304 (4 MB)Max JSON request body size
Production safety
The server refuses to start in production if JWT_SECRET is the default value.

Database

VariableDefaultDescription
DB_DRIVERsqlitesqlite / postgres / mysql / sqlserver
DATABASE_DSNkashvi.dbFull connection DSN

DSN examples:

# SQLite (dev)
DATABASE_DSN=kashvi.db

# PostgreSQL
DATABASE_DSN=host=localhost user=postgres password=secret dbname=kashvi port=5432 sslmode=disable

# MySQL
DATABASE_DSN=root:secret@tcp(127.0.0.1:3306)/kashvi?charset=utf8mb4&parseTime=True&loc=Local

Redis

VariableDefaultDescription
REDIS_ADDRlocalhost:6379Redis host:port
REDIS_PASSWORD(empty)Redis auth password
Non-fatal dependency
Redis is non-fatal — the server starts with a warning if Redis is unavailable and degrades gracefully (sessions won't persist, cache misses).

Storage

VariableDefaultDescription
STORAGE_DISKlocallocal or s3
STORAGE_LOCAL_ROOTstorageRoot directory for local disk
STORAGE_URLhttp://localhost:8080/storagePublic URL for local files

Reading Config in Code

go
import "github.com/shashiranjanraj/kashvi/config"

port   := config.AppPort()      // "8080"
env    := config.AppEnv()       // "local"
secret := config.JWTSecret()
bucket := config.StorageS3Bucket()

// Generic getter with a default:
val := config.Get("MY_CUSTOM_VAR", "default-value")

config/app.json Format

go
{
  "app_env":      "local",
  "app_port":     "8080",
  "jwt_secret":   "change-me",
  "db_driver":    "sqlite",
  "database_dsn": "kashvi.db",
  "redis_addr":   "localhost:6379"
}

Keys in app.json map 1:1 to env variable names (lowercase, underscores).