anvilsign in

collin/anvil

main / anvil.example.toml
1# anvil configuration. Copy to `anvil.toml` and edit. All fields are optional;
2# omitted fields fall back to the defaults shown here.
3
4# Root directory for all server state (database + repositories).
5data_dir = "data"
6
7[http]
8listen = "127.0.0.1:3000"
9base_url = "http://localhost:3000"
10# Memory budget (MiB) for the cache of syntax-highlighted file views.
11# Highlighting large files is CPU-heavy, so repeat views are served from this
12# cache. Set to 0 to disable it entirely on RAM-constrained hosts.
13highlight_cache_mb = 16
14# Maximum size (MiB) of a single uploaded attachment (e.g. an image pasted
15# into the web file editor). Larger uploads are rejected.
16attachment_max_mb = 16
17# Per-repository cap (MiB) on total stored attachments. An upload that would
18# exceed it is rejected; re-uploading existing (deduped) content is free.
19# 0 means unlimited.
20attachment_quota_mb = 0
21
22# Single sign-on against an OpenID Connect provider (see docs/oidc.md).
23# Off unless `issuer` is set; password sign-in keeps working either way.
24[oidc]
25# e.g. "https://login.richardscollin.com", or "https://login.localhost" for a
26# provider running locally. Empty disables single sign-on entirely.
27issuer = ""
28# Client id registered at the provider.
29client_id = "anvil"
30# Client secret. Prefer the ANVIL_OIDC_CLIENT_SECRET environment variable —
31# config files get committed, this must not. Empty for a public client.
32client_secret = ""
33# Defaults to base_url + "/-/oidc/callback". Must match the URI registered at
34# the provider exactly; there are no wildcards.
35redirect_uri = ""
36# Sign-in button text, after "Sign in with ". Defaults to the issuer's host.
37label = ""
38# Whether signing out of anvil also ends the provider's session. Needs a
39# post-logout URI registered for this client to come back here afterwards.
40sso_logout = true
41
42[ssh]
43enabled = false
44# Internal bind address. Under Docker, set host = "0.0.0.0" and forward the port.
45listen = "127.0.0.1:2222"
46# What to show users in SSH clone URLs. Set clone_port to the externally
47# forwarded port if it differs from the internal bind (e.g. Docker -p 2200:2222).
48clone_host = "localhost"
49clone_port = 2222
50clone_user = "git"
51
52[ci]
53# Shared secret a runner presents as X-Anvil-Runner-Token to claim and report
54# jobs (docs/remote-runners.md). anvil does NOT execute CI itself -- an empty
55# token means no runner can authenticate and queued runs simply sit there.
56#
57# Start a runner on a machine with room to build:
58# anvil-worker --url https://anvil.example.com --token "$ANVIL_RUNNER_TOKEN"
59runner_token = ""
60
61# Job sandbox. Containers always run with no Docker socket, no mounts, all
62# capabilities dropped, and no-new-privileges; these knobs bound resources
63# (0 = unlimited). Enforced by the runner, from these values -- tightening a
64# limit here does not need runners redeployed. See docs/untrusted-mode.md for
65# the threat model.
66# Images a pipeline may use: empty allows any; a tagless entry ("rust") allows
67# every tag of that image; a tagged one ("alpine:3.20") exactly itself.
68allowed_images = []
69memory_mb = 2048
70cpus = 2.0
71pids_limit = 512
72# Wall-clock limit per job, after which the container is killed.
73timeout_secs = 1800
74# Whether jobs get network access (most builds need it to fetch dependencies).
75network = true
76# User inside the job container, e.g. "1000:1000". Empty keeps the image default.
77run_as = ""
78# Image for a pipeline that omits `image:`. This is anvil's own runner, shared
79# with agent sessions and built by docker/runner/build.sh — it carries tmux,
80# git, fish and Claude Code. It is a LOCAL image with no registry behind it, so
81# anvil falls back to the local copy when the pull fails. Always allowed,
82# whatever allowed_images says.
83default_image = "anvil-runner:latest"
84# Platform (os/arch) for a pipeline that omits `platform:`. Empty runs every job
85# on whatever the claiming runner is native to.
86#
87# Set it to what you DEPLOY on when your runners are a different architecture:
88# an M-series Mac resolves a multi-arch image to arm64 and will happily green-light
89# code you ship as amd64. anvil routes a job to a runner that is natively its
90# platform when one is connected, and falls back to an emulating runner (Rosetta
91# on macOS -- turn it on in Docker Desktop) when none is, rather than leaving the
92# run queued. See docs/remote-runners.md.
93platform = ""
94
95[agent]
96# Agent sessions: a container per session running tmux plus an agent CLI
97# against one repository, attachable from a terminal in the browser.
98#
99# OFF by default, and deliberately so. CI runs code the pusher wrote; an agent
100# session runs a model that reads repository content, issue text and TODO items
101# as instructions, with network access it cannot do without. Prompt injection in
102# a README is therefore a code-execution path. See docs/untrusted-mode.md before
103# turning this on, and keep it to repositories you trust.
104enabled = false
105# Same image as [ci] default_image above.
106image = "anvil-runner:latest"
107# Directory holding the agent CLI's credentials (a ~/.claude for Claude Code).
108# Its contents are uploaded into each session container as a tar — never bind
109# mounted, so the container still cannot reach anvil's data directory. Empty
110# starts sessions unauthenticated.
111credentials_dir = ""
112# Session sandbox. Same shape as [ci]: all capabilities dropped, no socket, no
113# mounts. Memory defaults higher than CI's because Claude Code asks for 4 GB.
114memory_mb = 4096
115cpus = 2.0
116pids_limit = 1024
117# Reap a session after this long with no viewer attached AND no output. A
118# session someone is watching is never idle, however quiet the agent is.
119idle_timeout_secs = 3600
120# Hard cap regardless of activity.
121max_lifetime_secs = 86400
122# How many sessions may run at once across the instance. Each holds a container
123# open, so this is the real resource bound.
124max_concurrent = 4
125
126# Artifact caps (MiB, 0 = unlimited): one artifact / one run's total / the
127# rolling per-repo budget. Over the repo budget, the oldest commits' artifacts
128# are deleted after each run (branch tips pinned). See docs/ci-artifacts.md.
129artifact_max_mb = 256
130artifact_run_max_mb = 512
131artifact_quota_mb = 4096
132
133# Continuous deployment: on a green run of deploy_branch in the ONE repo named
134# by deploy_repo, POST to deploy_webhook with the X-Anvil-Deploy-Secret header.
135# Empty deploy_repo/deploy_webhook disables deploys entirely.
136deploy_repo = ""
137deploy_branch = "main"
138deploy_webhook = ""
139deploy_secret = ""