Compare commits

..

1 Commits

Author SHA1 Message Date
Nicolas Meienberger
bf33b15b3e fix: cleanup volumes on shutdown 2025-11-10 07:08:51 +01:00
3 changed files with 46 additions and 4 deletions

View File

@@ -3,3 +3,4 @@ export const VOLUME_MOUNT_BASE = "/var/lib/ironmount/volumes";
export const REPOSITORY_BASE = "/var/lib/ironmount/repositories"; export const REPOSITORY_BASE = "/var/lib/ironmount/repositories";
export const DATABASE_URL = "/var/lib/ironmount/data/ironmount.db"; export const DATABASE_URL = "/var/lib/ironmount/data/ironmount.db";
export const RESTIC_PASS_FILE = "/var/lib/ironmount/data/restic.pass"; export const RESTIC_PASS_FILE = "/var/lib/ironmount/data/restic.pass";
export const SOCKET_PATH = "/run/docker/plugins/ironmount.sock";

View File

@@ -17,6 +17,8 @@ import { backupScheduleController } from "./modules/backups/backups.controller";
import { eventsController } from "./modules/events/events.controller"; import { eventsController } from "./modules/events/events.controller";
import { handleServiceError } from "./utils/errors"; import { handleServiceError } from "./utils/errors";
import { logger } from "./utils/logger"; import { logger } from "./utils/logger";
import { shutdown } from "./modules/lifecycle/shutdown";
import { SOCKET_PATH } from "./core/constants";
export const generalDescriptor = (app: Hono) => export const generalDescriptor = (app: Hono) =>
openAPIRouteHandler(app, { openAPIRouteHandler(app, {
@@ -70,17 +72,15 @@ runDbMigrations();
const { docker } = await getCapabilities(); const { docker } = await getCapabilities();
if (docker) { if (docker) {
const socketPath = "/run/docker/plugins/ironmount.sock";
try { try {
await fs.mkdir("/run/docker/plugins", { recursive: true }); await fs.mkdir("/run/docker/plugins", { recursive: true });
Bun.serve({ Bun.serve({
unix: socketPath, unix: SOCKET_PATH,
fetch: driver.fetch, fetch: driver.fetch,
}); });
logger.info(`Docker volume plugin server running at ${socketPath}`); logger.info(`Docker volume plugin server running at ${SOCKET_PATH}`);
} catch (error) { } catch (error) {
logger.error(`Failed to start Docker volume plugin server: ${error}`); logger.error(`Failed to start Docker volume plugin server: ${error}`);
} }
@@ -96,3 +96,16 @@ startup();
logger.info(`Server is running at http://localhost:4096`); logger.info(`Server is running at http://localhost:4096`);
export type AppType = typeof app; export type AppType = typeof app;
process.on("SIGTERM", async () => {
logger.info("SIGTERM received, starting graceful shutdown...");
await shutdown();
process.exit(0);
});
process.on("SIGINT", async () => {
logger.info("SIGINT received, starting graceful shutdown...");
await shutdown();
process.exit(0);
});

View File

@@ -0,0 +1,28 @@
import { Scheduler } from "../../core/scheduler";
import { eq, or } from "drizzle-orm";
import { db } from "../../db/db";
import { volumesTable } from "../../db/schema";
import { logger } from "../../utils/logger";
import { SOCKET_PATH } from "../../core/constants";
import { createVolumeBackend } from "../backends/backend";
export const shutdown = async () => {
await Scheduler.stop();
await Bun.file(SOCKET_PATH)
.delete()
.catch(() => {
// Ignore errors if the socket file does not exist
});
const volumes = await db.query.volumesTable.findMany({
where: or(eq(volumesTable.status, "mounted")),
});
for (const volume of volumes) {
const backend = createVolumeBackend(volume);
const { status, error } = await backend.unmount();
logger.info(`Volume ${volume.name} unmount status: ${status}${error ? `, error: ${error}` : ""}`);
}
};