collin/anvil
d60232e675b92bbd35bdc08ff14ae69d6afe87f1 / 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). |
| 5 | data_dir = "data" |
| 6 | |
| 7 | [http] |
| 8 | listen = "127.0.0.1:3000" |
| 9 | base_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. |
| 13 | highlight_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. |
| 16 | attachment_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. |
| 20 | attachment_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. |
| 27 | issuer = "" |
| 28 | # Client id registered at the provider. |
| 29 | client_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. |
| 32 | client_secret = "" |
| 33 | # Defaults to base_url + "/-/oidc/callback". Must match the URI registered at |
| 34 | # the provider exactly; there are no wildcards. |
| 35 | redirect_uri = "" |
| 36 | # Sign-in button text, after "Sign in with ". Defaults to the issuer's host. |
| 37 | label = "" |
| 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. |
| 40 | sso_logout = true |
| 41 | |
| 42 | [ssh] |
| 43 | enabled = false |
| 44 | # Internal bind address. Under Docker, set host = "0.0.0.0" and forward the port. |
| 45 | listen = "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). |
| 48 | clone_host = "localhost" |
| 49 | clone_port = 2222 |
| 50 | clone_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" |
| 59 | runner_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. |
| 68 | allowed_images = [] |
| 69 | memory_mb = 2048 |
| 70 | cpus = 2.0 |
| 71 | pids_limit = 512 |
| 72 | # Wall-clock limit per job, after which the container is killed. |
| 73 | timeout_secs = 1800 |
| 74 | # Whether jobs get network access (most builds need it to fetch dependencies). |
| 75 | network = true |
| 76 | # User inside the job container, e.g. "1000:1000". Empty keeps the image default. |
| 77 | run_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. |
| 83 | default_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. |
| 93 | platform = "" |
| 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. |
| 104 | enabled = false |
| 105 | # Same image as [ci] default_image above. |
| 106 | image = "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. |
| 111 | credentials_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. |
| 114 | memory_mb = 4096 |
| 115 | cpus = 2.0 |
| 116 | pids_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. |
| 119 | idle_timeout_secs = 3600 |
| 120 | # Hard cap regardless of activity. |
| 121 | max_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. |
| 124 | max_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. |
| 129 | artifact_max_mb = 256 |
| 130 | artifact_run_max_mb = 512 |
| 131 | artifact_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. |
| 136 | deploy_repo = "" |
| 137 | deploy_branch = "main" |
| 138 | deploy_webhook = "" |
| 139 | deploy_secret = "" |