Skip to content

Grist

Note: this file is copied from the Daps grist template’s README.md, located in <daps repository>/templates/grist.

A template for running a self-hosted Grist instance in containers managed by DAPS.

Grist is an open-source spreadsheet/database hybrid. Self-hosting gives you a private data workspace with a built-in UI and a REST API for reading and writing data from other applications.


Before you start: replace the placeholder name

Section titled “Before you start: replace the placeholder name”

This template uses mygrist as a placeholder throughout. There are two ways to set up a project from this template:

From the DAPS root folder:

Terminal window
dapsman init --template grist --name yourprojectname

This copies the template, replaces all mygrist placeholders with your project name (in file contents and filenames), removes any inherited secrets, and registers the project in daps.yaml automatically.

Do a find-and-replace across the whole folder:

ReplaceWith
mygristyour project name (e.g. mypersonaldata)
mygrist.localhostyour local dev hostname (e.g. mypersonaldata.localhost)
mygrist.example.comyour real domain name (e.g. data.example.com)

Files to update (rename the files too):

  • _docker/compose_mygrist.yaml
  • _docker/compose_mygrist.dev.yaml
  • _docker/compose_mygrist.prod.yaml
  • _docker/compose_daps_mygrist.dev.yaml
  • _caddy_sites/mygrist.dev.caddy
  • _caddy_sites/mygrist.prod.caddy

Then add an entry to the root daps.yaml:

projects:
mygrist: # <-- your project name
path: ../mygrist # <-- path to this folder

Open _docker/compose_mygrist.yaml and replace admin@example.com with your email address. Grist uses this as the default account — it can’t be changed after the first run without resetting your data.

The Grist session secret is generated automatically by dapsman local build the first time you run it. It is written to _secrets/.env, which is gitignored.

To generate it manually, or to regenerate it (e.g. after a security incident), run:

Terminal window
./_scripts/prerequisites.dev.sh # skip existing secret
./_scripts/prerequisites.dev.sh --force # regenerate

Never commit the _secrets/ folder or share its contents.

dapsman local build runs prerequisites.dev.sh automatically, which will attempt to add the hosts entry for you:

  • Windows: requires an elevated terminal (right-click → Run as administrator). If not elevated, a warning is printed and you can add it manually.
  • Mac/Linux: requires sudo. If credentials aren’t cached, a warning is printed with the manual command.
  • Chrome and Firefox resolve *.localhost automatically without a hosts entry, so this step is only strictly needed for other tools.

If you need to add it manually:

# Windows: C:\Windows\System32\drivers\etc\hosts
# Mac/Linux: /etc/hosts
127.0.0.1 mygrist.localhost

From the DAPS root folder:

dapsman local build --project mygrist

Your Grist instance will be available at https://mygrist.localhost (via Caddy) or http://localhost:8484 (direct).

Open your site in a browser. Grist will prompt you to create an account. Use the email address you intend to set as GRIST_DEFAULT_EMAIL in the prod compose file.


In _docker/compose_mygrist.prod.yaml, replace admin@example.com with your email address. Grist uses this to associate documents with an owner.

2. Set up a password for the Caddy basic auth

Section titled “2. Set up a password for the Caddy basic auth”

The prod Caddy site file (_caddy_sites/mygrist.prod.caddy) uses HTTP basic auth to protect your Grist instance. You need to replace the placeholder hash with one generated for your chosen password:

Terminal window
docker run --rm caddy:latest caddy hash-password --plaintext 'yourpassword'

Copy the output hash into _caddy_sites/mygrist.prod.caddy, replacing $2a$14$REPLACEME_....

You can also change the username from admin to anything you like.

Confirm _caddy_sites/mygrist.prod.caddy names your real domain, not the mygrist.example.com placeholder, then read “DNS and HTTPS” in daps/docs/readme-deployment.md — whether you create the A record before or after deploying depends on whether the domain is already serving a live site.

Terminal window
dapsman prod deploy --project mygrist --provider <name>

Terminal window
dapsman prod backup --project mygrist --provider <name>

This rsyncs the remote /persist directory (where all Grist documents live as SQLite files) to _backups/from_prod/persist/ inside the project folder.

To snapshot the local instance instead:

Terminal window
dapsman local backup --project mygrist

This saves a timestamped persist/ archive to _backups/from_local/, keeping every snapshot rather than mirroring the latest one. Grist holds its SQLite documents open, so the container is stopped for the few seconds it takes to write the archive and restarted afterwards.

To roll back, stop the container, replace persist/ with the contents of the archive, and start it again — dapsman local restore does not yet support Grist.


mygrist/
├── _caddy_sites/ # Caddy reverse proxy configs (imported by DAPS)
│ ├── mygrist.dev.caddy
│ └── mygrist.prod.caddy
├── _docker/ # Docker Compose files
│ ├── compose_mygrist.yaml # Base config (shared dev + prod)
│ ├── compose_mygrist.dev.yaml # Dev overrides (port, bind mount)
│ ├── compose_mygrist.prod.yaml # Prod overrides (persist path, email)
│ └── compose_daps_mygrist.dev.yaml # Toolkit extension (mounts project into toolkit)
├── _scripts/ # Utility scripts
│ ├── generate-secrets.sh # Shared secret generation library
│ ├── prerequisites.dev.sh # Dev-only setup: secret + hosts entry (run automatically by dapsman)
│ ├── prerequisites.prod.sh # Prod setup: secret on remote (run automatically by dapsman)
│ ├── backup-remote.toolkit.sh # Pulls a backup down from prod (run from toolkit container)
│ └── backup-local.toolkit.sh # Snapshots the local instance (run from toolkit container)
├── _secrets/ # Generated secrets — gitignored, never commit
│ └── .env # Contains GRIST_SESSION_SECRET
├── _backups/ # Backup archive — gitignored
│ ├── from_prod/ # Pulled down by `dapsman prod backup`
│ └── from_local/ # Snapshots taken by `dapsman local backup`
└── persist/ # Grist data directory — gitignored, dev only

ServiceDev portDescription
grist8484Grist Core (Node.js)

The Grist version is pinned in _docker/compose_mygrist.yaml. Grist documents are stored as SQLite files in the /persist directory, which is bind-mounted from the host — they are not inside the container and are safe across image upgrades.

  1. Back up first (Grist may migrate document schemas on startup):

    dapsman prod backup --project mygrist --provider <name>
  2. Update the image tag in _docker/compose_mygrist.yaml:

    image: gristlabs/grist:1.7 → gristlabs/grist:1.8
  3. Test locally:

    dapsman local build --project mygrist

    Open https://mygrist.localhost and confirm your documents open correctly.

  4. Deploy:

    dapsman prod deploy --project mygrist --provider <name>

    Grist applies any necessary document migrations on first startup.


Grist exposes a REST API at https://mygrist.example.com/api/. You can read and write table data, making Grist useful as a lightweight backend where you manage data in the Grist UI and consume it from other applications.

See the Grist API documentation for details. You’ll need an API key, which you can generate in Grist under Profile → API key.