Skip to content

Instantly share code, notes, and snippets.

@corpix
Created November 15, 2024 03:32
Show Gist options
  • Save corpix/bc129bbe99e85ebc2c2b636ee9dc8207 to your computer and use it in GitHub Desktop.
Save corpix/bc129bbe99e85ebc2c2b636ee9dc8207 to your computer and use it in GitHub Desktop.
{ lib
, buildPythonPackage
, fetchPypi
, isPyPy
, pytestCheckHook
, asttokens
, executing
, pure-eval
, stack-data
, six
, ... }:
buildPythonPackage rec {
pname = "friendly-traceback";
version = "0.7.61";
format = "setuptools";
src = fetchPypi {
inherit pname version;
hash = "sha256-jKFJ6k7/oRSp1DVAeNAlLbxT4pHNzGPyPjS4+2W6FfM=";
};
propagatedBuildInputs = [
asttokens
executing
pure-eval
stack-data
six
];
doCheck = false;
}
#!/usr/bin/env bash
set -eu
export PATH=@path@
export GRIST_LOG_LEVEL=${GRIST_LOG_LEVEL:-info}
export GRIST_ORG_IN_PATH=${GRIST_ORG_IN_PATH:-true}
export GRIST_HOST=${GRIST_HOST:-0.0.0.0}
export GRIST_SINGLE_PORT=${GRIST_SINGLE_PORT:-true}
export GRIST_SERVE_SAME_ORIGIN=${GRIST_SERVE_SAME_ORIGIN:-true}
export GRIST_DATA_DIR=${GRIST_DATA_DIR:-$(pwd)/grist/data}
export GRIST_INST_DIR=${GRIST_INST_DIR:-$(pwd)/grist}
export GRIST_SESSION_COOKIE=${GRIST_SESSION_COOKIE:-grist-session}
export GRIST_SANDBOX_FLAVOR=${GRIST_SANDBOX_FLAVOR:-gvisor}
export GRIST_TELEMETRY_LEVEL=${GRIST_TELEMETRY_LEVEL:-off}
export GRIST_FORCE_LOGIN=${GRIST_FORCE_LOGIN:-true}
export GRIST_HIDE_UI_ELEMENTS=${GRIST_HIDE_UI_ELEMENTS:-helpCenter,billing,templates,multiSite,multiAccounts,sendToDrive,tutorials,supportGrist}
export TYPEORM_DATABASE=${TYPEORM_DATABASE:-$GRIST_INST_DIR/db.sqlite3}
export GVISOR_FLAGS=${GVISOR_FLAGS:-"-unprivileged -ignore-cgroups"}
cd @gristOut@
exec ./sandbox/run.sh
{ lib, stdenv, fetchFromGitHub, fetchYarnDeps
, yarn, python3, sqlite, nodejs, gvisor, gnused, coreutils
, ... }:
let
pname = "grist";
version = "1.2.1";
src = fetchFromGitHub {
owner = "gristlabs";
repo = "grist-core";
rev = "v${version}";
hash = "sha256-anrM6EJ8A+QG6f3NlTOdDdWPhjnA82uRcOXJUcnWsn0=";
};
offlineCache = fetchYarnDeps {
yarnLock = src + "/yarn.lock";
hash = "sha256-oK1Y65UcvYkhHW7GO3yufWY8O0YUeAMMLdEPPR4f+w4=";
};
gristPython = python3.withPackages (pkgs: let
inline = [ (pkgs.callPackage ./friendly-traceback.nix {}) ];
in inline ++ (with pkgs; [
openpyxl
astroid
asttokens
roman
chardet
iso8601
phonenumbers
python-dateutil
six
sortedcontainers
unittest-xml-reporting
]));
in stdenv.mkDerivation {
inherit pname version src;
nativeBuildInputs = [
yarn nodejs gristPython
nodejs.pkgs.node-pre-gyp
];
buildInputs = [
sqlite
];
preUnpack = ''
export HOME=$NIX_BUILD_TOP/yarn_home
'';
patchPhase = ''
patchShebangs buildtools/*
# Do not look up in the registry, but in the offline cache.
# TODO: Ask upstream to fix this mess. see yarn2nix-moretea
sed -i -E '/resolved /{s|https://registry.yarnpkg.com/||;s|[@/:-]|_|g}' yarn.lock
rm .yarnrc
'';
configurePhase = ''
yarn config --offline set yarn-offline-mirror ${offlineCache}
'';
buildPhase = ''
yarn install --offline --frozen-lockfile --ignore-scripts
patchShebangs node_modules/*/bin/*
( cd node_modules/@gristlabs/sqlite3
CPPFLAGS="-I${nodejs}/include/node" node-pre-gyp install \
--prefer-offline --build-from-source \
--nodedir=${nodejs}/include/node --sqlite=${sqlite.dev}
rm -r build-tmp-napi-v6 )
yarn --offline build:prod
'';
## FIXME cannot prune despite 300M savings:
## Error: Cannot find module 'chokidar'
# npm prune --omit=dev
installPhase = ''
mkdir -p $out/libexec $out/bin
cp -R . $out/libexec/grist
substitute ${./grist-run.sh.in} $out/bin/grist-run \
--subst-var-by gristOut $out/libexec/grist \
--subst-var-by path ${lib.makeBinPath [ gristPython nodejs gnused coreutils gvisor ]}
chmod +x $out/bin/grist-run
'';
}
{ config, lib, pkgs, ...}: let
inherit (lib)
types
mkOption
mkEnableOption
mkAfter
mkIf
mkDefault
attrNames
findFirst
escapeShellArg
concatMapStringsSep
;
cfg = config.services.grist;
user = "grist";
files = [
"GRIST_OIDC_IDP_CLIENT_SECRET"
"GRIST_SESSION_SECRET"
];
isFile = key: findFirst (name: name == key) false files != false;
in {
options.services.grist = {
enable = mkEnableOption {};
settings = mkOption { # todo: move to freeform settings
type = types.attrsOf types.str;
default = {};
apply = value: {
TYPEORM_TYPE = "postgres";
TYPEORM_DATABASE = user;
TYPEORM_USERNAME = user;
TYPEORM_HOST = "/run/postgresql";
TYPEORM_PORT = 5432;
} // value;
};
};
config = mkIf cfg.enable {
users.users.${user} = {
isSystemUser = true;
group = user;
};
users.groups.${user} = {};
users.groups."postgres".members =
mkIf (cfg.settings.TYPEORM_TYPE == "postgres")
[cfg.settings.TYPEORM_USERNAME];
systemd = {
tmpfiles.rules = [
"d /var/lib/${user} 0750 ${user} ${user} -"
];
services = {
# see: https://support.getgrist.com/self-managed/#what-is-a-home-database
postgresql.postStart = mkIf (cfg.settings.TYPEORM_TYPE == "postgres")
(mkAfter ''
$PSQL -tAc "ALTER DATABASE ${cfg.settings.TYPEORM_DATABASE} SET jit = off;"
'');
grist = {
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
script = ''
${concatMapStringsSep "\n"
(setting: let
value = if isFile setting
then ''"$(cat ${escapeShellArg cfg.settings.${setting}})"''
else escapeShellArg cfg.settings.${setting};
in ''export ${setting}=${value}'')
(attrNames cfg.settings)}
exec ${pkgs.grist}/bin/grist-run
'';
serviceConfig = {
Type = "simple";
User = user;
Group = user;
WorkingDirectory = "/var/lib/${user}";
# todo: improve systemd sandboxing
# SystemCallFilter = [ "@system-service" ];
# SystemCallErrorNumber = "EPERM";
# ProtectSystem = "strict";
NoNewPrivileges = true;
# RestrictNamespaces = true;
# ProtectHome = true;
# ProtectKernelTunables = true;
# ProtectKernelLogs = true;
# RestrictRealtime = true;
# RemoveIPC = true;
# RootDirectory = "/var/lib/${user}";
# ReadWritePaths = [
# "/var/lib/${user}"
# "/run/postgresql"
# ];
# ExecPaths = ["/nix/store"];
# PrivateUsers = false;
# PrivateNetwork = true;
# MemoryDenyWriteExecute = true;
# RestrictAddressFamilies = "AF_UNIX";
};
};
};
};
services = {
postgresql = {
ensureDatabases = [ cfg.settings.TYPEORM_DATABASE ];
ensureUsers = [{ name = cfg.settings.TYPEORM_USERNAME; ensureDBOwnership = true; }];
};
};
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment