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.yamlis looked for in the working directory, then next to the executable.--config <path>picks another file.- The
.envis 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,httpsandoriginsare the defaults forserve --http,--httpsand--origins.app: your app's folders and options: the same settings as the root flags (--dir,--dev,--hooksDir,--publicDirand the rest), plusenv_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
.envfirst, 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
.envtakesKEY=VALUElines. Blank lines,# commentsand anexportprefix are fine. Quote a value to keep its spaces; double quotes also understand\n,\t,\"and\\. - The
.envis 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 inapp.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
$VARthat is set in neither the.envnor 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 inpocketone config --jsonand in the key table on pocketone.dev. config.Loadchecks 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--configand--env-filebefore 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.envvalues into the process environment (whatapp.env_allowdoes).config.Describe()returns every section with its keys, types, defaults and docs (the data behind--json).config.NewCommand(opts)is theconfigcommand.
License
MIT
Questions and comments
Comments are a GitHub Discussions thread; sign in with GitHub to post.