Enterprise-Backup-, Recovery-, Verification-, Security- und Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme. Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes geht in keine Bewertung als "gut" ein. Umfang (Phasen 0-23): - Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll, Katalogaufbau allein aus den Manifesten — ohne Datenbank - Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck - Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell) - Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive - Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit - Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center, Ransomware-Heuristik (meldet, handelt nie) - Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing - Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository - Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64 Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs. Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md und docs/release-candidate.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
229 lines
8.8 KiB
Makefile
229 lines
8.8 KiB
Makefile
# Makefile für die Entwicklung an Syncova.
|
||
#
|
||
# Überblick über alle Ziele: make help
|
||
|
||
SHELL := /bin/bash
|
||
|
||
# Verzeichnis für gebaute Binaries.
|
||
BIN_DIR := bin
|
||
|
||
# Compose-Datei der lokalen Entwicklungsumgebung.
|
||
COMPOSE_FILE := deployment/docker-compose.yml
|
||
|
||
# Datei mit der lokalen Konfiguration. Sie wird von "make dev-env" erzeugt.
|
||
ENV_FILE := .env
|
||
|
||
# Version, die in die Binaries eingebrannt wird.
|
||
# Ohne Git-Tag wird der Kurz-Hash des Commits verwendet.
|
||
BUILD_VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "0.1.0-dev")
|
||
|
||
# Linker-Flags setzen die Version zur Bauzeit.
|
||
GO_LDFLAGS := -X main.buildVersion=$(BUILD_VERSION)
|
||
|
||
# Zu prüfende Go-Pakete.
|
||
#
|
||
# node_modules wird ausgeschlossen: einzelne NPM-Pakete bringen eigenen Go-Code
|
||
# mit, der sonst in Tests, Lint und Schwachstellenprüfung auftauchen würde.
|
||
GO_PACKAGES := $(shell go list ./... 2>/dev/null | grep -v '/node_modules/')
|
||
|
||
# Verzeichnisse mit eigenem Go-Quelltext (für gofmt, das keine Paketpfade kennt).
|
||
GO_SOURCE_DIRS := apps/api apps/agent packages migrations
|
||
|
||
# Alle Rezepte laufen mit den Variablen aus der .env, sofern vorhanden.
|
||
ifneq (,$(wildcard $(ENV_FILE)))
|
||
include $(ENV_FILE)
|
||
export
|
||
endif
|
||
|
||
.DEFAULT_GOAL := help
|
||
|
||
.PHONY: help
|
||
help: ## Zeigt diese Übersicht
|
||
@echo "Syncova – verfügbare Ziele:"
|
||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}'
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Entwicklungsumgebung
|
||
# ---------------------------------------------------------------------------
|
||
|
||
.PHONY: dev-env
|
||
dev-env: ## Erzeugt .env mit einem zufälligen Datenbankpasswort
|
||
@if [ -f $(ENV_FILE) ]; then \
|
||
echo "$(ENV_FILE) existiert bereits – es wird nicht überschrieben."; \
|
||
exit 0; \
|
||
fi
|
||
@cp .env.example $(ENV_FILE)
|
||
@# Das Passwort wird lokal zufällig erzeugt, damit es nirgends eingecheckt ist.
|
||
@GENERATED_PASSWORD="$$(openssl rand -base64 24 | tr -d '/+=' | head -c 32)"; \ # secretscan:erlaubt: erfundener Testwert
|
||
sed -i.bak "s|^SYNCOVA_DB_PASSWORD=.*|SYNCOVA_DB_PASSWORD=$$GENERATED_PASSWORD|" $(ENV_FILE); \
|
||
rm -f $(ENV_FILE).bak
|
||
@# Ohne Verschlüsselungsschlüssel startet kein Dienst; er wird deshalb
|
||
@# gleich miterzeugt. openssl liefert genau die geforderten 32 Byte.
|
||
@GENERATED_KEY="$$(openssl rand -base64 32)"; \
|
||
sed -i.bak "s|^SYNCOVA_ENCRYPTION_KEYS=.*|SYNCOVA_ENCRYPTION_KEYS=v1:$$GENERATED_KEY|" $(ENV_FILE); \
|
||
rm -f $(ENV_FILE).bak
|
||
@chmod 600 $(ENV_FILE)
|
||
@echo "$(ENV_FILE) wurde mit zufälligem Datenbankpasswort und Verschlüsselungsschlüssel erzeugt."
|
||
|
||
.PHONY: dev-up
|
||
dev-up: require-env ## Startet PostgreSQL und wartet auf Betriebsbereitschaft
|
||
@docker compose --env-file $(ENV_FILE) -f $(COMPOSE_FILE) up -d --wait
|
||
@echo "PostgreSQL ist bereit."
|
||
|
||
.PHONY: dev-down
|
||
dev-down: ## Stoppt die lokale Umgebung (Daten bleiben erhalten)
|
||
@docker compose -f $(COMPOSE_FILE) down
|
||
|
||
.PHONY: dev-reset
|
||
dev-reset: ## Stoppt die Umgebung und LÖSCHT alle lokalen Datenbankdaten
|
||
@echo "Achtung: Dieser Schritt löscht das lokale Datenbank-Volume."
|
||
@read -p "Fortfahren? [j/N] " CONFIRMATION; \
|
||
if [ "$$CONFIRMATION" = "j" ] || [ "$$CONFIRMATION" = "J" ]; then \
|
||
docker compose -f $(COMPOSE_FILE) down --volumes; \
|
||
echo "Lokale Datenbankdaten wurden gelöscht."; \
|
||
else \
|
||
echo "Abgebrochen."; \
|
||
fi
|
||
|
||
.PHONY: require-env
|
||
require-env: ## Prüft, ob die lokale Konfiguration vorhanden ist
|
||
@if [ ! -f $(ENV_FILE) ]; then \
|
||
echo "Es fehlt die Datei $(ENV_FILE). Bitte zuerst 'make dev-env' ausführen."; \
|
||
exit 1; \
|
||
fi
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Backend
|
||
# ---------------------------------------------------------------------------
|
||
|
||
.PHONY: build
|
||
build: ## Baut alle Go-Binaries nach ./bin
|
||
@mkdir -p $(BIN_DIR)
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-api ./apps/api/cmd/syncova-api
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-migrate ./apps/api/cmd/syncova-migrate
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-admin ./apps/api/cmd/syncova-admin
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-repo ./apps/api/cmd/syncova-repo
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-dr ./apps/api/cmd/syncova-dr
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-bench ./apps/api/cmd/syncova-bench
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-agent ./apps/agent/cmd/syncova-agent
|
||
@go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-proxmox ./apps/api/cmd/syncova-proxmox
|
||
@echo "Binaries gebaut (Version $(BUILD_VERSION))."
|
||
|
||
.PHONY: run-api
|
||
run-api: require-env ## Startet den API-Dienst lokal
|
||
@go run -ldflags "$(GO_LDFLAGS)" ./apps/api/cmd/syncova-api
|
||
|
||
.PHONY: migrate-up
|
||
migrate-up: require-env ## Wendet alle ausstehenden Datenbankmigrationen an
|
||
@go run ./apps/api/cmd/syncova-migrate up
|
||
|
||
.PHONY: migrate-status
|
||
migrate-status: require-env ## Zeigt den aktuellen Migrationsstand
|
||
@go run ./apps/api/cmd/syncova-migrate status
|
||
|
||
.PHONY: migrate-down
|
||
migrate-down: require-env ## Nimmt genau eine Migration zurück
|
||
@go run ./apps/api/cmd/syncova-migrate down
|
||
|
||
.PHONY: test
|
||
test: ## Führt alle Go-Tests mit Race-Detector aus
|
||
@go test -race $(GO_PACKAGES)
|
||
|
||
.PHONY: test-coverage
|
||
test-coverage: ## Führt die Go-Tests aus und schreibt einen Coverage-Bericht
|
||
@go test -race -coverprofile=coverage.out $(GO_PACKAGES)
|
||
@go tool cover -func=coverage.out | tail -1
|
||
|
||
.PHONY: lint
|
||
lint: ## Prüft Formatierung und statische Analyse des Go-Codes
|
||
@echo "==> gofmt"
|
||
@UNFORMATTED_FILES="$$(gofmt -l $(GO_SOURCE_DIRS))"; \
|
||
if [ -n "$$UNFORMATTED_FILES" ]; then \
|
||
echo "Nicht formatierte Dateien gefunden:"; echo "$$UNFORMATTED_FILES"; exit 1; \
|
||
fi
|
||
@echo "==> go vet"
|
||
@go vet $(GO_PACKAGES)
|
||
@echo "==> staticcheck"
|
||
@go run honnef.co/go/tools/cmd/staticcheck@latest $(GO_PACKAGES)
|
||
|
||
# Die Sicherheitsprüfungen laufen getrennt vom Lint, weil sie das Netz brauchen:
|
||
# govulncheck gleicht gegen die Schwachstellendatenbank von Go ab. In einer
|
||
# Umgebung ohne Netz soll `make lint` trotzdem durchlaufen.
|
||
# Die Plattformprüfung ist keine Formalie.
|
||
#
|
||
# Bis Phase 5 liess sich der Agent fuer Windows **gar nicht uebersetzen** —
|
||
# unix.Statfs gibt es dort nicht. Der Windows-Dienst galt als „geschrieben, aber
|
||
# ungeprueft"; tatsaechlich haette er sich nicht einmal bauen lassen. Ein
|
||
# Uebersetzungslauf je Zielplattform faengt das in Sekunden.
|
||
.PHONY: cross-build
|
||
cross-build: ## Prüft die Übersetzbarkeit für alle Zielplattformen
|
||
@echo "==> windows/amd64"
|
||
@GOOS=windows GOARCH=amd64 go build -o /dev/null ./apps/agent/cmd/syncova-agent
|
||
@GOOS=windows GOARCH=amd64 go build -o /dev/null ./apps/api/cmd/syncova-api
|
||
@GOOS=windows GOARCH=amd64 go build -o /dev/null ./apps/api/cmd/syncova-repo
|
||
@echo "==> linux/amd64"
|
||
@GOOS=linux GOARCH=amd64 go build -o /dev/null ./apps/agent/cmd/syncova-agent
|
||
@GOOS=linux GOARCH=amd64 go build -o /dev/null ./apps/api/cmd/syncova-api
|
||
@echo "==> linux/arm64"
|
||
@GOOS=linux GOARCH=arm64 go build -o /dev/null ./apps/agent/cmd/syncova-agent
|
||
@echo "Alle Zielplattformen übersetzen."
|
||
|
||
.PHONY: security-scan
|
||
security-scan: ## Prüft Abhängigkeiten auf bekannte Schwachstellen
|
||
@echo "==> govulncheck"
|
||
@go run golang.org/x/vuln/cmd/govulncheck@latest $(GO_PACKAGES)
|
||
@echo "==> npm audit (Frontend)"
|
||
@cd apps/web && npm audit --audit-level=high
|
||
|
||
.PHONY: tidy
|
||
tidy: ## Bereinigt die Go-Modulabhängigkeiten
|
||
@go mod tidy
|
||
|
||
.PHONY: generate-key
|
||
generate-key: ## Erzeugt einen neuen Verschlüsselungsschlüssel
|
||
@go run ./apps/api/cmd/syncova-admin generate-key
|
||
|
||
.PHONY: create-admin
|
||
create-admin: require-env ## Legt den ersten Administrator an (fragt nach dem Passwort)
|
||
@go run ./apps/api/cmd/syncova-admin create-admin --username $(USERNAME)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Frontend
|
||
# ---------------------------------------------------------------------------
|
||
|
||
.PHONY: web-install
|
||
web-install: ## Installiert die Frontend-Abhängigkeiten
|
||
@cd apps/web && npm ci
|
||
|
||
.PHONY: web-dev
|
||
web-dev: ## Startet den Frontend-Entwicklungsserver
|
||
@cd apps/web && npm run dev
|
||
|
||
.PHONY: web-build
|
||
web-build: ## Baut das Frontend für die Auslieferung
|
||
@cd apps/web && npm run build
|
||
|
||
.PHONY: web-test
|
||
web-test: ## Führt die Frontend-Tests aus
|
||
@cd apps/web && npm run test
|
||
|
||
.PHONY: web-lint
|
||
web-lint: ## Prüft den Frontend-Code
|
||
@cd apps/web && npm run lint
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Übergreifend
|
||
# ---------------------------------------------------------------------------
|
||
|
||
.PHONY: secret-scan
|
||
secret-scan: ## Durchsucht den Quellbestand nach Geheimnissen
|
||
@go test -count=1 -run TestRepositoryContainsNoSecrets ./packages/platform/secretscan/
|
||
|
||
.PHONY: release
|
||
release: ## Baut das Auslieferungspaket nach ./dist
|
||
@scripts/build-release.sh
|
||
|
||
.PHONY: check
|
||
check: lint cross-build test web-lint web-test ## Führt alle Prüfungen aus (wie in der CI)
|
||
@echo "Alle Prüfungen bestanden."
|