Add Immich installer #12

Merged
antman merged 29 commits from add-immich-installer into main 2026-08-14 07:03:43 +00:00
Owner

Motivation

We want to be able to specify applications for the server to install. The first application we're going to implement automatic installation for is Immich.

Ideally, we would have some external repository of installers. This way the server manager is not limited to only installing applications that were known at compile time. However, installing and configuring applications is an open ended problem. And however we solve this problem, it would benefit from being as declarative as possible; data, rather than scripts.

What we know at the moment:

  • Required: creating files such as .env and populate them with values derived from the ServerConfig
  • Required: creating systemd service unit definition files
  • Required: enabling systemd service units
  • Required: enabling service units as a user, e.g. systemctl --user -M runner@ enable --now podman.socket
  • Required: adding users, e.g. useradd --create-home runner
  • Required: configuring user groups, e.g. usermod -aG docker runner
  • Required: lingering users e.g. loginctl enable-linger runner
  • Likely: installing from dnf

A template language for populating files may be useful. So far all commands that need to be issued could be issued based on data, e.g. a list of packages to install, service units to enable, users to add and their groups and properties, etc.

One advantage of a declarative (data) approach is it allows the server manager to check if the current configuration matches target configuration. If an imperative script is partially executed, it may not be safely re executed. If a declarative data structure is partially applied, then declarations that match current state (the partially applied portion) can be ignored by the program and execution can continue from the unapplied portion of the target declaration. A declarative approach also facilitates drift detection and self healing

Solution

What I have learnt building an implementation for the above spec:

  • Declarative config via data in the manifest file has worked well in translation layer, but when that data is transformed into runtime implementation in code, it easily turns into a clumsy imperative implementation. Each piece of data in the application manifest needs to be transformed into runtime Resource entities that are stored in a ResourceTree. For example, resource types could include FileResource, FirewallResource, ServiceResource, etc.
  • Once we have a resource implementation, saving the state of these resources to disk becomes simpler
  • The simulation tests are incredibly slow, but they're also incredibly effective. We will need to parallelize these, as well as finding ways to improve execution speed. Might be worth getting the green server set up as a runner after all.

Currently the implementation doesn't open the firewall, it doesn't configure DNS (which is a big issue to figure out later), and it doesn't configure caddy. However, I think merging this code and then refactoring to the resource based implementation will be a better use of time

### Motivation We want to be able to specify applications for the server to install. The first application we're going to implement automatic installation for is Immich. Ideally, we would have some external repository of installers. This way the server manager is not limited to only installing applications that were known at compile time. However, installing and configuring applications is an open ended problem. And however we solve this problem, it would benefit from being as declarative as possible; data, rather than scripts. What we know at the moment: * Required: creating files such as `.env` and populate them with values derived from the ServerConfig * Required: creating systemd service unit definition files * Required: enabling systemd service units * Required: enabling service units as a user, e.g. `systemctl --user -M runner@ enable --now podman.socket` * Required: adding users, e.g. `useradd --create-home runner` * Required: configuring user groups, e.g. `usermod -aG docker runner` * Required: lingering users e.g. `loginctl enable-linger runner` * Likely: installing from `dnf` A template language for populating files may be useful. So far all commands that need to be issued could be issued based on data, e.g. a list of packages to install, service units to enable, users to add and their groups and properties, etc. One advantage of a declarative (data) approach is it allows the server manager to check if the current configuration matches target configuration. If an imperative script is partially executed, it may not be safely re executed. If a declarative data structure is partially applied, then declarations that match current state (the partially applied portion) can be ignored by the program and execution can continue from the unapplied portion of the target declaration. A declarative approach also facilitates drift detection and self healing ### Solution What I have learnt building an implementation for the above spec: * Declarative config via data in the manifest file has worked well in translation layer, but when that data is transformed into runtime implementation in code, it easily turns into a clumsy imperative implementation. Each piece of data in the application manifest needs to be transformed into runtime Resource entities that are stored in a ResourceTree. For example, resource types could include FileResource, FirewallResource, ServiceResource, etc. * Once we have a resource implementation, saving the state of these resources to disk becomes simpler * The simulation tests are incredibly slow, but they're also incredibly effective. We will need to parallelize these, as well as finding ways to improve execution speed. Might be worth getting the green server set up as a runner after all. Currently the implementation doesn't open the firewall, it doesn't configure DNS (which is a big issue to figure out later), and it doesn't configure caddy. However, I think merging this code and then refactoring to the resource based implementation will be a better use of time
Add installsImmich test
Some checks failed
/ test-and-lint (push) Failing after 1m56s
8b205f7b0d
start wiring up applications state property
Some checks failed
/ test-and-lint (push) Failing after 5s
9234db4152
add deriver and tests
Some checks failed
/ test-and-lint (push) Failing after 5s
5e4374ff9e
implement install app function
Some checks failed
/ test-and-lint (push) Failing after 7s
04e0c82606
fixed typo
Some checks failed
/ test-and-lint (push) Failing after 2m4s
f4d00251f8
separate simulation tests from unit tests
Some checks failed
/ test-and-lint (push) Failing after 6s
36d8be54e2
fixed tests
Some checks failed
/ test-and-lint (push) Failing after 2m0s
2f87381887
various bits of work
Some checks failed
/ test-and-lint (push) Failing after 2m1s
a7341d295f
want trace
Some checks failed
/ test-and-lint (push) Failing after 2m0s
d5c7bc7c46
derp
Some checks failed
/ test-and-lint (push) Failing after 1m54s
274da2c943
Add some logs to git clone
Some checks failed
/ test-and-lint (push) Failing after 2m0s
bdae6e38a7
log good
Some checks failed
/ test-and-lint (push) Failing after 2m0s
af81e4b7b3
Who knows
Some checks failed
/ test-and-lint (push) Failing after 2m0s
381ce23a6e
huh?!
Some checks failed
/ test-and-lint (push) Failing after 1m57s
af64e15258
doh
Some checks failed
/ test-and-lint (push) Failing after 2m1s
5ad3fb33ad
more logs and fix IP get
Some checks failed
/ test-and-lint (push) Failing after 2m2s
ac5afaf757
wait for containers to start and try running systemctl with sudo
Some checks failed
/ test-and-lint (push) Failing after 2m33s
fb70d28d46
huh?
Some checks failed
/ test-and-lint (push) Failing after 3m19s
bb1c64164e
echo results
Some checks failed
/ test-and-lint (push) Failing after 2m31s
93ed1febb6
wait longer for immich startup
Some checks failed
/ test-and-lint (push) Has been cancelled
d423fdaf3b
dddd
Some checks failed
/ test-and-lint (push) Failing after 4m1s
4aaa0f4c14
leave VM running
Some checks failed
/ test-and-lint (push) Failing after 4m0s
1334793777
wait even longer
All checks were successful
/ test-and-lint (push) Successful in 4m17s
20d937b172
Try a bit faster
Some checks failed
/ test-and-lint (push) Failing after 4m42s
6d6cda3cf1
antman changed title from WIP: Add Immich installer to Add Immich installer 2026-08-14 06:29:59 +00:00
derp
Some checks failed
/ test-and-lint (push) Has been cancelled
e090ec95b6
bump version number
Some checks failed
/ test-and-lint (push) Failing after 4m48s
223013d8a4
cleanup
Some checks failed
/ test-and-lint (push) Failing after 5m4s
db923d079a
parallelize simulation tests
Some checks failed
/ test-and-lint (push) Failing after 1m21s
ebd8c13240
ignore existing sim link
All checks were successful
/ test-and-lint (push) Successful in 4m2s
ea20677713
antman merged commit 1ee0569efa into main 2026-08-14 07:03:43 +00:00
antman deleted branch add-immich-installer 2026-08-14 07:03:43 +00:00
antman referenced this pull request from a commit 2026-08-14 07:03:44 +00:00
antman referenced this pull request from a commit 2026-08-19 08:38:46 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kill-the-cloud/server-manager!12
No description provided.