Grist core multi user docker setup

@paul-grist I must apologize for distracting you from your work.
How I admire your work, this is exactly what MS Access Online should look like, simple, understandable and as close as possible to MS Excel.

1 Like

Retry with gristlabs/grist:latest
Another attempt to solve the problem:
Docker log

info: SamlConfig: got SAML response for mail@mail.com () redirecting to http://my.grist.app/o/myorg/ stdout
21:51:09 2022-04-06 21:51:09.373 - error: ScopedSession[g-r8dXG2m6fKGpF92WkxVBLk]: Error updating sessionStore: Error: failed to load session stdout
21:51:09 2022-04-06 21:51:09.443 - debug: Auth[GET]: id 5 email mail@mail.com host my.grist.app path / org myorg
  1. I use reverse proxy https://my.grist.app to port 8484
    redirecting to http://my.grist.app/o/myorg/ stdout

Console log:

Mixed Content: The page at 'https://my.grist.app/o/myorg/' was loaded over HTTPS, but requested an insecure resource 'http://my.grist.app:8484/o/myorg/api/session/access/all'. This request has been blocked; the content must be served over HTTPS.
(anonymous) @ VM47:1
(anonymous) @ BaseAPI.ts:118
(anonymous) @ main.bundle.js:12
r @ main.bundle.js:12
request @ main.bundle.js:12
(anonymous) @ BaseAPI.ts:36
(anonymous) @ main.bundle.js:12
r @ main.bundle.js:12
i.value @ main.bundle.js:12
(anonymous) @ BaseAPI.ts:133
(anonymous) @ main.bundle.js:12
r @ main.bundle.js:12
requestJson @ main.bundle.js:12
(anonymous) @ BaseAPI.ts:36
(anonymous) @ main.bundle.js:12
r @ main.bundle.js:12
i.value @ main.bundle.js:12
(anonymous) @ UserAPI.ts:421
(anonymous) @ main.bundle.js:6
i @ main.bundle.js:6
getSessionAll @ main.bundle.js:6
(anonymous) @ AppModel.ts:164
(anonymous) @ main.bundle.js:6
i @ main.bundle.js:6
_fetchUsersAndOrgs @ main.bundle.js:6
v @ AppModel.ts:100
create @ dispose.ts:136
C @ App.ts:75
create @ dispose.ts:136
(anonymous) @ app.js:31
i @ jquery.min.js:2
fireWith @ jquery.min.js:2
ready @ jquery.min.js:2
J @ jquery.min.js:2
Show 4 more frames
GristWSConnection.ts:94 GristWSConnection not activating for hosted grist page with no document present
AppModel.ts:157 getSessionActive() failed: TypeError: Failed to fetch
errors.ts:82 ERROR: TypeError: Failed to fetch
    at <anonymous>:1:876
    at u.<anonymous> (BaseAPI.ts:118:29)
    at Generator.next (<anonymous>)
    at main.bundle.js:12:562303
    at new Promise (<anonymous>)
    at r (main.bundle.js:12:562048)
    at u.request (main.bundle.js:12:563823)
    at u.<anonymous> (BaseAPI.ts:36:57)
    at Generator.next (<anonymous>)
    at main.bundle.js:12:562303
    at new Promise (<anonymous>)
    at r (main.bundle.js:12:562048)
    at u.i.value (main.bundle.js:12:563017)
    at u.<anonymous> (BaseAPI.ts:133:24)
    at Generator.next (<anonymous>)
    at main.bundle.js:12:562303
f @ errors.ts:82
Promise.catch (async)
v @ AppModel.ts:100
create @ dispose.ts:136
C @ App.ts:75
create @ dispose.ts:136
(anonymous) @ app.js:31
i @ jquery.min.js:2
fireWith @ jquery.min.js:2
ready @ jquery.min.js:2
J @ jquery.min.js:2
...

Looks like the page, after loading, is requesting something at the wrong port and with the wrong url. Can you try setting APP_HOME_URL=https://my.grist.app?

Thanks, it helped and everything worked, but in vain, when I try to create a team site, I go to the page Loading... - Grist
Thank you for the help, hope has died now.
GRIST_ORG_IN_PATH=true
without
GRIST_SINGLE_ORG=some_org
Doesn’t make sense.

When you use GRIST_SINGLE_ORG=some_org, it will create that team for you and set you up as an owner of it. You can repeat with several GRIST_SINGLE_ORGs, and then switch to GRIST_ORG_IN_PATH to access the teams you have created. Not user-friendly, but it should work.

Team site creation is being reworked, it should get easier in future.

1 Like

@paul-grist Thank you.
I could not even think that GRIST_SINGLE_ORG can be used several times. I went to try.
Try:
GRIST_SINGLE_ORG=org1
GRIST_SINGLE_ORG=org2
GRIST_ORG_IN_PATH=true
Not working
GET https://my.grist.app/o/org1/api/templates?onlyFeatured=1 404
Have access only for org1

Thanks to this thread, I’ve successfully deployed grist and authentik to my VPS using reverse proxy. Everything has worked fine until now, though I encounter a small issue with the GRIST_SINGLE_ORG, it doesn’t present in the url.
It looks like https://my.example.com/kLzquuZKrbrG/data while it should be https://my.example.com/o/myorganization/data

I have included both lines in the grist env:

GRIST_SINGLE_ORG=myorganization
GRIST_ORG_IN_PATH=true
2 Likes

https://my.example.com/o/myorganization/data

I think it does not make sense since the organization is one.
So far I haven’t found a way to make multiple organizations.

Speed up self-hosted grist.
Hello Grist team.
As far as I can understand, there are two options for installing the container SERVER and WORKER (there is no documentation what is the difference and how to and for what apply it).

  1. I have an idea to install WORKER on Docker Desktop like as local remote client for SERVER. Will it give an increase in performance, speed and offload the server? Is it generally possible to package WORKER as . exe file if that makes sense?
  2. Do I need to install REDIS for caching? I see REDIS_URL env but did not find examples on how to specify the address and port of the container REDIS?
    REDIS_URL=redis_container:6379 is correct for same redis&Grist docker bridge network?

Are you experiencing performance issues?

Grist can be configured as a pool of “doc workers” that do everything related to individual documents and “home servers” that do everything else. Both pools are servers, in the sense that they need to be accessible to the end-user working on a document.

The easiest way to boost performance is to give Grist more CPU and RAM. I’d be interested in hearing what kind of performance issue you are seeing.

Redis is required for a multi-worker setup, to keep track of what docs are served by which workers. It will also store sessions (otherwise an Sqlite db is used). It also plays a role in webhooks. If you are seeing some performance issue, Redis is unlikely to be the key to fixing it.

The format of REDIS_URL is for example redis://hostname or redis://hostname:port or redis://hostname:port/N where N is a logical database number (like 0 or 1). You may need to read up online on how to handle networking between containers.

Thank you @paul-grist
I install grist on my old synology NAS with HDD not possible install SSD for cash.

  1. Yesterday I encountered the fact that when starting the background indexing of disks, noticeable delays began. So I thought that this could be compensated by REDIS.
  2. If you use grist for IoT logging (I currently have about 1200000 records in one sqlite table per quarter), then in the future if this is translated into grist I think how to speed up performance with minimal way.

Grist and as NocoDB is maximum fastest way create Headless CMS (much faster than Strapi or Directus). But NocoDB loses to Grist in data filling speed (thanks Excel-like spreadshets and widgets) and formulas, but wins in that it can act as an interface for almost any database (like as phpmyadmin). If using Grist backend and as single source data for many project from one document I also want to understand how to use Grist efficiently as possible.

But unfortunately, I have not yet found a way to read / write data directly to a table without using the REST API .grist (sqlite). Only manual import and export of records between the actual sqlite (or mysql) DB and self-hosted Grist App, like as stream endpoint.

Hi Paul, can you throw more light on this. To scale up, how should I decide what to scale up - home servers vs workers? Is there a fixed ratio I should follow (1 home server for every five workers or something)?

We find it is mostly the number of doc workers that needs to scale, since most work is being done within individual Grist documents. Making an individual host beefier is the way to go for most applications though.

Hi Paul,
Do you have any updated info regarding setting up multiple teams in self-hosted Grist? I have been experimenting with the different options of GRIST_SINGLE_ORG and GRIST_ORG_IN_PATH, but I was not able to get more than one team site (“home”) working.

@wht3v3r there isn’t yet a convenient way to create teams in the UI. But if you are experimenting locally, you can see multiple team site operation as follows.

Start, then stop Grist configured to use a single team (called say team1):

docker run -v /tmp/persist:/persist -p 8484:8484 -e GRIST_SINGLE_ORG=team1 -it gristlabs/grist

Start, then stop Grist configured to use a different team (called say team2):

docker run -v /tmp/persist:/persist -p 8484:8484 -e GRIST_SINGLE_ORG=team2 -it gristlabs/grist

Now run Grist without limiting it to a team:

docker run -v /tmp/persist:/persist -p 8484:8484 -it gristlabs/grist

You should now see the two teams available:

More generally, there is an endpoint for creating sites by POSTing to /api/orgs.

2 Likes

@paul-grist Thanks! The api worked perfectly!

I wasn’t able to get anywhere using the environment variables. I would get an error “Cannot figure out what organization the URL is for.” when going to /o/org and “The requested page could not be found” when going to the base domain. I didn’t find that that setting org_in_path did anything one way or the other.
I am running Grist in a kubernetes set up in case that makes a difference…

This doesn’t work using docker-compose and changing just GRIST_SINGLE_ORG variable. Maybe because I have also other variables set?

Do you have an example? I don’t find the API documentation for posting to /api/orgs here:

These are the relevant variables I have set:

APP_DOC_URL=https://docs.grist.example.com
APP_HOME_URL=https://docs.grist.example.com

GRIST_SAML_SP_HOST=https://docs.grist.example.com

GRIST_DOMAIN=grist.example.com
GRIST_ORG_IN_PATH=false

#GRIST_SINGLE_ORG=team2

I have enabled GRIST_SINGLE_ORG=team1 … team2… and did a docker-compose up … down. Accessing team1… team2.grist.example.com doesn’t worked.

Edit:
Also found the solution!! For all others:

Create an API in your users preferences, then run this API request:

curl -s -X POST -H "Content-Type: application/json" -d '{"name": "Team 1", "domain": "team1"}' -H "Authorization: Bearer <your api key>" https://docs.grist.example.com/api/orgs

Replace name and domain with your prefered name. Use a valid syntax for domain (eg. no spaces). Then you can access the team site with https://team1.grist.example.com. When you do a GET to /api/orgs, owner is nil and thats ok, because owner of the team is set from the API key you use.

Glad you found a solution @Helmut, and thanks for posting it. I’m surprised the GRIST_SINGLE_ORG trick didn’t work for you, one thing that comes to mind is to check that persistence is correctly set up and Grist isn’t losing state between restarts.

Hello ladies and gentlemen.
How we can disable the personal section @username in multiple team site?

By the way, multiple team site is the only way to separate physical document storage locations into user folders on the network storage.