From edfe6122b1d36fea27bd57d127acf1d2469d149b Mon Sep 17 00:00:00 2001 From: Tyler Koenig Date: Fri, 12 Jun 2026 08:39:30 -0400 Subject: [PATCH] fix: Kuma import tokens/paused, Docker hardening, migrate-secrets idempotency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Kuma import now maps push monitor tokens (generates crypto/rand token) and paused state (Active=false → Paused=true). Previously push monitors imported with empty token sat DOWN forever, and paused Kuma monitors came in unpaused and started alerting. 2. Dockerfile adds HEALTHCHECK against /api/health on port 8080. Container orchestrators can now detect unhealthy instances. 3. migrate-secrets sets the encryptor before loading alerts, so already-encrypted settings are decrypted correctly on second run instead of failing with a JSON unmarshal error. 4. docker-compose.yml adds container hardening: read_only filesystem, cap_drop ALL, no-new-privileges, tmpfs for /tmp. --- Dockerfile | 2 ++ cmd/uptop/main.go | 4 ++-- deploy/docker-compose.yml | 7 +++++++ internal/importer/kuma.go | 10 ++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e9ed9ee..2dcd8bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,6 +31,8 @@ ENV UPTOP_SSH_HOST_KEY=/data/.ssh/id_ed25519 ENV UPTOP_PORT=23234 EXPOSE 23234 +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD wget -qO- http://localhost:8080/api/health || exit 1 USER uptop ENTRYPOINT ["docker-entrypoint.sh"] CMD ["./uptop"] \ No newline at end of file diff --git a/cmd/uptop/main.go b/cmd/uptop/main.go index 71a280d..169fb6f 100644 --- a/cmd/uptop/main.go +++ b/cmd/uptop/main.go @@ -237,13 +237,13 @@ func runMigrateSecrets(args []string) { os.Exit(1) } + ss.SetEncryptor(enc) + alerts, err := ss.GetAllAlerts(context.Background()) if err != nil { slog.Error("failed to load alerts", "err", err) os.Exit(1) } - - ss.SetEncryptor(enc) migrated := 0 for _, a := range alerts { if err := ss.UpdateAlert(context.Background(), a.ID, a.Name, a.Type, a.Settings); err != nil { diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 19452af..b1ecf52 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -5,6 +5,13 @@ services: dockerfile: Dockerfile container_name: uptop restart: unless-stopped + read_only: true + cap_drop: + - ALL + security_opt: + - no-new-privileges:true + tmpfs: + - /tmp ports: - "23234:23234" - "8080:8080" diff --git a/internal/importer/kuma.go b/internal/importer/kuma.go index f17022d..2fdc508 100644 --- a/internal/importer/kuma.go +++ b/internal/importer/kuma.go @@ -1,6 +1,8 @@ package importer import ( + "crypto/rand" + "encoding/hex" "encoding/json" "fmt" "os" @@ -156,10 +158,18 @@ func convertKumaMonitor(m KumaMonitor, alertMap map[int]int) models.SiteConfig { site.DNSResolveType = m.DNSResolveType site.DNSServer = m.DNSResolveServer + site.Paused = !m.Active + switch m.Type { case "http": site.URL = m.URL site.CheckSSL = m.ExpiryNotif + case "push": + site.Type = "push" + b := make([]byte, 16) + if _, err := rand.Read(b); err == nil { + site.Token = hex.EncodeToString(b) + } case "ping": if m.Hostname != "" { site.Hostname = m.Hostname