Add grist

This commit is contained in:
Natsu Kagami 2025-03-11 13:50:21 +01:00
parent af56ad8f4e
commit 65f104373c
Signed by: nki
GPG key ID: 55A032EB38B49ADB
3 changed files with 143 additions and 3 deletions

View file

@ -27,6 +27,7 @@
./outline.nix
./vikunja.nix
./n8n.nix
./grist.nix
];
system.stateVersion = "21.11";
@ -202,6 +203,16 @@
envFile = config.sops.secrets.gts-env.path;
};
# Grist
sops.secrets."grist/env" = { restartUnits = [ "arion-grist.service" ]; };
cloud.grist = {
enable = true;
envFile = config.sops.secrets."grist/env".path;
host = "tables.dtth.ch";
dataDir = "/mnt/data/grist";
};
# ntfy
cloud.traefik.hosts.ntfy-sh = { host = "ntfy.nkagami.me"; port = 11161; noCloudflare = true; };
services.ntfy-sh = {

127
nki-personal-do/grist.nix Normal file
View file

@ -0,0 +1,127 @@
{ pkgs, config, lib, ... }:
with lib;
let
cfg = config.cloud.grist;
mkImage =
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage;
images = {
# https://hub.docker.com/r/gristlabs/grist/tags
grist = mkImage {
imageName = "docker.io/gristlabs/grist-oss";
finalImageTag = "1.4.2";
imageDigest = "sha256:508ed0024f08702ae8797a6607e42ca67e1a0be0ac95c02e75c2a226b5e9cb9b";
};
# https://hub.docker.com/r/valkey/valkey/tags
valkey = mkImage {
imageName = "docker.io/valkey/valkey";
finalImageTag = "8.0.2-alpine";
imageDigest = "sha256:0fae58181c223280867e8b6d9d5fa29fca507770aeb6819f36d059cab73fa2fd";
};
};
defaultEnv = {
GRIST_HIDE_UI_ELEMENTS = lib.concatStringsSep "," [ "helpCenter" "billing" "multiAccounts" "supportGrist" ];
GRIST_PAGE_TITLE_SUFFIX = " - DTTH Grist";
GRIST_FORCE_LOGIN = "true";
GRIST_WIDGET_LIST_URL = "https://github.com/gristlabs/grist-widget/releases/download/latest/manifest.json";
GRIST_EXTERNAL_ATTACHMENTS_MODE = "snapshots";
GRIST_SANDBOX_FLAVOR = "gvisor";
PYTHON_VERSION = "3";
PYTHON_VERSION_ON_CREATION = "3";
};
in
{
options.cloud.grist = {
enable = mkEnableOption "Grist database server";
envFile = mkOption {
type = types.path;
description = "Path to an environment file that specifies GRIST_SESSION_SECRET and others";
};
host = mkOption {
type = types.str;
description = "Exposed hostname";
};
port = mkOption {
type = types.int;
description = "Exposed port";
default = 9674;
};
dataDir = mkOption {
type = types.str;
description = "Path to the data directory";
};
settings = {
allowedWebhookDomains = mkOption {
type = types.listOf types.str;
description = "List of domains to be allowed in webhooks";
default = [ "dtth.ch" "nkagami.me" "discord.com" ];
};
defaultEmail = mkOption {
type = types.str;
description = "Default email address for admin user";
default = "nki@nkagami.me";
};
};
};
config = mkIf cfg.enable {
cloud.traefik.hosts.grist = {
inherit (cfg) port host;
};
systemd.services.arion-grist = {
serviceConfig.Type = "notify";
serviceConfig.NotifyAccess = "all";
serviceConfig.TimeoutSec = 300;
script = lib.mkBefore ''
${lib.getExe pkgs.wait4x} http http://127.0.0.1:${toString cfg.port} -t 0 -q -- systemd-notify --ready &
'';
unitConfig.RequiresMountsFor = [ cfg.dataDir ];
unitConfig.ReadWritePaths = [ cfg.dataDir ];
};
virtualisation.arion.projects.grist.settings = {
services.grist-server.service = {
image = images.grist;
restart = "unless-stopped";
volumes = [ "${cfg.dataDir}:/persist" ];
environment = defaultEnv // {
APP_HOME_URL = "https://${cfg.host}";
ALLOWED_WEBHOOK_DOMAINS = lib.concatStringsSep "," cfg.settings.allowedWebhookDomains;
GRIST_DEFAULT_EMAIL = cfg.settings.defaultEmail;
REDIS_URL = "redis://valkey/1";
};
env_file = [ cfg.envFile ];
ports = [
"127.0.0.1:${toString cfg.port}:8484"
];
};
services.valkey.service = {
image = images.valkey;
command = "--save 60 1 --loglevel warning";
restart = "unless-stopped";
healthcheck = {
test = [ "CMD-SHELL" "valkey-cli ping | grep PONG" ];
start_period = "20s";
interval = "30s";
retries = 5;
timeout = "3s";
};
volumes = [ "valkey:/data" ];
};
docker-compose.volumes = {
valkey.driver = "local";
};
};
systemd.tmpfiles.settings."10-grist".${cfg.dataDir}.d = {
user = "root";
group = "root";
mode = "0700";
};
};
}

View file

@ -47,6 +47,8 @@ vikunja:
provider-clientsecret: ENC[AES256_GCM,data:/fN1rH2CKoaivhespd+/KamERjBQOdwR7QQ+hoB+pQ3ZSrBVIKbLMWyOJe8f7rVwXAByqDxQIZJEVPjcjhWSU1eicwpu57FBx+/xJLFazspTVZ+5XKyAwR+UxTHDGAgtFV00QHN53l7ygg4joWWko4IPN1JIpNIASaIWWzpsrIo=,iv:NLsZcmE1kKlzV7B/XPVfENMWlpQtOpESH0ByX1KQ8IQ=,tag:P+ZmsKq0KJAeRTTbvbduMg==,type:str]
n8n:
env: ENC[AES256_GCM,data:LA/6tMfGgX0cDNfhIZ+n2Ay+6OW5gPPebcXQnfO3qQJSjMjf9vwauF2+W3KpIvM1Dsg3hyNEwqLNRn/28bgWC/qpBpgU2/gVI2n5oxcQaYGgnS/jB0nZWXvORVTnXjH0R+HBFCWgMJe7v+o0EeBH6kni/Nc9geb8paRkxZOGVKeJQy9K4OB2CN6FVO9KeR7gpeQpsh5V5SVW1MoND2tpCOiIK7d0uM6OHF/7p2RFrEEAarvJssj/dZRHjA/jALuqbQ6UDAaAppqlkEgIdZdFEfgebfCWR4e4aWjznW1DGOQQYtg4k/Kj8J/df8CWXX+lUO+9nTo/lhhcH395w+CRE8GUwze15yxQppUwqyLKdYwgmpK1tFnLP/W/As2f97c1fBB9rXrZYOUEIq4GspHOTPgjzcRfWOxX8cMKG69EmeZ3mWPsIDaC1ZvkVQjjcH/o9aC7QeFCwPfcy+mgI+9RjAaCw7qdig1CwgQabAaCd2hzQ4FTXBFJoZRfYZ1v3Rdwe8zqMivIcw2AHv6kYx6c9A==,iv:KmyJ/CLAGrYfzHjSWygtgA/+am9fUrKnOsGRPgV9QfU=,tag:G3LhfdSujcaC9ZZFUse0DQ==,type:str]
grist:
env: ENC[AES256_GCM,data:eT4eFHMU6UgCr/lNbdqFivzZgNREHcM4b/7ZEoKYWWNssrgIJybLm709BG8Q8/kKnBHaFUlczRQNvjS/nexZ3LymMeiXEHcuxC7lEM5otMqKzYFar2Z4YzPaUWGGezYcYBK56Ia5CF8TdWDdTbgnaSBY6R2ViJYTvS3QSdK6AhWfgGrdTVbye2lL6b11TrfI4vC25DhHJbrhFCXf995Q4nnwoACGAQ+Pkk6dsuYme4plV4WfZ8w61Y4SyNhdWYPp/rsJiAQkPajVCFjfZhH6cQCxVmSVn4c59H8MFx4qTbbXCKp3tXV5eQPWQBri5rc1XXAxgHKyrBUpx3QiYI6UDjGbf6hjXPSEWHQPXFLiLVPgH0CjXZeyxcYsr2ZLcOF87grUTR+CcxbiP4CshuJbvKyWiQ4ISOAm3m84XjXNVqn2WEf4ndqpNEG8H+BVbQ9RrGvrdlJqcrqD6rNzw0y+4SEiVPpv1NQ5M7+f+SABO8S2T4BFp95fvX2DmR/z+c9g2xiAOmZDFMzjG97rPrKuZq8+b+H3jlBZ4mxUBiz7l0c3NJ1RGtIUgr+idYGMwpSyh4C1a6LEzlW72F4vF5e5sEyWAHApRGxQCIMAP7ACBotMYgIKSPAzwThHtoTcUdBlDiQw8blsU/1c/FzkpAF5kotyNnk4vJea0H1yZ7NSz12E61qH6utG1YW5BZzZn+TKj7RfPEqzFE1POA0H8v1egE0bu1ClrYDX112iGEGI4IQHXMOu2p15O0/D+Y+QBOhpDwQWbgDXTf3ZMS2tyBtOiYT//ejfExYzV99V9t86xqmAvHODc69WC5nzWUp7SqkLLTP6gBUPSrkPs4ugZRE0q3STOmcnfxGkgpW94oj+jcZZY5supmYWK6zvJsPF9mn6,iv:pfIiOiWVEl0wEK03gnWj+ZKxOBwtBtf1hqzYOSpTm10=,tag:il0r2A/Z8q88sAiVgsuEEA==,type:str]
sops:
kms: []
gcp_kms: []
@ -80,8 +82,8 @@ sops:
by9kZFlTRVdCZFkxYTVVb0RIRk8zUlkKCqMw9oL9RaYBV5Hhy3o8Nm5xmGrPH8Sd
hv36sxRFFNZT/DCKaHaSRbT3mfpBZSTXJt1dgl4nZe6whH54t/1KmA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-12-07T23:38:16Z"
mac: ENC[AES256_GCM,data:GKCMZJVKj5Fq7Ak4wQgI/pAl8JKDdzAYCBRwnxHlg0Z10AstbchAYm+LLwCaE85ebl6m/JexmfJeutJo0yGXuOIQKcEgfyNq9O/i/y34ISc4looQ6cyH5Hcxsd9JXgrmgQzVPquBXQzDHz4rj93VhNrvqmw+SgDPZVwcUznvCBI=,iv:HtUmf0qjvbYW7ngocISpqycX7ceNv0YsILgZhOMTSMg=,tag:kJ7EFOLL8o/2OFkn5PhvJw==,type:str]
lastmodified: "2025-03-06T23:20:44Z"
mac: ENC[AES256_GCM,data:XSYbqif2lhjTW2yUnoqtQehXG3DjS9It1IX4LplRMSxPkK0cpK64z/ouFRi12a1tjzE5YkdmZ9DDIxkAVPG8/5kgcZr5c4ddS/Zt4d97bCeeij47yuvhhoKMRzgIDSokMMmoelOV1k4FkDOfTDuMp2+tjyCao//N9YJjhhRPFYc=,iv:YpNNrIPotZAAQOF8GXBTpMjTFxYDdAFSLB1CBvLOE+k=,tag:1eGTkLRlL4s8TruVDPCA/g==,type:str]
pgp: []
unencrypted_suffix: _unencrypted
version: 3.9.1
version: 3.9.4