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

> Explore Immich maintenance tasks in maintenance.service.ts. Discover seven public methods like startMaintenance startRestoreFlow and detectPriorInstall triggered programmatically via NestJS HTTP or internal events.

- Repository: [Immich/immich](https://github.com/immich-app/immich)
- Tags: how-to-guide
- Published: 2026-02-27

---

**The `MaintenanceService` in [`server/src/services/maintenance.service.ts`](https://github.com/immich-app/immich/blob/main/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`](https://github.com/immich-app/immich/blob/main/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.

```typescript
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`](https://github.com/immich-app/immich/blob/main/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.

```typescript
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:

- **[`server/src/controllers/maintenance.controller.ts`](https://github.com/immich-app/immich/blob/main/server/src/controllers/maintenance.controller.ts)** - HTTP routing layer that forwards requests to `MaintenanceService`
- **[`server/src/dtos/maintenance.dto.ts`](https://github.com/immich-app/immich/blob/main/server/src/dtos/maintenance.dto.ts)** - TypeScript definitions for `SetMaintenanceModeDto`, `MaintenanceAuthDto`, and related data transfer objects
- **[`server/src/enum.ts`](https://github.com/immich-app/immich/blob/main/server/src/enum.ts)** - `MaintenanceAction` enum containing `Start`, `End`, `SelectDatabaseRestore`, and `RestoreDatabase` values
- **[`server/src/utils/maintenance.ts`](https://github.com/immich-app/immich/blob/main/server/src/utils/maintenance.ts)** - Helper functions for cryptographic secret generation and JWT signing
- **[`server/src/services/base.service.ts`](https://github.com/immich-app/immich/blob/main/server/src/services/base.service.ts)** - Base class providing `MaintenanceService` with access to `systemMetadataRepository` and `eventRepository`

## Summary

- The `MaintenanceService` in [`server/src/services/maintenance.service.ts`](https://github.com/immich-app/immich/blob/main/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`](https://github.com/immich-app/immich/blob/main/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.