Zig 0.17.0

Configuration

An app has two places for settings. What is the same everywhere goes in spider.config.zig, which is compiled in. What changes from one machine to another, and what is secret, goes in the environment.

The code on this page is from Posts, the example app in examples/posts (source).

spider.config.zig

zig
const spider = @import("spider");

pub const config = spider.Config{
    .views_dir = "./src",
    .port = 3000,
    .host = "0.0.0.0",
};

Everything has a default, so the file only lists what the app changes. The settings used most:

  • port and host: where the app listens. 0.0.0.0 accepts connections from other machines, which a container needs.
  • views_dir: the folder the templates are under.
  • static_dir: the folder served as static files. null serves none.
  • max_body_bytes: the largest request body accepted, 10 MB unless you say otherwise. A bigger one is answered 413 before it is read.
  • require_route_access: with true, the app refuses to start while a route does not say who may call it, and names each one.

The environment

Variables come from the environment of the process, and from a file named .env in the folder the app runs in. spider new writes .env and keeps it out of git, with .env.example as the copy that is committed:

text
# Copy to .env (spider new already did): cp .env.example .env

# Database: the SQLite file, created by `spider migrate`
SQLITE_PATH=db.sqlite

# Auth
JWT_SECRET=change_me_in_production

# App
LOG_LEVEL=warn

When the same variable is in both, the environment wins over the file: that is how a server or a container sets its own values. A file named .env.local, if there is one, wins over .env, and never over the environment.

Spider reads a few variables itself:

  • PORT: the port, in place of the one in spider.config.zig.
  • SQLITE_PATH, or PG_HOST, PG_PORT, PG_USER, PG_PASSWORD and PG_DB: the database.
  • JWT_SECRET: what login sessions are signed with.
  • SPIDER_MIGRATE: when it is set, the app applies its PostgreSQL migrations and exits instead of serving (Migrations in production).
  • SPIDER_CHECK: when it is set, the app prints whether its modules are ready and exits (spider check --modules sets it).

A module lists the variables it reads. The server does not start while one it requires is not set, or is blank, and says which.

Your own settings

spider.env reads a variable from the same places. Posts takes the key of its API from one:

zig
/// The key clients must send: POSTS_API_KEY from the environment or .env.
/// Without one the API uses "dev-key", fine on your own machine only.
fn apiKey() []const u8 {
    const Once = struct {
        var key: ?[]const u8 = null;
    };
    if (Once.key == null) Once.key = spider.env.getOr("POSTS_API_KEY", "dev-key");
    return Once.key.?;
}

getOr gives a default when the variable is not set; get gives null. Nothing is allocated: the value is the process's own, valid while it runs, so reading it on every request costs nothing. Posts keeps the key after the first read only because it never changes.

Secrets

Keep secrets in the environment, never in spider.config.zig or anywhere else in git. .env is for your own machine. In production, set the variables where the app runs: Docker shows how to give them to a container.