What Grist Does That Google Sheets Cannot
Spreadsheets have a ceiling. Once a project grows beyond a few hundred rows, shared formulas start breaking, column types become inconsistent, and relational data gets hacked together with VLOOKUP chains that nobody wants to maintain. Grist sits in the gap between a traditional spreadsheet and a full relational database – it gives you the familiar grid interface while letting you define column types, link tables together, and build custom views on top of the same underlying data. It runs entirely in a browser, stores everything locally when self-hosted, and requires no SQL knowledge to operate day-to-day.
What makes Grist worth setting up on your own server is data ownership. Cloud spreadsheet tools process your data on their infrastructure, which creates compliance headaches for anyone handling sensitive records – client lists, financial data, internal project tracking. Self-hosting Grist means the database lives on hardware you control, with no third-party retention policies in play.
The self-hosted version is free, open source, and ships as a Docker image.

Prerequisites Before You Start
This setup assumes you have a Linux server or VPS running Docker and Docker Compose. A machine with 1GB of RAM and 10GB of storage handles Grist comfortably for small teams. If you are already running Docker-based self-hosted tools – like Portainer for container management – you can deploy Grist through the same stack without adding infrastructure. You will also want a domain or subdomain pointing to your server if you plan to expose Grist over HTTPS, and a reverse proxy like Nginx or Caddy to handle SSL termination.
Port 8484 is Grist’s default. Make sure that port is open on your firewall, or that your reverse proxy can reach it internally. If you are running UFW, a quick sudo ufw allow 8484 handles it, though exposing this directly without HTTPS is not recommended for anything beyond local testing. Plan to put it behind a proxy before sharing access with anyone else.
Create a working directory before pulling anything. Something like /opt/grist keeps it organized alongside other self-hosted services. Inside that directory, you will place a single docker-compose.yml file and a persistent data folder. Grist writes its SQLite databases to a volume mount, so as long as that directory survives, your data survives container rebuilds.
Deploying Grist with Docker Compose
Create your docker-compose.yml file inside /opt/grist and paste in the following configuration:
- Image: gristlabs/grist:latest
- Container name: grist
- Restart policy: unless-stopped
- Port mapping: 8484:8484
- Volume: ./grist-data:/persist
- Environment variable: GRIST_SESSION_SECRET set to a long random string
The full compose block looks like this:
version: “3”
services:
grist:
image: gristlabs/grist:latest
container_name: grist
restart: unless-stopped
ports:
– “8484:8484”
volumes:
– ./grist-data:/persist
environment:
– GRIST_SESSION_SECRET=your_random_secret_here
Run docker compose up -d from inside /opt/grist. Docker pulls the image, starts the container, and Grist becomes available at your server’s IP on port 8484 within about thirty seconds. On first load, you are greeted with a login screen. By default in sandbox mode, Grist accepts any email address as a login – no password required – which is fine for solo use on a private network but should be locked down before exposing the instance publicly.

Configuring Authentication and Access Control
Out of the box, Grist’s sandbox login is not suitable for multi-user environments or anything internet-facing. The cleanest authentication path for self-hosters is pairing Grist with an external identity provider through the GRIST_OIDC_IDP_* environment variables, which support any OpenID Connect provider – Authentik, Keycloak, and Authelia all work. If you do not want to run a full identity stack, setting GRIST_DEFAULT_EMAIL to your own email address in the compose file restricts the instance to a single owner account without requiring an external provider.
For teams, the OIDC route is worth the extra setup. Once connected, Grist’s built-in workspace permissions handle the rest – documents can be shared at the workspace level or individually, with view-only, editor, and owner roles assignable per user. This makes Grist practical for small teams sharing financial trackers or project databases without giving everyone full access to every file.
SSL setup through Caddy is the fastest option. Add a Caddyfile entry pointing your subdomain at localhost:8484 with the reverse_proxy directive, and Caddy handles certificate renewal automatically. Nginx works equally well with a standard proxy_pass block. Either way, once HTTPS is in place and authentication is configured, the instance is ready for real use.
Building Your First Document
Grist organizes everything into documents, each of which can contain multiple tables. Creating your first document is as simple as clicking Add New from the home screen and selecting Create empty document. The interface opens to a default table view that looks like a standard spreadsheet, but column behavior here is different – each column has a defined type (text, integer, date, reference, toggle, and so on), and Grist enforces those types consistently.
The reference column type is where Grist separates itself from plain spreadsheets. A reference column in one table can point to rows in another table, creating a link between datasets that updates automatically as data changes. A project table referencing a clients table, for example, means each project row carries a live link to the correct client record – no VLOOKUP, no duplicated data. Editing the client’s name in one place updates every reference to it across the document.
Card views, chart views, and custom widgets can all be layered on top of the same tables. A sales database might show the same underlying table as a grid for data entry, a chart for monthly totals, and a card view for account managers browsing individual records. All three reflect the same data in real time. Formulas in Grist use Python syntax rather than Excel syntax, which takes a short adjustment period but gives considerably more flexibility for complex calculations.

One practical note for anyone migrating from existing spreadsheets: Grist imports CSV and Excel files directly through the Add New menu, and it preserves column names while letting you reassign types after import. The import process is not perfect – merged cells and heavy formatting from Excel do not carry over cleanly – but flat tabular data moves in without friction, which covers the majority of real-world migration cases. That alone makes it a workable drop-in for teams sitting on years of spreadsheet data they have been too cautious to move anywhere.





