aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Fechner <mfechner@FreeBSD.org>2026-05-19 15:04:49 +0000
committerMatthias Fechner <mfechner@FreeBSD.org>2026-05-19 15:05:38 +0000
commit4cc36f92de872bd28d92bd2a07910a6cfcc47a04 (patch)
tree417122886f361c13699fe2368da346672edaaf50
parent3d5723cdc92963d879b8978a96a81c5adc255ac2 (diff)
-rw-r--r--GIDs2
-rw-r--r--UIDs2
-rw-r--r--www/Makefile1
-rw-r--r--www/grist-core/Makefile110
-rw-r--r--www/grist-core/distinfo5
-rw-r--r--www/grist-core/files/grist.conf.sample26
-rw-r--r--www/grist-core/files/grist.in59
-rw-r--r--www/grist-core/files/pkg-message.in52
-rw-r--r--www/grist-core/pkg-descr3
9 files changed, 258 insertions, 2 deletions
diff --git a/GIDs b/GIDs
index 1c59c25fb85c..bf446d5faa1b 100644
--- a/GIDs
+++ b/GIDs
@@ -490,7 +490,7 @@ ejabberd:*:543:
# free: 547
# free: 548
# free: 549
-# free: 550
+grist:*:550:
# free: 551
kresd:*:552:
knot:*:553:
diff --git a/UIDs b/UIDs
index 0e6ddb206356..f7d9ca583863 100644
--- a/UIDs
+++ b/UIDs
@@ -496,7 +496,7 @@ ejabberd:*:543:543::0:0:ejabberd pseudo user:/var/spool/ejabberd:/bin/sh
# free: 547
# free: 548
# free: 549
-# free: 550
+grist:*:550:550::0:0:Grist Daemon User:/usr/local/www/grist-core:/usr/sbin/nologin
# free: 551
kresd:*:552:552::0:0:Knot DNS Resolver:/nonexistent:/usr/sbin/nologin
knot:*:553:553::0:0:Knot DNS Server:/nonexistent:/usr/sbin/nologin
diff --git a/www/Makefile b/www/Makefile
index 02cd97ecfe45..3cf9db4fa019 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -257,6 +257,7 @@
SUBDIR += grafanactl
SUBDIR += grails
SUBDIR += gregarius
+ SUBDIR += grist-core
SUBDIR += groupoffice
SUBDIR += grr
SUBDIR += gstreamer1-plugins-neon
diff --git a/www/grist-core/Makefile b/www/grist-core/Makefile
new file mode 100644
index 000000000000..9a0b9eb85927
--- /dev/null
+++ b/www/grist-core/Makefile
@@ -0,0 +1,110 @@
+PORTNAME= grist-core
+PORTVERSION= 1.7.13
+DISTVERSIONPREFIX= v
+CATEGORIES= www
+MASTER_SITES= LOCAL/mfechner/${PORTNAME}/:yarncache
+DISTFILES= ${PORTNAME}-yarn-offline-cache-${DISTVERSION}${EXTRACT_SUFX}:yarncache
+
+MAINTAINER= mfechner@FreeBSD.org
+COMMENT= Modern relational spreadsheet running in browser
+WWW= https://github.com/gristlabs/grist-core
+
+LICENSE= APACHE20
+LICENSE_FILE= ${WRKSRC}/LICENSE.txt
+
+ONLY_FOR_ARCHS= amd64
+ONLY_FOR_ARCHS_REASON= Yarn cache only for amd64 generated
+
+MY_DEPENDS= yarn${NODEJS_SUFFIX}>=1.10.0:www/yarn${NODEJS_SUFFIX} \
+ bash:shells/bash
+BUILD_DEPENDS= ${MY_DEPENDS} \
+ libuv>=1.34.0:devel/libuv
+RUN_DEPENDS= ${MY_DEPENDS} \
+ ${PYTHON_PKGNAMEPREFIX}pip>=22.2.2:devel/py-pip@${PY_FLAVOR}
+
+USES= compiler:c++17-lang gmake nodejs python shebangfix
+
+USE_GITHUB= yes
+GH_ACCOUNT= gristlabs
+USE_RC_SUBR= grist
+SHEBANG_FILES= sandbox/gvisor/run.py
+
+# Required for node-gyp to work
+MAKE_ENV+= npm_config_build_from_source=true
+MAKE_ENV+= npm_config_nodedir=${PREFIX}
+MAKE_ENV+= npm_config_node_gyp=${LOCALBASE}/bin/node-gyp
+MAKE_ENV+= PYTHON=${PYTHON_CMD}
+MAKE_ENV+= COREPACK_ENABLE_DOWNLOAD_PROMPT=0
+CPPFLAGS+= -I${LOCALBASE}/include
+CXXFLAGS+= -I${LOCALBASE}/include
+
+WWWDIR= ${PREFIX}/www/grist-core
+SUB_FILES= pkg-message
+SUB_LIST= GRIST_USER=${USERS} \
+ GRIST_GROUP=${GROUPS} \
+ PYTHON_CMD="${PYTHON_CMD}"
+USERS= grist
+GROUPS= grist
+
+post-patch:
+ # setup yarnrc for offline node_modules installation
+ @${ECHO_CMD} 'yarn-offline-mirror "${WRKDIR}/yarn-offline-cache"' >> ${WRKSRC}/.yarnrc
+
+pre-build:
+ #(cd ${WORKSRC} && ${SETENV} ${MAKE_ENV} HOME=${WRKDIR} && yarn config set python /usr/local/bin/python3.11)
+ @cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} HOME=${WRKDIR} PUPPETEER_SKIP_DOWNLOAD=true npm_config_build_from_source=true yarn install --offline
+
+do-build:
+ @cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} yarn build:prod
+
+do-install:
+ # Rebuild production-only node_modules
+ ${RM} -r ${WRKSRC}/node_modules
+ @cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} HOME=${WRKDIR} PUPPETEER_SKIP_DOWNLOAD=true npm_config_build_from_source=true yarn install --offline --prod
+
+ # Cleanup broken sqlite3 build leftovers
+ ${RM} -r ${WRKSRC}/node_modules/@gristlabs/sqlite3/build-tmp-napi-v6/Release/.deps/Release/obj.target/nothing \
+ ${WRKSRC}/node_modules/@gristlabs/sqlite3/build-tmp-napi-v6/Release/obj.target/nothing
+
+ # Install main directories
+.for d in node_modules _build bower_components plugins static
+ (cd ${WRKSRC} && ${COPYTREE_SHARE} ${d} ${STAGEDIR}${WWWDIR})
+.endfor
+
+ ${INSTALL_SCRIPT} ${WRKSRC}/app/cli.sh ${STAGEDIR}${WWWDIR}/cli
+ ${INSTALL_DATA} ${WRKSRC}/package.json ${STAGEDIR}${WWWDIR}
+ #
+ # Skip files having executable bit
+ ${CHMOD} +x ${WRKSRC}/sandbox/run.sh
+ (cd ${WRKSRC} && ${COPYTREE_SHARE} sandbox ${STAGEDIR}${WWWDIR} "-not ( -type f -perm -a=x )")
+ # now copy all files having an execution bit and preserve to x bit
+ (cd ${WRKSRC} && ${COPYTREE_BIN} sandbox ${STAGEDIR}${WWWDIR} "-type f -perm -a=x")
+
+ #${MKDIR} ${STAGEDIR}/var/db/grist
+ # Configuration
+ ${INSTALL_DATA} ${FILESDIR}/grist.conf.sample ${STAGEDIR}${PREFIX}/etc/grist.conf.sample
+
+post-install:
+ ${FIND} -s ${STAGEDIR}${WWWDIR} -not -type d | ${SORT} | \
+ ${SED} -e 's#^${STAGEDIR}${PREFIX}/##' | \
+ ${SED} -E -e '/sample$$/ s#^#@sample #; \
+ /grist.conf.sample$$/ s#^@sample #@sample(grist,wheel,0600) #;' >> ${TMPPLIST}
+ #@${ECHO_CMD} "@dir(grist,grist) /var/db/grist" >> ${TMPPLIST}
+ @${ECHO_CMD} "@sample(grist,wheel,0600) etc/grist.conf.sample" >> ${TMPPLIST}
+
+# To update
+# 1. comment DISTFILES
+# 2. Run 'make makesum'
+# 3. Run 'make make-yarn-cache'
+# 4. Upload yarn cache
+# 5. Uncomment DITSFILES
+# 6. Run 'make makesum'
+make-yarn-cache: patch
+ ${RM} -r ${WRKDIR}/yarn-offline-cache
+ #cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true yarn --frozen-lockfile --ignore-scripts
+ cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true yarn --frozen-lockfile
+ cd ${WRKDIR} && ${TAR} -c --zstd -f ${PORTNAME}-yarn-offline-cache-${DISTVERSION}${EXTRACT_SUFX} yarn-offline-cache
+ @${ECHO_CMD} upload ${PORTNAME}-yarn-offline-cache-${DISTVERSION}${EXTRACT_SUFX}
+ @${ECHO_CMD} "Please upload the file: scp ${WRKDIR}/${PORTNAME}-yarn-offline-cache-${DISTVERSION}${EXTRACT_SUFX} mfechner@freefall.freebsd.org:public_distfiles/${PORTNAME}/"
+
+.include <bsd.port.mk>
diff --git a/www/grist-core/distinfo b/www/grist-core/distinfo
new file mode 100644
index 000000000000..14db6c03e852
--- /dev/null
+++ b/www/grist-core/distinfo
@@ -0,0 +1,5 @@
+TIMESTAMP = 1779187958
+SHA256 (grist-core-yarn-offline-cache-1.7.13.tar.gz) = 19d729af60e6e57eb201d0e224c04ebd6d7c45c937da89a9342d34372fd42513
+SIZE (grist-core-yarn-offline-cache-1.7.13.tar.gz) = 246856693
+SHA256 (gristlabs-grist-core-v1.7.13_GH0.tar.gz) = e09c965651358c2a39b29f5d5924b3c53d72c6b52fd4bd235a21454a83536dbf
+SIZE (gristlabs-grist-core-v1.7.13_GH0.tar.gz) = 21376912
diff --git a/www/grist-core/files/grist.conf.sample b/www/grist-core/files/grist.conf.sample
new file mode 100644
index 000000000000..6b6595154a8a
--- /dev/null
+++ b/www/grist-core/files/grist.conf.sample
@@ -0,0 +1,26 @@
+export GRIST_SESSION_SECRET="set_secret_min_36_characters"
+
+#export GRIST_DB_TYPE="postgres"
+#export GRIST_DB_HOST="127.0.0.1"
+#export GRIST_DB_NAME="grist"
+#export GRIST_DB_USER="grist"
+#export GRIST_DB_PASSWORD="very_secret_password"
+
+export GRIST_SERVE_STATIC="true"
+export GRIST_HOST="0.0.0.0"
+export GRIST_PORT="8484"
+
+export APP_HOME_URL="https://grist.set-to-your-domain"
+
+# admin user
+export GRIST_DEFAULT_EMAIL="email of your admin user"
+
+export GRIST_SINGLE_ORG="main"
+
+# Auth using authelia
+#export GRIST_AUTH_TYPE="forward"
+#export GRIST_TRUST_PROXY="1"
+#export GRIST_FORWARD_AUTH_HEADER="X-Forwarded-Email"
+
+# Path to store documents
+export GRIST_DATA_DIR="/var/db/grist"
diff --git a/www/grist-core/files/grist.in b/www/grist-core/files/grist.in
new file mode 100644
index 000000000000..3092d36af3db
--- /dev/null
+++ b/www/grist-core/files/grist.in
@@ -0,0 +1,59 @@
+#!/bin/sh
+# PROVIDE: grist
+# REQUIRE: LOGIN
+# KEYWORD: shutdown
+
+. /etc/rc.subr
+
+export PATH=$PATH:/usr/local/bin
+export HOME=${workingdir}
+export COREPACK_ENABLE_DOWNLOAD_PROMPT=0
+
+name="grist"
+rcvar="${name}_enable"
+
+load_rc_config $name
+: ${grist_enable:=no}
+: ${grist_user:="%%GRIST_USER%%"}
+: ${grist_group:="%%GRIST_GROUP%%"}
+
+logfile="/var/log/${name}/${name}.log"
+pidfile="/var/run/${name}/${name}.pid"
+workingdir="%%WWWDIR%%"
+venvdir="${workingdir}/venv"
+
+command="/usr/sbin/daemon"
+command_args="-H -o ${logfile} -t ${name} -P ${pidfile} \
+ bash -c 'cd $workingdir && source venv/bin/activate && source /usr/local/etc/grist.conf && sandbox/run.sh'"
+
+start_precmd="${name}_precmd"
+start_cmd="${name}_start"
+
+grist_precmd()
+{
+ # Ensure pid directory exists
+ install -d -g "${grist_group}" -o "${grist_user}" "$(dirname "${pidfile}")"
+
+ # Ensure log directory exists
+ install -d -g "${grist_group}" -o "${grist_user}" "$(dirname "${logfile}")"
+
+ # Ensure document directory exists
+ install -d -g "${grist_group}" -o "${grist_user}" "/var/db/grist"
+
+ # Ensure virtualenv exists
+ if [ ! -d "${venvdir}" ]; then
+ echo "Creating Python virtual environment..."
+ su -m "${grist_user}" -c "%%PYTHON_CMD%% -m venv ${venvdir}" || return 1
+ fi
+
+ echo "Installing Python requirements..."
+ su -m "${grist_user}" -c "cd ${workingdir} && ${venvdir}/bin/python -m pip install -r ${workingdir}/sandbox/requirements.txt" || return 1
+}
+
+grist_start()
+{
+ su -m ${grist_user} -c "${command} ${command_args}"
+}
+
+run_rc_command "$1"
+
diff --git a/www/grist-core/files/pkg-message.in b/www/grist-core/files/pkg-message.in
new file mode 100644
index 000000000000..a78b3d7b2213
--- /dev/null
+++ b/www/grist-core/files/pkg-message.in
@@ -0,0 +1,52 @@
+[
+{
+ message: <<EOM
+Grist was installed successfully.
+
+WARNING:
+********
+I highly recommend to install grist in a jail!
+Grist calls python to calculate formulars in the sheet.
+Grist on FreeBSD does not use a sandboxed python so use the jail as the sandbox.
+********
+
+Please configure grist using export commands in:
+%%PREFIX%%/etc/grist.conf
+
+for more details check the configuration options (some useful ones are already define or must be changed):
+https://github.com/gristlabs/grist-core/tree/main#environment-variables
+
+To enable grist on startup:
+sysrc grist_enable="YES"
+
+You should put a reverse proxy like nginx in front of it.
+In the default configuration grist listens on is http://localhost:8484/
+A sample nginx configuration can be found here:
+https://support.getgrist.com/self-managed/#how-do-i-run-grist-on-a-server
+
+You must have a SSL certificate available (like letsencrypt).
+How to do this is not explained here.
+
+To start grist:
+service grist start
+
+Logfile are on:
+/var/log/grist/grist.log
+
+To authenticate with the boot key (you can find in the log file) access:
+https://grist.your-domain/boot
+
+EOM
+ type: install
+}
+{
+ message: <<EOM
+To apply required python lib upgrade, restart grist:
+
+service grist restart
+
+EOM
+ type: upgrade
+}
+]
+
diff --git a/www/grist-core/pkg-descr b/www/grist-core/pkg-descr
new file mode 100644
index 000000000000..0e24e3b9c71e
--- /dev/null
+++ b/www/grist-core/pkg-descr
@@ -0,0 +1,3 @@
+Grist is a modern relational spreadsheet. It combines the flexibility of a
+spreadsheet with the robustness of a database.
+Fully available using a webbrowser.