Private photo albums with opt-in face detection, automatic EXIF stripping, and a geotag toggle. Your photos stay on your server, processed locally — no cloud vision API calls, no metadata leaving your VPS.
nself-photos is part of the ɳFamily bundle. Stores images in your MinIO (nself object storage). Set your license key with nself license set nself_pro_... before installing.
nself license set nself_pro_...
nself plugin install photos
nself build
nself startnself-photos uses nself object storage (MinIO). Enable it with nself config set storage.enabled true before building.
nself-photos organizes photos into albums. Each album has a name, cover photo, and membership list — you control exactly who can see each album. Uploads are processed on your server: thumbnails are generated at 400px and 1200px, EXIF data is stripped by default, and geotags are removed unless you explicitly enable them.
Face detection runs locally using an embedded model (no API key required). When enabled, the plugin groups photos by detected faces across all albums a member can access. Each face cluster can be named — Grandma, Kids 2024 — and tagged photos become searchable. Members must individually opt in to being recognized; untagged faces are never stored.
Photos attach to nself-social posts by media ID. The social plugin never stores image data — it references IDs from nself-photos. This means deleting a photo from the album removes it from any post it was attached to.
| Variable | Required | Default | Description |
|---|---|---|---|
PLUGIN_PHOTOS_STRIP_EXIF | No | true | Remove all EXIF metadata on upload. Set to false to preserve. |
PLUGIN_PHOTOS_STRIP_GEOTAGS | No | true | Remove GPS coordinates even if EXIF stripping is off |
PLUGIN_PHOTOS_FACE_DETECTION | No | false | Enable local face detection. Requires consent opt-in per member. |
PLUGIN_PHOTOS_MAX_UPLOAD_MB | No | 50 | Max file size per photo upload in megabytes |
PLUGIN_PHOTOS_THUMBNAIL_SIZES | No | 400,1200 | Comma-separated thumbnail widths generated on upload |
PLUGIN_PHOTOS_STORAGE_BUCKET | No | family-photos | MinIO bucket name. Created automatically on first run. |
| Endpoint | Method | Description |
|---|---|---|
/photos/albums | GET / POST | List accessible albums or create a new one |
/photos/albums/:id | GET / PATCH / DELETE | Get, update, or delete an album |
/photos/albums/:id/upload | POST | Upload photo(s) to an album. Accepts multipart/form-data. |
/photos/albums/:id/media | GET | Paginated photo list for an album |
/photos/media/:id | GET / DELETE | Fetch metadata or delete a single photo |
/photos/faces | GET | List face clusters for the authenticated member (requires consent) |
/photos/faces/:id/tag | POST | Name a face cluster |
/health | GET | Plugin health check |
| Table | Purpose |
|---|---|
np_photos_albums | Album name, owner, cover media ID, visibility |
np_photos_media | MinIO object key, MIME type, dimensions, size, upload timestamp |
np_photos_album_members | Album-to-member access grants |
np_photos_face_clusters | Detected face embeddings, optional human label, consent flag per member |
np_photos_face_tags | Links a face cluster to a media item and bounding box |
| Event | Payload |
|---|---|
photos.media.uploaded | Media ID, album ID, uploader ID, MIME type |
photos.album.created | Album ID, name, owner ID |
photos.face.tagged | Cluster ID, label, tagger ID |
nself-photos is a media provider for nself-social. Attach photos to posts by including their media IDs in the post body. The social feed renders thumbnails directly from your MinIO storage via pre-signed URLs.
# Upload a photo to album abc123
curl -X POST http://127.0.0.1:3826/photos/albums/abc123/upload \
-H "Authorization: Bearer <member_token>" \
-F "file=@/path/to/photo.jpg"
# Response includes media_id for use in social posts
# { "media_id": "med_xyz789", "url": "https://...", "thumbnail_400": "..." }| Feature | nself-photos | Google Photos | iCloud |
|---|---|---|---|
| Data location | Your VPS / local MinIO | Google servers | Apple servers |
| Face recognition | Local model, opt-in per member | Cloud, always on | On-device |
| EXIF stripping | On by default | Partial | No |
| Family sharing | Album-level, member-controlled | Shared albums | iCloud Family (5 people) |
| Symptom | Fix |
|---|---|
| Upload returns 413 | File exceeds PLUGIN_PHOTOS_MAX_UPLOAD_MB. Raise the limit or compress the photo. |
| Thumbnails not generated | Check MinIO is running: nself status. Thumbnails are generated async — check plugin logs. |
| Face detection returns empty | Confirm PLUGIN_PHOTOS_FACE_DETECTION=true and the member has opted in via POST /photos/faces/consent. |
Port: 3826 | Bundle: ɳFamily ($0.99/mo) or ɳSelf+ ($3.99/mo) | Last Updated: May 2026 | Plugin Version 1.0.13