grove
Documentation menu

Deployment

Grove is a single server process with the web app built in. It needs a persistent data directory, a secret key, and a way for your users to sign in. Everything else is configured in the app.

Grove is under active development. Releases can change the database schema and add or remove features, so back up the data directory before upgrading.

Requirements

  • CPU and memory: searches read memory-mapped indices, so memory for the page cache keeps them fast; more cores speed up indexing and broad searches. Requirements grow with the amount of indexed code.
  • Disk: room for a bare mirror of every repository plus its search index. Fast local storage helps.
  • Network: outbound HTTPS to your code hosts (API and git), your OIDC provider and SMTP server if used.
  • Binaries: git and universal-ctags (not Exuberant Ctags). The container image includes both.

Running the container

The image runs Grove as the unprivileged user grove (UID/GID 10001) with DATA_DIR=/data and ctags preconfigured. Grove listens on port 8080 unless you set PORT.

docker run -d --name grove \
  -p 8080:8080 \
  -v grove-data:/data \
  -e SECRET_KEY="$(openssl rand -base64 32)" \
  -e PUBLIC_URL=https://grove.example.com \
  -e OIDC_PROVIDER_URL=https://accounts.google.com \
  -e OIDC_CLIENT_ID=… \
  -e OIDC_CLIENT_SECRET=… \
  grove

Keep SECRET_KEY somewhere safe and pass the same value on every start; generating a new one on each start would make stored code host tokens unreadable. An --env-file works well for this.

Docker Compose with PostgreSQL

services:
 grove:
  image: grove
  ports: ['8080:8080']
  env_file: grove.env
  environment:
   DSN: postgres://grove:secret@db:5432/grove?sslmode=disable
  volumes: ['grove-data:/data']
  depends_on: [db]
 db:
  image: postgres:17
  environment:
   POSTGRES_USER: grove
   POSTGRES_PASSWORD: secret
   POSTGRES_DB: grove
  volumes: ['pg-data:/var/lib/postgresql/data']
volumes:
 grove-data:
 pg-data:

First start

  1. Start Grove and sign in once with your identity provider (or open it directly on a public or development instance).

  2. Make that account a superuser from the server’s command line:

    docker exec -it grove ./server createsuperuser

    It asks for the account’s email or user ID. Superusers can promote others under Settings → Users.

  3. Under Settings → Code hosts, add your GitHub, GitLab or Bitbucket connection. See Code hosts.

  4. Watch repositories arrive under Settings → Repositories. Each one is cloned, indexed and then searchable.

The repositories page listing each repository's sync status and fetch scheduleThe repositories page listing each repository's sync status and fetch schedule

Database

Grove keeps users, settings, saved searches and commit metadata in a database. Search indices always live in DATA_DIR.

  • SQLite (default): a file at $DATA_DIR/db.sqlite. Nothing to set up; a good fit for one server.
  • PostgreSQL: set DSN=postgres://…. Create an empty database and a user that owns it; Grove creates and migrates the schema itself.

Migrations run automatically on startup.

Data directory

Path Contents
repos/ bare git mirrors of every repository
indices/ Zoekt search indices
db.sqlite the database, when using SQLite
extension-key.pem signing key for the self-updating browser extension

Mirrors and indices can be rebuilt from the code hosts; the database and extension-key.pem can’t. Back those up.

Behind a reverse proxy

Terminate TLS at your proxy and forward to Grove’s port. Then:

  • set PUBLIC_URL to the external https:// origin; Grove ignores X-Forwarded-Host,
  • set COOKIE_SECURE=true so session cookies are never sent over plain HTTP,
  • allow long requests: searches can take up to SEARCH_TIMEOUT (40 seconds), result downloads up to EXPORT_TIMEOUT (60 seconds),
  • set MCP_ALLOWED_ORIGINS to your origin.

If the proxy authenticates users, Grove can trust its headers instead of using OIDC; see proxy headers.

Monitoring

Grove exposes Prometheus metrics at /metrics, or on a separate listener when METRICS_PORT is set. Besides server, sync and indexing metrics, tracked saved searches with a metric label publish their result counts there. Settings → Stats shows index and disk usage in the app.

Logs go to stdout; use LOG_FORMAT=json for log collectors.

Restricting outbound traffic

Grove clones from the URLs your code hosts’ APIs report. For tighter deployments, allow outbound connections only to your code hosts, OIDC provider and SMTP server at the network level (firewall, egress proxy or a Kubernetes NetworkPolicy).

Next steps