Last active 2 months ago

swee revised this gist 2 months ago. Go to revision

1 file changed, 1 insertion, 1 deletion

manual.md

@@ -59,7 +59,7 @@ Install your favorite TUI text editor
59 59 Install dependencies
60 60
61 61 ```
62 - # apt install -y curl wget valkey-server ca-certificates sudo git
62 + # apt install -y curl wget valkey-server ca-certificates sudo git netcat-openbsd
63 63 # install -d /usr/share/postgresql-common/pgdg
64 64 # curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
65 65 # echo 'deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt trixie-pgdg main' > /etc/apt/sources.list.d/pgdg.list

swee revised this gist 2 months ago. Go to revision

1 file changed, 4 insertions, 2 deletions

manual.md

@@ -85,7 +85,9 @@ Adding the user
85 85 # chmod 700 /var/lib/immich
86 86 ```
87 87
88 - Building (yes, this is a lot of steps)
88 + # Step 2: Building
89 +
90 + (yes, this is a lot of steps)
89 91
90 92 ```
91 93 # su immich
@@ -246,7 +248,7 @@ $ sftp <ip to server>
246 248 sftp> put immich.tar.gz
247 249 ```
248 250
249 - # 3. Installation
251 + # Step 3. Installation
250 252
251 253 **At this point, you should be using your FreeBSD server for this.**
252 254

swee revised this gist 2 months ago. Go to revision

1 file changed, 1 insertion, 1 deletion

manual.md

@@ -437,4 +437,4 @@ server {
437 437
438 438 # What the hell was that?
439 439
440 - Yep, you did a very cursed but possible thing in FreeBSD using Linuxulator, FreeBSD's decent Linux compatibility layer, it seems to be good enough to flawlessly run Immich.
440 + Yep, you did a very cursed but possible thing in FreeBSD using Linuxulator, FreeBSD's decent Linux compatibility layer, it has the power to run a whole chroot rootfs and seems to be good enough to flawlessly run Immich.

swee revised this gist 2 months ago. Go to revision

1 file changed, 440 insertions

manual.md(file created)

@@ -0,0 +1,440 @@
1 + Yes, this is not clickbait! I set up Immich on FreeBSD yesterday without going insane, so I am documenting how I did this magic.
2 +
3 + I am not using ML in this setup.
4 +
5 + Note: I did steal some documentation and read the install script from https://github.com/arter97/immich-native
6 +
7 + ## Requirements
8 +
9 + - A FreeBSD server (duh, tested in FreeBSD 15)
10 + - A Linux machine (for bootstrapping and building)
11 + - SSH connection between the two machines (or any other remote access)
12 +
13 + Note: Do know the distinct difference on the shell prefixes of each code block, `$` = normal user recommended, `#` = root/sudo required
14 +
15 + # Step 1: Bootstrapping
16 +
17 + First, get your Linux machine to install `debootstrap`, it's available on any Debian-based distro, and some other distros
18 +
19 + Debian/Ubuntu:
20 +
21 + ```
22 + # apt install debootstrap
23 + ```
24 +
25 + Alpine Linux:
26 +
27 + ```
28 + # apk add debootstrap
29 + ```
30 +
31 + Then, create a Devuan rootfs
32 +
33 + ```shell-session
34 + $ mkdir immich
35 + # debootstrap --arch=amd64 excalibur immich https://deb.devuan.org/merged trixie
36 + ```
37 +
38 + **The error about cron depending on systemd is not fatal**
39 +
40 + Chroot into the new rootfs
41 +
42 + ```shell-session
43 + # chroot immich
44 + ```
45 +
46 + **At this point, you should be running commands on the chroot shell and _not your host._**
47 +
48 + Debloat and update
49 +
50 + ```
51 + # echo "nameserver 9.9.9.9" > /etc/resolv.conf
52 + # apt autoremove cron* sysvinit-core
53 + # apt update
54 + # apt upgrade
55 + ```
56 +
57 + Install your favorite TUI text editor
58 +
59 + Install dependencies
60 +
61 + ```
62 + # apt install -y curl wget valkey-server ca-certificates sudo git
63 + # install -d /usr/share/postgresql-common/pgdg
64 + # curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
65 + # echo 'deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt trixie-pgdg main' > /etc/apt/sources.list.d/pgdg.list
66 + # curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
67 + # curl -s https://repo.jellyfin.org/install-debuntu.sh | bash
68 + NOTE: Because Jellyfin doesn't recognize Devuan, type distro debian with version trixie
69 + NOTE: At this part, CTRL+C immediately when it begins to install jellyfin.
70 + # apt update
71 + # apt --no-install-recommends install postgresql-client jellyfin-ffmpeg7 nodejs python3-pip python3-venv python3-dev uuid-runtime autoconf build-essential unzip jq perl libnet-ssleay-perl libio-socket-ssl-perl libcapture-tiny-perl libfile-which-perl libfile-chdir-perl libpkgconfig-perl libffi-checklib-perl libtest-warnings-perl libtest-fatal-perl libtest-needs-perl libtest2-suite-perl libsort-versions-perl libpath-tiny-perl libtry-tiny-perl libterm-table-perl libany-uri-escape-perl libmojolicious-perl libfile-slurper-perl liblcms2-2 libgl1
72 + # npm install corepack@latest -g
73 + # corepack enable
74 + ```
75 +
76 + Adding the user
77 +
78 + ```
79 + # mkdir -p /var/lib/immich/home
80 + # mkdir /var/lib/immich/app
81 + # mkdir /var/lib/immich/cache
82 + # mkdir -p /var/log/immich
83 + # adduser --home /var/lib/immich/home --shell=/sbin/nologin --no-create-home --disabled-password immich
84 + # chown -R immich:immich /var/lib/immich /var/log/immich
85 + # chmod 700 /var/lib/immich
86 + ```
87 +
88 + Building (yes, this is a lot of steps)
89 +
90 + ```
91 + # su immich
92 + $ git clone https://github.com/immich-app/immich /tmp/immich --depth=1 -b v2.7.5
93 + $ cd /tmp/immich
94 + $ grep -Rl /usr/src | xargs -n1 sed -i -e "s@/usr/src@/var/lib/immich@g"
95 + $ grep -RlE "\"/build\"|'/build'" | xargs -n1 sed -i -e "s@\"/build\"@\"/var/lib/immich/app\"@g" -e "s@'/build'@'/var/lib/immich/app'@g"
96 + $ corepack use pnpm@latest
97 + $ curl -O https://raw.githubusercontent.com/extism/js-pdk/main/install.sh
98 + $ sed -i -e 's@sudo@@g' -e "s@/usr/local/binaryen@$HOME/binaryen@g" -e "s@/usr/local/bin@$HOME/.local/bin@g" install.sh
99 + $ export PATH="$PATH:/var/lib/immich/home/.local/bin"
100 + $ ./install.sh
101 + $ rm install.sh
102 + $ cd server
103 + $ pnpm install --frozen-lockfile --force
104 + $ pnpm run build
105 + $ pnpm prune --prod --no-optional --config.ci=true
106 + $ cd ../open-api/typescript-sdk
107 + $ pnpm install --frozen-lockfile --force
108 + $ pnpm run build
109 + $ cd ../../web
110 + $ pnpm install --frozen-lockfile --force
111 + $ pnpm run build
112 + $ cd ../plugins
113 + $ pnpm install --frozen-lockfile --force
114 + $ pnpm run build
115 + $ cd ..
116 + $ cp -aL server/node_modules server/dist server/bin /var/lib/immich/app/
117 + $ cp -a web/build /var/lib/immich/app/www
118 + $ cp -a server/package.json pnpm-lock.yaml /var/lib/immich/app/
119 + $ mkdir -p /var/lib/immich/app/corePlugin
120 + $ cp -a plugins/dist /var/lib/immich/app/corePlugin/
121 + $ cp -a plugins/manifest.json /var/lib/immich/app/corePlugin/
122 + $ cp -a LICENSE /var/lib/immich/app/
123 + $ cp -a i18n /var/lib/immich/
124 + $ cd /var/lib/immich/app
125 + $ mkdir upload
126 + $ pnpm store prune
127 + $ pnpm install sharp
128 + $ mkdir geodata
129 + $ cd geodata
130 + $ wget -o - https://download.geonames.org/export/dump/admin1CodesASCII.txt
131 + $ wget -o - https://download.geonames.org/export/dump/admin2Codes.txt
132 + $ wget -o - https://download.geonames.org/export/dump/cities500.zip
133 + $ wget -o - https://raw.githubusercontent.com/nvkelso/natural-earth-vector/v5.1.2/geojson/ne_10m_admin_0_countries.geojson
134 + $ unzip cities500.zip
135 + $ date --iso-8601=seconds | tr -d "\n" > geodata-date.txt
136 + $ rm cities500.zip
137 + ```
138 +
139 + You're almost done, create this file at `/var/lib/immich/app/start.sh`
140 +
141 + ```shell
142 + #!/bin/bash
143 +
144 + export PATH=/usr/lib/jellyfin-ffmpeg:/var/lib/immich/home/.local/bin:$PATH
145 +
146 + set -a
147 + . /var/lib/immich/env
148 + set +a
149 +
150 + cd $APP
151 + exec node /var/lib/immich/app/dist/main "$@"
152 + ```
153 +
154 + And this at `/var/lib/immich/env`
155 +
156 + Generate a random password in place of YOUR_STRONG_RANDOM_PW and remember it for database setup.
157 +
158 + ```shell
159 + DB_PASSWORD=YOUR_STRONG_RANDOM_PW
160 +
161 + NODE_ENV=production
162 +
163 + DB_USERNAME=immich
164 + DB_DATABASE_NAME=immich
165 +
166 + UPLOAD_LOCATION=./library
167 +
168 + IMMICH_VERSION=release
169 +
170 + IMMICH_HOST=0.0.0.0
171 + IMMICH_PORT=2283
172 + DB_HOSTNAME=192.168.123.1
173 + REDIS_HOSTNAME=127.0.0.1
174 + ```
175 +
176 + Cleanup
177 +
178 + ```shell-session
179 + $ rm -rf /tmp/* ~/.wget-hsts ~/.pnpm ~/.local/share/pnpm ~/.cache
180 + $ exit
181 + ```
182 +
183 + While still being in the chroot, create the file `/sbin/swinit`
184 +
185 + ```shell
186 + #!/bin/bash
187 + set -x
188 + /rescue/ifconfig lo0 inet 127.0.0.1 up
189 + /rescue/ifconfig epair0b inet 192.168.123.2/24 up
190 + /rescue/route add default 192.168.123.1
191 + nohup /usr/sbin/swinit-init &
192 + ```
193 +
194 + Create `/sbin/swinit-init` (this is a tiny and WiP supervisor)
195 +
196 + ```shell
197 + #!/bin/sh
198 + echo Waiting for PostgreSQL to start on FreeBSD...
199 + while :; do
200 + if nc -z 192.168.123.1 5432 ; then
201 + break
202 + fi
203 + sleep 2
204 + done
205 +
206 + echo Starting Valkey.
207 + sudo -u valkey valkey-server /etc/valkey/valkey.conf
208 + sleep 1
209 +
210 + echo Starting Immich.
211 + sudo -u immich /var/lib/immich/app/start.sh &
212 + IMMICH_PID=$!
213 +
214 + sleep inf
215 + ```
216 +
217 + And then create `/sbin/swshutdown`
218 +
219 + ```shell
220 + #!/bin/sh
221 + pkill valkey-server
222 + pkill node
223 + true
224 + ```
225 +
226 + Then finish up
227 +
228 + ```
229 + # chmod +x /sbin/swinit /sbin/swshutdown /sbin/swinit-init
230 + # exit
231 + ```
232 +
233 + **At this point, you should be running commands on the _host_ again.**
234 +
235 + Pack the Immich chroot
236 +
237 + ```shell-session
238 + # umount immich/proc
239 + # tar -C immich -czf immich.tar.gz .
240 + ```
241 +
242 + Send it to your FreeBSD server, with SFTP:
243 +
244 + ```
245 + $ sftp <ip to server>
246 + sftp> put immich.tar.gz
247 + ```
248 +
249 + # 3. Installation
250 +
251 + **At this point, you should be using your FreeBSD server for this.**
252 +
253 + Install dependencies
254 +
255 + ```shell-session
256 + # pkg install postgresql18-server postgresql18-contrib postgresql18-pgvector sudo
257 + # sysrc gateway_enable="YES"
258 + # sysrc pf_enable="YES"
259 + # sysrc pf_rules="/etc/pf.conf"
260 + # sysrc cloned_interfaces="bridge1"
261 + # sysrc ifconfig_bridge1="inet 192.168.123.1/24 description jailnet up"
262 + # sysrc linux_enable="YES"
263 + # sysrc jail_enable="YES"
264 + # sysrc postgresql_enable="YES"
265 + # service linux start
266 + # echo 'if_epair_load="YES"' >> /boot/loader.conf
267 + # echo 'if_bridge_load="YES"' >> /boot/loader.conf
268 + # echo 'pf_load="YES"' >> /boot/loader.conf
269 + # echo 'nmdm_load="YES"' >> /boot/loader.conf
270 + # kldload if_epair
271 + # kldload if_bridge
272 + # kldload pf
273 + # kldload nmdm
274 + ```
275 +
276 + Create this at `/etc/pf.conf`, replace `em0` with your main internet-accessible interface
277 +
278 + ```
279 + ext_if = "em0"
280 + jail_net = "192.168.123.0/24"
281 +
282 + nat on $ext_if from $jail_net to any -> ($ext_if)
283 +
284 + pass in all
285 + pass out all
286 + ```
287 +
288 + Then start the networking stuff
289 +
290 + ```shell-session
291 + # service gateway start
292 + # ifconfig bridge0 inet 192.168.123.1/24 description jailnet up
293 + # service pf start
294 + ```
295 +
296 + Compile VectorChord
297 +
298 + ```shell-session
299 + # pkg install git rust llvm21 curl
300 + # curl -fsSL https://github.com/tensorchord/VectorChord/archive/refs/tags/1.1.1.tar.gz | tar -xz
301 + # cd VectorChord-1.1.1
302 + # make build PG_CONFIG="$(which pg_config)"
303 + # cp build/sharedir/extension/* /usr/local/share/postgresql/extension/
304 + # cp build/pkglibdir/* /usr/local/lib/postgresql/
305 + # cd ..
306 + ```
307 +
308 + Setup database
309 +
310 + ```shell-session
311 + # service postgresql initdb
312 + # service postgresql start
313 + # sudo -u postgres psql
314 + postgres=# ALTER SYSTEM SET shared_preload_libraries = "vchord";
315 + postgres=# \q
316 + # service postgresql restart
317 + # sudo -u postgres psql
318 + ```
319 +
320 + ```sql
321 + CREATE USER immich WITH ENCRYPTED PASSWORD 'YOUR_STRONG_RANDOM_PW';
322 + CREATE DATABASE immich OWNER immich;
323 + ALTER USER immich WITH SUPERUSER;
324 + CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
325 + \q
326 + ```
327 +
328 + ```shell-session
329 + # sudo -u postgres psql -U immich
330 + ```
331 +
332 + ```sql
333 + CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
334 + \q
335 + ```
336 +
337 + Unpack Devuan rootfs
338 +
339 + ```shell-session
340 + # mkdir -p /usr/jail/immich
341 + # tar -C /usr/jail/immich -xzf immich.tar.gz
342 + ```
343 +
344 + Create `/etc/jail.conf`
345 +
346 + Note that this a compacted version of my own setup, which also has FreeBSD jails, so it's a bit messy.
347 +
348 + ```
349 + # Global parameters
350 + exec.start = "/bin/sh /etc/rc";
351 + exec.stop = "/bin/sh /etc/rc.shutdown";
352 + exec.clean;
353 + mount.devfs;
354 + allow.raw_sockets;
355 + allow.sysvipc;
356 +
357 + # VNET-specific parameters
358 + vnet;
359 + vnet.interface = "epair${nid}b";
360 + exec.prestart = "ifconfig epair${nid} create up";
361 + exec.prestart += "ifconfig epair${nid}a up";
362 + exec.prestart += "ifconfig bridge1 addm epair${nid}a";
363 + exec.poststop = "ifconfig epair${nid}a destroy";
364 +
365 + # Path parameters
366 + path = "/usr/jail/${name}";
367 + host.hostname = "${name}.jail";
368 +
369 + immich {
370 + # This is a Linux jail.
371 + # If you want to use external storage, uncomment the two and replace /mnt/hdds/immich with whatever path
372 + $nid = 0;
373 + allow.mount;
374 + exec.prestart += "mount -t linprocfs linprocfs /usr/jail/immich/proc";
375 + exec.prestart += "mount -t linsysfs linsysfs /usr/jail/immich/sys";
376 + exec.prestart += "mount -t tmpfs tmpfs /usr/jail/immich/tmp";
377 + exec.prestart += "mount -t nullfs /rescue /usr/jail/immich/rescue";
378 + # exec.prestart += "mount -t nullfs /mnt/hdds/immich /usr/jail/immich/var/lib/immich/app/upload";
379 +
380 + exec.poststop += "umount /usr/jail/immich/proc";
381 + exec.poststop += "umount /usr/jail/immich/sys";
382 + exec.poststop += "umount /usr/jail/immich/tmp";
383 + exec.poststop += "umount /usr/jail/immich/rescue";
384 + # exec.poststop += "umount /usr/jail/immich/var/lib/immich/app/upload";
385 +
386 + exec.start = "/bin/sh /sbin/swinit";
387 + exec.stop = "/bin/sh /sbin/swshutdown";
388 + }
389 + ```
390 +
391 + Start jail
392 +
393 + ```shell-session
394 + # service jail start
395 + ```
396 +
397 + And if set up correctly, you should be able to access Immich!
398 +
399 + Example NGINX config for reverse proxying immich
400 +
401 + ```nginx
402 + server {
403 + listen 80;
404 + listen [::]:80;
405 + listen 443 ssl;
406 + listen [::]:443 ssl;
407 + listen 443 quic;
408 + listen [::]:443 quic;
409 +
410 + server_name immich.example.com;
411 +
412 + client_max_body_size 50000M;
413 + proxy_request_buffering off;
414 + client_body_buffer_size 1024k;
415 + proxy_set_header Host $host;
416 + proxy_set_header X-Real-IP $remote_addr;
417 + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
418 + proxy_set_header X-Forwarded-Proto $scheme;
419 + proxy_http_version 1.1;
420 + proxy_redirect off;
421 + proxy_read_timeout 600s;
422 + proxy_send_timeout 600s;
423 + send_timeout 600s;
424 +
425 + location / {
426 + proxy_pass http://192.168.123.2:2283;
427 + proxy_set_header Upgrade $http_upgrade;
428 + proxy_set_header Connection "upgrade";
429 + }
430 +
431 + ssl_certificate /etc/letsencrypt/live/immich.example.com/fullchain.pem;
432 + ssl_certificate_key /etc/letsencrypt/live/immich.example.com/privkey.pem;
433 + include /etc/letsencrypt/options-ssl-nginx.conf;
434 + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
435 + }
436 + ```
437 +
438 + # What the hell was that?
439 +
440 + Yep, you did a very cursed but possible thing in FreeBSD using Linuxulator, FreeBSD's decent Linux compatibility layer, it seems to be good enough to flawlessly run Immich.
Newer Older