vibecarbon 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +663 -0
- package/README.md +188 -0
- package/carbon/.claude/hooks/task-completed-gate.sh +19 -0
- package/carbon/.claude/hooks/teammate-idle-gate.sh +29 -0
- package/carbon/.claude/settings.json +29 -0
- package/carbon/.cursor/rules/vibecarbon.mdc +6 -0
- package/carbon/.dockerignore +57 -0
- package/carbon/.env.example +219 -0
- package/carbon/.github/copilot-instructions.md +3 -0
- package/carbon/.github/workflows/deploy.yml +346 -0
- package/carbon/.github/workflows/vibecarbon-build.yml +81 -0
- package/carbon/.windsurfrules +74 -0
- package/carbon/AGENTS.md +422 -0
- package/carbon/CLAUDE.md +3 -0
- package/carbon/DEVELOPMENT.md +187 -0
- package/carbon/Dockerfile +98 -0
- package/carbon/LICENSE +21 -0
- package/carbon/PRODUCTION.md +364 -0
- package/carbon/README.md +193 -0
- package/carbon/TESTING.md +138 -0
- package/carbon/backup/Dockerfile +75 -0
- package/carbon/backup/backup.sh +95 -0
- package/carbon/backup/compose-backup.sh +140 -0
- package/carbon/biome.json +83 -0
- package/carbon/cloud-init/docker-ce-setup.yaml +55 -0
- package/carbon/cloud-init/k3s/master-init.sh +215 -0
- package/carbon/cloud-init/k3s/supabase-init.sh +167 -0
- package/carbon/cloud-init/k3s/worker-init.sh +147 -0
- package/carbon/components.json +24 -0
- package/carbon/content/blog/authentication-guide.mdx +34 -0
- package/carbon/content/blog/getting-started.mdx +41 -0
- package/carbon/content/changelog/v0-1-0.mdx +40 -0
- package/carbon/content/docs/analytics.mdx +90 -0
- package/carbon/content/docs/authentication.mdx +231 -0
- package/carbon/content/docs/background-jobs.mdx +116 -0
- package/carbon/content/docs/cli.mdx +630 -0
- package/carbon/content/docs/database.mdx +236 -0
- package/carbon/content/docs/deployment.mdx +227 -0
- package/carbon/content/docs/development.mdx +238 -0
- package/carbon/content/docs/environments.mdx +84 -0
- package/carbon/content/docs/getting-started.mdx +112 -0
- package/carbon/content/docs/legal/privacy-policy.mdx +89 -0
- package/carbon/content/docs/legal/terms-of-service.mdx +99 -0
- package/carbon/content/docs/optional-services.mdx +160 -0
- package/carbon/db/Dockerfile +23 -0
- package/carbon/docker-compose.dev-init.yml +5 -0
- package/carbon/docker-compose.metabase.override.yml +14 -0
- package/carbon/docker-compose.metabase.prod.yml +28 -0
- package/carbon/docker-compose.metabase.yml +84 -0
- package/carbon/docker-compose.n8n.override.yml +14 -0
- package/carbon/docker-compose.n8n.prod.yml +31 -0
- package/carbon/docker-compose.n8n.yml +97 -0
- package/carbon/docker-compose.observability.override.yml +18 -0
- package/carbon/docker-compose.observability.prod.yml +28 -0
- package/carbon/docker-compose.observability.yml +125 -0
- package/carbon/docker-compose.override.yml +28 -0
- package/carbon/docker-compose.prod.yml +294 -0
- package/carbon/docker-compose.yml +508 -0
- package/carbon/docker-entrypoint.sh +12 -0
- package/carbon/ha/activate-standby.sh +52 -0
- package/carbon/ha/primary-init.sql +36 -0
- package/carbon/ha/standby-init.sh +74 -0
- package/carbon/k8s/LICENSE +99 -0
- package/carbon/k8s/README.md +272 -0
- package/carbon/k8s/base/app/deployment.yaml +130 -0
- package/carbon/k8s/base/app/hpa.yaml +44 -0
- package/carbon/k8s/base/app/kustomization.yaml +10 -0
- package/carbon/k8s/base/app/network-policy.yaml +124 -0
- package/carbon/k8s/base/app/pdb.yaml +14 -0
- package/carbon/k8s/base/app/rbac.yaml +36 -0
- package/carbon/k8s/base/app/service.yaml +16 -0
- package/carbon/k8s/base/backup/cronjob.yaml +120 -0
- package/carbon/k8s/base/backup/kustomization.yaml +7 -0
- package/carbon/k8s/base/backup/network-policy.yaml +31 -0
- package/carbon/k8s/base/backup/rbac.yaml +7 -0
- package/carbon/k8s/base/cluster-autoscaler/deployment.yaml +103 -0
- package/carbon/k8s/base/cluster-autoscaler/kustomization.yaml +17 -0
- package/carbon/k8s/base/cluster-autoscaler/rbac.yaml +109 -0
- package/carbon/k8s/base/config/configmap.yaml +48 -0
- package/carbon/k8s/base/config/kustomization.yaml +8 -0
- package/carbon/k8s/base/hetzner-ccm/kustomization.yaml +9 -0
- package/carbon/k8s/base/hetzner-csi/kustomization.yaml +9 -0
- package/carbon/k8s/base/kustomization.yaml +43 -0
- package/carbon/k8s/base/namespace.yaml +7 -0
- package/carbon/k8s/base/network-policies.yaml +95 -0
- package/carbon/k8s/base/registry/kustomization.yaml +5 -0
- package/carbon/k8s/base/registry/local-registry.yaml +193 -0
- package/carbon/k8s/base/traefik/certificate.yaml +21 -0
- package/carbon/k8s/base/traefik/configmap.yaml +13 -0
- package/carbon/k8s/base/traefik/deployment.yaml +165 -0
- package/carbon/k8s/base/traefik/ingressroute.yaml +141 -0
- package/carbon/k8s/base/traefik/kustomization.yaml +11 -0
- package/carbon/k8s/base/traefik/middleware.yaml +109 -0
- package/carbon/k8s/base/traefik/network-policy.yaml +92 -0
- package/carbon/k8s/base/traefik/service.yaml +38 -0
- package/carbon/k8s/flux/README.md +49 -0
- package/carbon/k8s/flux/clusters/primary/vibecarbon.yaml +128 -0
- package/carbon/k8s/flux/clusters/standby/vibecarbon.yaml +83 -0
- package/carbon/k8s/gitops/cert-manager-webhook-hetzner/helm-release.yaml +38 -0
- package/carbon/k8s/gitops/cert-manager-webhook-hetzner/helm-repository.yaml +16 -0
- package/carbon/k8s/gitops/cert-manager-webhook-hetzner/kustomization.yaml +10 -0
- package/carbon/k8s/gitops/supabase/helm-release.yaml +66 -0
- package/carbon/k8s/gitops/supabase/helm-repository.yaml +18 -0
- package/carbon/k8s/gitops/supabase/kustomization.yaml +33 -0
- package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-cloudflare.yaml +51 -0
- package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-hetzner.yaml +59 -0
- package/carbon/k8s/infra/cert-manager-resources/cluster-issuers-manual.yaml +43 -0
- package/carbon/k8s/infra/cert-manager-resources/kustomization.yaml +15 -0
- package/carbon/k8s/infra/kustomization.yaml +21 -0
- package/carbon/k8s/infra/traefik-crds/kustomization.yaml +10 -0
- package/carbon/k8s/overlays/local/configmap.yaml +23 -0
- package/carbon/k8s/overlays/local/ingressroute-studio.yaml +104 -0
- package/carbon/k8s/overlays/local/kustomization.yaml +215 -0
- package/carbon/k8s/overlays/local/namespace.yaml +8 -0
- package/carbon/k8s/overlays/local/secrets.yaml +32 -0
- package/carbon/k8s/overlays/production/kustomization.yaml +34 -0
- package/carbon/k8s/test-local.sh +318 -0
- package/carbon/k8s/values/supabase.values.yaml +133 -0
- package/carbon/package.json +154 -0
- package/carbon/runtime.Dockerfile +17 -0
- package/carbon/scripts/_dev-jwt.mjs +45 -0
- package/carbon/scripts/check-rls.ts +53 -0
- package/carbon/scripts/dev-init.js +191 -0
- package/carbon/scripts/dev.js +191 -0
- package/carbon/scripts/docker-down.js +63 -0
- package/carbon/scripts/docker-logs.js +59 -0
- package/carbon/scripts/docker-up.js +222 -0
- package/carbon/scripts/generate-dev-configs.sh +131 -0
- package/carbon/scripts/generate-rss.ts +116 -0
- package/carbon/scripts/generate-sitemap.ts +102 -0
- package/carbon/scripts/k8s-apply.js +71 -0
- package/carbon/scripts/k8s-delete.js +75 -0
- package/carbon/scripts/lib/manifest.js +176 -0
- package/carbon/scripts/secret-scan.mjs +278 -0
- package/carbon/scripts/validate-dev-configs.sh +101 -0
- package/carbon/src/client/App.tsx +202 -0
- package/carbon/src/client/assets/hyperformant-dark.svg +29 -0
- package/carbon/src/client/assets/hyperformant-light.svg +29 -0
- package/carbon/src/client/assets/logos/aider.svg +1 -0
- package/carbon/src/client/assets/logos/antigravity.svg +1 -0
- package/carbon/src/client/assets/logos/bolt.svg +1 -0
- package/carbon/src/client/assets/logos/claude-code.svg +1 -0
- package/carbon/src/client/assets/logos/copilot.svg +1 -0
- package/carbon/src/client/assets/logos/cursor.svg +1 -0
- package/carbon/src/client/assets/logos/gemini-cli.svg +1 -0
- package/carbon/src/client/assets/logos/lovable.svg +1 -0
- package/carbon/src/client/assets/logos/openai-codex.svg +1 -0
- package/carbon/src/client/assets/logos/v0.svg +1 -0
- package/carbon/src/client/assets/logos/windsurf.svg +1 -0
- package/carbon/src/client/assets/vibecarbon-icon.svg +19 -0
- package/carbon/src/client/assets/vibecarbon-logo-dark.svg +29 -0
- package/carbon/src/client/assets/vibecarbon-logo-light.svg +29 -0
- package/carbon/src/client/components/AIIntegrationSection.tsx +120 -0
- package/carbon/src/client/components/AppSidebar.tsx +760 -0
- package/carbon/src/client/components/ArchitectureSection.tsx +46 -0
- package/carbon/src/client/components/CTAFooter.tsx +59 -0
- package/carbon/src/client/components/ComparisonSection.tsx +132 -0
- package/carbon/src/client/components/ContentPanel.tsx +66 -0
- package/carbon/src/client/components/ContentSkeleton.tsx +21 -0
- package/carbon/src/client/components/ErrorBoundary.tsx +46 -0
- package/carbon/src/client/components/FAQSection.tsx +76 -0
- package/carbon/src/client/components/FileUpload.tsx +210 -0
- package/carbon/src/client/components/HeaderActions.tsx +17 -0
- package/carbon/src/client/components/Hero.tsx +608 -0
- package/carbon/src/client/components/ImpersonationBanner.tsx +31 -0
- package/carbon/src/client/components/LanguageSwitcher.tsx +67 -0
- package/carbon/src/client/components/Logo.tsx +87 -0
- package/carbon/src/client/components/LogoStrip.tsx +76 -0
- package/carbon/src/client/components/MetricsStrip.tsx +48 -0
- package/carbon/src/client/components/Nav.tsx +195 -0
- package/carbon/src/client/components/NewsletterSignup.tsx +147 -0
- package/carbon/src/client/components/NotificationDrawer.tsx +171 -0
- package/carbon/src/client/components/PageHeader.tsx +24 -0
- package/carbon/src/client/components/PlanGate.tsx +36 -0
- package/carbon/src/client/components/PricingSection.tsx +371 -0
- package/carbon/src/client/components/SEO.tsx +34 -0
- package/carbon/src/client/components/SmoothScroll.tsx +45 -0
- package/carbon/src/client/components/TechStackSection.tsx +165 -0
- package/carbon/src/client/components/WorkflowSection.tsx +604 -0
- package/carbon/src/client/components/admin/DockerLogs.tsx +276 -0
- package/carbon/src/client/components/admin/PerformanceMetrics.tsx +230 -0
- package/carbon/src/client/components/admin/ServiceCard.tsx +45 -0
- package/carbon/src/client/components/admin/ServicesStatus.tsx +296 -0
- package/carbon/src/client/components/architecture/ArchitectureDiagram.tsx +413 -0
- package/carbon/src/client/components/auth/AuthProvider.tsx +466 -0
- package/carbon/src/client/components/effects/FilmGrainOverlay.tsx +35 -0
- package/carbon/src/client/components/effects/FresnelEdge.tsx +49 -0
- package/carbon/src/client/components/effects/GlowTracker.tsx +46 -0
- package/carbon/src/client/components/effects/SparkBurst.tsx +145 -0
- package/carbon/src/client/components/effects/VGlowEffect.tsx +83 -0
- package/carbon/src/client/components/effects/index.ts +2 -0
- package/carbon/src/client/components/layouts/SidebarLayout.tsx +20 -0
- package/carbon/src/client/components/scroll/ScrollSection.tsx +76 -0
- package/carbon/src/client/components/scroll/ScrollytellingProvider.tsx +81 -0
- package/carbon/src/client/components/scroll/index.ts +2 -0
- package/carbon/src/client/components/ui/accordion.tsx +71 -0
- package/carbon/src/client/components/ui/alert-dialog.tsx +162 -0
- package/carbon/src/client/components/ui/alert.tsx +73 -0
- package/carbon/src/client/components/ui/aspect-ratio.tsx +22 -0
- package/carbon/src/client/components/ui/avatar.tsx +91 -0
- package/carbon/src/client/components/ui/badge.tsx +50 -0
- package/carbon/src/client/components/ui/breadcrumb.tsx +100 -0
- package/carbon/src/client/components/ui/button-group.tsx +78 -0
- package/carbon/src/client/components/ui/button.tsx +120 -0
- package/carbon/src/client/components/ui/calendar.tsx +182 -0
- package/carbon/src/client/components/ui/card.tsx +85 -0
- package/carbon/src/client/components/ui/carousel.tsx +227 -0
- package/carbon/src/client/components/ui/chart.tsx +357 -0
- package/carbon/src/client/components/ui/checkbox.tsx +27 -0
- package/carbon/src/client/components/ui/collapsible.tsx +15 -0
- package/carbon/src/client/components/ui/command.tsx +178 -0
- package/carbon/src/client/components/ui/context-menu.tsx +233 -0
- package/carbon/src/client/components/ui/dialog.tsx +132 -0
- package/carbon/src/client/components/ui/drawer.tsx +118 -0
- package/carbon/src/client/components/ui/dropdown-menu.tsx +242 -0
- package/carbon/src/client/components/ui/empty.tsx +94 -0
- package/carbon/src/client/components/ui/field.tsx +226 -0
- package/carbon/src/client/components/ui/hover-card.tsx +44 -0
- package/carbon/src/client/components/ui/input-group.tsx +146 -0
- package/carbon/src/client/components/ui/input-otp.tsx +83 -0
- package/carbon/src/client/components/ui/input.tsx +20 -0
- package/carbon/src/client/components/ui/item.tsx +188 -0
- package/carbon/src/client/components/ui/kbd.tsx +26 -0
- package/carbon/src/client/components/ui/label.tsx +21 -0
- package/carbon/src/client/components/ui/menubar.tsx +250 -0
- package/carbon/src/client/components/ui/navigation-menu.tsx +155 -0
- package/carbon/src/client/components/ui/pagination.tsx +102 -0
- package/carbon/src/client/components/ui/popover.tsx +75 -0
- package/carbon/src/client/components/ui/progress.tsx +66 -0
- package/carbon/src/client/components/ui/radio-group.tsx +36 -0
- package/carbon/src/client/components/ui/resizable.tsx +46 -0
- package/carbon/src/client/components/ui/scroll-area.tsx +48 -0
- package/carbon/src/client/components/ui/select.tsx +186 -0
- package/carbon/src/client/components/ui/separator.tsx +21 -0
- package/carbon/src/client/components/ui/sheet.tsx +124 -0
- package/carbon/src/client/components/ui/sidebar.tsx +702 -0
- package/carbon/src/client/components/ui/skeleton.tsx +13 -0
- package/carbon/src/client/components/ui/slider.tsx +57 -0
- package/carbon/src/client/components/ui/sonner.tsx +45 -0
- package/carbon/src/client/components/ui/spinner.tsx +15 -0
- package/carbon/src/client/components/ui/switch.tsx +30 -0
- package/carbon/src/client/components/ui/table.tsx +89 -0
- package/carbon/src/client/components/ui/tabs.tsx +73 -0
- package/carbon/src/client/components/ui/textarea.tsx +18 -0
- package/carbon/src/client/components/ui/toggle-group.tsx +87 -0
- package/carbon/src/client/components/ui/toggle.tsx +44 -0
- package/carbon/src/client/components/ui/tooltip.tsx +56 -0
- package/carbon/src/client/hooks/api/index.ts +14 -0
- package/carbon/src/client/hooks/api/useAuthSettings.ts +80 -0
- package/carbon/src/client/hooks/api/useSubscription.ts +87 -0
- package/carbon/src/client/hooks/use-mobile.ts +21 -0
- package/carbon/src/client/hooks/useMousePosition.ts +91 -0
- package/carbon/src/client/hooks/useNotifications.tsx +124 -0
- package/carbon/src/client/hooks/useOrganizationMembers.ts +127 -0
- package/carbon/src/client/hooks/useOrganizations.tsx +230 -0
- package/carbon/src/client/hooks/usePackageManager.ts +69 -0
- package/carbon/src/client/hooks/useReducedMotion.ts +20 -0
- package/carbon/src/client/hooks/useRunningServices.ts +114 -0
- package/carbon/src/client/hooks/useScrollProgress.ts +56 -0
- package/carbon/src/client/index.css +467 -0
- package/carbon/src/client/index.html +56 -0
- package/carbon/src/client/lib/admin-services.ts +151 -0
- package/carbon/src/client/lib/api.ts +32 -0
- package/carbon/src/client/lib/blog.ts +35 -0
- package/carbon/src/client/lib/changelog.ts +33 -0
- package/carbon/src/client/lib/docs-search.ts +101 -0
- package/carbon/src/client/lib/docs.ts +37 -0
- package/carbon/src/client/lib/i18n.ts +32 -0
- package/carbon/src/client/lib/supabase.ts +72 -0
- package/carbon/src/client/lib/tailwind-colors.ts +357 -0
- package/carbon/src/client/lib/theme.ts +117 -0
- package/carbon/src/client/lib/utils.ts +22 -0
- package/carbon/src/client/locales/de.json +529 -0
- package/carbon/src/client/locales/en.json +461 -0
- package/carbon/src/client/locales/es.json +529 -0
- package/carbon/src/client/locales/fr.json +529 -0
- package/carbon/src/client/locales/pt.json +529 -0
- package/carbon/src/client/main.tsx +56 -0
- package/carbon/src/client/mdx.d.ts +13 -0
- package/carbon/src/client/pages/ApiDocs.tsx +76 -0
- package/carbon/src/client/pages/AuthCallback.tsx +34 -0
- package/carbon/src/client/pages/Blog.tsx +167 -0
- package/carbon/src/client/pages/Changelog.tsx +171 -0
- package/carbon/src/client/pages/Charts.tsx +388 -0
- package/carbon/src/client/pages/Checkout.tsx +227 -0
- package/carbon/src/client/pages/Contact.tsx +174 -0
- package/carbon/src/client/pages/Dashboard.tsx +368 -0
- package/carbon/src/client/pages/Docs.tsx +372 -0
- package/carbon/src/client/pages/ForgotPassword.tsx +111 -0
- package/carbon/src/client/pages/Home.tsx +187 -0
- package/carbon/src/client/pages/Legal.tsx +100 -0
- package/carbon/src/client/pages/Login.tsx +408 -0
- package/carbon/src/client/pages/MFAVerify.tsx +156 -0
- package/carbon/src/client/pages/NotFound.tsx +21 -0
- package/carbon/src/client/pages/Onboarding.tsx +246 -0
- package/carbon/src/client/pages/ResetPassword.tsx +200 -0
- package/carbon/src/client/pages/UIComponents.tsx +390 -0
- package/carbon/src/client/pages/admin/ContactSubmissions.tsx +220 -0
- package/carbon/src/client/pages/admin/Dashboard.tsx +24 -0
- package/carbon/src/client/pages/admin/Infrastructure.tsx +257 -0
- package/carbon/src/client/pages/admin/Jobs.tsx +225 -0
- package/carbon/src/client/pages/admin/Logs.tsx +18 -0
- package/carbon/src/client/pages/admin/Newsletter.tsx +300 -0
- package/carbon/src/client/pages/admin/Notifications.tsx +603 -0
- package/carbon/src/client/pages/admin/Organizations.tsx +306 -0
- package/carbon/src/client/pages/admin/Settings.tsx +314 -0
- package/carbon/src/client/pages/admin/Theme.tsx +465 -0
- package/carbon/src/client/pages/admin/Users.tsx +365 -0
- package/carbon/src/client/pages/api-docs.css +156 -0
- package/carbon/src/client/pages/organizations/Details.tsx +200 -0
- package/carbon/src/client/pages/organizations/Members.tsx +402 -0
- package/carbon/src/client/pages/settings/Billing.tsx +473 -0
- package/carbon/src/client/pages/settings/Profile.tsx +160 -0
- package/carbon/src/client/pages/settings/Security.tsx +341 -0
- package/carbon/src/client/public/favicon.svg +19 -0
- package/carbon/src/client/public/robots.txt +8 -0
- package/carbon/src/server/billing/index.ts +104 -0
- package/carbon/src/server/billing/provider.ts +81 -0
- package/carbon/src/server/billing/providers/paddle.ts +314 -0
- package/carbon/src/server/billing/providers/polar.ts +325 -0
- package/carbon/src/server/billing/providers/stripe.ts +233 -0
- package/carbon/src/server/emails/templates.ts +116 -0
- package/carbon/src/server/index.ts +554 -0
- package/carbon/src/server/lib/auth.ts +6 -0
- package/carbon/src/server/lib/email.ts +64 -0
- package/carbon/src/server/lib/env.ts +112 -0
- package/carbon/src/server/lib/errors.ts +21 -0
- package/carbon/src/server/lib/logger.ts +17 -0
- package/carbon/src/server/lib/rate-limiter.ts +288 -0
- package/carbon/src/server/lib/request.ts +34 -0
- package/carbon/src/server/lib/stripe.ts +42 -0
- package/carbon/src/server/lib/supabase.ts +65 -0
- package/carbon/src/server/middleware/requirePlan.ts +80 -0
- package/carbon/src/server/routes/_internal/services-status.ts +958 -0
- package/carbon/src/server/routes/_internal/verify-role.ts +185 -0
- package/carbon/src/server/routes/health.ts +48 -0
- package/carbon/src/server/routes/v1/admin/contact.ts +128 -0
- package/carbon/src/server/routes/v1/admin/jobs.ts +171 -0
- package/carbon/src/server/routes/v1/admin/newsletter.ts +237 -0
- package/carbon/src/server/routes/v1/auth.ts +390 -0
- package/carbon/src/server/routes/v1/billing.ts +718 -0
- package/carbon/src/server/routes/v1/contact.ts +93 -0
- package/carbon/src/server/routes/v1/index.ts +1333 -0
- package/carbon/src/server/routes/v1/newsletter.ts +181 -0
- package/carbon/src/server/routes/v1/performance.ts +157 -0
- package/carbon/src/server/routes/v1/stats.ts +170 -0
- package/carbon/src/server/routes/v1/theme.ts +106 -0
- package/carbon/src/server/routes/webhooks/billing.ts +376 -0
- package/carbon/src/server/routes/webhooks/stripe.ts +276 -0
- package/carbon/src/server/types.ts +11 -0
- package/carbon/src/shared/pricing.ts +155 -0
- package/carbon/src/shared/types.ts +338 -0
- package/carbon/supabase/migrations/00001_init.sql +717 -0
- package/carbon/supabase/migrations/00002_theme_settings.sql +13 -0
- package/carbon/supabase/migrations/00003_pg_cron.sql +121 -0
- package/carbon/supabase/migrations/00004_contact_newsletter.sql +81 -0
- package/carbon/supabase/migrations/00005_localization_languages.sql +22 -0
- package/carbon/supabase/seed.sql +16 -0
- package/carbon/tests/_helpers/app.ts +45 -0
- package/carbon/tests/_helpers/env.ts +37 -0
- package/carbon/tests/_helpers/factories.ts +69 -0
- package/carbon/tests/_helpers/jwt.ts +23 -0
- package/carbon/tests/_helpers/setup-integration.ts +20 -0
- package/carbon/tests/_helpers/setup-rtl.ts +12 -0
- package/carbon/tests/component/ErrorBoundary.test.tsx +53 -0
- package/carbon/tests/component/use-auth-settings.test.tsx +119 -0
- package/carbon/tests/integration/server/routes/contact.test.ts +162 -0
- package/carbon/tests/integration/server/routes/health.test.ts +61 -0
- package/carbon/tests/structural/i18n-parity.test.ts +42 -0
- package/carbon/tests/unit/client/utils.test.ts +49 -0
- package/carbon/tests/unit/shared/pricing.test.ts +93 -0
- package/carbon/tsconfig.json +27 -0
- package/carbon/tsconfig.server.json +27 -0
- package/carbon/tsconfig.test.json +9 -0
- package/carbon/vite.config.ts +110 -0
- package/carbon/vitest.config.ts +74 -0
- package/carbon/volumes/db/jwt.sql +57 -0
- package/carbon/volumes/db/metabase-init.sh +29 -0
- package/carbon/volumes/db/n8n-init.sh +25 -0
- package/carbon/volumes/db/realtime.sql +33 -0
- package/carbon/volumes/db/roles.sql +93 -0
- package/carbon/volumes/db/set-passwords.sh +12 -0
- package/carbon/volumes/db/super-admin.dev.sql +113 -0
- package/carbon/volumes/db/super-admin.generated.sql +113 -0
- package/carbon/volumes/db/super-admin.sql +114 -0
- package/carbon/volumes/grafana/dashboards/logs.json +179 -0
- package/carbon/volumes/grafana/dashboards/overview.json +523 -0
- package/carbon/volumes/grafana/dashboards/postgresql.json +337 -0
- package/carbon/volumes/grafana/dashboards.dev/logs.json +179 -0
- package/carbon/volumes/grafana/dashboards.dev/overview.json +156 -0
- package/carbon/volumes/grafana/dashboards.dev/postgresql.json +337 -0
- package/carbon/volumes/grafana/provisioning/dashboards/dashboards.dev.yml +16 -0
- package/carbon/volumes/grafana/provisioning/dashboards/dashboards.yml +16 -0
- package/carbon/volumes/grafana/provisioning/datasources/datasources.yml +43 -0
- package/carbon/volumes/kong/docker-entrypoint.sh +9 -0
- package/carbon/volumes/kong/kong.yml +208 -0
- package/carbon/volumes/loki/loki-config.yml +58 -0
- package/carbon/volumes/n8n/hooks.js +131 -0
- package/carbon/volumes/n8n/scripts/setup.sh +66 -0
- package/carbon/volumes/prometheus/prometheus.yml +43 -0
- package/carbon/volumes/promtail/promtail-config.yml +64 -0
- package/carbon/volumes/traefik/middlewares.dev.yml +83 -0
- package/carbon/volumes/traefik/middlewares.yml +95 -0
- package/carbon/volumes/traefik/vite-dev.yml +20 -0
- package/package.json +95 -0
- package/src/access.js +354 -0
- package/src/activate.js +187 -0
- package/src/add.js +718 -0
- package/src/backup.js +786 -0
- package/src/cli.js +350 -0
- package/src/configure.js +967 -0
- package/src/console.js +155 -0
- package/src/create.js +1499 -0
- package/src/deploy.js +311 -0
- package/src/destroy.js +2033 -0
- package/src/diagnose.js +735 -0
- package/src/down.js +80 -0
- package/src/failover.js +1032 -0
- package/src/lib/backup-s3.js +179 -0
- package/src/lib/build.js +33 -0
- package/src/lib/checksum.js +28 -0
- package/src/lib/ci-setup.js +666 -0
- package/src/lib/cli/help.js +129 -0
- package/src/lib/cli/parse-flags.js +160 -0
- package/src/lib/cli/select-action.js +65 -0
- package/src/lib/cli/select-environment.js +108 -0
- package/src/lib/cli/tty-guard.js +75 -0
- package/src/lib/cloudflare.js +447 -0
- package/src/lib/colors.js +52 -0
- package/src/lib/command.js +361 -0
- package/src/lib/config.js +359 -0
- package/src/lib/cost.js +103 -0
- package/src/lib/deploy/bundle.js +231 -0
- package/src/lib/deploy/compose/acme-verify.js +121 -0
- package/src/lib/deploy/compose/build-args.js +78 -0
- package/src/lib/deploy/compose/ha.js +1874 -0
- package/src/lib/deploy/compose/index.js +1294 -0
- package/src/lib/deploy/compose/reconcile.js +74 -0
- package/src/lib/deploy/github.js +382 -0
- package/src/lib/deploy/image.js +191 -0
- package/src/lib/deploy/index.js +119 -0
- package/src/lib/deploy/k8s/LICENSE +99 -0
- package/src/lib/deploy/k8s/gitops-deploy.js +298 -0
- package/src/lib/deploy/k8s/ha/index.js +1000 -0
- package/src/lib/deploy/k8s/index.js +62 -0
- package/src/lib/deploy/k8s/k3s.js +2515 -0
- package/src/lib/deploy/orchestrator.js +1401 -0
- package/src/lib/deploy/prompts.js +545 -0
- package/src/lib/deploy/remote-build.js +130 -0
- package/src/lib/deploy/state.js +120 -0
- package/src/lib/deploy/utils.js +328 -0
- package/src/lib/deploy-logger.js +93 -0
- package/src/lib/dns-propagation.js +48 -0
- package/src/lib/environment.js +58 -0
- package/src/lib/fetch-retry.js +103 -0
- package/src/lib/github-environments.js +335 -0
- package/src/lib/hetzner-dns.js +377 -0
- package/src/lib/hetzner-guided-setup.js +275 -0
- package/src/lib/host-keys.js +37 -0
- package/src/lib/iac/cloud-init.js +52 -0
- package/src/lib/iac/index.js +325 -0
- package/src/lib/iac/programs/hetzner-compose.js +130 -0
- package/src/lib/iac/programs/hetzner-k8s.js +320 -0
- package/src/lib/kubectl.js +81 -0
- package/src/lib/licensing/index.js +259 -0
- package/src/lib/licensing/tiers.js +181 -0
- package/src/lib/licensing/validator.js +171 -0
- package/src/lib/merge-package-json.js +90 -0
- package/src/lib/operator-ip.js +381 -0
- package/src/lib/package-manager.js +111 -0
- package/src/lib/perf.js +71 -0
- package/src/lib/project-guard.js +39 -0
- package/src/lib/project.js +334 -0
- package/src/lib/providers/base.js +276 -0
- package/src/lib/providers/hetzner-s3.js +656 -0
- package/src/lib/providers/hetzner.js +755 -0
- package/src/lib/providers/index.js +164 -0
- package/src/lib/s3.js +510 -0
- package/src/lib/secret-scan.js +583 -0
- package/src/lib/secrets.js +63 -0
- package/src/lib/server-types.js +195 -0
- package/src/lib/shell.js +91 -0
- package/src/lib/ssh.js +241 -0
- package/src/lib/tracker.js +242 -0
- package/src/lib/upgrade-policy.js +170 -0
- package/src/lib/validators.js +105 -0
- package/src/lib/version.js +5 -0
- package/src/remove.js +292 -0
- package/src/reset.js +97 -0
- package/src/restore.js +871 -0
- package/src/scale.js +1734 -0
- package/src/shell.js +222 -0
- package/src/status.js +981 -0
- package/src/up.js +264 -0
- package/src/upgrade.js +721 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
apiVersion: networking.k8s.io/v1
|
|
2
|
+
kind: NetworkPolicy
|
|
3
|
+
metadata:
|
|
4
|
+
name: traefik-policy
|
|
5
|
+
namespace: vibecarbon
|
|
6
|
+
spec:
|
|
7
|
+
podSelector:
|
|
8
|
+
matchLabels:
|
|
9
|
+
app: vibecarbon-traefik
|
|
10
|
+
policyTypes:
|
|
11
|
+
- Ingress
|
|
12
|
+
- Egress
|
|
13
|
+
ingress:
|
|
14
|
+
# Allow external traffic on HTTP and HTTPS (from LB and direct)
|
|
15
|
+
- ports:
|
|
16
|
+
- protocol: TCP
|
|
17
|
+
port: 80
|
|
18
|
+
- protocol: TCP
|
|
19
|
+
port: 443
|
|
20
|
+
# Allow health check probes on traefik port
|
|
21
|
+
- ports:
|
|
22
|
+
- protocol: TCP
|
|
23
|
+
port: 8080
|
|
24
|
+
egress:
|
|
25
|
+
# Allow connection to all pods in namespace (Traefik routes to app, kong, studio)
|
|
26
|
+
- to:
|
|
27
|
+
- podSelector: {}
|
|
28
|
+
# Allow DNS resolution
|
|
29
|
+
- to:
|
|
30
|
+
- namespaceSelector: {}
|
|
31
|
+
podSelector:
|
|
32
|
+
matchLabels:
|
|
33
|
+
k8s-app: kube-dns
|
|
34
|
+
ports:
|
|
35
|
+
- protocol: UDP
|
|
36
|
+
port: 53
|
|
37
|
+
- protocol: TCP
|
|
38
|
+
port: 53
|
|
39
|
+
# Kubernetes API egress for traefik's CRD/Ingress informers.
|
|
40
|
+
# Without these rules kube-router rejects outbound traffic from
|
|
41
|
+
# traefik to the apiserver, traefik loops on `connect: connection
|
|
42
|
+
# refused`, never loads IngressRoutes, and serves its default 404
|
|
43
|
+
# on every request. Surfaced in k8s-ha 2026-04-28 deploy run
|
|
44
|
+
# (verify-1df-1dg log) when the public probe got 404 even though
|
|
45
|
+
# the app pods + Service endpoints were healthy.
|
|
46
|
+
#
|
|
47
|
+
# CIDR coupling: the two ranges below are k3s defaults
|
|
48
|
+
# (--service-cidr 10.43.0.0/16, --cluster-cidr 10.42.0.0/16) that
|
|
49
|
+
# carbon/cloud-init/k3s/master-init.sh does NOT override. If you
|
|
50
|
+
# ever pass --service-cidr or --cluster-cidr there, also update
|
|
51
|
+
# both this file AND carbon/k8s/base/app/network-policy.yaml.
|
|
52
|
+
# k8s NetworkPolicy has no Service-name selector, so we have to
|
|
53
|
+
# name the CIDRs explicitly.
|
|
54
|
+
#
|
|
55
|
+
# 10.43.0.1:443 = kubernetes.default Service ClusterIP via kube-proxy
|
|
56
|
+
# DNAT (works on worker nodes).
|
|
57
|
+
- to:
|
|
58
|
+
- ipBlock:
|
|
59
|
+
cidr: 10.43.0.1/32
|
|
60
|
+
ports:
|
|
61
|
+
- protocol: TCP
|
|
62
|
+
port: 443
|
|
63
|
+
# 0.0.0.0/0:6443 = the apiserver, dial-anywhere on apiserver-protocol
|
|
64
|
+
# port. Background: the kubernetes Service ClusterIP (10.43.0.1) DNATs
|
|
65
|
+
# at the OUTPUT chain BEFORE the CNI evaluates NetworkPolicy egress, so
|
|
66
|
+
# the policy sees the *post-NAT* destination — the master node IP from
|
|
67
|
+
# the EndpointSlice. With k3s installed via `--node-ip=<public>` and
|
|
68
|
+
# HCLOUD_NETWORK NOT set on the Hetzner CCM (the patch that would
|
|
69
|
+
# populate InternalIP=10.0.1.x was reverted in src/lib/deploy/k8s/k3s.js
|
|
70
|
+
# because it broke kubelet's TLS cert SAN — cert is generated for the
|
|
71
|
+
# public IP only, so kubectl logs/exec fail x509 verify when InternalIP
|
|
72
|
+
# changes post-startup), the master's reported IP is the public IP. So
|
|
73
|
+
# 10.0.0.0/8 doesn't match and 10.42.0.0/16 (pod CIDR) was never on the
|
|
74
|
+
# wire — both diagnostically wrong RCAs from earlier.
|
|
75
|
+
#
|
|
76
|
+
# The IP changes every deploy, so we can't list it. Allow any
|
|
77
|
+
# destination on 6443 — port 6443 is apiserver-protocol; the only
|
|
78
|
+
# listeners are k8s control planes. Deny-by-default is preserved on
|
|
79
|
+
# every other port.
|
|
80
|
+
#
|
|
81
|
+
# Repro chain:
|
|
82
|
+
# - k8s deploy fanout4 2026-04-30 e3: 10.42.0.0/16:6443 → connection refused
|
|
83
|
+
# - k8s-ha deploy fanout4b 2026-05-01: tightened to 10.0.0.0/8 + tried
|
|
84
|
+
# CCM HCLOUD_NETWORK; reverted CCM (cert SAN) — left 10.0.0.0/8
|
|
85
|
+
# - k8s-ha restore fanout5 2026-05-01: same connection-refused on
|
|
86
|
+
# redeploy because Endpoint resolved to public IP again. Final fix.
|
|
87
|
+
- to:
|
|
88
|
+
- ipBlock:
|
|
89
|
+
cidr: 0.0.0.0/0
|
|
90
|
+
ports:
|
|
91
|
+
- protocol: TCP
|
|
92
|
+
port: 6443
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Service
|
|
3
|
+
metadata:
|
|
4
|
+
name: traefik
|
|
5
|
+
labels:
|
|
6
|
+
app: vibecarbon-traefik
|
|
7
|
+
component: ingress
|
|
8
|
+
spec:
|
|
9
|
+
type: ClusterIP
|
|
10
|
+
ports:
|
|
11
|
+
- port: 80
|
|
12
|
+
targetPort: web
|
|
13
|
+
protocol: TCP
|
|
14
|
+
name: web
|
|
15
|
+
- port: 443
|
|
16
|
+
targetPort: websecure
|
|
17
|
+
protocol: TCP
|
|
18
|
+
name: websecure
|
|
19
|
+
selector:
|
|
20
|
+
app: vibecarbon-traefik
|
|
21
|
+
---
|
|
22
|
+
# Internal service for dashboard access
|
|
23
|
+
apiVersion: v1
|
|
24
|
+
kind: Service
|
|
25
|
+
metadata:
|
|
26
|
+
name: traefik-dashboard
|
|
27
|
+
labels:
|
|
28
|
+
app: vibecarbon-traefik
|
|
29
|
+
component: ingress
|
|
30
|
+
spec:
|
|
31
|
+
type: ClusterIP
|
|
32
|
+
ports:
|
|
33
|
+
- port: 8080
|
|
34
|
+
targetPort: traefik
|
|
35
|
+
protocol: TCP
|
|
36
|
+
name: traefik
|
|
37
|
+
selector:
|
|
38
|
+
app: vibecarbon-traefik
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Flux CD GitOps Configuration
|
|
2
|
+
|
|
3
|
+
This directory contains Flux CD cluster-level glue (the `clusters/` GitRepositories + Kustomizations that wire the app manifests). Chart-level resources (HelmRepositories + HelmReleases) moved to `carbon/k8s/gitops/<component>/` in Phases 2–3 of the GitOps refactor (see `plans/gitops-refactor-2026-04-20.md`).
|
|
4
|
+
|
|
5
|
+
You do **not** need the `flux` CLI locally — `deploy.js` bootstraps Flux via a single `kubectl apply -f <release url>`.
|
|
6
|
+
|
|
7
|
+
## Directory layout
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
carbon/k8s/
|
|
11
|
+
├── flux/
|
|
12
|
+
│ ├── clusters/
|
|
13
|
+
│ │ ├── primary/vibecarbon.yaml # GitRepository + Kustomizations (app manifests)
|
|
14
|
+
│ │ └── standby/vibecarbon.yaml
|
|
15
|
+
│ └── README.md # you are here
|
|
16
|
+
└── gitops/
|
|
17
|
+
├── supabase/
|
|
18
|
+
│ ├── kustomization.yaml # configMapGenerator + resources list
|
|
19
|
+
│ ├── helm-repository.yaml # supabase-community HelmRepository
|
|
20
|
+
│ └── helm-release.yaml # supabase HelmRelease (reads supabase-values ConfigMap)
|
|
21
|
+
└── cert-manager-webhook-hetzner/
|
|
22
|
+
├── kustomization.yaml
|
|
23
|
+
├── helm-repository.yaml # hetzner-cloud HelmRepository
|
|
24
|
+
└── helm-release.yaml
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## How deploy wires Flux
|
|
28
|
+
|
|
29
|
+
1. `ensureFluxRunning(env)` — applies `https://github.com/fluxcd/flux2/releases/download/v2.8.5/install.yaml`, then `kubectl rollout status` on the four flux-system controllers (`source`, `helm`, `kustomize`, `notification`).
|
|
30
|
+
2. **Cert-manager webhook** (only when DNS provider = hetzner): `kubectl apply -k carbon/k8s/gitops/cert-manager-webhook-hetzner/` → `kubectl wait helmrelease/cert-manager-webhook-hetzner`.
|
|
31
|
+
3. **Supabase**: deploy renders `supabase.values.yaml` (substituting `{{DOMAIN}}` / `{{PROJECT_NAME}}`) into a tempdir containing the bundle files, then `kubectl apply -k <tempdir>` (kustomize generates the `supabase-values` ConfigMap from the rendered file). Then `kubectl wait helmrelease/supabase` (25 min budget).
|
|
32
|
+
|
|
33
|
+
Flux's 5-minute HelmRepository interval means transient source-controller fetch failures self-heal inside the HelmRelease wait budget. There is no client-side reconcile poking.
|
|
34
|
+
|
|
35
|
+
## Useful commands (post-deploy, for debugging)
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
kubectl get helmrelease,kustomization,helmrepository -A
|
|
39
|
+
kubectl describe helmrelease supabase -n flux-system
|
|
40
|
+
kubectl annotate --overwrite helmrelease/supabase -n flux-system reconcile.fluxcd.io/requestedAt="$(date -u +%FT%TZ)"
|
|
41
|
+
kubectl logs -n flux-system deploy/helm-controller --tail=200
|
|
42
|
+
kubectl logs -n flux-system deploy/source-controller --tail=200
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Secrets
|
|
46
|
+
|
|
47
|
+
The Supabase HelmRelease reads secrets from the `vibecarbon-secrets` Secret in the `vibecarbon` namespace (created by deploy before the HelmRelease is applied). The cert-manager-webhook-hetzner HelmRelease reads `hetzner-api-token` in the `cert-manager` namespace.
|
|
48
|
+
|
|
49
|
+
If you need to ship additional secrets through Git (e.g. for other HelmReleases), use Sealed Secrets, SOPS, or External Secrets Operator. Phase 4 of the GitOps refactor (GitRepository-driven reconciliation, see plan doc) is when we introduce this.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Flux GitRepository + Kustomizations for the primary cluster.
|
|
3
|
+
#
|
|
4
|
+
# URL is templated at project-create time via substitution of
|
|
5
|
+
# {{GITHUB_OWNER}}/{{PROJECT_NAME}} (see src/create.js PLACEHOLDERS).
|
|
6
|
+
# Applied once by the GitHub Actions deploy workflow at
|
|
7
|
+
# .github/workflows/deploy.yml — after that, Flux reconciles the repo's
|
|
8
|
+
# k8s/ directory every minute (GitRepository interval) and the
|
|
9
|
+
# Kustomizations every 10 min.
|
|
10
|
+
#
|
|
11
|
+
# Layout in the customer's repo:
|
|
12
|
+
# k8s/base/ # app + traefik + backup + etc.
|
|
13
|
+
# k8s/gitops/supabase/ # HelmRepo + HelmRelease + values CM
|
|
14
|
+
# k8s/gitops/cert-manager-webhook-hetzner/ # HelmRepo + HelmRelease
|
|
15
|
+
# k8s/overlays/production-<region>/ # per-env overlay on top of base
|
|
16
|
+
apiVersion: source.toolkit.fluxcd.io/v1
|
|
17
|
+
kind: GitRepository
|
|
18
|
+
metadata:
|
|
19
|
+
name: vibecarbon
|
|
20
|
+
namespace: flux-system
|
|
21
|
+
spec:
|
|
22
|
+
# 1-min poll keeps the "git push → reconcile" feedback loop tight.
|
|
23
|
+
interval: 1m
|
|
24
|
+
url: https://github.com/{{GITHUB_OWNER}}/{{PROJECT_NAME}}
|
|
25
|
+
ref:
|
|
26
|
+
branch: main
|
|
27
|
+
# Secret populated by the deploy workflow at first run, containing a
|
|
28
|
+
# `username` + `password` (PAT or GitHub App token with repo:read).
|
|
29
|
+
secretRef:
|
|
30
|
+
name: flux-system
|
|
31
|
+
---
|
|
32
|
+
# Base manifests (namespace, network policies, app, traefik, backup,
|
|
33
|
+
# hetzner-ccm/csi placeholder kustomizations).
|
|
34
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
35
|
+
kind: Kustomization
|
|
36
|
+
metadata:
|
|
37
|
+
name: vibecarbon-base
|
|
38
|
+
namespace: flux-system
|
|
39
|
+
spec:
|
|
40
|
+
interval: 10m
|
|
41
|
+
targetNamespace: vibecarbon
|
|
42
|
+
sourceRef:
|
|
43
|
+
kind: GitRepository
|
|
44
|
+
name: vibecarbon
|
|
45
|
+
path: ./k8s/base
|
|
46
|
+
prune: true
|
|
47
|
+
wait: true
|
|
48
|
+
timeout: 10m
|
|
49
|
+
healthChecks:
|
|
50
|
+
- apiVersion: apps/v1
|
|
51
|
+
kind: Deployment
|
|
52
|
+
name: app
|
|
53
|
+
namespace: vibecarbon
|
|
54
|
+
---
|
|
55
|
+
# Supabase chart install (Phase 2 overlay from 2026-04-20 refactor).
|
|
56
|
+
# The `supabase-values` ConfigMap content is generated by kustomize from
|
|
57
|
+
# values.yaml inside the overlay — Flux's kustomize-controller runs the
|
|
58
|
+
# same generation as `kubectl apply -k`.
|
|
59
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
60
|
+
kind: Kustomization
|
|
61
|
+
metadata:
|
|
62
|
+
name: vibecarbon-supabase
|
|
63
|
+
namespace: flux-system
|
|
64
|
+
spec:
|
|
65
|
+
interval: 10m
|
|
66
|
+
targetNamespace: flux-system
|
|
67
|
+
sourceRef:
|
|
68
|
+
kind: GitRepository
|
|
69
|
+
name: vibecarbon
|
|
70
|
+
path: ./k8s/gitops/supabase
|
|
71
|
+
prune: true
|
|
72
|
+
wait: true
|
|
73
|
+
timeout: 30m
|
|
74
|
+
dependsOn:
|
|
75
|
+
- name: vibecarbon-base
|
|
76
|
+
healthChecks:
|
|
77
|
+
- apiVersion: helm.toolkit.fluxcd.io/v2
|
|
78
|
+
kind: HelmRelease
|
|
79
|
+
name: supabase
|
|
80
|
+
namespace: flux-system
|
|
81
|
+
---
|
|
82
|
+
# cert-manager-webhook-hetzner chart install (Phase 3 overlay).
|
|
83
|
+
# Applied unconditionally; the ClusterIssuer DNS01 solver in
|
|
84
|
+
# ./k8s/base/cert-manager/ references the webhook at install time.
|
|
85
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
86
|
+
kind: Kustomization
|
|
87
|
+
metadata:
|
|
88
|
+
name: vibecarbon-cert-manager-webhook-hetzner
|
|
89
|
+
namespace: flux-system
|
|
90
|
+
spec:
|
|
91
|
+
interval: 10m
|
|
92
|
+
targetNamespace: flux-system
|
|
93
|
+
sourceRef:
|
|
94
|
+
kind: GitRepository
|
|
95
|
+
name: vibecarbon
|
|
96
|
+
path: ./k8s/gitops/cert-manager-webhook-hetzner
|
|
97
|
+
prune: true
|
|
98
|
+
wait: true
|
|
99
|
+
timeout: 10m
|
|
100
|
+
dependsOn:
|
|
101
|
+
- name: vibecarbon-base
|
|
102
|
+
healthChecks:
|
|
103
|
+
- apiVersion: helm.toolkit.fluxcd.io/v2
|
|
104
|
+
kind: HelmRelease
|
|
105
|
+
name: cert-manager-webhook-hetzner
|
|
106
|
+
namespace: flux-system
|
|
107
|
+
---
|
|
108
|
+
# Production overlay (region-specific patches on top of ./k8s/base).
|
|
109
|
+
# Applied only when the region matches; the deploy workflow renders the
|
|
110
|
+
# correct overlay name (production-nbg1, production-hel1, etc.) into a
|
|
111
|
+
# Kustomization name specific to the cluster at apply time.
|
|
112
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
113
|
+
kind: Kustomization
|
|
114
|
+
metadata:
|
|
115
|
+
name: vibecarbon-production-nbg1
|
|
116
|
+
namespace: flux-system
|
|
117
|
+
spec:
|
|
118
|
+
interval: 10m
|
|
119
|
+
targetNamespace: vibecarbon
|
|
120
|
+
sourceRef:
|
|
121
|
+
kind: GitRepository
|
|
122
|
+
name: vibecarbon
|
|
123
|
+
path: ./k8s/overlays/production-nbg1
|
|
124
|
+
prune: true
|
|
125
|
+
wait: true
|
|
126
|
+
timeout: 10m
|
|
127
|
+
dependsOn:
|
|
128
|
+
- name: vibecarbon-base
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Flux GitRepository + Kustomizations for the standby cluster (HA setup).
|
|
3
|
+
#
|
|
4
|
+
# Mirror of clusters/primary/vibecarbon.yaml, minus the supabase
|
|
5
|
+
# HelmRelease (the standby only runs replication-ready base resources;
|
|
6
|
+
# Supabase runs on primary and replicates its DB to the standby's
|
|
7
|
+
# postgres StatefulSet). The path layout + templating is identical.
|
|
8
|
+
#
|
|
9
|
+
# Applied once by the deploy workflow at first standby-cluster bootstrap.
|
|
10
|
+
apiVersion: source.toolkit.fluxcd.io/v1
|
|
11
|
+
kind: GitRepository
|
|
12
|
+
metadata:
|
|
13
|
+
name: vibecarbon
|
|
14
|
+
namespace: flux-system
|
|
15
|
+
spec:
|
|
16
|
+
interval: 1m
|
|
17
|
+
url: https://github.com/{{GITHUB_OWNER}}/{{PROJECT_NAME}}
|
|
18
|
+
ref:
|
|
19
|
+
branch: main
|
|
20
|
+
secretRef:
|
|
21
|
+
name: flux-system
|
|
22
|
+
---
|
|
23
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
24
|
+
kind: Kustomization
|
|
25
|
+
metadata:
|
|
26
|
+
name: vibecarbon-base
|
|
27
|
+
namespace: flux-system
|
|
28
|
+
spec:
|
|
29
|
+
interval: 10m
|
|
30
|
+
targetNamespace: vibecarbon
|
|
31
|
+
sourceRef:
|
|
32
|
+
kind: GitRepository
|
|
33
|
+
name: vibecarbon
|
|
34
|
+
path: ./k8s/base
|
|
35
|
+
prune: true
|
|
36
|
+
wait: true
|
|
37
|
+
timeout: 10m
|
|
38
|
+
healthChecks:
|
|
39
|
+
- apiVersion: apps/v1
|
|
40
|
+
kind: StatefulSet
|
|
41
|
+
name: postgres
|
|
42
|
+
namespace: vibecarbon
|
|
43
|
+
---
|
|
44
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
45
|
+
kind: Kustomization
|
|
46
|
+
metadata:
|
|
47
|
+
name: vibecarbon-cert-manager-webhook-hetzner
|
|
48
|
+
namespace: flux-system
|
|
49
|
+
spec:
|
|
50
|
+
interval: 10m
|
|
51
|
+
targetNamespace: flux-system
|
|
52
|
+
sourceRef:
|
|
53
|
+
kind: GitRepository
|
|
54
|
+
name: vibecarbon
|
|
55
|
+
path: ./k8s/gitops/cert-manager-webhook-hetzner
|
|
56
|
+
prune: true
|
|
57
|
+
wait: true
|
|
58
|
+
timeout: 10m
|
|
59
|
+
dependsOn:
|
|
60
|
+
- name: vibecarbon-base
|
|
61
|
+
healthChecks:
|
|
62
|
+
- apiVersion: helm.toolkit.fluxcd.io/v2
|
|
63
|
+
kind: HelmRelease
|
|
64
|
+
name: cert-manager-webhook-hetzner
|
|
65
|
+
namespace: flux-system
|
|
66
|
+
---
|
|
67
|
+
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
|
68
|
+
kind: Kustomization
|
|
69
|
+
metadata:
|
|
70
|
+
name: vibecarbon-production-hel1
|
|
71
|
+
namespace: flux-system
|
|
72
|
+
spec:
|
|
73
|
+
interval: 10m
|
|
74
|
+
targetNamespace: vibecarbon
|
|
75
|
+
sourceRef:
|
|
76
|
+
kind: GitRepository
|
|
77
|
+
name: vibecarbon
|
|
78
|
+
path: ./k8s/overlays/production-hel1
|
|
79
|
+
prune: true
|
|
80
|
+
wait: true
|
|
81
|
+
timeout: 10m
|
|
82
|
+
dependsOn:
|
|
83
|
+
- name: vibecarbon-base
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Flux-managed replacement for the former imperative `helm install
|
|
3
|
+
# cert-manager-webhook-hetzner` in deploy.js. Installed only when the
|
|
4
|
+
# deployment uses Hetzner DNS (Cloudflare DNS01 has its own path).
|
|
5
|
+
#
|
|
6
|
+
# The webhook requires: cert-manager CRDs + controller Ready (installed
|
|
7
|
+
# imperatively earlier in deploy) and the `hetzner-api-token` Secret in
|
|
8
|
+
# the cert-manager namespace (created by deploy before this is applied).
|
|
9
|
+
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
10
|
+
kind: HelmRelease
|
|
11
|
+
metadata:
|
|
12
|
+
name: cert-manager-webhook-hetzner
|
|
13
|
+
namespace: flux-system
|
|
14
|
+
spec:
|
|
15
|
+
interval: 10m
|
|
16
|
+
releaseName: cert-manager-webhook-hetzner
|
|
17
|
+
targetNamespace: cert-manager
|
|
18
|
+
chart:
|
|
19
|
+
spec:
|
|
20
|
+
chart: cert-manager-webhook-hetzner
|
|
21
|
+
sourceRef:
|
|
22
|
+
kind: HelmRepository
|
|
23
|
+
name: hetzner-cloud
|
|
24
|
+
namespace: flux-system
|
|
25
|
+
install:
|
|
26
|
+
timeout: 5m
|
|
27
|
+
remediation:
|
|
28
|
+
# First install failures are usually secret-missing or CRD-missing.
|
|
29
|
+
# Fail fast so the deploy surfaces the real issue.
|
|
30
|
+
retries: 0
|
|
31
|
+
upgrade:
|
|
32
|
+
timeout: 5m
|
|
33
|
+
remediation:
|
|
34
|
+
retries: 2
|
|
35
|
+
values:
|
|
36
|
+
secret:
|
|
37
|
+
name: hetzner-api-token
|
|
38
|
+
key: api-token
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Hetzner Cloud Helm chart repository. Used by the
|
|
3
|
+
# cert-manager-webhook-hetzner HelmRelease in this same overlay.
|
|
4
|
+
# Migrated from carbon/k8s/flux/helm-repositories.yaml as part of
|
|
5
|
+
# Phase 3 of the GitOps refactor.
|
|
6
|
+
apiVersion: source.toolkit.fluxcd.io/v1
|
|
7
|
+
kind: HelmRepository
|
|
8
|
+
metadata:
|
|
9
|
+
name: hetzner-cloud
|
|
10
|
+
namespace: flux-system
|
|
11
|
+
spec:
|
|
12
|
+
# 5-minute interval matches Phase 1 convention. Short enough that
|
|
13
|
+
# initial source-controller fetch failures retry within the
|
|
14
|
+
# HelmRelease wait budget.
|
|
15
|
+
interval: 5m
|
|
16
|
+
url: https://charts.hetzner.cloud
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Phase 3 of the GitOps refactor: cert-manager-webhook-hetzner as a
|
|
2
|
+
# single kustomize bundle. Applied via `kubectl apply -k` directly from
|
|
3
|
+
# this directory (no values templating needed — the HelmRelease's
|
|
4
|
+
# values are static).
|
|
5
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
6
|
+
kind: Kustomization
|
|
7
|
+
namespace: flux-system
|
|
8
|
+
resources:
|
|
9
|
+
- helm-repository.yaml
|
|
10
|
+
- helm-release.yaml
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Flux-managed replacement for the former imperative `helm install supabase`
|
|
3
|
+
# in deploy.js. The values shape comes straight from supabase.values.yaml;
|
|
4
|
+
# {{DOMAIN}} and {{PROJECT_NAME}} are substituted at deploy time.
|
|
5
|
+
#
|
|
6
|
+
# The HelmRelease reads secrets from the pre-created vibecarbon-secrets
|
|
7
|
+
# Secret in the vibecarbon namespace (populated by our deploy flow before
|
|
8
|
+
# this resource is applied).
|
|
9
|
+
apiVersion: helm.toolkit.fluxcd.io/v2
|
|
10
|
+
kind: HelmRelease
|
|
11
|
+
metadata:
|
|
12
|
+
name: supabase
|
|
13
|
+
namespace: flux-system
|
|
14
|
+
spec:
|
|
15
|
+
interval: 10m
|
|
16
|
+
releaseName: supabase
|
|
17
|
+
targetNamespace: vibecarbon
|
|
18
|
+
chart:
|
|
19
|
+
spec:
|
|
20
|
+
chart: supabase
|
|
21
|
+
sourceRef:
|
|
22
|
+
kind: HelmRepository
|
|
23
|
+
name: supabase-community
|
|
24
|
+
namespace: flux-system
|
|
25
|
+
install:
|
|
26
|
+
# First-time chart install includes postgres-init + DB migrations + all
|
|
27
|
+
# subchart init containers (wait-for-db). Observed 20+ min on cold nodes
|
|
28
|
+
# where images pull from Docker Hub in parallel. Budget 25m to give it
|
|
29
|
+
# headroom without blowing up the overall deploy timeout.
|
|
30
|
+
timeout: 25m
|
|
31
|
+
remediation:
|
|
32
|
+
# First install failures are usually schema / values / image problems.
|
|
33
|
+
# Fail fast instead of burning another 25m on a doomed retry.
|
|
34
|
+
retries: 0
|
|
35
|
+
upgrade:
|
|
36
|
+
timeout: 15m
|
|
37
|
+
remediation:
|
|
38
|
+
retries: 1
|
|
39
|
+
valuesFrom:
|
|
40
|
+
- kind: ConfigMap
|
|
41
|
+
name: supabase-values
|
|
42
|
+
valuesKey: values.yaml
|
|
43
|
+
# Expose PostgreSQL port 5432 on the node's interface so cross-cluster
|
|
44
|
+
# replication works. The standby cluster's supabase node opens a TCP
|
|
45
|
+
# connection to the primary's public IP on 5432 during pg_basebackup and
|
|
46
|
+
# subsequent streaming. Without hostPort the service is only reachable
|
|
47
|
+
# via ClusterIP or NodePort; NodePort cross-cluster was historically
|
|
48
|
+
# blocked by Hetzner Cloud firewalls even with a rule in place (see
|
|
49
|
+
# memory project_replication_broken.md). hostPort binds the port on the
|
|
50
|
+
# node's host network namespace, so it's reachable at the public node IP
|
|
51
|
+
# — and the Hetzner firewall rule for 5432 that src/lib/deploy/k8s/ha/
|
|
52
|
+
# index.js:254-266 adds now has something to route traffic to.
|
|
53
|
+
postRenderers:
|
|
54
|
+
- kustomize:
|
|
55
|
+
patches:
|
|
56
|
+
- target:
|
|
57
|
+
kind: StatefulSet
|
|
58
|
+
name: supabase-supabase-db
|
|
59
|
+
patch: |
|
|
60
|
+
- op: add
|
|
61
|
+
path: /spec/template/spec/containers/0/ports/-
|
|
62
|
+
value:
|
|
63
|
+
containerPort: 5432
|
|
64
|
+
hostPort: 5432
|
|
65
|
+
protocol: TCP
|
|
66
|
+
name: postgres-host
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Supabase community Helm chart repository.
|
|
3
|
+
# Extracted from carbon/k8s/flux/helm-repositories.yaml as part of the
|
|
4
|
+
# Phase 2 Supabase-kustomize bundle. The other HelmRepository
|
|
5
|
+
# (`hetzner-cloud`) stays in the old file until Phase 3 migrates
|
|
6
|
+
# cert-manager-webhook-hetzner.
|
|
7
|
+
apiVersion: source.toolkit.fluxcd.io/v1
|
|
8
|
+
kind: HelmRepository
|
|
9
|
+
metadata:
|
|
10
|
+
name: supabase-community
|
|
11
|
+
namespace: flux-system
|
|
12
|
+
spec:
|
|
13
|
+
# 5-minute interval matches the global convention set in
|
|
14
|
+
# carbon/k8s/flux/helm-repositories.yaml. Short enough that initial
|
|
15
|
+
# source-controller fetch failures retry within our HelmRelease wait
|
|
16
|
+
# budget.
|
|
17
|
+
interval: 5m
|
|
18
|
+
url: https://supabase-community.github.io/supabase-kubernetes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Phase 2 of the GitOps refactor: Supabase HelmRepository + HelmRelease +
|
|
2
|
+
# values ConfigMap as a single kustomize bundle. See
|
|
3
|
+
# plans/gitops-refactor-2026-04-20.md.
|
|
4
|
+
#
|
|
5
|
+
# How the deploy code uses this:
|
|
6
|
+
# 1. Render carbon/k8s/values/supabase.values.yaml into a tempdir
|
|
7
|
+
# (substituting {{DOMAIN}} + {{PROJECT_NAME}}).
|
|
8
|
+
# 2. Copy this kustomization + helm-repository.yaml + helm-release.yaml
|
|
9
|
+
# into the same tempdir.
|
|
10
|
+
# 3. Run `kubectl apply -k <tempdir>`. Kustomize generates the values
|
|
11
|
+
# ConfigMap from the rendered values.yaml; Flux reconciles
|
|
12
|
+
# HelmRepository → HelmChart → HelmRelease in dependency order.
|
|
13
|
+
# 4. Wait for `helmrelease/supabase` Ready condition.
|
|
14
|
+
#
|
|
15
|
+
# Replaces the imperative apply/poke/wait flow in
|
|
16
|
+
# src/lib/deploy/k8s/index.js (~40 LOC eliminated).
|
|
17
|
+
apiVersion: kustomize.config.k8s.io/v1beta1
|
|
18
|
+
kind: Kustomization
|
|
19
|
+
namespace: flux-system
|
|
20
|
+
resources:
|
|
21
|
+
- helm-repository.yaml
|
|
22
|
+
- helm-release.yaml
|
|
23
|
+
configMapGenerator:
|
|
24
|
+
- name: supabase-values
|
|
25
|
+
files:
|
|
26
|
+
- values.yaml
|
|
27
|
+
generatorOptions:
|
|
28
|
+
# Kustomize defaults to hashed ConfigMap names (supabase-values-abc123)
|
|
29
|
+
# so rolling updates trigger. Our HelmRelease references the name
|
|
30
|
+
# directly via `valuesFrom.name: supabase-values`, so we disable the
|
|
31
|
+
# hash suffix. Flux will notice ConfigMap changes via generation bumps
|
|
32
|
+
# and re-reconcile.
|
|
33
|
+
disableNameSuffixHash: true
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Let's Encrypt ClusterIssuers for the `cloudflare` DNS provider strategy.
|
|
2
|
+
#
|
|
3
|
+
# Uses cert-manager's native Cloudflare DNS-01 solver: the controller
|
|
4
|
+
# writes a TXT record under `_acme-challenge.<domain>` via the
|
|
5
|
+
# Cloudflare API, Let's Encrypt resolves it to validate, no port-80
|
|
6
|
+
# round trip and no interaction with Cloudflare's edge proxy. Required
|
|
7
|
+
# when the domain is orange-clouded (HTTPS upgrade at the edge breaks
|
|
8
|
+
# HTTP-01) and is the right default for any user already running
|
|
9
|
+
# Cloudflare DNS.
|
|
10
|
+
#
|
|
11
|
+
# Requires Secret `cloudflare-api-token` with key `api-token` in the
|
|
12
|
+
# cert-manager namespace, scoped at minimum to:
|
|
13
|
+
# - Zone:DNS:Edit on the target zone
|
|
14
|
+
# - Zone:Zone:Read on all zones (cert-manager reads zone metadata)
|
|
15
|
+
# `applyK3sManifests` creates this Secret from `cloudflareApiToken`
|
|
16
|
+
# before applying these issuers; without it cert-manager Orders pin
|
|
17
|
+
# Pending forever.
|
|
18
|
+
apiVersion: cert-manager.io/v1
|
|
19
|
+
kind: ClusterIssuer
|
|
20
|
+
metadata:
|
|
21
|
+
name: letsencrypt-prod-cloudflare
|
|
22
|
+
spec:
|
|
23
|
+
acme:
|
|
24
|
+
server: https://acme-v02.api.letsencrypt.org/directory
|
|
25
|
+
email: "{{ADMIN_EMAIL}}"
|
|
26
|
+
privateKeySecretRef:
|
|
27
|
+
name: letsencrypt-prod-cloudflare-account-key
|
|
28
|
+
solvers:
|
|
29
|
+
- dns01:
|
|
30
|
+
cloudflare:
|
|
31
|
+
apiTokenSecretRef:
|
|
32
|
+
name: cloudflare-api-token
|
|
33
|
+
key: api-token
|
|
34
|
+
---
|
|
35
|
+
apiVersion: cert-manager.io/v1
|
|
36
|
+
kind: ClusterIssuer
|
|
37
|
+
metadata:
|
|
38
|
+
name: letsencrypt-staging-cloudflare
|
|
39
|
+
spec:
|
|
40
|
+
acme:
|
|
41
|
+
# Staging has higher rate limits but issues untrusted certs.
|
|
42
|
+
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
|
43
|
+
email: "{{ADMIN_EMAIL}}"
|
|
44
|
+
privateKeySecretRef:
|
|
45
|
+
name: letsencrypt-staging-cloudflare-account-key
|
|
46
|
+
solvers:
|
|
47
|
+
- dns01:
|
|
48
|
+
cloudflare:
|
|
49
|
+
apiTokenSecretRef:
|
|
50
|
+
name: cloudflare-api-token
|
|
51
|
+
key: api-token
|