Config

PocketOne's config file: pocketone.yaml, with secrets in a .env beside it. Put your app's settings in one file instead of a long line of flags. Each extension has its own section in the file.

Install · Configure · Use · Integrations · Example

Install

Config is built into pocketone and always on. Without a pocketone.yaml, nothing changes: every setting keeps its default and the flags work as usual.

In your own Go build, load the file before the app is created, so its values can be the flags' defaults:

cfg, err := config.Load(config.FromArgs(os.Args[1:]))
if err != nil {
	log.Fatal(err)
}
appCfg, _ := config.App.Get()
app := pocketbase.NewWithConfig(pocketbase.Config{DefaultDataDir: cfg.ResolvePath(appCfg.Dir)})
app.RootCmd.AddCommand(config.NewCommand(func() config.Options { return config.FromArgs(os.Args[1:]) }))

The module is github.com/pockethost/pocketone/ext/config. examples/pocketone/main.go shows the full wiring: every app key as a flag default, and the server keys as the serve command's defaults.

Configure

Where the files are

  • pocketone.yaml is looked for in the working directory, then next to the executable. --config <path> picks another file.
  • The .env is looked for beside the config file (or in the working directory when there is no config file). --env-file <path> picks another one.
  • Relative paths in the file are relative to the file's folder, so it works from any working directory.

What goes in it

Each top-level key is one section, owned by the extension that uses it. This package owns three:

  • server: how the app listens. http, https and origins are the defaults for serve --http, --https and --origins.
  • app: your app's folders and options: the same settings as the root flags (--dir, --dev, --hooksDir, --publicDir and the rest), plus env_allow.
  • provider: set it only to run many instances from one binary (see Integrations).
server:
  http: 127.0.0.1:8090
  origins: ["*"]
app:
  dir: ./pb_data
  hooks_dir: ./pb_hooks
  env_allow: [STRIPE_KEY]
pitr:
  retention: 168h

Other extensions' sections (such as pitr above) are described on their own pages. pocketone config lists every section your binary knows.

Flags win

A flag on the command line always wins over the file. The file only changes the defaults.

Secrets in the .env

Write $VAR or ${VAR} in any value, and keep the secret in the .env:

autotls:
  dns:
    api_token: $CF_API_TOKEN
# .env
CF_API_TOKEN=abc123
  • A name is looked up in the .env first, then in the process environment. $$ is a literal $.
  • A name that is set nowhere stops the app at startup, with the missing names listed.
  • The .env takes KEY=VALUE lines. Blank lines, # comments and an export prefix are fine. Quote a value to keep its spaces; double quotes also understand \n, \t, \" and \\.
  • The .env is used only for these references. It is never put in the process environment, so your JS hooks ($os.getenv) don't see it, unless you list a name in app.env_allow.

pocketone.yaml reference

app:

The single app: data dir, dev mode, encryption, hooks, migrations, public dir, and the .env names it may read (env_allow). Not used when a provider runs many instances.

Key Type Default Description
dir string The data folder (pb_data). Default: pb_data next to the executable. The --dir flag wins.
dev bool Dev mode: logs and SQL statements printed to the console. The --dev flag wins.
encryption_env string Name of the environment variable holding a 32-character key that encrypts the app settings. The --encryptionEnv flag wins.
query_timeout duration Default timeout for SELECT queries, such as 30s. The --queryTimeout flag wins.
hooks_dir string The JS hooks folder. Default: pb_hooks next to pb_data. The --hooksDir flag wins.
hooks_watch bool Restart the app when a pb_hooks file changes. On unless false. The --hooksWatch flag wins.
hooks_pool int How many JS runtimes are kept ready for hooks. Default 15. The --hooksPool flag wins.
migrations_dir string The migrations folder. Default: pb_migrations next to pb_data. The --migrationsDir flag wins.
automigrate bool Write a migration file when you change collections in the dashboard. On unless false. The --automigrate flag wins.
public_dir string The static files folder. Default: pb_public next to the executable. The --publicDir flag wins.
index_fallback bool Serve index.html for a missing static path, for single-page apps. On unless false. The --indexFallback flag wins.
env_allow list of string Names from the .env the app and its JS hooks may read. Default none.

provider:

The runtime provider that runs many instances (pocker or docker). Omit for a single stock app.

server:

How the binary listens: http, https and CORS origins (single-app mode: the serve command's defaults).

Key Type Default Description
http string Plain HTTP address, such as 127.0.0.1:8090. Single app: the --http default (the flag wins). Many instances: redirects to https when https is set.
https string HTTPS address. Single app: the --https default (the flag wins). Many instances: the main address.
origins list of string Allowed CORS origins. Single app: the --origins default (the flag wins).
plain list of string Many instances only: extra plain HTTP addresses with no redirect.
tls.cert string Many instances only: the certificate file, reloaded when it changes.
tls.key string Many instances only: the private key file, reloaded when it changes.
shutdown_timeout duration Many instances only: how long in-flight requests get to finish at stop.

Use

See every section

pocketone config

It prints each section with its description and defaults, as YAML you can copy into your file. For the same list as JSON (each section's name, description, owning extension, and each key with its type and default):

pocketone config --json

Check your file

pocketone config check

It reads the file and the .env and reports problems, or a line like:

/srv/app/pocketone.yaml: ok (3 sections), secrets from /srv/app/.env

With no file it says no config file: defaults only.

What stops startup

The app won't start, and says why, when the file has:

  • a top-level key no extension in the binary owns (usually a typo); the error lists the sections it knows;
  • the same section twice;
  • a value that doesn't fit its key (for example text where a number goes);
  • a $VAR that is set in neither the .env nor the environment.

An empty section (pitr: with nothing after it) is allowed and means all defaults.

Integrations

Works with

Extension How they fit
Every extension with a section Each extension declares its own section; its values become that extension's defaults or flag defaults. PITR, S3 Redirect and Auto TLS are examples.
Pocker and Docker Set provider: pocker or provider: docker and pocketone serve runs many instances instead of one app. The app section and env_allow don't apply then; each instance has its own folder under the provider's root.

The server section with many instances

With a provider, server has a few more keys: https is the main address, http then redirects plain HTTP to it (http alone serves plain HTTP), plain lists extra plain-HTTP addresses with no redirect, tls names a certificate and key file (reloaded when they change), and shutdown_timeout limits how long in-flight requests get at stop.

provider: pocker
server:
  https: ":443"
  http: ":80"
  plain: [":8080"]
  tls: { cert: /etc/certs/cert.pem, key: /etc/certs/key.pem }

Give your extension a section

Declare it in your own package with a typed key and defaults:

type Config struct {
	Limit int `yaml:"limit" doc:"Requests per minute. The --limit flag wins."`
}

var Section = extkit.NewSection("firewall", Config{Limit: 60}, "Request limits for the app.")

cfg, found := firewall.Section.Get()   // the defaults with the file's values applied
cfg, err := firewall.Section.Require() // fails when the file doesn't have the section
  • An extension reads a section only through its owner's key, so it can read only sections from packages it imports. There is no lookup by name and no access to the raw file.
  • The doc:"…" tag on each field describes the key in pocketone config --json and in the key table on pocketone.dev.
  • config.Load checks every section when the app starts, so a bad value fails early.

Example

Config is built into pocketone: examples/pocketone/main.go loads pocketone.yaml with it before the app starts and adds the config command.

Go API

  • config.FromArgs(args) reads --config and --env-file before the full flag parse.
  • config.Load(opts) finds, reads and checks the files, and makes them the source for every section. config.Read(opts) does the same without checking or installing them.
  • (*Config).ResolvePath(p) makes a relative path from the file absolute, relative to the file's folder.
  • (*Config).AllowEnv(names) copies those .env values into the process environment (what app.env_allow does).
  • config.Describe() returns every section with its keys, types, defaults and docs (the data behind --json).
  • config.NewCommand(opts) is the config command.

License

MIT