git: 7cf929a46fd7 - main - www/immich: Add New Port

Jochen Neumeister <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.ports
Message-ID <[email protected]>
The branch main has been updated by joneum:

URL: https://cgit.FreeBSD.org/ports/commit/?id=7cf929a46fd7cfe9b4737d29fd18a7e41b82a8b4

commit 7cf929a46fd7cfe9b4737d29fd18a7e41b82a8b4
Author:     Jochen Neumeister <[email protected]>
AuthorDate: 2026-08-16 17:58:33 +0000
Commit:     Jochen Neumeister <[email protected]>
CommitDate: 2026-08-16 18:03:16 +0000

    www/immich: Add New Port
    
    High performance self-hosted photo and video management solution.
    This port contains the Immich server including the bundled web
    frontend, built natively with node22/pnpm against the system
    libvips. Requires PostgreSQL with the pgvector and vchord
    extensions and a Redis-compatible cache such as valkey. Smart
    search, duplicate detection and facial recognition additionally
    require the machine-learning service from www/immich-ml.
    
    WWW: https://immich.app/
    
    Sponsored by:   Netzkommune GmbH
---
 GIDs                              |   2 +-
 UIDs                              |   2 +-
 www/Makefile                      |   1 +
 www/immich/Makefile               | 102 ++++++++++++++++++++++++++++++++++++++
 www/immich/distinfo               |   5 ++
 www/immich/files/immich_server.in |  70 ++++++++++++++++++++++++++
 www/immich/pkg-descr              |  12 +++++
 www/immich/pkg-message            |  45 +++++++++++++++++
 www/immich/pkg-plist              |  11 ++++
 9 files changed, 248 insertions(+), 2 deletions(-)

diff --git a/GIDs b/GIDs
index 2bbce925224a..b94830b8d7e3 100644
--- a/GIDs
+++ b/GIDs
@@ -334,7 +334,7 @@ ldap:*:389:
 bunkerweb:*:390:
 dirsrv:*:391:
 _turnserver:*:392:
-# free: 393
+immich:*:393:
 # free: 394
 # free: 395
 # free: 396
diff --git a/UIDs b/UIDs
index 58282d895bed..8bc61d39e26a 100644
--- a/UIDs
+++ b/UIDs
@@ -339,7 +339,7 @@ ldap:*:389:389::0:0:OpenLDAP Server:/nonexistent:/usr/sbin/nologin
 bunkerweb:*:390:390::0:0:Bunkerweb Service:/nonexistent:/usr/sbin/nologin
 dirsrv:*:391:391::0:0:389 Directory Server:/usr/local/share/dirsrv:/usr/sbin/nologin
 _turnserver:*:392:392::0:0:Coturn Turnserver Daemon:/nonexistent:/usr/sbin/nologin
-# free: 393
+immich:*:393:393::0:0:Immich Daemon:/nonexistent:/usr/sbin/nologin
 # free: 394
 # free: 395
 # free: 396
diff --git a/www/Makefile b/www/Makefile
index 115d96a1d85a..745bd04552eb 100644
--- a/www/Makefile
+++ b/www/Makefile
@@ -310,6 +310,7 @@
     SUBDIR += ikiwiki
     SUBDIR += ilias
     SUBDIR += imaginary
+    SUBDIR += immich
     SUBDIR += iocaine
     SUBDIR += iridium
     SUBDIR += janus
diff --git a/www/immich/Makefile b/www/immich/Makefile
new file mode 100644
index 000000000000..9ade94a423b7
--- /dev/null
+++ b/www/immich/Makefile
@@ -0,0 +1,102 @@
+PORTNAME=	immich
+DISTVERSIONPREFIX=	v
+DISTVERSION=	3.1.0
+CATEGORIES=	www
+MASTER_SITES=	https://github.com/joneum/FreeBSD-Immich/releases/download/v${DISTVERSION}/:buildkit
+DISTFILES=	immich-freebsd-buildkit-${DISTVERSION}${EXTRACT_SUFX}:buildkit
+
+MAINTAINER=	[email protected]
+COMMENT=	High performance self-hosted photo and video management solution
+WWW=		https://immich.app/
+
+LICENSE=	AGPLv3
+LICENSE_FILE=	${WRKSRC}/LICENSE
+
+ONLY_FOR_ARCHS=	aarch64 amd64
+ONLY_FOR_ARCHS_REASON=	native Node.js modules are only tested on 64-bit platforms
+
+BUILD_DEPENDS=	npm-node22>0:www/npm-node22
+LIB_DEPENDS=	libheif.so:graphics/libheif \
+		libraw.so:graphics/libraw \
+		libvips.so:graphics/vips
+RUN_DEPENDS=	exiftool:graphics/p5-Image-ExifTool \
+		ffmpeg:multimedia/ffmpeg
+
+USES=		gmake nodejs:22,build,run pkgconfig python:build
+
+USE_GITHUB=	yes
+GH_ACCOUNT=	immich-app
+
+USE_RC_SUBR=	immich_server
+
+BUILDKIT=	${WRKDIR}/immich-freebsd-buildkit-${DISTVERSION}
+PNPM=		${WRKDIR}/pnpm-prefix/bin/pnpm
+
+MAKE_ENV=	CI=1 \
+		COREPACK_ENABLE_STRICT=0 \
+		NODE_OPTIONS=--max-old-space-size=4096 \
+		npm_config_build_from_source=true \
+		npm_config_nodedir=${LOCALBASE} \
+		npm_config_python=${PYTHON_CMD} \
+		PYTHON=${PYTHON_CMD} \
+		SHARP_FORCE_GLOBAL_LIBVIPS=1
+
+SUB_LIST=	NODE=${LOCALBASE}/bin/node
+
+USERS=		immich
+GROUPS=		immich
+
+post-extract:
+	cd ${WRKSRC} && ${ECHO_CMD} "trustLockfile: true" >> pnpm-workspace.yaml
+
+pre-build:
+	cd ${WRKDIR} && ${SETENV} PATH=${PATH} \
+		npm install -g --prefix ${WRKDIR}/pnpm-prefix \
+		${BUILDKIT}/pnpm-11.13.1.tgz
+
+do-build:
+	cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
+		${PNPM} install --offline --frozen-lockfile \
+		--store-dir ${BUILDKIT}/pnpm-store
+	cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
+		${PNPM} --filter @immich/plugin-sdk --filter @immich/sdk \
+		--filter immich build
+	cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
+		${PNPM} --filter immich-web build
+	cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
+		${PNPM} --store-dir ${BUILDKIT}/pnpm-store --filter immich \
+		--prod --no-optional deploy ${WRKDIR}/server-pruned
+	SHARP=$$(${ECHO_CMD} ${WRKDIR}/server-pruned/node_modules/.pnpm/sharp@*/node_modules/sharp); \
+	NODEGYP=$$(${ECHO_CMD} ${WRKDIR}/server-pruned/node_modules/.pnpm/node-gyp@*/node_modules/node-gyp/bin/node-gyp.js); \
+	${REINPLACE_CMD} -e "s|VIPS,|VIPS, UHDR,|" $$SHARP/src/common.h; \
+	${REINPLACE_CMD} \
+		-e 's|{ "VipsForeignLoadJpegFile"|{ "VipsForeignLoadUhdrFile", ImageType::UHDR }, &|' \
+		-e 's|{ "VipsForeignLoadJpegFile"|{ "VipsForeignLoadUhdrBuffer", ImageType::UHDR }, &|' \
+		$$SHARP/src/common.cc; \
+	cd $$SHARP/src && ${SETENV} ${MAKE_ENV} \
+		${LOCALBASE}/bin/node $$NODEGYP rebuild
+
+do-install:
+	${MKDIR} ${STAGEDIR}${WWWDIR}/server \
+		${STAGEDIR}${WWWDIR}/build-data/www \
+		${STAGEDIR}${WWWDIR}/build-data/geodata \
+		${STAGEDIR}${WWWDIR}/build-data/plugins/immich-plugin-core
+	cd ${WRKDIR}/server-pruned && ${PAX} -rw . ${STAGEDIR}${WWWDIR}/server
+	cd ${WRKSRC}/web/build && ${PAX} -rw . ${STAGEDIR}${WWWDIR}/build-data/www
+	cd ${BUILDKIT}/geodata && ${PAX} -rw . ${STAGEDIR}${WWWDIR}/build-data/geodata
+	cd ${BUILDKIT}/plugins/immich-plugin-core && ${PAX} -rw . \
+		${STAGEDIR}${WWWDIR}/build-data/plugins/immich-plugin-core
+	${MKDIR} ${STAGEDIR}/var/db/immich ${STAGEDIR}/var/log/immich
+
+post-install:
+	@${FIND} ${STAGEDIR}${WWWDIR}/server/node_modules -type f \
+		\( -name "*.sh" -o -name "*.py" -o -name build_tag_lookup \
+		-o -name validate \) -exec ${CHMOD} a-x {} +
+	@${FIND} ${STAGEDIR}${WWWDIR}/server -type d \
+		\( -name .tmp -o -name .deps -o -name nothing \) \
+		-exec ${RM} -r {} + 2>/dev/null || ${TRUE}
+	@cd ${STAGEDIR}${PREFIX} && ${FIND} www/${PORTNAME}/server \
+		www/${PORTNAME}/build-data/www \( -type f -o -type l \) | \
+		${SORT} >> ${TMPPLIST}
+
+.include <bsd.port.mk>
diff --git a/www/immich/distinfo b/www/immich/distinfo
new file mode 100644
index 000000000000..f8a38219c067
--- /dev/null
+++ b/www/immich/distinfo
@@ -0,0 +1,5 @@
+TIMESTAMP = 1786867736
+SHA256 (immich-freebsd-buildkit-3.1.0.tar.gz) = c04c9055198152d150fd0417151f090232664978fa7b0ae76d15f1a6d17e4d70
+SIZE (immich-freebsd-buildkit-3.1.0.tar.gz) = 367404006
+SHA256 (immich-app-immich-v3.1.0_GH0.tar.gz) = af0fba69cc5830093392de4f5576eeb7f2ccf28ba55154b7598e10f596fdfb40
+SIZE (immich-app-immich-v3.1.0_GH0.tar.gz) = 74961232
diff --git a/www/immich/files/immich_server.in b/www/immich/files/immich_server.in
new file mode 100644
index 000000000000..233fa271764c
--- /dev/null
+++ b/www/immich/files/immich_server.in
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# PROVIDE: immich_server
+# REQUIRE: LOGIN
+# KEYWORD: shutdown
+#
+# Add these lines to /etc/rc.conf.local or /etc/rc.conf
+# to enable this service:
+#
+# immich_server_enable (bool):		Set to NO by default.
+#					Set it to YES to enable immich-server.
+# immich_server_media_location (str):	Upload/media location.
+#					Default: /var/db/immich
+# immich_server_port (int):		Listen port. Default: 2283
+# immich_server_env_file (str):		Environment file with additional
+#					IMMICH_*/DB_*/REDIS_* variables.
+#					Default: %%PREFIX%%/etc/immich.env
+
+. /etc/rc.subr
+
+name=immich_server
+rcvar=immich_server_enable
+
+load_rc_config $name
+
+: ${immich_server_enable:=NO}
+: ${immich_server_user:=immich}
+: ${immich_server_group:=immich}
+: ${immich_server_media_location:=/var/db/immich}
+: ${immich_server_port:=2283}
+: ${immich_server_env_file:=%%PREFIX%%/etc/immich.env}
+: ${immich_server_env:="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
+	HOME=${immich_server_media_location} \
+	NODE_ENV=production \
+	IMMICH_BUILD_DATA=%%PREFIX%%/www/immich/build-data \
+	IMMICH_MEDIA_LOCATION=${immich_server_media_location} \
+	IMMICH_PORT=${immich_server_port}"}
+
+pidfile=/var/run/immich/${name}.pid
+required_dirs="%%PREFIX%%/www/immich/server"
+
+immich_server_chdir=%%PREFIX%%/www/immich/server
+start_precmd=immich_server_precmd
+stop_cmd=immich_server_stop
+command=/usr/sbin/daemon
+command_args="-f -S -P ${pidfile} \
+	-o /var/log/immich/${name}.log \
+	%%NODE%% dist/main"
+
+immich_server_stop()
+{
+	local pid
+	pid=$(check_pidfile ${pidfile} ${command})
+	if [ -z "$pid" ]; then
+		echo "${name} not running? (check ${pidfile})."
+		return 1
+	fi
+	echo "Stopping ${name}."
+	kill -TERM -- -${pid} 2>/dev/null || kill -TERM ${pid}
+	wait_for_pids ${pid}
+	rm -f ${pidfile}
+}
+
+immich_server_precmd()
+{
+	install -d -o ${immich_server_user} -g ${immich_server_group} \
+		/var/run/immich /var/log/immich ${immich_server_media_location}
+}
+
+run_rc_command "$1"
diff --git a/www/immich/pkg-descr b/www/immich/pkg-descr
new file mode 100644
index 000000000000..0ff4be3085d1
--- /dev/null
+++ b/www/immich/pkg-descr
@@ -0,0 +1,12 @@
+Immich is a high performance self-hosted photo and video management
+solution. It is designed as a privacy-friendly replacement for cloud
+photo services and offers automatic mobile backup (iOS/Android apps),
+a fast web interface, albums, sharing, timeline and map views,
+duplicate detection, smart search and facial recognition.
+
+This port contains the Immich server including the bundled web
+frontend. It requires a PostgreSQL database with the pgvector and
+vchord extensions and a Redis-compatible cache such as valkey.
+Smart search, duplicate detection and facial recognition
+additionally require the machine-learning service from
+www/immich-ml.
diff --git a/www/immich/pkg-message b/www/immich/pkg-message
new file mode 100644
index 000000000000..50132387aee6
--- /dev/null
+++ b/www/immich/pkg-message
@@ -0,0 +1,45 @@
+[
+{ type: install
+  message: <<EOM
+Immich server was installed.
+
+Requirements:
+ * PostgreSQL with the extensions pgvector and vchord, e.g.:
+     pkg install postgresql18-server postgresql18-contrib \
+         postgresql18-pgvector postgresql18-vchord
+ * Redis-compatible cache, e.g.:
+     pkg install valkey && sysrc valkey_enable=YES
+
+Configuration:
+ 1. VectorChord must be preloaded. Add to postgresql.conf:
+      shared_preload_libraries = 'vchord.so'
+    and restart PostgreSQL.
+ 2. Create a database and user for immich, then create the
+    extensions as superuser in that database:
+      CREATE EXTENSION vector;
+      CREATE EXTENSION vchord CASCADE;
+      CREATE EXTENSION cube;
+      CREATE EXTENSION earthdistance;
+      CREATE EXTENSION pg_trgm;
+    The immich role needs superuser during schema migrations,
+    or pre-create the extensions as shown above.
+ 3. Put the connection settings into %%PREFIX%%/etc/immich.env:
+      DB_HOSTNAME=localhost
+      DB_USERNAME=immich
+      DB_PASSWORD=secret
+      DB_DATABASE_NAME=immich
+      REDIS_HOSTNAME=localhost
+ 4. Enable and start the service:
+      sysrc immich_server_enable=YES
+      service immich_server start
+ 5. Optional: install www/immich-ml for smart search, duplicate
+    detection and facial recognition, then set the machine-learning
+    URL in the admin web UI (Administration > Settings >
+    Machine Learning) to http://127.0.0.1:3003
+
+The web interface listens on port 2283 by default. The upload
+location defaults to /var/db/immich and can be changed with
+sysrc immich_server_media_location=/path.
+EOM
+}
+]
diff --git a/www/immich/pkg-plist b/www/immich/pkg-plist
new file mode 100644
index 000000000000..5310bb6ec2de
--- /dev/null
+++ b/www/immich/pkg-plist
@@ -0,0 +1,11 @@
+%%WWWDIR%%/build-data/geodata/admin1CodesASCII.txt
+%%WWWDIR%%/build-data/geodata/admin2Codes.txt
+%%WWWDIR%%/build-data/geodata/cities500.txt
+%%WWWDIR%%/build-data/geodata/geodata-date.txt
+%%WWWDIR%%/build-data/geodata/ne_10m_admin_0_countries.geojson
+%%WWWDIR%%/build-data/plugins/immich-plugin-core/dist/index.d.ts
+%%WWWDIR%%/build-data/plugins/immich-plugin-core/dist/index.js
+%%WWWDIR%%/build-data/plugins/immich-plugin-core/dist/plugin.wasm
+%%WWWDIR%%/build-data/plugins/immich-plugin-core/manifest.json
+@dir(immich,immich,750) /var/db/immich
+@dir(immich,immich,750) /var/log/immich
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.