backup: pre-hardening baseline

This commit is contained in:
backup 2026-09-02 11:20:31 -05:00
commit 9e4c612dcb
57 changed files with 10393 additions and 0 deletions

View file

@ -0,0 +1,111 @@
package main
import (
"context"
"flag"
"log"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/traefik/traefik-gui/backend/internal/api"
"github.com/traefik/traefik-gui/backend/internal/config"
"github.com/traefik/traefik-gui/backend/internal/database"
"github.com/traefik/traefik-gui/backend/internal/traefik"
"github.com/traefik/traefik-gui/backend/pkg/version"
)
func main() {
var (
addr = flag.String("addr", ":8080", "HTTP server address")
dbPath = flag.String("db", "./data/traefik-gui.db", "SQLite database path")
sessionSecret = flag.String("session-secret", "", "Session signing secret (required)")
corsOrigin = flag.String("cors-origin", "http://localhost:5173", "CORS allowed origin")
traefikAPIURL = flag.String("traefik-api", "http://localhost:8080/api", "Traefik API base URL")
configDir = flag.String("config-dir", "./configs/dynamic", "File provider config directory")
devMode = flag.Bool("dev", false, "Development mode (serves frontend from Vite)")
adminPassword = flag.String("admin-password", os.Getenv("GUI_ADMIN_PASSWORD"), "Admin password (env GUI_ADMIN_PASSWORD)")
showVersion = flag.Bool("version", false, "Show version and exit")
)
flag.Parse()
// Also allow env fallback for session secret
if *sessionSecret == "" {
*sessionSecret = os.Getenv("GUI_SESSION_SECRET")
}
if *sessionSecret == "" {
*sessionSecret = os.Getenv("GUI_SESSION_SECRET")
}
if *showVersion {
version.Print()
os.Exit(0)
}
if *sessionSecret == "" {
log.Fatal("SESSION_SECRET environment variable or -session-secret flag is required")
}
if len(*sessionSecret) < 32 {
log.Fatal("session-secret must be at least 32 characters")
}
cfg := &config.Config{
Addr: *addr,
DBPath: *dbPath,
SessionSecret: *sessionSecret,
CORSOrigin: *corsOrigin,
TraefikAPIURL: *traefikAPIURL,
ConfigDir: *configDir,
DevMode: *devMode,
}
db, err := database.New(cfg.DBPath)
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
defer db.Close()
if err := db.Migrate(); err != nil {
log.Fatalf("Failed to migrate database: %v", err)
}
if err := db.EnsureAdminPasswordViaEnv(*adminPassword, *devMode); err != nil {
log.Fatalf("Failed to configure admin password: %v", err)
}
traefikClient := traefik.NewMockClient()
server := api.NewServer(cfg, db, traefikClient)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
log.Println("Shutdown signal received")
cancel()
}()
go func() {
if err := server.Start(ctx); err != nil && err != http.ErrServerClosed {
log.Printf("Server error: %v", err)
cancel()
}
}()
<-ctx.Done()
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second)
defer shutdownCancel()
if err := server.Shutdown(shutdownCtx); err != nil {
log.Printf("Graceful shutdown failed: %v", err)
}
log.Println("Server stopped")
}