 | tech_notesA collection of notes on setups and implementations.
|
|
Log | Files | Refs | README |
commit 5e62893d37f0fc012b1b0e4e7d41cc409825f9c3
parent 715e4894982c7f06e7fcb525db74bb43cf1ad57c
Author: Julian Piribauer <julian.piribauer@gmail.com>
Date: Sat, 2 May 2026 18:28:50 +0000
Add Family Tree installation notes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat:
| A | familytree.md | | | 96 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 96 insertions(+), 0 deletions(-)
diff --git a/familytree.md b/familytree.md
@@ -0,0 +1,96 @@
+# Family Tree app
+
+We document the installation of the self-hosted family tree app running at [familytree.piribauer.ch](https://familytree.piribauer.ch).
+The source is available at [git.piribauer.ch/familytree](https://git.piribauer.ch/familytree).
+
+The app is built with FastAPI and stores its data in a SQLite database.
+Authentication is handled entirely by an Authentik outpost via nginx forward-auth; the app reads the `X-Authentik-Username` and `X-Authentik-Email` headers injected by nginx and never touches the Authentik API directly.
+
+We assume that nginx and an Authentik outpost are already running, and that the repo has been cloned to `/home/julian/familytree`.
+
+## Python environment
+
+The system Python on Arch Linux is PEP 668-managed and rejects direct `pip install` calls.
+We therefore use a virtual environment:
+
+```console
+$ python -m venv /home/julian/familytree/venv
+$ /home/julian/familytree/venv/bin/pip install -r /home/julian/familytree/requirements.txt
+```
+
+## Database directory
+
+The app stores its data in a SQLite database under `/var/lib/familytree/`.
+We create the directory and assign ownership to the service user:
+
+```console
+# mkdir -p /var/lib/familytree
+# chown julian:julian /var/lib/familytree
+```
+
+## Environment file
+
+The app reads its configuration from `/home/julian/familytree/.env`.
+We create it with the database URL:
+
+```bash
+DATABASE_URL=sqlite:////var/lib/familytree/familytree.db
+```
+
+## Systemd service
+
+We install the unit file included in the repo:
+
+```console
+# cp /home/julian/familytree/familytree.service /etc/systemd/system/familytree.service
+# systemctl daemon-reload
+# systemctl enable --now familytree
+```
+
+The service runs as user `julian`, listening on `127.0.0.1:8766`.
+We can verify it started cleanly with
+
+```console
+$ systemctl status familytree
+```
+
+## Nginx
+
+We copy the nginx config from the repo and enable it:
+
+```console
+# cp /home/julian/familytree/nginx/family /etc/nginx/sites-available/family
+# ln -s /etc/nginx/sites-available/family /etc/nginx/sites-enabled/family
+# nginx -t && systemctl reload nginx
+```
+
+The config forwards all requests through the Authentik outpost running on `127.0.0.1:9000`.
+On success, nginx extracts the username and email from the outpost response and passes them to the app:
+
+```nginx
+auth_request_set $authentik_username $upstream_http_x_authentik_username;
+auth_request_set $authentik_email $upstream_http_x_authentik_email;
+
+proxy_set_header X-Authentik-Username $authentik_username;
+proxy_set_header X-Authentik-Email $authentik_email;
+```
+
+Unauthenticated requests are redirected to the Authentik login page.
+
+## Schema migrations
+
+SQLAlchemy creates missing tables on startup with `create_all`, but does not modify tables that already exist.
+If a column is added to the models, it must be applied to the existing database manually.
+For example, adding a `notes` column to the `persons` table:
+
+```console
+$ sqlite3 /var/lib/familytree/familytree.db "ALTER TABLE persons ADD COLUMN notes TEXT;"
+```
+
+## Invitation flow
+
+Users are invited by email address from within the app.
+The invitation is stored as a pending record linked to the tree.
+When the invited user logs in for the first time, their Authentik email is matched against all pending invitations and the corresponding tree memberships are created automatically.
+Trees have three roles: `owner`, `editor`, and `viewer`.
+Only owners can invite others or change roles.