# How Photo Providers (Immich & Synology) Integrate with the Journey Addon in TREK

> Discover how Immich and Synology photo providers integrate with the Journey addon in TREK using server-side credentials, proxy streaming, and a REST API for seamless asset referencing without data duplication.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: how-to-guide
- Published: 2026-06-26

---

**Photo providers extend the Journey addon by connecting external image libraries through server-side credential storage, proxy streaming, and a REST API that references assets without duplicating binary data.**

The **Journey** addon in TREK transforms the platform into a photo-first travel journal, allowing users to document trips with geotagged entries. To prevent vendor lock-in and support existing self-hosted media libraries, TREK integrates with **Immich** and **Synology Photos** through a provider abstraction layer. This integration keeps sensitive credentials encrypted server-side while streaming images on-demand through TREK’s secure proxy.

## Enabling Photo Providers in the Admin Panel

Before users can link external libraries, an administrator must activate the Journey addon and explicitly enable the desired photo providers.

1. Navigate to **Admin → Addons** and toggle the Journey addon.
2. Once enabled, two sub-toggles appear: **Immich** and **Synology Photos**.
3. Activating either provider exposes a **Photo Providers** section in every user’s **Settings → Integrations** page.

According to the source configuration in [`wiki/Admin-Addons.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Admin-Addons.md), the system stores these preferences as JSON:

```json
{
  "addons": {
    "journey": true,
    "photo_providers": {
      "immich": true,
      "synologyphotos": false
    }
  }
}

```

## Configuring User Credentials and Scopes

Each user authenticates their personal photo libraries through the Integrations tab. Credentials are encrypted at rest and never exposed to the browser.

**Required parameters for both providers:**
- **Server URL** – The full API endpoint (e.g., `https://immich.example.com/api` or `https://nas:5001/photo`).
- **API token / passphrase** – Stored encrypted in the database.
- **Scope selection** – For Immich, the mandatory OAuth scope is `timeline.read` for browsing. Enable `asset.upload` only if you want TREK to mirror Journey uploads back to Immich.

If your provider runs on a private LAN, you must whitelist the URL in **Admin → Internal Network Access** so the TREK server can reach it, as documented in [`wiki/Internal-Network-Access.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Internal-Network-Access.md).

## API Integration and Photo Fetching

When a user attaches an external photo to a Journey entry, the frontend calls the protected endpoint:

```bash
POST /api/journeys/:entryId/provider-photos

```

The request payload follows the Zod schema defined in [`shared/src/journey/journey.schema.ts`](https://github.com/mauriceboe/TREK/blob/main/shared/src/journey/journey.schema.ts):

```bash
curl -X POST "https://trek.example.com/api/journeys/42/provider-photos" \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
        "provider": "immich",
        "asset_id": "ae3f5d4c-1b2c-4d5e-9f6a-7b8c9d0e1f2a",
        "caption": "Sunset at the beach",
        "passphrase": "optional-secret"
      }'

```

**Backend processing flow:**
- `JourneyController.providerPhotos` (lines 148-155 in [`server/src/nest/journey/journey.controller.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/nest/journey/journey.controller.ts)) validates the JWT and checks for the `journey:write` scope.
- The controller delegates to `JourneyService.addProviderPhoto`, which stores only the reference tuple (`provider` + `asset_id`) rather than the file itself.
- The action is logged under `admin.places_photos` in the audit log for compliance tracking.

## Displaying Photos via Proxy Streaming

Journey entries display thumbnails by streaming images through TREK’s server-side proxy, ensuring provider tokens remain server-side only.

The UI references images via:

```html
<img src="/api/public/journey/12" alt="Sunset at the beach"/>

```

When this route is hit, TREK reads the stored reference from the database, fetches the raw bytes from Immich or Synology, and streams the response to the client with proper `Cache-Control` headers. This architecture prevents credential leakage while allowing offline caching of frequently viewed images.

## Mirroring Uploads to Immich

If the admin enables **"Mirror journey photos to Immich on upload"**, TREK performs a dual-write operation:

1. The uploaded file is stored locally under `uploads/photos/` for fast retrieval and offline resilience.
2. Simultaneously, the image is pushed to the configured Immich instance using the `asset.upload` scope.

This synchronization happens inside `JourneyService` and is documented in the mirroring table within [`wiki/Photo-Providers.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Photo-Providers.md). Local storage remains the primary source; the Immich copy serves as a backup in the user’s existing photo library.

## Summary

- **Enablement**: Admins activate Immich and Synology Photos as sub-toggles under the Journey addon in [`Admin-Addons.md`](https://github.com/mauriceboe/TREK/blob/main/Admin-Addons.md).
- **Security**: API tokens are encrypted in the database and never transmitted to the frontend; images are proxied through `/api/public/journey/:photoId`.
- **Storage efficiency**: Only asset references (`provider` + `asset_id`) are stored in TREK’s database; binary data streams on-demand.
- **Permissions**: Adding provider photos requires the `journey:write` scope and is audited under `admin.places_photos`.
- **Bidirectional sync**: Optional mirroring pushes Journey uploads to Immich while keeping local copies for performance.

## Frequently Asked Questions

### Where are photo provider credentials stored in TREK?

Credentials are encrypted in the TREK database and decrypted only server-side when making requests to Immich or Synology APIs. They are never sent to the browser or exposed in network logs, following the security model defined in [`wiki/Photo-Providers.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Photo-Providers.md).

### Can I use Immich and Synology Photos simultaneously?

Yes. The Journey addon supports multiple active providers. Users can link both an Immich server and a Synology Photos account in their **Settings → Integrations**, then choose which provider to source from when adding photos to an entry via the `provider` field in the API payload.

### Why does TREK proxy images instead of storing them directly?

TREK stores only lightweight references (`asset_id`) to avoid duplicating large binary files in its own storage. The proxy route (`/api/public/journey/:photoId`) fetches images on-demand from the external provider, ensuring credentials remain server-side while allowing TREK to apply caching headers and access control.

### What permission is required to add a provider photo to a Journey entry?

Users must possess the `journey:write` OAuth scope. This scope is validated by `JourneyController.providerPhotos` before `JourneyService.addProviderPhoto` processes the request, and successful additions are logged to the audit trail under `admin.places_photos`.