- Passwort-Reset
cd management
npm run reset-password -- admin "neues-passwort"
- Agent-Hardening
backend/.env unterstützt jetzt:
ALLOWED_MANAGEMENT_IPS="127.0.0.1,DEINE-MANAGEMENT-IP"
Wenn gesetzt, akzeptiert der Agent nur Requests von diesen IPs.
- Audit-Log
Management speichert Aktionen wie Login, Logout, Node-Änderungen, Schedule-Updates, Backup/Restore, Settings-Änderungen.
- Job-History
Management speichert gestartete Backup/Restore/Scheduler-Jobs mit Node, VM, Typ, Agent-Job-ID und Status.
- Operations-Seite
Neue UI-Seite Operations mit:
- Job History
- Audit Log
- systemd Templates
deploy/systemd/incus-backup-agent.service
deploy/systemd/incus-backup-management.service
- Deployment-Doku
docs/deployment.md
This commit is contained in:
@@ -9,3 +9,4 @@ RESTIC_KEEP_WEEKLY=0
|
||||
RESTIC_KEEP_MONTHLY=0
|
||||
PORT=3000
|
||||
API_TOKEN=""
|
||||
ALLOWED_MANAGEMENT_IPS=""
|
||||
|
||||
@@ -17,6 +17,10 @@ export const requiredEnv = [
|
||||
export const config = {
|
||||
port: Number(process.env.PORT || 3000),
|
||||
apiToken: process.env.API_TOKEN || '',
|
||||
allowedManagementIps: (process.env.ALLOWED_MANAGEMENT_IPS || '')
|
||||
.split(',')
|
||||
.map((value) => value.trim())
|
||||
.filter(Boolean),
|
||||
zfsPoolName: process.env.ZFS_POOL_NAME || '',
|
||||
resticEnv: {
|
||||
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID || '',
|
||||
@@ -44,6 +48,7 @@ export const editableEnv = [
|
||||
{ key: 'RESTIC_KEEP_MONTHLY', label: 'Keep monthly snapshots', required: false, secret: false },
|
||||
{ key: 'PORT', label: 'API port', required: false, secret: false },
|
||||
{ key: 'API_TOKEN', label: 'API token', required: false, secret: true },
|
||||
{ key: 'ALLOWED_MANAGEMENT_IPS', label: 'Allowed management IPs', required: false, secret: false },
|
||||
];
|
||||
|
||||
export function missingEnvVars() {
|
||||
@@ -108,6 +113,10 @@ function applyRuntimeEnv(values) {
|
||||
}
|
||||
config.port = Number(process.env.PORT || 3000);
|
||||
config.apiToken = process.env.API_TOKEN || '';
|
||||
config.allowedManagementIps = (process.env.ALLOWED_MANAGEMENT_IPS || '')
|
||||
.split(',')
|
||||
.map((value) => value.trim())
|
||||
.filter(Boolean);
|
||||
config.zfsPoolName = process.env.ZFS_POOL_NAME || '';
|
||||
config.resticEnv.AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID || '';
|
||||
config.resticEnv.AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY || '';
|
||||
|
||||
@@ -17,6 +17,10 @@ app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
app.use((req, res, next) => {
|
||||
if (config.allowedManagementIps.length && !config.allowedManagementIps.includes(normalizeIp(req.ip))) {
|
||||
res.status(403).json({ error: 'Forbidden management source.' });
|
||||
return;
|
||||
}
|
||||
if (!config.apiToken) {
|
||||
next();
|
||||
return;
|
||||
@@ -29,6 +33,10 @@ app.use((req, res, next) => {
|
||||
res.status(401).json({ error: 'Unauthorized.' });
|
||||
});
|
||||
|
||||
function normalizeIp(value) {
|
||||
return String(value || '').replace(/^::ffff:/, '');
|
||||
}
|
||||
|
||||
app.use('/api/health', healthRouter);
|
||||
app.use('/api/vms', vmsRouter);
|
||||
app.use('/api/snapshots', snapshotsRouter);
|
||||
|
||||
Reference in New Issue
Block a user