Immich Maintenance Tasks in maintenance.service.ts: Available Methods and Programmatic Triggers

The MaintenanceService in server/src/services/maintenance.service.ts exposes seven public methods—including startMaintenance(), startRestoreFlow(), and detectPriorInstall()—that manage Immich's maintenance mode, and they can be triggered programmatically via NestJS dependency injection, HTTP controller endpoints, or internal AppRestart event emission.

The Immich photo backup platform (immich-app/immich) provides a dedicated maintenance subsystem for database restoration and server state management. The MaintenanceService class encapsulates all server-side logic for entering maintenance mode, detecting prior installations, and generating authenticated access tokens. Understanding these maintenance tasks in maintenance.service.ts allows developers to automate backup workflows and integrate custom maintenance routines into the NestJS application lifecycle.

Available Maintenance Tasks in maintenance.service.ts

The service implements seven distinct operations that control the server's maintenance lifecycle. Each method is located in server/src/services/maintenance.service.ts and serves a specific purpose in the maintenance workflow.

Query and Status Methods

getMaintenanceMode() returns the complete maintenance state including the isMaintenanceMode boolean, active secret, and current action identifier. This method reads directly from systemMetadataRepository and reflects the server's real-time operational status (lines 26-30).

getMaintenanceStatus() provides a lightweight status DTO consumed by the public API to report whether a maintenance action is currently active. This endpoint supports health checks and UI state synchronization without exposing sensitive secrets (lines 32-37).

Installation Detection

detectPriorInstall() executes heuristics that scan the host filesystem to identify previous Immich installations. This validation step is critical for database restore flows, ensuring that restoration targets an appropriate existing data directory (lines 39-41).

Maintenance State Control

startMaintenance(actionDto, username) initiates maintenance mode for specific MaintenanceAction types. Supported actions include start, end, select_database_restore, and restore_database. This method generates a cryptographic secret, persists the mode state to system metadata, emits an AppRestart event, and returns a JWT token for authenticating subsequent maintenance requests (lines 43-58).

startRestoreFlow() begins the database-restore workflow by first verifying that no admin user exists—a mandatory pre-restore safety condition. Upon validation, it delegates to startMaintenance() with MaintenanceAction.SelectDatabaseRestore and returns the authentication JWT (lines 60-71).

Authentication Utilities

createLoginUrl(authDto, secret?) constructs one-time login URLs for clients that are already in maintenance mode. If the secret parameter is omitted, the method reads the current secret from system metadata state. This utility supports external maintenance interfaces and CLI tools requiring authenticated access (lines 82-96).

Event Handling

onRestart(event, ack?) listens for internal AppRestart events emitted by the maintenance system. Upon receiving the event, it invokes appRepository.exitApp() to terminate the Node process, allowing the container or process manager to restart the application with new maintenance configuration (lines 74-80).

How to Trigger Maintenance Tasks Programmatically

Immich supports three primary mechanisms for invoking these tasks outside the standard web interface.

NestJS Dependency Injection

The most direct approach injects MaintenanceService into your service or worker class using standard NestJS providers.

import { Injectable } from '@nestjs/common';
import { MaintenanceService } from 'src/services/maintenance.service';
import { SetMaintenanceModeDto, MaintenanceAction } from 'src/dtos/maintenance.dto';

@Injectable()
export class MaintenanceWorker {
  constructor(private readonly maintenance: MaintenanceService) {}

  async enableMaintenance(userName: string) {
    const dto: SetMaintenanceModeDto = { action: MaintenanceAction.Start };
    const { jwt } = await this.maintenance.startMaintenance(dto, userName);
    // Store or transmit JWT for authenticated maintenance operations
    return jwt;
  }

  async beginRestore() {
    const { jwt } = await this.maintenance.startRestoreFlow();
    return jwt;
  }

  async checkMaintenanceStatus() {
    const state = await this.maintenance.getMaintenanceMode();
    return state.isMaintenanceMode;
  }

  async generateLoginUrl() {
    const auth = { client: 'web', redirectUri: 'https://immich.local/maint' };
    return this.maintenance.createLoginUrl(auth);
  }
}

HTTP Controller Endpoints

For external integrations or microservice communication, the MaintenanceController (server/src/controllers/maintenance.controller.ts) exposes REST endpoints that delegate to the service methods:

  • GET /admin/maintenance/status → invokes getMaintenanceStatus()
  • GET /admin/maintenance/detect-install → invokes detectPriorInstall()
  • POST /admin/maintenance → invokes startMaintenance() with a JSON body containing the action field

When triggering via HTTP, authentication follows Immich's admin middleware pipeline. The POST endpoint returns the same JWT tokens that the dependency injection method provides, enabling subsequent authenticated maintenance requests.

Internal Event Emission

Advanced scenarios may require manual emission of the AppRestart event, though startMaintenance() handles this automatically when entering maintenance mode.

import { EventEmitter2 } from '@nestjs/event-emitter';

// Inside your service or bootstrap logic
eventEmitter.emit('AppRestart', { isMaintenanceMode: true });

The onRestart handler inside MaintenanceService captures this event and calls process.exit() via the application repository to apply configuration changes immediately.

Supporting Files and Architecture

Several adjacent files define the contracts and utilities used by the maintenance system:

Summary

  • The MaintenanceService in server/src/services/maintenance.service.ts exposes seven public methods for managing Immich's maintenance lifecycle.
  • Query methods (getMaintenanceMode, getMaintenanceStatus) retrieve current state without side effects.
  • Action methods (startMaintenance, startRestoreFlow) transition the server into maintenance mode and generate JWT authentication tokens for secure access.
  • Detection methods (detectPriorInstall) validate prerequisites for database restoration workflows.
  • Utility methods (createLoginUrl) generate authenticated access links for maintenance clients using secrets stored in system metadata.
  • Trigger these tasks via NestJS dependency injection for internal services, HTTP endpoints in MaintenanceController for external integrations, or manual AppRestart event emission for advanced automation.
  • All maintenance actions persist state through systemMetadataRepository and trigger application restarts via AppRestart events handled by onRestart().

Frequently Asked Questions

How do I check if Immich is currently in maintenance mode programmatically?

Call getMaintenanceMode() from an injected MaintenanceService instance and inspect the isMaintenanceMode property of the returned state object. This method queries systemMetadataRepository and returns the active secret and current action alongside the boolean flag, providing complete visibility into the server's operational state.

What MaintenanceAction values are supported when calling startMaintenance()?

According to the MaintenanceAction enum defined in server/src/enum.ts, the supported actions are start, end, select_database_restore, and restore_database. Each action transitions the server between operational states, with select_database_restore specifically initiating the database restoration workflow that requires prior validation of admin user absence.

Can I trigger maintenance tasks from outside the NestJS application?

Yes. Send authenticated HTTP requests to the MaintenanceController endpoints at /admin/maintenance/* using valid admin credentials. The POST endpoint accepts a JSON body containing the action field matching the MaintenanceAction enum values, while GET endpoints provide status and installation detection without requiring request bodies.

Where does the maintenance secret get stored and how is it validated?

The startMaintenance() method generates a cryptographically secure secret and persists it via systemMetadataRepository alongside the maintenance mode flag. Subsequent calls to createLoginUrl() read this secret from the repository state to sign JWTs, ensuring that only processes with access to the current system metadata can generate authenticated maintenance URLs or validate maintenance sessions.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →