Skip to content
Configuration

Configuration

Your application needs to know things that are not code: which database to connect to, which port to listen on, the password for your mail server. Those answers differ between your laptop and your production server, and the password must not be committed to git. Configuration is where they live.

Lemmego keeps them in two places, and the split is the thing to understand:

  • internal/configs/*.go — the shape of your configuration, in Go. Here you say “there is a database setting, and its driver is whatever DB_DRIVER says, or sqlite if nothing says”. You commit these files.
  • .env — the values for this one machine. Here you say DB_DRIVER=postgres. You never commit this file; it is in .gitignore already.

That way the structure is shared and reviewable, while the secrets and the per-machine details stay out of your repository. An environment variable is simply a named value handed to your program by whatever starts it, and a .env file is a convenient way to set a pile of them while you work locally.

Reading and writing configuration

You’ll find your settings in internal/configs/, defined in init() functions — Go runs these automatically when the package loads, so there is nothing for you to call:

// internal/configs/app.go
package configs

import "github.com/lemmego/api/config"

func init() {
    config.Set("app", config.M{
        "name":  config.MustEnv("APP_NAME", "Lemmego"),
        "port":  config.MustEnv("APP_PORT", 8080),
        "env":   config.MustEnv("APP_ENV", "development"),
        "debug": config.MustEnv("APP_DEBUG", false),
    })
}

Config files are auto-loaded via a blank import in cmd/app/main.go:

import _ "github.com/lemmego/lemmego/internal/configs"

Reading Configuration

port := config.Get("app.port").(int)
name := config.Get("app.name", "default").(string)

Or using the typed accessor on a config.M map:

cfg := config.GetAll()
port := cfg.Int("app.port")
debug := cfg.Bool("app.debug")

Available accessor methods on config.M:

  • String(key, defaultVal...) string
  • Int(key, defaultVal...) int
  • Int64(key, defaultVal...) int64
  • Bool(key, defaultVal...) bool
  • Float64(key, defaultVal...) float64
  • Duration(key, defaultVal...) time.Duration
  • Time(key, defaultVal...) time.Time

Environment Variables

The framework loads .env files automatically via github.com/joho/godotenv/autoload. For type-safe environment variable access:

port := config.MustEnv("APP_PORT", 8080)
debug := config.MustEnv("APP_DEBUG", false)

MustEnv[T] supports string, int, float64, and bool types.

Configuration Sections

A generated project includes these configuration files:

app.go — Application Settings

Config KeyEnv VariableDefaultDescription
app.nameAPP_NAMELemmegoApplication display name
app.portAPP_PORT8080HTTP server port
app.envAPP_ENVdevelopmentEnvironment (production, development)
app.debugAPP_DEBUGfalseEnable debug mode
app.urlAPP_URLhttp://localhost:8080Application URL

database.go — Database Connections

Config KeyEnv VariableDefaultDescription
sql.defaultDB_CONNECTIONsqliteDefault connection name
sql.connections.sqlite.databaseDB_DATABASEstorage/database.sqliteSQLite path
sql.connections.mysql.hostDB_HOST127.0.0.1MySQL host
sql.connections.mysql.portDB_PORT3306MySQL port

Only the connection the project chose is written, so a SQLite project has no mysql block to ignore.

keyvalue.go — the shared Redis connection

Written when anything in the project uses Redis: the cache, the queue or sessions. It is one connection that all three fall back to, so a single server is configured once.

Config keyEnv variableDefault
keyvalue.connections.redis.hostREDIS_HOSTlocalhost
keyvalue.connections.redis.portREDIS_PORT6379
keyvalue.connections.redis.passwordREDIS_PASSWORD—

A subsystem can still point somewhere else by setting its own key — CACHE_REDIS_ADDR or TASKER_REDIS_ADDR — which overrides the shared value.

cache.go — the cache

Config keyEnv variableDefault
cache.driverCACHE_DRIVERthe driver chosen at scaffold time
cache.prefixCACHE_PREFIXlemmego_cache:
cache.ttlCACHE_TTL3600 (seconds)
cache.codecCACHE_CODECjson
cache.lenientCACHE_LENIENTfalse

See Caching for what each driver can do.

tasker.go — the background queue

Config keyEnv variableDefault
tasker.driverTASKER_DRIVERthe driver chosen at scaffold time
tasker.queueTASKER_QUEUEdefault
tasker.max_attemptsTASKER_MAX_ATTEMPTS3
tasker.workers.defaultTASKER_WORKERS3
tasker.route_prefixTASKER_ROUTE_PREFIX/tasker
—TASKER_ADMINSempty: nobody may open the dashboard

With the SQL driver and no TASKER_DSN, the queue uses the application’s own database connection, so there is one database rather than two that can drift apart.

TASKER_ADMINS is read by the scaffolded DashboardAuth predicate in bootstrap/providers.go, not by the tasker config itself — it is a rule your application owns, so it lives in Go where you can change it to anything. Empty means the dashboard refuses everyone.

filesystems.go — Storage Disks

Config KeyEnv VariableDefaultDescription
filesystems.defaultFILESYSTEM_DISKlocalDefault storage disk
filesystems.disks.local.root—storage/appLocal storage root

session.go — Session Configuration

Config KeyEnv VariableDefaultDescription
session.driverSESSION_DRIVERfileSession store driver (memory, file, redis, database)
session.lifetimeSESSION_LIFETIME120Session lifetime (minutes)
session.cookieSESSION_COOKIElemmego_sessionCookie name

Adding Custom Configuration

You can add your own configuration by creating new files in internal/configs/:

// internal/configs/mail.go
package configs

import "github.com/lemmego/api/config"

func init() {
    config.Set("mail", config.M{
        "default":  config.MustEnv("MAIL_MAILER", "smtp"),
        "host":     config.MustEnv("MAIL_HOST", "smtp.mailtrap.io"),
        "port":     config.MustEnv("MAIL_PORT", 2525),
    })
}

Access your config anywhere in your application:

mailHost := config.Get("mail.host").(string)