Compare commits

...

1 commit

Author SHA1 Message Date
Nicolas Meienberger
9c62b9dd88 revert: remove cifs-utils from the image
Some checks failed
Release Workflow / determine-release-type (push) Has been cancelled
Release Workflow / checks (push) Has been cancelled
Release Workflow / e2e-tests (push) Has been cancelled
Release Workflow / build-images (push) Has been cancelled
Release Workflow / publish-release (push) Has been cancelled
2026-01-16 23:42:33 +01:00
5 changed files with 247 additions and 95 deletions

View file

@ -12,7 +12,7 @@ ENV VITE_RESTIC_VERSION=${RESTIC_VERSION} \
RUN apk update --no-cache && \ RUN apk update --no-cache && \
apk upgrade --no-cache && \ apk upgrade --no-cache && \
apk add --no-cache davfs2=1.6.1-r2 openssh-client fuse3 sshfs tini nfs-utils cifs-utils util-linux apk add --no-cache davfs2=1.6.1-r2 openssh-client fuse3 sshfs tini nfs-utils util-linux
ENTRYPOINT ["/sbin/tini", "-s", "--"] ENTRYPOINT ["/sbin/tini", "-s", "--"]

View file

@ -3,7 +3,12 @@
import { createSseClient } from "../core/serverSentEvents.gen"; import { createSseClient } from "../core/serverSentEvents.gen";
import type { HttpMethod } from "../core/types.gen"; import type { HttpMethod } from "../core/types.gen";
import { getValidRequestBody } from "../core/utils.gen"; import { getValidRequestBody } from "../core/utils.gen";
import type { Client, Config, RequestOptions, ResolvedRequestOptions } from "./types.gen"; import type {
Client,
Config,
RequestOptions,
ResolvedRequestOptions,
} from "./types.gen";
import { import {
buildUrl, buildUrl,
createConfig, createConfig,
@ -29,7 +34,12 @@ export const createClient = (config: Config = {}): Client => {
return getConfig(); return getConfig();
}; };
const interceptors = createInterceptors<Request, Response, unknown, ResolvedRequestOptions>(); const interceptors = createInterceptors<
Request,
Response,
unknown,
ResolvedRequestOptions
>();
const beforeRequest = async (options: RequestOptions) => { const beforeRequest = async (options: RequestOptions) => {
const opts = { const opts = {
@ -95,7 +105,12 @@ export const createClient = (config: Config = {}): Client => {
for (const fn of interceptors.error.fns) { for (const fn of interceptors.error.fns) {
if (fn) { if (fn) {
finalError = (await fn(error, undefined as any, request, opts)) as unknown; finalError = (await fn(
error,
undefined as any,
request,
opts,
)) as unknown;
} }
} }
@ -128,9 +143,14 @@ export const createClient = (config: Config = {}): Client => {
if (response.ok) { if (response.ok) {
const parseAs = const parseAs =
(opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json"; (opts.parseAs === "auto"
? getParseAs(response.headers.get("Content-Type"))
: opts.parseAs) ?? "json";
if (response.status === 204 || response.headers.get("Content-Length") === "0") { if (
response.status === 204 ||
response.headers.get("Content-Length") === "0"
) {
let emptyData: any; let emptyData: any;
switch (parseAs) { switch (parseAs) {
case "arrayBuffer": case "arrayBuffer":
@ -226,28 +246,34 @@ export const createClient = (config: Config = {}): Client => {
}; };
}; };
const makeMethodFn = (method: Uppercase<HttpMethod>) => (options: RequestOptions) => request({ ...options, method }); const makeMethodFn =
(method: Uppercase<HttpMethod>) => (options: RequestOptions) =>
request({ ...options, method });
const makeSseFn = (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => { const makeSseFn =
const { opts, url } = await beforeRequest(options); (method: Uppercase<HttpMethod>) => async (options: RequestOptions) => {
return createSseClient({ const { opts, url } = await beforeRequest(options);
...opts, return createSseClient({
body: opts.body as BodyInit | null | undefined, ...opts,
headers: opts.headers as unknown as Record<string, string>, body: opts.body as BodyInit | null | undefined,
method, headers: opts.headers as unknown as Record<string, string>,
onRequest: async (url, init) => { method,
let request = new Request(url, init); onRequest: async (url, init) => {
for (const fn of interceptors.request.fns) { let request = new Request(url, init);
if (fn) { for (const fn of interceptors.request.fns) {
request = await fn(request, opts); if (fn) {
request = await fn(request, opts);
}
} }
} return request;
return request; },
}, serializedBody: getValidRequestBody(opts) as
serializedBody: getValidRequestBody(opts) as BodyInit | null | undefined, | BodyInit
url, | null
}); | undefined,
}; url,
});
};
return { return {
buildUrl, buildUrl,

View file

@ -73,7 +73,7 @@ export type ListVolumesResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -100,7 +100,8 @@ export type ListVolumesResponses = {
}>; }>;
}; };
export type ListVolumesResponse = ListVolumesResponses[keyof ListVolumesResponses]; export type ListVolumesResponse =
ListVolumesResponses[keyof ListVolumesResponses];
export type CreateVolumeData = { export type CreateVolumeData = {
body?: { body?: {
@ -142,7 +143,7 @@ export type CreateVolumeData = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -208,7 +209,7 @@ export type CreateVolumeResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -235,7 +236,8 @@ export type CreateVolumeResponses = {
}; };
}; };
export type CreateVolumeResponse = CreateVolumeResponses[keyof CreateVolumeResponses]; export type CreateVolumeResponse =
CreateVolumeResponses[keyof CreateVolumeResponses];
export type TestConnectionData = { export type TestConnectionData = {
body?: { body?: {
@ -277,7 +279,7 @@ export type TestConnectionData = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -308,7 +310,8 @@ export type TestConnectionResponses = {
}; };
}; };
export type TestConnectionResponse = TestConnectionResponses[keyof TestConnectionResponses]; export type TestConnectionResponse =
TestConnectionResponses[keyof TestConnectionResponses];
export type DeleteVolumeData = { export type DeleteVolumeData = {
body?: never; body?: never;
@ -328,7 +331,8 @@ export type DeleteVolumeResponses = {
}; };
}; };
export type DeleteVolumeResponse = DeleteVolumeResponses[keyof DeleteVolumeResponses]; export type DeleteVolumeResponse =
DeleteVolumeResponses[keyof DeleteVolumeResponses];
export type GetVolumeData = { export type GetVolumeData = {
body?: never; body?: never;
@ -396,7 +400,7 @@ export type GetVolumeResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -467,7 +471,7 @@ export type UpdateVolumeData = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -542,7 +546,7 @@ export type UpdateVolumeResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -569,7 +573,8 @@ export type UpdateVolumeResponses = {
}; };
}; };
export type UpdateVolumeResponse = UpdateVolumeResponses[keyof UpdateVolumeResponses]; export type UpdateVolumeResponse =
UpdateVolumeResponses[keyof UpdateVolumeResponses];
export type MountVolumeData = { export type MountVolumeData = {
body?: never; body?: never;
@ -590,7 +595,8 @@ export type MountVolumeResponses = {
}; };
}; };
export type MountVolumeResponse = MountVolumeResponses[keyof MountVolumeResponses]; export type MountVolumeResponse =
MountVolumeResponses[keyof MountVolumeResponses];
export type UnmountVolumeData = { export type UnmountVolumeData = {
body?: never; body?: never;
@ -611,7 +617,8 @@ export type UnmountVolumeResponses = {
}; };
}; };
export type UnmountVolumeResponse = UnmountVolumeResponses[keyof UnmountVolumeResponses]; export type UnmountVolumeResponse =
UnmountVolumeResponses[keyof UnmountVolumeResponses];
export type HealthCheckVolumeData = { export type HealthCheckVolumeData = {
body?: never; body?: never;
@ -639,7 +646,8 @@ export type HealthCheckVolumeResponses = {
}; };
}; };
export type HealthCheckVolumeResponse = HealthCheckVolumeResponses[keyof HealthCheckVolumeResponses]; export type HealthCheckVolumeResponse =
HealthCheckVolumeResponses[keyof HealthCheckVolumeResponses];
export type ListFilesData = { export type ListFilesData = {
body?: never; body?: never;
@ -701,7 +709,8 @@ export type BrowseFilesystemResponses = {
}; };
}; };
export type BrowseFilesystemResponse = BrowseFilesystemResponses[keyof BrowseFilesystemResponses]; export type BrowseFilesystemResponse =
BrowseFilesystemResponses[keyof BrowseFilesystemResponses];
export type ListRepositoriesData = { export type ListRepositoriesData = {
body?: never; body?: never;
@ -815,7 +824,8 @@ export type ListRepositoriesResponses = {
}>; }>;
}; };
export type ListRepositoriesResponse = ListRepositoriesResponses[keyof ListRepositoriesResponses]; export type ListRepositoriesResponse =
ListRepositoriesResponses[keyof ListRepositoriesResponses];
export type CreateRepositoryData = { export type CreateRepositoryData = {
body?: { body?: {
@ -928,7 +938,8 @@ export type CreateRepositoryResponses = {
}; };
}; };
export type CreateRepositoryResponse = CreateRepositoryResponses[keyof CreateRepositoryResponses]; export type CreateRepositoryResponse =
CreateRepositoryResponses[keyof CreateRepositoryResponses];
export type ListRcloneRemotesData = { export type ListRcloneRemotesData = {
body?: never; body?: never;
@ -947,7 +958,8 @@ export type ListRcloneRemotesResponses = {
}>; }>;
}; };
export type ListRcloneRemotesResponse = ListRcloneRemotesResponses[keyof ListRcloneRemotesResponses]; export type ListRcloneRemotesResponse =
ListRcloneRemotesResponses[keyof ListRcloneRemotesResponses];
export type DeleteRepositoryData = { export type DeleteRepositoryData = {
body?: never; body?: never;
@ -967,7 +979,8 @@ export type DeleteRepositoryResponses = {
}; };
}; };
export type DeleteRepositoryResponse = DeleteRepositoryResponses[keyof DeleteRepositoryResponses]; export type DeleteRepositoryResponse =
DeleteRepositoryResponses[keyof DeleteRepositoryResponses];
export type GetRepositoryData = { export type GetRepositoryData = {
body?: never; body?: never;
@ -1083,7 +1096,8 @@ export type GetRepositoryResponses = {
}; };
}; };
export type GetRepositoryResponse = GetRepositoryResponses[keyof GetRepositoryResponses]; export type GetRepositoryResponse =
GetRepositoryResponses[keyof GetRepositoryResponses];
export type UpdateRepositoryData = { export type UpdateRepositoryData = {
body?: { body?: {
@ -1213,7 +1227,8 @@ export type UpdateRepositoryResponses = {
}; };
}; };
export type UpdateRepositoryResponse = UpdateRepositoryResponses[keyof UpdateRepositoryResponses]; export type UpdateRepositoryResponse =
UpdateRepositoryResponses[keyof UpdateRepositoryResponses];
export type DeleteSnapshotsData = { export type DeleteSnapshotsData = {
body?: { body?: {
@ -1235,7 +1250,8 @@ export type DeleteSnapshotsResponses = {
}; };
}; };
export type DeleteSnapshotsResponse = DeleteSnapshotsResponses[keyof DeleteSnapshotsResponses]; export type DeleteSnapshotsResponse =
DeleteSnapshotsResponses[keyof DeleteSnapshotsResponses];
export type ListSnapshotsData = { export type ListSnapshotsData = {
body?: never; body?: never;
@ -1262,7 +1278,8 @@ export type ListSnapshotsResponses = {
}>; }>;
}; };
export type ListSnapshotsResponse = ListSnapshotsResponses[keyof ListSnapshotsResponses]; export type ListSnapshotsResponse =
ListSnapshotsResponses[keyof ListSnapshotsResponses];
export type DeleteSnapshotData = { export type DeleteSnapshotData = {
body?: never; body?: never;
@ -1283,7 +1300,8 @@ export type DeleteSnapshotResponses = {
}; };
}; };
export type DeleteSnapshotResponse = DeleteSnapshotResponses[keyof DeleteSnapshotResponses]; export type DeleteSnapshotResponse =
DeleteSnapshotResponses[keyof DeleteSnapshotResponses];
export type GetSnapshotDetailsData = { export type GetSnapshotDetailsData = {
body?: never; body?: never;
@ -1309,7 +1327,8 @@ export type GetSnapshotDetailsResponses = {
}; };
}; };
export type GetSnapshotDetailsResponse = GetSnapshotDetailsResponses[keyof GetSnapshotDetailsResponses]; export type GetSnapshotDetailsResponse =
GetSnapshotDetailsResponses[keyof GetSnapshotDetailsResponses];
export type ListSnapshotFilesData = { export type ListSnapshotFilesData = {
body?: never; body?: never;
@ -1350,7 +1369,8 @@ export type ListSnapshotFilesResponses = {
}; };
}; };
export type ListSnapshotFilesResponse = ListSnapshotFilesResponses[keyof ListSnapshotFilesResponses]; export type ListSnapshotFilesResponse =
ListSnapshotFilesResponses[keyof ListSnapshotFilesResponses];
export type RestoreSnapshotData = { export type RestoreSnapshotData = {
body?: { body?: {
@ -1381,7 +1401,8 @@ export type RestoreSnapshotResponses = {
}; };
}; };
export type RestoreSnapshotResponse = RestoreSnapshotResponses[keyof RestoreSnapshotResponses]; export type RestoreSnapshotResponse =
RestoreSnapshotResponses[keyof RestoreSnapshotResponses];
export type DoctorRepositoryData = { export type DoctorRepositoryData = {
body?: never; body?: never;
@ -1407,7 +1428,8 @@ export type DoctorRepositoryResponses = {
}; };
}; };
export type DoctorRepositoryResponse = DoctorRepositoryResponses[keyof DoctorRepositoryResponses]; export type DoctorRepositoryResponse =
DoctorRepositoryResponses[keyof DoctorRepositoryResponses];
export type TagSnapshotsData = { export type TagSnapshotsData = {
body?: { body?: {
@ -1432,7 +1454,8 @@ export type TagSnapshotsResponses = {
}; };
}; };
export type TagSnapshotsResponse = TagSnapshotsResponses[keyof TagSnapshotsResponses]; export type TagSnapshotsResponse =
TagSnapshotsResponses[keyof TagSnapshotsResponses];
export type ListBackupSchedulesData = { export type ListBackupSchedulesData = {
body?: never; body?: never;
@ -1555,7 +1578,15 @@ export type ListBackupSchedulesResponses = {
name: string; name: string;
shortId: string; shortId: string;
status: "error" | "healthy" | "unknown" | null; status: "error" | "healthy" | "unknown" | null;
type: "azure" | "gcs" | "local" | "r2" | "rclone" | "rest" | "s3" | "sftp"; type:
| "azure"
| "gcs"
| "local"
| "r2"
| "rclone"
| "rest"
| "s3"
| "sftp";
updatedAt: number; updatedAt: number;
}; };
repositoryId: string; repositoryId: string;
@ -1610,7 +1641,7 @@ export type ListBackupSchedulesResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -1639,7 +1670,8 @@ export type ListBackupSchedulesResponses = {
}>; }>;
}; };
export type ListBackupSchedulesResponse = ListBackupSchedulesResponses[keyof ListBackupSchedulesResponses]; export type ListBackupSchedulesResponse =
ListBackupSchedulesResponses[keyof ListBackupSchedulesResponses];
export type CreateBackupScheduleData = { export type CreateBackupScheduleData = {
body?: { body?: {
@ -1702,7 +1734,8 @@ export type CreateBackupScheduleResponses = {
}; };
}; };
export type CreateBackupScheduleResponse = CreateBackupScheduleResponses[keyof CreateBackupScheduleResponses]; export type CreateBackupScheduleResponse =
CreateBackupScheduleResponses[keyof CreateBackupScheduleResponses];
export type DeleteBackupScheduleData = { export type DeleteBackupScheduleData = {
body?: never; body?: never;
@ -1722,7 +1755,8 @@ export type DeleteBackupScheduleResponses = {
}; };
}; };
export type DeleteBackupScheduleResponse = DeleteBackupScheduleResponses[keyof DeleteBackupScheduleResponses]; export type DeleteBackupScheduleResponse =
DeleteBackupScheduleResponses[keyof DeleteBackupScheduleResponses];
export type GetBackupScheduleData = { export type GetBackupScheduleData = {
body?: never; body?: never;
@ -1847,7 +1881,15 @@ export type GetBackupScheduleResponses = {
name: string; name: string;
shortId: string; shortId: string;
status: "error" | "healthy" | "unknown" | null; status: "error" | "healthy" | "unknown" | null;
type: "azure" | "gcs" | "local" | "r2" | "rclone" | "rest" | "s3" | "sftp"; type:
| "azure"
| "gcs"
| "local"
| "r2"
| "rclone"
| "rest"
| "s3"
| "sftp";
updatedAt: number; updatedAt: number;
}; };
repositoryId: string; repositoryId: string;
@ -1902,7 +1944,7 @@ export type GetBackupScheduleResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -1931,7 +1973,8 @@ export type GetBackupScheduleResponses = {
}; };
}; };
export type GetBackupScheduleResponse = GetBackupScheduleResponses[keyof GetBackupScheduleResponses]; export type GetBackupScheduleResponse =
GetBackupScheduleResponses[keyof GetBackupScheduleResponses];
export type UpdateBackupScheduleData = { export type UpdateBackupScheduleData = {
body?: { body?: {
@ -1995,7 +2038,8 @@ export type UpdateBackupScheduleResponses = {
}; };
}; };
export type UpdateBackupScheduleResponse = UpdateBackupScheduleResponses[keyof UpdateBackupScheduleResponses]; export type UpdateBackupScheduleResponse =
UpdateBackupScheduleResponses[keyof UpdateBackupScheduleResponses];
export type GetBackupScheduleForVolumeData = { export type GetBackupScheduleForVolumeData = {
body?: never; body?: never;
@ -2120,7 +2164,15 @@ export type GetBackupScheduleForVolumeResponses = {
name: string; name: string;
shortId: string; shortId: string;
status: "error" | "healthy" | "unknown" | null; status: "error" | "healthy" | "unknown" | null;
type: "azure" | "gcs" | "local" | "r2" | "rclone" | "rest" | "s3" | "sftp"; type:
| "azure"
| "gcs"
| "local"
| "r2"
| "rclone"
| "rest"
| "s3"
| "sftp";
updatedAt: number; updatedAt: number;
}; };
repositoryId: string; repositoryId: string;
@ -2175,7 +2227,7 @@ export type GetBackupScheduleForVolumeResponses = {
server: string; server: string;
share: string; share: string;
username: string; username: string;
vers?: "1.0" | "2.0" | "2.1" | "3.0" | "auto"; vers?: "1.0" | "2.0" | "2.1" | "3.0";
port?: number; port?: number;
domain?: string; domain?: string;
readOnly?: boolean; readOnly?: boolean;
@ -2225,7 +2277,8 @@ export type RunBackupNowResponses = {
}; };
}; };
export type RunBackupNowResponse = RunBackupNowResponses[keyof RunBackupNowResponses]; export type RunBackupNowResponse =
RunBackupNowResponses[keyof RunBackupNowResponses];
export type StopBackupData = { export type StopBackupData = {
body?: never; body?: never;
@ -2361,7 +2414,16 @@ export type GetScheduleNotificationsResponses = {
enabled: boolean; enabled: boolean;
id: number; id: number;
name: string; name: string;
type: "custom" | "discord" | "email" | "generic" | "gotify" | "ntfy" | "pushover" | "slack" | "telegram"; type:
| "custom"
| "discord"
| "email"
| "generic"
| "gotify"
| "ntfy"
| "pushover"
| "slack"
| "telegram";
updatedAt: number; updatedAt: number;
}; };
destinationId: number; destinationId: number;
@ -2471,7 +2533,16 @@ export type UpdateScheduleNotificationsResponses = {
enabled: boolean; enabled: boolean;
id: number; id: number;
name: string; name: string;
type: "custom" | "discord" | "email" | "generic" | "gotify" | "ntfy" | "pushover" | "slack" | "telegram"; type:
| "custom"
| "discord"
| "email"
| "generic"
| "gotify"
| "ntfy"
| "pushover"
| "slack"
| "telegram";
updatedAt: number; updatedAt: number;
}; };
destinationId: number; destinationId: number;
@ -2601,7 +2672,15 @@ export type GetScheduleMirrorsResponses = {
name: string; name: string;
shortId: string; shortId: string;
status: "error" | "healthy" | "unknown" | null; status: "error" | "healthy" | "unknown" | null;
type: "azure" | "gcs" | "local" | "r2" | "rclone" | "rest" | "s3" | "sftp"; type:
| "azure"
| "gcs"
| "local"
| "r2"
| "rclone"
| "rest"
| "s3"
| "sftp";
updatedAt: number; updatedAt: number;
}; };
repositoryId: string; repositoryId: string;
@ -2609,7 +2688,8 @@ export type GetScheduleMirrorsResponses = {
}>; }>;
}; };
export type GetScheduleMirrorsResponse = GetScheduleMirrorsResponses[keyof GetScheduleMirrorsResponses]; export type GetScheduleMirrorsResponse =
GetScheduleMirrorsResponses[keyof GetScheduleMirrorsResponses];
export type UpdateScheduleMirrorsData = { export type UpdateScheduleMirrorsData = {
body?: { body?: {
@ -2731,7 +2811,15 @@ export type UpdateScheduleMirrorsResponses = {
name: string; name: string;
shortId: string; shortId: string;
status: "error" | "healthy" | "unknown" | null; status: "error" | "healthy" | "unknown" | null;
type: "azure" | "gcs" | "local" | "r2" | "rclone" | "rest" | "s3" | "sftp"; type:
| "azure"
| "gcs"
| "local"
| "r2"
| "rclone"
| "rest"
| "s3"
| "sftp";
updatedAt: number; updatedAt: number;
}; };
repositoryId: string; repositoryId: string;
@ -2739,7 +2827,8 @@ export type UpdateScheduleMirrorsResponses = {
}>; }>;
}; };
export type UpdateScheduleMirrorsResponse = UpdateScheduleMirrorsResponses[keyof UpdateScheduleMirrorsResponses]; export type UpdateScheduleMirrorsResponse =
UpdateScheduleMirrorsResponses[keyof UpdateScheduleMirrorsResponses];
export type GetMirrorCompatibilityData = { export type GetMirrorCompatibilityData = {
body?: never; body?: never;
@ -2761,7 +2850,8 @@ export type GetMirrorCompatibilityResponses = {
}>; }>;
}; };
export type GetMirrorCompatibilityResponse = GetMirrorCompatibilityResponses[keyof GetMirrorCompatibilityResponses]; export type GetMirrorCompatibilityResponse =
GetMirrorCompatibilityResponses[keyof GetMirrorCompatibilityResponses];
export type ReorderBackupSchedulesData = { export type ReorderBackupSchedulesData = {
body?: { body?: {
@ -2781,7 +2871,8 @@ export type ReorderBackupSchedulesResponses = {
}; };
}; };
export type ReorderBackupSchedulesResponse = ReorderBackupSchedulesResponses[keyof ReorderBackupSchedulesResponses]; export type ReorderBackupSchedulesResponse =
ReorderBackupSchedulesResponses[keyof ReorderBackupSchedulesResponses];
export type ListNotificationDestinationsData = { export type ListNotificationDestinationsData = {
body?: never; body?: never;
@ -2866,7 +2957,16 @@ export type ListNotificationDestinationsResponses = {
enabled: boolean; enabled: boolean;
id: number; id: number;
name: string; name: string;
type: "custom" | "discord" | "email" | "generic" | "gotify" | "ntfy" | "pushover" | "slack" | "telegram"; type:
| "custom"
| "discord"
| "email"
| "generic"
| "gotify"
| "ntfy"
| "pushover"
| "slack"
| "telegram";
updatedAt: number; updatedAt: number;
}>; }>;
}; };
@ -3026,7 +3126,16 @@ export type CreateNotificationDestinationResponses = {
enabled: boolean; enabled: boolean;
id: number; id: number;
name: string; name: string;
type: "custom" | "discord" | "email" | "generic" | "gotify" | "ntfy" | "pushover" | "slack" | "telegram"; type:
| "custom"
| "discord"
| "email"
| "generic"
| "gotify"
| "ntfy"
| "pushover"
| "slack"
| "telegram";
updatedAt: number; updatedAt: number;
}; };
}; };
@ -3154,7 +3263,16 @@ export type GetNotificationDestinationResponses = {
enabled: boolean; enabled: boolean;
id: number; id: number;
name: string; name: string;
type: "custom" | "discord" | "email" | "generic" | "gotify" | "ntfy" | "pushover" | "slack" | "telegram"; type:
| "custom"
| "discord"
| "email"
| "generic"
| "gotify"
| "ntfy"
| "pushover"
| "slack"
| "telegram";
updatedAt: number; updatedAt: number;
}; };
}; };
@ -3324,7 +3442,16 @@ export type UpdateNotificationDestinationResponses = {
enabled: boolean; enabled: boolean;
id: number; id: number;
name: string; name: string;
type: "custom" | "discord" | "email" | "generic" | "gotify" | "ntfy" | "pushover" | "slack" | "telegram"; type:
| "custom"
| "discord"
| "email"
| "generic"
| "gotify"
| "ntfy"
| "pushover"
| "slack"
| "telegram";
updatedAt: number; updatedAt: number;
}; };
}; };
@ -3387,7 +3514,8 @@ export type GetSystemInfoResponses = {
}; };
}; };
export type GetSystemInfoResponse = GetSystemInfoResponses[keyof GetSystemInfoResponses]; export type GetSystemInfoResponse =
GetSystemInfoResponses[keyof GetSystemInfoResponses];
export type GetUpdatesData = { export type GetUpdatesData = {
body?: never; body?: never;
@ -3431,4 +3559,5 @@ export type DownloadResticPasswordResponses = {
200: string; 200: string;
}; };
export type DownloadResticPasswordResponse = DownloadResticPasswordResponses[keyof DownloadResticPasswordResponses]; export type DownloadResticPasswordResponse =
DownloadResticPasswordResponses[keyof DownloadResticPasswordResponses];

View file

@ -26,7 +26,7 @@ export const smbConfigSchema = type({
share: "string", share: "string",
username: "string", username: "string",
password: "string", password: "string",
vers: type("'1.0' | '2.0' | '2.1' | '3.0' | 'auto'").default("auto"), vers: type("'1.0' | '2.0' | '2.1' | '3.0'").default("3.0"),
domain: "string?", domain: "string?",
port: type("string.integer").or(type("number")).to("1 <= number <= 65535").default(445), port: type("string.integer").or(type("number")).to("1 <= number <= 65535").default(445),
readOnly: "boolean?", readOnly: "boolean?",

View file

@ -40,11 +40,14 @@ const mount = async (config: BackendConfig, path: string) => {
const source = `//${config.server}/${config.share}`; const source = `//${config.server}/${config.share}`;
const { uid, gid } = os.userInfo(); const { uid, gid } = os.userInfo();
const options = [`user=${config.username}`, `pass=${password}`, `port=${config.port}`, `uid=${uid}`, `gid=${gid}`]; const options = [
`user=${config.username}`,
if (config.vers && config.vers !== "auto") { `pass=${password}`,
options.push(`vers=${config.vers}`); `vers=${config.vers}`,
} `port=${config.port}`,
`uid=${uid}`,
`gid=${gid}`,
];
if (config.domain) { if (config.domain) {
options.push(`domain=${config.domain}`); options.push(`domain=${config.domain}`);
@ -59,13 +62,7 @@ const mount = async (config: BackendConfig, path: string) => {
logger.debug(`Mounting SMB volume ${path}...`); logger.debug(`Mounting SMB volume ${path}...`);
logger.info(`Executing mount: mount ${args.join(" ")}`); logger.info(`Executing mount: mount ${args.join(" ")}`);
try { await executeMount(args);
await executeMount(args);
} catch (error) {
logger.warn(`Initial SMB mount failed, retrying with -i flag: ${toMessage(error)}`);
// Fallback with -i flag if the first mount fails using the mount helper
await executeMount(["-i", ...args]);
}
logger.info(`SMB volume at ${path} mounted successfully.`); logger.info(`SMB volume at ${path} mounted successfully.`);
return { status: BACKEND_STATUS.mounted }; return { status: BACKEND_STATUS.mounted };