summaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md198
1 files changed, 198 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..168edfd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,198 @@
+# Albumen — Photo Album Server
+
+Self-hosted photo/video album. Directory hierarchy = album hierarchy. Ruby/Sinatra
+back end, plain HTML/CSS/JS front end. Live at **https://albumen.jots.org**.
+
+---
+
+## Directory layout
+
+| Path | Purpose |
+|---|---|
+| `/opt/albumen/` | Application root |
+| `/opt/albumen/app.rb` | Sinatra application |
+| `/opt/albumen/views/` | ERB templates |
+| `/opt/albumen/public/` | CSS, JS, static assets |
+| `/opt/albumen/scripts/` | CLI utilities |
+| `/opt/albumen/cache/thumbs/` | Auto-generated thumbnails (safe to delete/regenerate) |
+| `/opt/albumen/config.yml` | Admin password hash + session secret (mode 600) |
+| `/opt/albumen/log/` | Puma stdout/stderr logs |
+| `/var/albumen/` | **Your photos live here** |
+
+Each subdirectory under `/var/albumen/` is an album. Nesting is unlimited.
+The directory name is the album name; the admin UI lets you assign a prettier title.
+
+---
+
+## Uploading photos
+
+Drop files into `/var/albumen/` (or any subdirectory) via `rsync` or `scp`
+from your local machine:
+
+```bash
+rsync -av ~/Pictures/2024-Italy/ root@albumen.jots.org:/var/albumen/2024-Italy/
+
+# or a single file
+scp photo.jpg root@albumen.jots.org:/var/albumen/2024-Italy/
+```
+
+After any upload **run the update script** (see below).
+
+---
+
+## Running the update script
+
+The update script walks the media tree, creates/updates `album.json` files with
+EXIF dates and image dimensions, and pre-generates thumbnails.
+
+```bash
+# On the server — process the entire tree
+ruby /opt/albumen/scripts/update.rb
+
+# Process only one album (and its sub-albums)
+ruby /opt/albumen/scripts/update.rb 2024-Italy
+
+# With an absolute path
+ruby /opt/albumen/scripts/update.rb /var/albumen/2024-Italy
+```
+
+**Resilience guarantees — safe to interrupt and re-run at any point:**
+- `album.json` is written atomically (temp file + rename); no partial writes.
+- Thumbnails that already exist are skipped entirely.
+- EXIF metadata already recorded is not re-extracted.
+- Deleted files are pruned from `album.json` automatically.
+
+Typical workflow:
+
+```bash
+rsync -av ~/Pictures/trip/ root@albumen.jots.org:/var/albumen/trip/
+ssh root@albumen.jots.org 'ruby /opt/albumen/scripts/update.rb trip'
+```
+
+---
+
+## album.json reference
+
+Each directory gets an `album.json` created by the update script.
+You can edit these by hand or through the admin UI at `/admin`.
+
+```jsonc
+{
+ "title": "Italy 2024", // overrides the directory name in the UI
+ "description": "Two weeks in Rome and Florence",
+ "cover": "DSC_0042.jpg", // which file to use as album thumbnail
+ "cover_dynamic": false, // true = play video/animation on hover
+ "visible": true, // false = hidden from non-admin users
+ "files": {
+ "DSC_0042.jpg": {
+ "title": "Colosseum", // shown in lightbox (defaults to filename)
+ "caption": "Just after sunrise, no crowds yet.",
+ "visible": true,
+ "taken_at": "2024-06-03T06:14:00", // from EXIF; set by update script
+ "width": 6000,
+ "height": 4000
+ }
+ }
+}
+```
+
+Fields set by the update script (`taken_at`, `width`, `height`) are not
+overwritten if already present — safe to correct by hand.
+
+---
+
+## Admin interface
+
+Go to `https://albumen.jots.org/admin` and log in. From there:
+
+- Edit album title, description, cover image, visibility
+- Edit per-file title, caption, visibility
+- Navigate into sub-albums
+
+### Changing the admin password
+
+```bash
+ssh root@albumen.jots.org
+ruby /opt/albumen/scripts/set_password.rb
+```
+
+The bcrypt hash is stored in `/opt/albumen/config.yml` (readable only by the
+`albumen` service user).
+
+---
+
+## Service management
+
+```bash
+systemctl status albumen # is it running?
+systemctl restart albumen # restart (e.g. after editing app.rb)
+journalctl -u albumen -f # live service logs
+tail -f /opt/albumen/log/puma.stdout.log # Puma access log
+tail -f /opt/albumen/log/puma.stderr.log # Puma error log
+```
+
+The service runs as the `albumen` user. App code lives in `/opt/albumen/`.
+
+---
+
+## Thumbnail cache
+
+Thumbnails are stored in `/opt/albumen/cache/thumbs/`, mirroring the media
+tree. The cache is fully regenerable — delete any or all of it and the app
+regenerates on demand (or run the update script to pre-generate).
+
+```bash
+# Regenerate all thumbnails for one album
+rm -rf /opt/albumen/cache/thumbs/2024-Italy
+ruby /opt/albumen/scripts/update.rb 2024-Italy
+```
+
+---
+
+## Infrastructure
+
+| Component | Location | Notes |
+|---|---|---|
+| App server | `192.168.10.245` | Puma on port 4567, nginx on 80 |
+| Reverse proxy | `192.168.10.1` (prouter) | Apache, handles TLS termination |
+| DNS | `mirkwood.jots.org` (209.141.48.158) | BIND 9, zone `/etc/bind/zones/jots.org.zone` |
+| TLS cert | `/etc/letsencrypt/live/albumen.jots.org/` on prouter | Expires 2026-08-07; auto-renewed by certbot |
+| Public URL | `https://albumen.jots.org` | → prouter → 192.168.10.245:80 |
+
+### Sinatra settings required for the proxy setup
+
+Two settings in `app.rb` are necessary when running behind an HTTPS reverse proxy:
+
+- `set :absolute_redirects, false` — Sinatra redirects use relative paths (`/foo`)
+ so the browser stays on HTTPS rather than following an `http://` Location header.
+- `set :protection, except: :http_origin` — prevents Rack::Protection from
+ dropping the admin session when the `Origin` header's scheme (`https://`)
+ doesn't match the backend connection scheme (`http://`).
+
+### Cert renewal
+
+Certbot auto-renewal is managed by the system cron on prouter. To test:
+
+```bash
+ssh root@192.168.10.1 'certbot renew --dry-run'
+```
+
+---
+
+## Re-deploying after code changes
+
+```bash
+# From your workstation
+scp -r /home/ken/albumen/. root@albumen.jots.org:/opt/albumen/
+ssh root@albumen.jots.org 'chown -R albumen:albumen /opt/albumen && systemctl restart albumen'
+```
+
+---
+
+## Supported file types
+
+| Category | Extensions |
+|---|---|
+| Images | jpg jpeg png gif webp heic heif tiff bmp |
+| Videos | mp4 mov avi mkv webm m4v ogv |
+| Audio | mp3 flac ogg wav m4a aac |