Skip to content

feat: yucca integration - #27817

Draft
insertish wants to merge 75 commits into
mainfrom
feat/yucca-integration
Draft

feat: yucca integration#27817
insertish wants to merge 75 commits into
mainfrom
feat/yucca-integration

Conversation

@insertish

@insertish insertish commented Apr 15, 2026

Copy link
Copy Markdown
Member

Integrates yucca with the:

  • Server: mounted as a NestJS module
  • Web: Svelte library that provides all the UI

Some key things to point out from the PR:

  • Adds @futo-org/backups-orchestrator-* dependencies
  • Adds blanket authentication for /api/yucca to api & maintenance auth guards
  • New LibraryCreate|Update|Delete events for synchronising state to orchestrator
  • Hooks up the orchestration api module in api and maintenance modules (currently hard-coded to use my staging environment)
  • Installs restic 0.19.0 in through mise
  • Refactors the maintenance database backup pages to split the card into its own component so that we can have a separate page where a database backup is auto-selected (after backup restore)
  • Updates the restore flow to support orchestrator
  • Adds a separate backups page on the main left sidebar for orchestrator page
  • Adds better-sqlite3 as a native dependency
  • Adds a new link target, /link?target=backups, which enables "Backups" in the sidebar
    • Adds backups.beta: boolean to system config which is exposed in the server features API

TBD:

  • Pollutes OpenAPI spec and generators with API routes
  • Currently does not have i18n in the actual backups UI, but this probably doesn't matter for closed beta - one solution would just be to re-use the same svelte translations library and put the translation keys in Immich
  • Always shows in Immich onboarding/maintenance "restore from FUTO Backups"

How Has This Been Tested?

Screenshots

Main interface

Screen Shot 2026-06-18 at 11 12 11 Screen Shot 2026-06-18 at 11 12 21 Screen Shot 2026-06-18 at 11 12 28

Setup flow

Restore flow

Checklist:

  • I have carefully read CONTRIBUTING.md
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation if applicable
  • I have no unrelated changes in the PR.
  • I have confirmed that any new dependencies are strictly necessary.
  • I have written tests for new code (if applicable)
  • I have followed naming conventions/patterns in the surrounding code
  • All code in src/services/ uses repositories implementations for database calls, filesystem operations, etc.
  • All code in src/repositories/ is pretty basic/simple and does not have any immich specific logic (that belongs in src/services/)

Please describe to which degree, if any, an LLM was used in creating this pull request.

Used where appropriate for prototypes.

@insertish
insertish force-pushed the feat/yucca-integration branch from 8df2ac9 to b803a7d Compare June 22, 2026 14:29
Comment thread server/src/middleware/auth.guard.ts Outdated
Comment on lines +91 to +94
if (request.path.startsWith('/api/yucca')) {
request.user = await this.authService.authenticate({
headers: request.headers,
queryParams: request.query as Record<string, string>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change the flow so that if the path is yucca is sets the metadata directly otherwise it gets it from this.reflector, and then both paths have a single request.user = await this.authService.authenticate({ metadata }) call?

Comment thread server/src/services/yucca.service.ts Outdated
Comment on lines +1 to +2
import { EventsGateway, ModuleConfigRepository } from '@futo-org/backups-orchestrator-api/dist';
import { GatewayEvent } from '@futo-org/backups-orchestrator-api/dist/events/events.gateway';

@jrasm91 jrasm91 Jun 24, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should just import directly from @futo-org/backups-orchestrator-api

Comment thread server/src/services/yucca.service.ts Outdated
Comment on lines +30 to +42
onModuleInit() {
if (this.eventsGateway) {
this.eventsGateway.setAuthFn(async (client) =>
this.authService.authenticate({
headers: client.request.headers,
queryParams: {},
metadata: { adminRoute: true, sharedLinkRoute: false, uri: '/api/yucca/socket.io' },
}),
);

this.eventsGateway.on(this.onInternalEvent);
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is configuration that belongs in Module.forRoot(). The Yucca module should have it's own websocket gateway, path, etc. If it wants to defer authentication to Immich's system, it should do something like:

OrchestrationApiModule.forRootAsync({
  ...
  useFactory: (authService) => {
    authenticate: (request) => authService.authenticate(...)
  },
  inject: [AuthService],
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this whole file should just be "on immich events, call a method on the YuccaService", which should be injected via @Optional() private readonly yuccaService: YuccaService. The file should just be, onConfig => call this yuccaService method, onLibraryCreate => call this yuccaService method.

Comment thread server/src/main.ts Outdated

onError(name: ImmichWorker, error: Error) {
console.error(`${name} worker error: ${error}, stack: ${error.stack}`);
console.error(`${name} worker error: ${JSON.stringify(error)}, stack: ${error.stack}`);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems wrong/unrelated

@immich-push-o-matic

Copy link
Copy Markdown

Deploying preview environment to https://pr-27817.preview.internal.immich.build/

Signed-off-by: izzy <me@insrt.uk>
@insertish
insertish force-pushed the feat/yucca-integration branch from a4b8b0f to 7b093bc Compare July 27, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants