Grist core multi user docker setup

Hello
The fourth day trying to figure out the installation Grist and Authentik
Lack of clear documentation on installing a docker container for Authentik to the search for an alternative of the form Keycloak maybe it’s redundant.
Dear community, does anyone have any guides or instructions for building in Portainer working Grist core multi user setup?

There’s been a big spike in self-hosters in the last week. For Authentik, here are a few threads that may help:

We do plan to pull everyone’s experiences together and get a tutorial written. For now, here is a summary. On the Grist side, the following environment variables are needed. I’m assuming a localhost install of Grist and Authentik for concreteness, with Grist at port 8484 and Authentik at port 9443. If using Grist inside docker, make sure the volume containing keys and certs is shared. For the keys and certs mentioned, see the Authentik side of configuration just after this.

GRIST_SAML_SP_HOST=http://localhost:8484
GRIST_SAML_SP_KEY=/persist/sp.key
GRIST_SAML_SP_CERT=/persist/sp.pem
GRIST_SAML_IDP_LOGIN=https://localhost:9443/application/saml/grist/sso/binding/redirect/
GRIST_SAML_IDP_LOGOUT=https://localhost:9443/if/session-end/grist/
GRIST_SAML_IDP_CERTS=/persist/idp.pem
GRIST_SAML_IDP_UNENCRYPTED=1

On the Authentik side, add a Provider called Grist with:

  • ACS URL: http://localhost:8484/saml/assert
  • Set Service provider binding: Post
  • Add a signing certificate (this should line up with idp.pem in Grist configuration)
  • Add a verification certificate (this should line up with sp.key/pem in Grist configuration)

Then add an Application also called Grist (I’m not very imaginative) that:

At this point logins should work.

3 Likes

I’m in the same boat as Bibo, except I’m less informed.
I have Authentik installed and Grist installed and both are running.
I am using apache reverse proxy to guide requests for grist.mydomain.com to the localhost:8484
and requests for auth.mydomain.com to localhost:9000 (I think, can’t remember off-hand – the default port for authintik).

My question is about the certs.
Can I use Authentik’s self-signed cert?
If so how?
I can download the file - Authentik Self-signed_certificate.pem
And the SAML Metadata XML for the provider I’ve created.
I can also download the Authentik Self-signed certificate_private_key.pem if I need that.
But I don’t know enough and can’t find an explanation I understand regarding which if any of these are the files that satisfy the environment vars:
GRIST_SAML_IDP_CERTS
GRIST_SAML_SP_KEY
GRIST_SAML_SP_CERT

My docker grist invocation looks like this so far:

docker run --env DEBUG=1 -p 8484:8484 \
  --env GRIST_SAML_IDP_LOGIN=http://auth.MY_DOMAIN.com/application/saml/grist/sso/binding/init/ \
  --env GRIST_SAML_IDP_LOGOUT=http://auth.MY_DOMAIN.com/if/session-end/grist/ \
  --env GRIST_SAML_IDP_CERTS=persist/???? \
  --env GRIST_SAML_SP_KEY=persist/???? \
  --env GRIST_SAML_IDP_UNENCRYPTED=1 \
  --env GRIST_SAML_SP_HOST=http://grist.MY_DOMAIN.com \
  --env GRIST_SAML_SP_CERT=persist/???? \
  -v $PWD/persist:/persist -it gristlabs/grist

Any guidance would be greatly appreciated.

Thanks,
Jeff

Hi @Jeff_2022, welcome to the forum!

In Authentik, in SAML Provider settings, advanced protocol settings, you can set the Signing Certificate to be the Authentik Self-signed Certificate there. You should then download that as a public certificate, place in the persist subdirectory, and use that for GRIST_SAML_IDP_CERTS.

Again in advanced protocol settings, for the Verification Certificate you need a separate certificate. You can create one with Authentik, in the Certificates section. You’ll need to download the certificate and private key for that, place them in the persist subdirectory, and use them for GRIST_SAML_SP_CERT and GRIST_SAML_SP_KEY respectively.

The Authentik part of this tutorial has screenshots that may help:

Thanks!

That got me farther than I have been able to get so far. I think it solved the cert problem, only to expose the next ones. I’ll start new posts for those.

I really appreciate your quick response and direct answer. Big help.

Thanks again.

Glad it helped! For other problems, if you haven’t recently updated your Grist image, that would be worth doing. A bunch of awkward configuration issues were streamlined recently.

Ok, I guess my questions still belong here, but if not let me know and I’ll start another topic. I have very little experience with much of this stuff so please forgive my ignorance.

QUESTIONS:

  1. What should the ACS URL be in my Authentik SAML Provider → Protocal Settings?
    Currently I have it as ht tp://grist.mydomain.com/saml/assert.

  2. What should the value of “Issuer” be in the same section in Authentik?
    Currently I have it as simply “authentik” which was filled in by default.

  3. Do I need to do something with the SAML Metadata XML doc?

Thanks for looking.

DETAILS ABOUT WHAT’S HAPPENING IF YOU NEED THEM:

I have an installation of grist reverseProxied with apache - grist.[mydomain].com → localhost:8484
On the same server I have Authentik reverseProxied with apache - auth.[mydomain].com → localhost:9000

I run grist with these vars:

docker run --env DEBUG=1 -p 8484:8484 \
  --env GRIST_DEFAULT_EMAIL=myemail@gmail.com \
  --env GRIST_SAML_IDP_LOGIN=http://auth.mydomain.com/application/saml/grist/sso/binding/init/ \
  --env GRIST_SAML_IDP_LOGOUT=http://auth.mydomain.com/if/session-end/grist/ \
  --env GRIST_SAML_IDP_CERTS=persist/authentik_self_signed_cert.pem \
  --env GRIST_SAML_IDP_UNENCRYPTED=1 \
  --env GRIST_SAML_SP_KEY=persist/Grist_SAML_SP_private_key.pem \
  --env GRIST_SAML_SP_HOST=http://grist.mydomain.com \
  --env GRIST_SAML_SP_CERT=persist/Grist_SAML_SP_certificate.pem \
  -v $PWD/persist:/persist -it gristlabs/grist

When I go to ht tp://grist.mydomain.com I get the “Welcome” page as a guest. (It’s running!)

I am the admin user in my Authentik app with the same myemail@gmail.com email address.

When I click either “sign in” in the grist menu or “sign up” on the welcome splash page I am redirected to my Authentik installation (also running seemingly correctly) at the URL
ht tp://auth.mydomain.com/if/flow/default-provider-authorization-explicit-consent/?SAMLRequest=[REQUEST_STRING]

Since it is set to “explicit” I get a prompt that has my name for my Authentik user and “You’re about to sign into Grist App.” [Continue]

I click [Continue] and either POST or am redirected (I’ve tried both)
to ht tp://grist.mydomain.com/saml/assert with the SAMLresponse.
If I POST I get a 400 Bad Request. If I redirect I get a 404 not found

Thanks again.

For 1. and 2. what you have seems good. No, you don’t need to do anything with the metadata. POSTing is the right choice. Do you see any more information on the Grist logs for why that 400 response happens? Sorry, I don’t see an obvious problem with your settings.

Not sure to which logs you are referring. Is there a Grist log file that I can locate?

The error logs in apache for grist.mydomain.com have no entry for the 400 error because it doesn’t seem to be a routing problem.

The only thing I can identify that might be an issue is that the origin header is null. But the complaint
isn’t a CORS issue.

Here are the headers:

REQUEST HEADERS:
POST /saml/assert HTTP/1.1
Host: grist.mydomain.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 6846
Origin: null
DNT: 1
Connection: keep-alive
Cookie: grist_core=s%3Ag-pLvchJt1R7zppN9p1tgqv2.WW21M7bevfSGo2o%2FI6aTumH168UK0Pf37Wm3kDI5wB4
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
Pragma: no-cache
Cache-Control: no-cache

REQUEST BODY:
ACSUrl	"http://grist.mydomain.com/saml/assert"
SAMLResponse	"[RESPONSE_STRING]"

RESPONSE HEADERS:
HTTP/1.1 400 Bad Request
Date: Sat, 19 Mar 2022 04:54:47 GMT
Server: Apache/2.4.53 (Ubuntu)
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 685
ETag: W/"2ad-vEECqfytTiwX3jhVG9Od24LWSfY"
Connection: close

Authentik logs an “Application authorized” event that looks like it accepts the credentials but I’m not sure if it’s logging success or just an attempt.
Here is the event object:

Context
{
    "flow": "d689989e22204f4b9cd069b485ab1edb",
    "http_request": {
        "args": {
            "query": "SAMLRequest=[REQUEST_STRING]"
        },
        "path": "/api/v3/flows/executor/default-provider-authorization-explicit-consent/",
        "method": "GET"
    },
    "authorized_application": {
        "pk": "ba49f375dfa6435cb4018f267ece2322",
        "app": "authentik_core",
        "name": "Grist App",
        "model_name": "application"
    }
}
User
{
    "pk": 1,
    "email": "myemail@gmail.com",
    "username": "Jeff Lastname"
}

Thanks for your help.

For Grist logs, I meant its console output, which (if running directly with docker) you could see with docker logs. For example, if I sign in with Authentik, I see these messages there:

2022-03-19 15:31:40.448 localhost:8484 GET /o/docs/signin?next=http%3A%2F%2Flocalhost%3A8484%2Fo%2Fdocs%2F 302 24.802 ms - 3006
2022-03-19 15:31:46.077 - info: SamlConfig: got SAML response for paul@getgrist.com () redirecting to http://localhost:8484/o/docs/
2022-03-19 15:31:46.085 localhost:8484 POST /saml/assert 302 58.638 ms - 102
2022-03-19 15:31:46.142 - debug: Auth[GET]: id 6 email paul@getgrist.com host localhost:8484 path / org docs
2022-03-19 15:31:46.142 - debug: welcoming user: paul

I’m wondering if you see anything around the time the 400 error is reported. However, I expect there won’t be anything useful.

I noticed your GRIST_SAML_IDP_LOGIN ends in /binding/init/ rather than /binding/redirect/. Can you try it with redirect? If I replace redirect with init in a test, I can replicate the error you see.

With GRIST_SAML_IDP_LOGIN changed from /binding/init/ to /binding/redirect/
I get an identical load of the Grist welcome screen.
I click [sign in] at Grist.

Instead of getting a log showing the POST and the 400 bad request status returned, the POST isn’t even attempted according to the Grist log in the console.
Instead, a GET request is logged in the browser and an error page from Athentik URL:
ht tp://auth.mydomain.com/application/saml/grist/sso/binding/redirect/?SAMLRequest=[REQUEST_STRING]

The message is:

Bad Request. Provider does not have a Validation Certificate configured. [Go to home]

So I’ll revisit the certificate setup and try again with /binding/redirect/ and let you know the results.

Details below if you want to view them

Thank you.

// NAVIGATE TO grist.mydomain.com
// BEGIN LOAD OF GRIST WELCOME SCREEN

2022-03-19 23:08:54.737 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com path / org
2022-03-19 23:08:54.740 - debug: Redirecting anonymous user to: http://grist.mydomain.com/o/docs/
2022-03-19 23:08:54.797 grist.mydomain.com GET / 302 19.911 ms - 122
2022-03-19 23:08:54.814 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com path / org docs
2022-03-19 23:08:54.860 grist.mydomain.com GET /o/docs/ 200 8.149 ms - 3381
2022-03-19 23:08:55.150 grist.mydomain.com GET /v/unknown/jqueryui/themes/smoothness/jquery-ui.css 200 8.282 ms - 36536
2022-03-19 23:08:55.208 grist.mydomain.com GET /v/unknown/bootstrap-datepicker/dist/css/bootstrap-datepicker3.min.css 200 11.304 ms - 21100
2022-03-19 23:08:55.218 grist.mydomain.com GET /v/unknown/jqueryui/jquery-ui.min.js 200 8.276 ms - 253669
2022-03-19 23:08:55.219 grist.mydomain.com GET /v/unknown/bootstrap/dist/css/bootstrap.min.css 200 15.006 ms - 122540
2022-03-19 23:08:55.223 grist.mydomain.com GET /v/unknown/bundle.css 200 14.195 ms - 75789
2022-03-19 23:08:55.224 grist.mydomain.com GET /v/unknown/icons/icons.css 200 14.618 ms - 165797
2022-03-19 23:08:55.225 grist.mydomain.com GET /v/unknown/jquery/dist/jquery.min.js 200 16.892 ms - 85630
2022-03-19 23:08:55.231 grist.mydomain.com GET /v/unknown/hljs.default.css 200 0.898 ms - 1159
2022-03-19 23:08:55.249 grist.mydomain.com GET /v/unknown/bootstrap/dist/js/bootstrap.min.js 200 0.847 ms - 36816
2022-03-19 23:08:55.274 grist.mydomain.com GET /v/unknown/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js 200 1.188 ms - 33693
2022-03-19 23:08:55.286 grist.mydomain.com GET /v/unknown/browser-check.js 200 1.740 ms - 113780
2022-03-19 23:08:55.318 grist.mydomain.com GET /v/unknown/main.bundle.js 200 0.835 ms - 3348481
2022-03-19 23:08:55.777 grist.mydomain.com GET /v/unknown/img/gplaypattern.png 200 0.918 ms - 12047
2022-03-19 23:08:56.483 - debug: Auth[OPTIONS]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/active org docs
2022-03-19 23:08:56.491 - debug: Auth[OPTIONS]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/all org docs
2022-03-19 23:08:56.541 grist.mydomain.com:8484 OPTIONS /o/docs/api/session/access/active 200 5.454 ms - 2
2022-03-19 23:08:56.591 grist.mydomain.com:8484 OPTIONS /o/docs/api/session/access/all 200 2.532 ms - 2
2022-03-19 23:08:56.624 grist.mydomain.com GET /v/unknown/icons/favicon.png 200 1.119 ms - 15365
2022-03-19 23:08:56.716 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/active org docs
2022-03-19 23:08:56.729 grist.mydomain.com:8484 GET /o/docs/api/session/access/active 200 13.976 ms - 523
2022-03-19 23:08:56.730 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/all org docs
2022-03-19 23:08:56.752 grist.mydomain.com:8484 GET /o/docs/api/session/access/all 200 26.556 ms - 109
2022-03-19 23:08:57.142 - debug: Auth[OPTIONS]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /orgs/0/workspaces org docs
2022-03-19 23:08:57.146 - debug: Auth[OPTIONS]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /templates org docs
2022-03-19 23:08:57.197 grist.mydomain.com:8484 OPTIONS /o/docs/api/orgs/0/workspaces?includeSupport=1 200 3.274 ms - 2
2022-03-19 23:08:57.291 grist.mydomain.com:8484 OPTIONS /o/docs/api/templates?onlyFeatured=1 200 2.214 ms - 2
2022-03-19 23:08:57.292 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /orgs/0/workspaces org docs
2022-03-19 23:08:57.342 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /templates org docs
2022-03-19 23:08:57.365 grist.mydomain.com:8484 GET /o/docs/api/orgs/0/workspaces?includeSupport=1 200 204.735 ms - 2
2022-03-19 23:08:57.367 grist.mydomain.com:8484 GET /o/docs/api/templates?onlyFeatured=1 404 158.348 ms - 34
 
// END LOAD OF GRIST WELCOME SCREEN WITH 404 ^^^

// CLICK [SIGN-IN] ON WELCOME SCREEN MENU

// NAVIGATES TO URL
2022-03-19 23:09:41.771 grist.mydomain.com GET /o/docs/signin?next=http%3A%2F%2Fgrist.mydomain.com%2Fo%2Fdocs%2F 302 30.617 ms - 3072

// HERE IS WHERE THE RESULTS DIFFER

++ WITH GRIST_SAML_IDP_LOGIN = /binding/redirect/

++ NO FURTHER GRIST LOGS -- NO POST OR RETURN IS LOGGED
++ GET REQUEST TO URL ht tp://auth.mydomain.com/application/saml/grist/sso/binding/redirect/?SAMLRequest=[REQUEST_STRING]
++ ERROR PAGE FROM Athentik URL DISPLAYED

-- WITH GRIST_SAML_IDP_LOGIN = /binding/init/

-- Authentik SPLASH SCREEN WITH PROMT AND [continue] PROPERLY DISPLAYED

-- // CLICK [CONTINUE] ON Authentik PROMT TO POST - ** 400 BAD REQUEST ERROR HERE **
-- 2022-03-19 23:10:25.015 grist.mydomain.com POST /saml/assert 400 25.101 ms - 685  

-- // REDIRECTS TO GRIST ERROR SCREEN
-- 2022-03-19 23:10:25.256 grist.mydomain.com GET /v/unknown/icons/icons.css 200 1.758 ms - 165797
-- 2022-03-19 23:10:25.297 grist.mydomain.com GET /v/unknown/errorPages.bundle.js 200 8.574 ms - 3246312
-- 2022-03-19 23:10:26.133 - debug: Auth[OPTIONS]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/active org
-- 2022-03-19 23:10:26.151 - debug: Auth[OPTIONS]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/all org
-- 2022-03-19 23:10:26.279 grist.mydomain.com:8484 OPTIONS /api/session/access/active 200 2.968 ms - 2
-- 2022-03-19 23:10:26.543 grist.mydomain.com GET /v/unknown/icons/favicon.png 200 0.858 ms - 15365
-- 2022-03-19 23:10:27.175 grist.mydomain.com:8484 OPTIONS /api/session/access/all 200 2.164 ms - 2
-- 2022-03-19 23:10:27.177 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/active org
-- 2022-03-19 23:10:27.195 - debug: Auth[GET]: id 1 email anon@getgrist.com host grist.mydomain.com:8484 path /session/access/all org
-- 2022-03-19 23:10:27.227 grist.mydomain.com:8484 GET /api/session/access/all 200 1022.262 ms - 109
-- 2022-03-19 23:10:27.235 grist.mydomain.com:8484 GET /api/session/access/active 200 1034.314 ms - 107

Hi @Jeff_2022, I can tickle this error if I remove the verification certificate setting from the SAML Provider settings in Authentik:

Can you check you have a certificate set there? One way to create one is using the Generate button in Authentik’s Certificates section:

Before I saw this I had already deleted the certificate that was causing the error. I did have my created certificate selected in the verification certificate dropdown, but the cert was incorrect due to me completely misunderstanding the process in creating it.

I created the certificate correctly and I’m in!

And yes, if I change that setting to remove the verification cert selection from the SAML provider I reproduce the error.

Thank you very much for your help. I hope this thread comes in handy to someone else.

Jeff

2 Likes

Hello Grist team.
After many days, I was able to run Grist + Authentik (it was terrible).

# Authentik SETUP
# URL=https://authentik.app
## Certificates
### Generate grist cert *OU=Self-signed,O=authentik,CN=grist*
## Application
### Name=grist.app
### Slug=grist
### Provider=grist
## SAML Provider
### Name=grist
### Authorization flow=-implicit-
### ACS URL=https://grist.app/saml/assert
### Issuer=authentik
### Service Provider Binding=Post
### Signing Certificate=grist
### Verification Certificate=grist
# gristlabs/grist SETUP
# URL=https://grist.app
PYTHON_VERSION_ON_CREATION=3
GRIST_ORG_IN_PATH=true
GRIST_HOST=0.0.0.0
GRIST_SINGLE_PORT=true
GRIST_SERVE_SAME_ORIGIN=true
GRIST_DATA_DIR=/persist/docs
GRIST_INST_DIR=/persist
GRIST_SESSION_COOKIE=grist_core
TYPEORM_DATABASE=/persist/home.sqlite3
GRIST_DEFAULT_EMAIL=same-as-authentik-admin@mail.com
TIMEZONE=see on https://timezonedb.com
GRIST_SINGLE_ORG=docs
GRIST_ADAPT_DOMAIN=false
APP_HOME_URL=https://grist.app
APP_DOC_URL=https://grist.app
APP_DOC_INTERNAL_URL=https://grist.app
GRIST_SAML_SP_HOST=https://grist.app
GRIST_SAML_IDP_LOGIN=https://authentik.app/application/saml/grist/sso/binding/redirect/
GRIST_SAML_IDP_LOGOUT=http://authentik.app/if/session-end/grist/
GRIST_SAML_IDP_CERTS=persist/grist_certificate.pem
GRIST_SAML_IDP_UNENCRYPTED=1
GRIST_SAML_SP_KEY=persist/grist_private_key.pem
GRIST_SAML_SP_CERT=persist/grist_certificate.pem

Questions immediately arose:

  1. How to set up user invitations (emails not sending)?
  2. How to prevent guests from creating new documents, this wastes server resources and can hypothetically lead to hacks?

It’s been 6 hours and my container has crashed, how can I secure the web-accessible application?
The log of the last messages of the container:

debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path / org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /session/access/all org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /session/access/active org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /templates org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /orgs/0/workspaces org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path / org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /session/access/active org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /session/access/all org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /orgs/0/workspaces org docs stdout
debug: Auth[GET]: id 1 email anon@getgrist.com host my-grist.app path /templates org docs

Authentik/SAML Provider/NameID Property Mapping
What we need setup in this field: userID or Email?

Hello.
Is possible to disallow as global settings new user create workspaces and documents?

For user invitations: self-hosted Grist doesn’t yet have built in email templates, this is a TODO (some notes at feature request: smtp settings for self hosted installation · Issue #146 · gristlabs/grist-core · GitHub).

To limit what guests can do: you could change GRIST_SINGLE_ORG=docs to anything else but docs such as bibo. When set to docs, Grist will work like docs.getgrist.com and allow people to try out Grist anonymously, which I agree doesn’t make sense for your server. When set to something else, such as bibo, Grist will create a bibo “team site” and grant access to the user with email GRIST_DEFAULT_EMAIL. That user can then grant access to others, including optionally the general public (but the public won’t have access by default).

Before changing GRIST_SINGLE_ORG, be aware that you afterwards you won’t be able to find any existing docs via the website. One option is to download them first, then re-upload afterwards.

Not sure why your container crashed, everything in the log you pasted is innocuous looking GETs.

The default worked for me. If you’re having trouble: generally, Grist identifies users by email.

1 Like

Thank you @paul-grist
I’m redoing today authentik (I have no idea how you dealt with him with such documentation, I admire you).
To rebuild Grist I use gristlabs/grist:latest image.
We have a chance with this image to use team sites in path
GRIST_ORG_IN_PATH=true
without
GRIST_SINGLE_ORG=some_org
?
BCS if I delete env variable GRIST_SINGLE_ORG
I can’t access to https://my.grist.app
When I run https://my.grist.app i redirect to http://docs.grist.app/ no chanses access to https://my.grist.app
2022-04-04 14:42:35.260 - debug: Redirecting anonymous user to: http://docs.grist.app/

@BiBo I do see a problem when using GRIST_ORG_IN_PATH without GRIST_SINGLE_ORG - working on a fix, will post when it is in. Sorry about that!