changed to incubator

added new install script
updated security
updated ETA
This commit is contained in:
Philipp
2026-06-04 17:19:46 +02:00
parent 507945fd87
commit 568c90f06d
10 changed files with 125 additions and 40 deletions
+1
View File
@@ -7,6 +7,7 @@ RESTIC_KEEP_HOURLY=0
RESTIC_KEEP_DAILY=7
RESTIC_KEEP_WEEKLY=0
RESTIC_KEEP_MONTHLY=0
RESTIC_RETRY_LOCK="5m"
HOST="0.0.0.0"
PORT=3000
API_TOKEN="change-me-to-at-least-32-characters"
+3
View File
@@ -34,6 +34,7 @@ export const config = {
RESTIC_REPOSITORY: process.env.RESTIC_REPOSITORY || '',
RESTIC_PASSWORD: process.env.RESTIC_PASSWORD || '',
},
resticRetryLock: process.env.RESTIC_RETRY_LOCK || '5m',
retention: {
keepHourly: Number(process.env.RESTIC_KEEP_HOURLY || 0),
keepDaily: Number(process.env.RESTIC_KEEP_DAILY || 7),
@@ -60,6 +61,7 @@ export const editableEnv = [
{ key: 'RESTIC_KEEP_DAILY', label: 'Keep daily snapshots', required: false, secret: false },
{ key: 'RESTIC_KEEP_WEEKLY', label: 'Keep weekly snapshots', required: false, secret: false },
{ key: 'RESTIC_KEEP_MONTHLY', label: 'Keep monthly snapshots', required: false, secret: false },
{ key: 'RESTIC_RETRY_LOCK', label: 'Restic lock retry duration', required: false, secret: false },
{ key: 'PORT', label: 'API port', required: false, secret: false },
{ key: 'HOST', label: 'API bind host', required: false, secret: false },
{ key: 'API_TOKEN', label: 'API token', required: true, secret: true },
@@ -161,6 +163,7 @@ function applyRuntimeEnv(values) {
config.resticEnv.AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY || '';
config.resticEnv.RESTIC_REPOSITORY = process.env.RESTIC_REPOSITORY || '';
config.resticEnv.RESTIC_PASSWORD = process.env.RESTIC_PASSWORD || '';
config.resticRetryLock = process.env.RESTIC_RETRY_LOCK || '5m';
config.retention.keepHourly = Number(process.env.RESTIC_KEEP_HOURLY || 0);
config.retention.keepDaily = Number(process.env.RESTIC_KEEP_DAILY || 7);
config.retention.keepWeekly = Number(process.env.RESTIC_KEEP_WEEKLY || 0);
+9 -3
View File
@@ -1,6 +1,6 @@
import { spawn } from 'node:child_process';
import { PassThrough, Transform } from 'node:stream';
import { resticProcessEnv } from './config.js';
import { config, resticProcessEnv } from './config.js';
export class CommandError extends Error {
constructor(message, result) {
@@ -68,14 +68,14 @@ export function spawnCommand(command, args = [], options = {}) {
}
export function runRestic(args, options = {}) {
return spawnCommand('restic', args, {
return spawnCommand('restic', resticArgs(args, options), {
...options,
env: resticProcessEnv(),
});
}
export async function resticSnapshotFileSize(snapshotId, filename) {
const result = await runRestic(['ls', '--json', snapshotId]);
const result = await runRestic(['--no-lock', 'ls', '--json', snapshotId], { retryLock: false });
const wanted = `/${filename}`;
for (const line of result.stdout.split('\n')) {
if (!line.trim()) continue;
@@ -89,6 +89,12 @@ export async function resticSnapshotFileSize(snapshotId, filename) {
throw error;
}
export function resticArgs(args, options = {}) {
if (options.retryLock === false || !config.resticRetryLock) return args;
if (args.includes('--no-lock') || args.includes('--retry-lock')) return args;
return ['--retry-lock', config.resticRetryLock, ...args];
}
export function createProgressStream(totalBytes, onProgress) {
let currentBytes = 0;
return new Transform({
+3 -3
View File
@@ -6,7 +6,7 @@ import path from 'node:path';
import { finished } from 'node:stream/promises';
import { setTimeout as delay } from 'node:timers/promises';
import { config } from '../config.js';
import { createProgressStream, resticSnapshotFileSize, spawnCommand, runRestic } from '../executor.js';
import { createProgressStream, resticArgs, resticSnapshotFileSize, spawnCommand, runRestic } from '../executor.js';
import { appendJobLog, createJob, finishJob, setJobProgress, setJobRunning, setJobStep } from '../jobs.js';
import { validateVmExists } from '../validators.js';
@@ -70,7 +70,7 @@ export async function runBackupJob(job, instance = null) {
});
});
try {
const result = await spawnCommand('restic', ['backup', '--stdin', '--stdin-filename', `${job.vmName}.raw`, '--tag', job.vmName, '--tag', 'data', '--tag', 'virtual-machine'], {
const result = await spawnCommand('restic', resticArgs(['backup', '--stdin', '--stdin-filename', `${job.vmName}.raw`, '--tag', job.vmName, '--tag', 'data', '--tag', 'virtual-machine']), {
env: { ...process.env, ...config.resticEnv },
input: snapshotStream.pipe(progressStream),
log: (line) => appendJobLog(job, line),
@@ -140,7 +140,7 @@ async function runContainerBackupJob(job) {
});
let resticOk = false;
try {
const result = await spawnCommand('restic', ['backup', '--stdin', '--stdin-filename', `${job.vmName}.zfs`, '--tag', job.vmName, '--tag', 'data', '--tag', 'container'], {
const result = await spawnCommand('restic', resticArgs(['backup', '--stdin', '--stdin-filename', `${job.vmName}.zfs`, '--tag', job.vmName, '--tag', 'data', '--tag', 'container']), {
env: { ...process.env, ...config.resticEnv },
input: zfs.stdout.pipe(progressStream),
log: (line) => appendJobLog(job, line),