Command line

Margaret generates your application's command line from your code. Run box_office --help to see yours:

$ box_office --help
Usage: box_office [COMMAND]

Commands:
  add-promoter      Lets a promoter publish line-ups from a GitHub repository
  add-staff-member  Lets a customer sign in to the back office
  import-concerts   Imports concerts from a promoter's JSON Lines file
  lineup            Shows the upcoming concerts
  send-test-email   Sends a test email to check the mail settings
  serve
  schema
  help              Print this message or the help of the given subcommand(s)

Commands

CommandAppears when you have
your own commands#[console_command]
serveHTTP routes, WebSocket sessions, or background services
schemamodels, or features that keep their own tables, like sessions and signing keys

Each command accepts the settings of the singletons it reaches, and nothing else. schema needs no settings at all: it describes the database your models need, and you feed it to a fresh database with box_office schema | psql "$DATABASE_URL".

serve flags

FlagAppears when
---addra route or session uses that server
---urla route or session uses that server, except the server at your issuer's address
---upload-dira route on that server takes UploadedFiles
---transportany server needs service identity
--spiffe-trust-domain, --spire-agent-addryou use service identity, or consume sessions
your own flagsany served singleton asks for them, see Configuration

A server URL is an origin, like https://tickets.example.com, with no path.

Environment variables

VariableComes from
the two names you pick, like DATABASE_URL and DATABASE_MAX_CONNECTIONS#[postgres_database(url_from = ..., max_connections_from = ...)]
your own#[environment_variable(from = ...)]
a client secret, like GOOGLE_CLIENT_SECRETClientSecretBasic(client_secret_from = ...) in #[oauth_client]
a cookie domain, like SESSION_COOKIE_DOMAINSessionCookies::SharedWithDomain(domain_from = ...)
a cookie domain and a refresh URL#[consumes_sessions(cookie_domain_from = ..., refresh_url_from = ...)]

The finished box office

Here's how the box office from these docs starts in production, with every flag and variable its code asks for:

$ DATABASE_URL=postgres://... DATABASE_MAX_CONNECTIONS=16 \
  MAIL_API_TOKEN=... GOOGLE_CLIENT_SECRET=... \
  box_office serve \
    --public-addr 0.0.0.0:8080 --public-transport plain \
    --admin-addr 10.0.0.5:9090 --admin-url https://admin.tickets.internal --admin-transport plain \
    --admin-upload-dir /var/lib/box_office/uploads \
    --internal-addr 0.0.0.0:9443 --internal-url https://box-office.internal:9443 --internal-transport spiffe_mtls \
    --spiffe-trust-domain example.org --spire-agent-addr unix:///run/spire/agent.sock \
    --mail-api-url https://mail.example.com/send --mail-sender tickets@example.com \
    --payments-url https://payments.internal/ --payments-spiffe-id spiffe://example.org/payments

The public server runs at the issuer's address, https://tickets.example.com, so it has no --public-url.

The door scanner

$ DATABASE_URL=postgres://... DATABASE_MAX_CONNECTIONS=4 \
  door_scanner serve \
    --public-addr 0.0.0.0:8080 --public-url https://doors.example.com \
    --gate-addr 10.0.1.5:8443 --gate-url https://gate.doors.internal \
    --box-office-url https://tickets.example.com/