All docs

Running Fettlecode

Settings

Every setting Fettlecode reads, how to set them with Docker Compose, and how to set up email, Git over SSH and Pages.

Fettlecode reads its settings from the environment. With Docker Compose, put them in a .env file next to compose.yaml and run docker compose up -d again. Only APP_URL matters for a first try.

compose.yaml passes the common settings through to the app. For the rest (marked † below), also add them to the environment: list in compose.yaml, or in a compose.override.yaml so upgrades don't overwrite your change.

The basics

SettingDefaultWhat it does
APP_URLhttp://localhost:3200The address people use, with no slash at the end. Links in emails and webhooks use it.
POSTGRES_PASSWORDfettlecodeThe database password (Compose). Set a long random one before others use it.
DATABASE_URL †(from Compose)Use your own PostgreSQL 16 or later instead: postgres://user:pass@host:5432/fettlecode.
AUTH_SECRET(made for you)Signs sessions and encrypts stored secrets. At least 32 characters. Made on first start and kept in the data volume if unset.
SETUP_CODE(made for you)The code that creates the first account, at least 8 characters. If unset, a new one is printed in the log at each start until there's an account.
ALLOW_SIGNUPfalsetrue lets anyone who can reach Fettlecode make an account.
TRUST_PROXYfalsetrue behind a reverse proxy that sets X-Forwarded-For, so rate limits and the audit log see real addresses.
HTTP_PORT3200The port the app is published on, on the host (Compose).
LOG_LEVELinfofatal, error, warn, info, debug or trace.
UPDATE_CHECKtrueOnce a day, check code.fettle.software for a newer release, and tell instance administrators. Nothing about this install is sent. false turns it off.

Email

SettingDefaultWhat it does
SMTP_URL(none)smtps://user:pass@smtp.example.com:465 or smtp://user:pass@host:port. Without it there's no email, and invitations show a link to copy.
MAIL_FROMFettlecode <fettlecode@localhost>Who emails come from.

Git

SettingDefaultWhat it does
SSH_PUBLISHED_PORT2222The SSH port on the host (Compose).
SSH_PORT †2222The port SSH listens on inside the container. 0 turns SSH off.
SSH_HOSTAPP_URL's hostThe host shown in SSH clone addresses.
LFS_MAX_OBJECT_MB2048The largest single file Git LFS takes, in megabytes.
MAX_CHANGES_PER_PUSH †50The most commits one push for review can turn into changes (up to 500).

Pages

Pages publishes static sites from repositories (see Releases and Pages). It needs a domain of its own, not a subdomain of Fettlecode's, because sites run their own scripts: something like example-pages.net, with a wildcard DNS record (*.example-pages.net) pointing at the server.

SettingDefaultWhat it does
PAGES_URL(off)Where sites are served, such as https://example-pages.net. Each owner gets a subdomain: https://wren.example-pages.net/bookings/.
PAGES_PUBLISHED_PORT3201The port Pages is published on, on the host. Point the wildcard host's proxy here.

With Caddy:

*.example-pages.net {
  tls {
    on_demand
  }
  reverse_proxy localhost:3201
}

Caddy's on-demand certificates need an ask endpoint, or use a wildcard certificate; use whichever your setup supports.

Connections

SettingDefaultWhat it does
INTEGRATIONS_ALLOW_PRIVATEfalse (Compose)true lets imports, mirrors, webhooks, AI and the Fettle app connections reach private network addresses, such as an internal Git host, a local model server, or Fettleboard on the same network.
GITHUB_URL, GITHUB_API_URL †GitHub.comPoint imports, the pull request bridge and GitHub sign-in at GitHub Enterprise Server.
GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY, GITHUB_APP_WEBHOOK_SECRET †(none)A GitHub App for the pull request bridge. The private key is the PEM itself or a path to the .pem file.

Sign-in settings (single sign-on, LDAP and GitHub) are in Sign-in and single sign-on.

Set up in the app

Everything else, such as AI, the MCP server and CI runners, is set up in the app by an instance admin, under Your settings → This Fettlecode.

Checking it's healthy

  • GET /healthz answers {"ok":true} when the server is up. The image's health check uses it.
  • Logs are JSON lines on standard output: docker compose logs -f app.

Commands

Run inside the container:

docker compose exec app node dist/cli/create-user.js alice "Alice Example" alice@example.com

create-user prints a password and a personal access token, once.