gristlabs_grist-core/stubs/app/server/server.ts
Paul Fitzpatrick 2563fb745a (core) make Grist easier to run with a single server
Summary:
This makes many small changes so that Grist is less fussy to run as a single instance behind a reverse proxy. Some users had difficulty with the self-connections Grist would make, due to internal network setup, and since these are unnecessary in any case in this scenario, they are now optimized away. Likewise some users had difficulties related to doc worker urls, which are now also optimized away. With these changes, users should be able to get a lot further on first try, at least far enough to open and edit documents.

The `GRIST_SINGLE_ORG` setting was proving a bit confusing, since it appeared to only work when set to `docs`. This diff
adds a check for whether the specified org exists, and if not, it creates it. This still depends on having a user email to make as the owner of the team, so there could be remaining difficulties there.

Test Plan: tested manually with nginx

Reviewers: jarek

Reviewed By: jarek

Differential Revision: https://phab.getgrist.com/D3299
2022-03-05 13:30:45 -05:00

109 lines
3.2 KiB
TypeScript

/**
* Main entrypoint for grist-core server.
*
* By default, starts up on port 8484.
*/
import {isAffirmative} from 'app/common/gutil';
import {HomeDBManager} from 'app/gen-server/lib/HomeDBManager';
const debugging = isAffirmative(process.env.DEBUG) || isAffirmative(process.env.VERBOSE);
// Set log levels before importing anything.
if (!debugging) {
// Be a lot less noisy by default.
setDefaultEnv('GRIST_LOG_LEVEL', 'error');
setDefaultEnv('GRIST_LOG_SKIP_HTTP', 'true');
}
// Use a distinct cookie. Bump version to 2.
setDefaultEnv('GRIST_SESSION_COOKIE', 'grist_core2');
setDefaultEnv('GRIST_SERVE_SAME_ORIGIN', 'true');
setDefaultEnv('GRIST_SINGLE_PORT', 'true');
setDefaultEnv('GRIST_DEFAULT_PRODUCT', 'Free');
if (!process.env.GRIST_SINGLE_ORG) {
// org identifiers in domains are fiddly to configure right, so by
// default don't do that.
setDefaultEnv('GRIST_ORG_IN_PATH', 'true');
}
import {updateDb} from 'app/server/lib/dbUtils';
import {main as mergedServerMain} from 'app/server/mergedServerMain';
import * as fse from 'fs-extra';
const G = {
port: parseInt(process.env.PORT!, 10) || 8484,
};
// Set a default for an environment variable.
function setDefaultEnv(name: string, value: string) {
if (process.env[name] === undefined) {
process.env[name] = value;
}
}
// tslint:disable:no-console
export async function main() {
console.log('Welcome to Grist.');
if (!debugging) {
console.log(`In quiet mode, see http://localhost:${G.port} to use.`);
console.log('For full logs, re-run with DEBUG=1');
}
// If SAML is not configured, there's no login system, so provide a default email address.
setDefaultEnv('GRIST_DEFAULT_EMAIL', 'you@example.com');
// Set directory for uploaded documents.
setDefaultEnv('GRIST_DATA_DIR', 'docs');
await fse.mkdirp(process.env.GRIST_DATA_DIR!);
// Make a blank db if needed.
await updateDb();
// If a team/organization is specified, make sure it exists.
const org = process.env.GRIST_SINGLE_ORG;
if (org && org !== 'docs') {
const db = new HomeDBManager();
await db.connect();
await db.initializeSpecialIds({skipWorkspaces: true});
try {
db.unwrapQueryResult(await db.getOrg({
userId: db.getPreviewerUserId(),
includeSupport: false,
}, org));
} catch(e) {
if (!String(e).match(/organization not found/)) {
throw e;
}
const email = process.env.GRIST_DEFAULT_EMAIL;
if (!email) {
throw new Error('need GRIST_DEFAULT_EMAIL to create site');
}
const user = await db.getUserByLogin(email, {
email,
name: email,
});
if (!user) {
// This should not happen.
throw new Error('failed to create GRIST_DEFAULT_EMAIL user');
}
await db.addOrg(user, {
name: org,
domain: org,
}, {
setUserAsOwner: false,
useNewPlan: true,
planType: 'free'
});
}
}
// Launch single-port, self-contained version of Grist.
const server = await mergedServerMain(G.port, ["home", "docs", "static"]);
if (process.env.GRIST_TESTING_SOCKET) {
await server.addTestingHooks();
}
}
if (require.main === module) {
main().catch((err) => console.error(err));
}