anvilsign in

collin/anvil

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 deploy/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
85[agent]
86# Agent sessions: a container per session running tmux plus an agent CLI
87# against one repository, attachable from a terminal in the browser.
88#
89# OFF by default, and deliberately so. CI runs code the pusher wrote; an agent
90# session runs a model that reads repository content, issue text and TODO items
91# as instructions, with network access it cannot do without. Prompt injection in
92# a README is therefore a code-execution path. See docs/untrusted-mode.md before
93# turning this on, and keep it to repositories you trust.
94enabled = false
95# Same image as [ci] default_image above.
96image = "anvil-runner:latest"
97# Directory holding the agent CLI's credentials (a ~/.claude for Claude Code).
98# Its contents are uploaded into each session container as a tar — never bind
99# mounted, so the container still cannot reach anvil's data directory. Empty
100# starts sessions unauthenticated.
101credentials_dir = ""
102# Session sandbox. Same shape as [ci]: all capabilities dropped, no socket, no
103# mounts. Memory defaults higher than CI's because Claude Code asks for 4 GB.
104memory_mb = 4096
105cpus = 2.0
106pids_limit = 1024
107# Reap a session after this long with no viewer attached AND no output. A
108# session someone is watching is never idle, however quiet the agent is.
109idle_timeout_secs = 3600
110# Hard cap regardless of activity.
111max_lifetime_secs = 86400
112# How many sessions may run at once across the instance. Each holds a container
113# open, so this is the real resource bound.
114max_concurrent = 4
115
116# Artifact caps (MiB, 0 = unlimited): one artifact / one run's total / the
117# rolling per-repo budget. Over the repo budget, the oldest commits' artifacts
118# are deleted after each run (branch tips pinned). See docs/ci-artifacts.md.
119artifact_max_mb = 256
120artifact_run_max_mb = 512
121artifact_quota_mb = 4096
122
123# Continuous deployment: on a green run of deploy_branch in the ONE repo named
124# by deploy_repo, POST to deploy_webhook with the X-Anvil-Deploy-Secret header.
125# Empty deploy_repo/deploy_webhook disables deploys entirely.
126deploy_repo = ""
127deploy_branch = "main"
128deploy_webhook = ""
129deploy_secret = ""