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,99 @@
|
|
|
1
|
+
Elastic License 2.0 (ELv2)
|
|
2
|
+
|
|
3
|
+
## Acceptance
|
|
4
|
+
|
|
5
|
+
By using the Software, you agree to all of the terms and conditions below.
|
|
6
|
+
|
|
7
|
+
## Copyright License
|
|
8
|
+
|
|
9
|
+
The licensor grants you a non-exclusive, royalty-free, worldwide,
|
|
10
|
+
non-sublicensable, non-transferable license to use, copy, distribute, make
|
|
11
|
+
available, and prepare derivative works of the Software, in each case subject
|
|
12
|
+
to the limitations and conditions below.
|
|
13
|
+
|
|
14
|
+
## Limitations
|
|
15
|
+
|
|
16
|
+
You may not provide the Software to third parties as a hosted or managed
|
|
17
|
+
service, where the service provides users with access to any substantial set
|
|
18
|
+
of the features or functionality of the Software.
|
|
19
|
+
|
|
20
|
+
You may not move, change, disable, or circumvent the license key functionality
|
|
21
|
+
in the Software, and you may not remove or obscure any functionality in the
|
|
22
|
+
Software that is protected by the license key.
|
|
23
|
+
|
|
24
|
+
You may not alter, remove, or obscure any licensing, copyright, or other
|
|
25
|
+
notices of the licensor in the Software. Any use of the licensor's trademarks
|
|
26
|
+
is subject to applicable law.
|
|
27
|
+
|
|
28
|
+
## Patents
|
|
29
|
+
|
|
30
|
+
The licensor grants you a license, under any patent claims the licensor can
|
|
31
|
+
license, or becomes able to license, to make, have made, use, sell, offer for
|
|
32
|
+
sale, import and have imported the Software, in each case subject to the
|
|
33
|
+
limitations and conditions in this license. This license does not cover any
|
|
34
|
+
patent claims that you cause to be infringed by modifications or additions to
|
|
35
|
+
the Software. If you or your company make any written claim that the Software
|
|
36
|
+
infringes or contributes to infringement of any patent, your patent license
|
|
37
|
+
for the Software granted under these terms ends immediately. If your company
|
|
38
|
+
makes such a claim, your patent license ends immediately for work on behalf of
|
|
39
|
+
your company.
|
|
40
|
+
|
|
41
|
+
## Notices
|
|
42
|
+
|
|
43
|
+
You must ensure that anyone who gets a copy of any part of the Software from
|
|
44
|
+
you also gets a copy of these terms.
|
|
45
|
+
|
|
46
|
+
If you modify the Software, you must include in any modified copies of the
|
|
47
|
+
Software prominent notices stating that you have modified the Software.
|
|
48
|
+
|
|
49
|
+
## No Other Rights
|
|
50
|
+
|
|
51
|
+
These terms do not imply any licenses other than those expressly granted in
|
|
52
|
+
these terms.
|
|
53
|
+
|
|
54
|
+
## Termination
|
|
55
|
+
|
|
56
|
+
If you use the Software in violation of these terms, such use is not licensed,
|
|
57
|
+
and your licenses will automatically terminate. If the licensor provides you
|
|
58
|
+
with a notice of your violation, and you cease all violation of this license
|
|
59
|
+
no later than 30 days after you receive that notice, your licenses will be
|
|
60
|
+
reinstated retroactively. However, if you violate these terms after such
|
|
61
|
+
reinstatement, any additional violation of these terms will cause your
|
|
62
|
+
licenses to terminate automatically and permanently.
|
|
63
|
+
|
|
64
|
+
## No Liability
|
|
65
|
+
|
|
66
|
+
As far as the law allows, the Software comes as is, without any warranty or
|
|
67
|
+
condition, and the licensor will not be liable to you for any damages arising
|
|
68
|
+
out of these terms or the use or nature of the Software, under any kind of
|
|
69
|
+
legal claim.
|
|
70
|
+
|
|
71
|
+
## Definitions
|
|
72
|
+
|
|
73
|
+
The "licensor" is the entity offering these terms, Vibecarbon.
|
|
74
|
+
|
|
75
|
+
The "Software" is the software the licensor makes available under these terms,
|
|
76
|
+
including any portion of it.
|
|
77
|
+
|
|
78
|
+
"You" refers to the individual or entity agreeing to these terms.
|
|
79
|
+
|
|
80
|
+
"Your company" is any legal entity, sole proprietorship, or other kind of
|
|
81
|
+
organization that you work for, plus all organizations that have control over,
|
|
82
|
+
are under the control of, or are under common control with that organization.
|
|
83
|
+
"Control" means ownership of substantially all the assets of an entity, or the
|
|
84
|
+
power to direct its management and policies by vote, contract, or otherwise.
|
|
85
|
+
Control can be direct or indirect.
|
|
86
|
+
|
|
87
|
+
"Your licenses" are all the licenses granted to you for the Software under
|
|
88
|
+
these terms.
|
|
89
|
+
|
|
90
|
+
"Use" means anything you do with the Software requiring one of your licenses.
|
|
91
|
+
|
|
92
|
+
"Trademark" means trademarks, service marks, and similar rights.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
Copyright (c) 2026 Vibecarbon
|
|
97
|
+
|
|
98
|
+
For the full Elastic License 2.0 text, see:
|
|
99
|
+
https://www.elastic.co/licensing/elastic-license
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Vibecarbon Kubernetes Deployment (Fullerene Tier)
|
|
2
|
+
|
|
3
|
+
> **Note**: Kubernetes deployment requires a Vibecarbon Fullerene license. For compose-based deployments (including HA with PostgreSQL replication), see the [Hetzner deployment guide](../../docs/deploy-hetzner.md).
|
|
4
|
+
|
|
5
|
+
This directory contains Kubernetes manifests for deploying Vibecarbon with enterprise-grade autoscaling and high availability.
|
|
6
|
+
|
|
7
|
+
## Architecture Overview
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Cloudflare DNS
|
|
11
|
+
(health checks, failover)
|
|
12
|
+
|
|
|
13
|
+
+---------------+---------------+
|
|
14
|
+
| |
|
|
15
|
+
Hetzner LB (nbg1) Hetzner LB (hel1)
|
|
16
|
+
| |
|
|
17
|
+
k3s Cluster k3s Cluster
|
|
18
|
+
+--------------+ +--------------+
|
|
19
|
+
| app: 2-10 | | app: 0 (standby)
|
|
20
|
+
| kong: 2 | WAL repl | kong: 0
|
|
21
|
+
| rest: 2-5 | <-----------> | rest: 0
|
|
22
|
+
| PostgreSQL | | PostgreSQL (replica)
|
|
23
|
+
| PRIMARY | | HOT STANDBY
|
|
24
|
+
+--------------+ +--------------+
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Directory Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
k8s/
|
|
31
|
+
├── base/ # Base Kubernetes manifests
|
|
32
|
+
│ ├── namespace.yaml
|
|
33
|
+
│ ├── network-policy.yaml # Default-deny NetworkPolicy
|
|
34
|
+
│ ├── secrets/ # Secrets and ConfigMaps
|
|
35
|
+
│ ├── hetzner-ccm/ # Hetzner Cloud Controller
|
|
36
|
+
│ ├── hetzner-csi/ # Hetzner CSI Driver
|
|
37
|
+
│ ├── app/ # Vibecarbon application
|
|
38
|
+
│ │ ├── deployment.yaml
|
|
39
|
+
│ │ ├── local-registry.yaml # Local OCI registry for k3s image distribution
|
|
40
|
+
│ │ └── rbac.yaml # ServiceAccount for pod listing
|
|
41
|
+
│ ├── supabase/ # Supabase services
|
|
42
|
+
│ │ ├── postgres/
|
|
43
|
+
│ │ ├── kong/
|
|
44
|
+
│ │ ├── auth/
|
|
45
|
+
│ │ ├── rest/
|
|
46
|
+
│ │ ├── realtime/
|
|
47
|
+
│ │ ├── storage/
|
|
48
|
+
│ │ ├── imgproxy/
|
|
49
|
+
│ │ ├── meta/
|
|
50
|
+
│ │ └── studio/
|
|
51
|
+
│ └── traefik/ # Ingress controller
|
|
52
|
+
├── infra/ # Infrastructure-level resources (applied once)
|
|
53
|
+
│ └── cert-manager-resources/ # ClusterIssuers for TLS certificates
|
|
54
|
+
├── overlays/ # Environment-specific patches
|
|
55
|
+
│ ├── production-nbg1/ # Primary region (Nuremberg)
|
|
56
|
+
│ └── production-hel1/ # Standby region (Helsinki)
|
|
57
|
+
└── flux/ # GitOps configuration
|
|
58
|
+
└── clusters/
|
|
59
|
+
├── primary/
|
|
60
|
+
└── standby/
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Prerequisites
|
|
64
|
+
|
|
65
|
+
1. **Hetzner Cloud Account** with API token
|
|
66
|
+
2. **Cloudflare Account** with API token and domain
|
|
67
|
+
3. **kubectl** installed locally
|
|
68
|
+
4. **kustomize** installed (or use `kubectl -k`)
|
|
69
|
+
5. **Flux CLI** (optional, for GitOps)
|
|
70
|
+
|
|
71
|
+
## Deployment Steps
|
|
72
|
+
|
|
73
|
+
### Step 1: Provision Infrastructure
|
|
74
|
+
|
|
75
|
+
`vibecarbon deploy <env>` provisions the Hetzner servers, network, firewall,
|
|
76
|
+
and floating IP via Pulumi (Automation API; no Pulumi CLI required). Stack
|
|
77
|
+
state is stored in your Hetzner S3 bucket — there are no `.tf` files or
|
|
78
|
+
local state to manage.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
vibecarbon deploy production
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For HA (two regions), pass `--ha`. The command writes the resulting
|
|
85
|
+
kubeconfig(s) to `~/.vibecarbon/kubeconfig-<env>-<region>.yaml`.
|
|
86
|
+
|
|
87
|
+
### Step 2: Get Kubeconfig
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
export KUBECONFIG=~/.vibecarbon/kubeconfig-production-nbg1.yaml
|
|
91
|
+
|
|
92
|
+
# For HA, the standby kubeconfig is alongside it:
|
|
93
|
+
# ~/.vibecarbon/kubeconfig-production-hel1.yaml
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Step 3: Deploy Secrets
|
|
97
|
+
|
|
98
|
+
Before deploying, update the secrets with real values:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Create secrets manually (recommended for initial setup)
|
|
102
|
+
kubectl create secret generic vibecarbon-secrets \
|
|
103
|
+
--namespace=vibecarbon \
|
|
104
|
+
--from-literal=DB_PASSWORD=<your-password> \
|
|
105
|
+
--from-literal=JWT_SECRET=<your-jwt-secret> \
|
|
106
|
+
--from-literal=ANON_KEY=<your-anon-key> \
|
|
107
|
+
--from-literal=SERVICE_ROLE_KEY=<your-service-key> \
|
|
108
|
+
--from-literal=REALTIME_SECRET=<your-realtime-secret> \
|
|
109
|
+
--from-literal=VAULT_ENC_KEY=<your-vault-key> \
|
|
110
|
+
--from-literal=PG_META_CRYPTO_KEY=<your-meta-key> \
|
|
111
|
+
--from-literal=LOGFLARE_API_KEY=<your-logflare-key>
|
|
112
|
+
|
|
113
|
+
kubectl create secret generic hcloud-token \
|
|
114
|
+
--namespace=vibecarbon \
|
|
115
|
+
--from-literal=token=<your-hetzner-token>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Step 4: Deploy to Primary Cluster
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
export KUBECONFIG=kubeconfig-nbg1.yaml
|
|
122
|
+
|
|
123
|
+
# Using kustomize
|
|
124
|
+
kubectl apply -k overlays/production-nbg1
|
|
125
|
+
|
|
126
|
+
# Or using kubectl
|
|
127
|
+
kustomize build overlays/production-nbg1 | kubectl apply -f -
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Step 5: Deploy to Standby Cluster
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
export KUBECONFIG=kubeconfig-hel1.yaml
|
|
134
|
+
kubectl apply -k overlays/production-hel1
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Step 6: Verify Deployment
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
# Check pods
|
|
141
|
+
kubectl get pods -n vibecarbon
|
|
142
|
+
|
|
143
|
+
# Check HPA
|
|
144
|
+
kubectl get hpa -n vibecarbon
|
|
145
|
+
|
|
146
|
+
# Check services
|
|
147
|
+
kubectl get svc -n vibecarbon
|
|
148
|
+
|
|
149
|
+
# Check ingress/load balancer
|
|
150
|
+
kubectl get svc traefik -n vibecarbon
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Autoscaling
|
|
154
|
+
|
|
155
|
+
### Horizontal Pod Autoscaler (HPA)
|
|
156
|
+
|
|
157
|
+
The following services have HPA configured:
|
|
158
|
+
|
|
159
|
+
| Service | Min Replicas | Max Replicas | CPU Target |
|
|
160
|
+
|---------|--------------|--------------|------------|
|
|
161
|
+
| app | 2 | 10 | 70% |
|
|
162
|
+
| rest | 2 | 5 | 70% |
|
|
163
|
+
|
|
164
|
+
Worker VMs are provisioned via `vibecarbon deploy --min-workers N --max-workers M` (default `min=1, max=3`). The static floor is Pulumi-managed; cluster-autoscaler spawns and reaps additional workers (up to `max - min`) based on pending-pod pressure. See the Cluster Autoscaler section below.
|
|
165
|
+
|
|
166
|
+
### Cluster Autoscaler (VPS-level)
|
|
167
|
+
|
|
168
|
+
VPS-level autoscaling is on by default with a bounded ceiling — every k8s deploy installs cluster-autoscaler against the Hetzner Cloud API.
|
|
169
|
+
|
|
170
|
+
**Defaults**
|
|
171
|
+
|
|
172
|
+
- `min=1, max=3` — one static worker, plus up to two CA-spawned workers on demand.
|
|
173
|
+
|
|
174
|
+
**Deploy-time bounds**
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Override the default bounds at deploy
|
|
178
|
+
vibecarbon deploy prod --k8s --min-workers 2 --max-workers 10
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Re-tuning bounds without a full deploy**
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# Change the upper bound only — no Pulumi run needed for the CA-managed pool
|
|
185
|
+
vibecarbon scale prod --max-workers 8
|
|
186
|
+
|
|
187
|
+
# Or both bounds at once
|
|
188
|
+
vibecarbon scale prod --min-workers 2 --max-workers 8
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Static floor + CA-on-top model**
|
|
192
|
+
|
|
193
|
+
| Layer | Managed by | Server name pattern |
|
|
194
|
+
|-------|-----------|---------------------|
|
|
195
|
+
| Static floor (`minWorkers` nodes) | Pulumi | `<cluster>-worker-N` (deterministic) |
|
|
196
|
+
| CA-spawned (0 to `max - min` extra nodes) | cluster-autoscaler via Hetzner Cloud API | `worker-pool-<rand>` |
|
|
197
|
+
|
|
198
|
+
The static floor is what your project quota is reserved for; CA scales additional workers on top of it as pending pods appear, then reaps them when CPU pressure subsides.
|
|
199
|
+
|
|
200
|
+
**HA mode symmetry**
|
|
201
|
+
|
|
202
|
+
In `--ha` mode both clusters use the same `--min-workers/--max-workers` bounds — the standby is kept failover-ready (its scaler doesn't bring up additional workers while the cluster is dormant, but the bounds are pre-configured so failover is instant).
|
|
203
|
+
|
|
204
|
+
**Hetzner project quota**
|
|
205
|
+
|
|
206
|
+
Trial Hetzner Cloud projects cap at ~50 servers across all resource types; verified accounts get higher limits. If you set `--max-workers` aggressively, make sure your project quota covers the worst case across all clusters in the project (master + supabase + workers + CA-spawned, x2 in HA).
|
|
207
|
+
|
|
208
|
+
**Token requirement: Read+Write**
|
|
209
|
+
|
|
210
|
+
The Hetzner Cloud API token in your `hcloud-token` secret must have **Read+Write** permissions on the project. Read-only tokens cannot create servers, and CA scale-up will fail silently with permission errors in the cluster-autoscaler pod logs. Verify with:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
kubectl logs -n kube-system -l app=cluster-autoscaler --tail=200 | grep -i 'permission\|forbidden\|unauthor'
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Failover
|
|
217
|
+
|
|
218
|
+
Cloudflare DNS health checks monitor both regions every 60 seconds. When the primary region fails, initiate failover with one command:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
vibecarbon failover prod
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
This promotes the standby database to primary, scales up services in the standby region, and updates DNS to point to the new primary.
|
|
225
|
+
|
|
226
|
+
### Manual Failover (kubectl)
|
|
227
|
+
|
|
228
|
+
To failover manually with kubectl:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Scale up standby
|
|
232
|
+
export KUBECONFIG=kubeconfig-hel1.yaml
|
|
233
|
+
kubectl scale deployment app --replicas=2 -n vibecarbon
|
|
234
|
+
kubectl scale deployment kong --replicas=2 -n vibecarbon
|
|
235
|
+
kubectl scale deployment auth --replicas=2 -n vibecarbon
|
|
236
|
+
kubectl scale deployment rest --replicas=2 -n vibecarbon
|
|
237
|
+
kubectl scale deployment realtime --replicas=2 -n vibecarbon
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Monitoring (Optional)
|
|
241
|
+
|
|
242
|
+
To enable Prometheus + Grafana monitoring:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
kubectl apply -k base/monitoring/ # If monitoring manifests exist
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Troubleshooting
|
|
249
|
+
|
|
250
|
+
### Pods not starting
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
kubectl describe pod <pod-name> -n vibecarbon
|
|
254
|
+
kubectl logs <pod-name> -n vibecarbon
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Load Balancer not created
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
kubectl describe svc traefik -n vibecarbon
|
|
261
|
+
kubectl logs -l app=hcloud-cloud-controller-manager -n kube-system
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Cost Estimate
|
|
265
|
+
|
|
266
|
+
| Component | Monthly Cost (EUR) |
|
|
267
|
+
|-----------|-------------------|
|
|
268
|
+
| k3s master x2 | 8.70 |
|
|
269
|
+
| k3s workers (1-10) | 4-44 |
|
|
270
|
+
| Hetzner LB x2 | 10.78 |
|
|
271
|
+
| Hetzner volumes | ~2 |
|
|
272
|
+
| **Total** | **~25-65** |
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: app
|
|
5
|
+
labels:
|
|
6
|
+
app: vibecarbon-app
|
|
7
|
+
component: application
|
|
8
|
+
spec:
|
|
9
|
+
replicas: 2
|
|
10
|
+
# 900s (15m) — cold k8s deploys race the rollout window: `kubectl set image`
|
|
11
|
+
# triggers the rollout BEFORE `helm install supabase --wait` returns, and the
|
|
12
|
+
# app's readiness probe (/api/health/ready) stays 503 until kong is up. On
|
|
13
|
+
# the slow HA path the sideload + helm install consumed >29m before kong was
|
|
14
|
+
# reachable; the old 120s deadline tripped before kong existed and the
|
|
15
|
+
# subsequent `kubectl rollout status` failed even though pods were healthy
|
|
16
|
+
# by then. 900s covers worst-observed cold path; warm rollouts still finish
|
|
17
|
+
# in <60s so this only matters on the cold cycle.
|
|
18
|
+
progressDeadlineSeconds: 900
|
|
19
|
+
strategy:
|
|
20
|
+
type: RollingUpdate
|
|
21
|
+
rollingUpdate:
|
|
22
|
+
maxUnavailable: 0
|
|
23
|
+
maxSurge: 1
|
|
24
|
+
selector:
|
|
25
|
+
matchLabels:
|
|
26
|
+
app: vibecarbon-app
|
|
27
|
+
template:
|
|
28
|
+
metadata:
|
|
29
|
+
labels:
|
|
30
|
+
app: vibecarbon-app
|
|
31
|
+
component: application
|
|
32
|
+
spec:
|
|
33
|
+
terminationGracePeriodSeconds: 30
|
|
34
|
+
serviceAccountName: vibecarbon-app
|
|
35
|
+
containers:
|
|
36
|
+
- name: app
|
|
37
|
+
image: ghcr.io/{{GITHUB_OWNER}}/{{PROJECT_NAME}}:main
|
|
38
|
+
imagePullPolicy: IfNotPresent
|
|
39
|
+
securityContext:
|
|
40
|
+
runAsNonRoot: true
|
|
41
|
+
runAsUser: 1000
|
|
42
|
+
runAsGroup: 1000
|
|
43
|
+
readOnlyRootFilesystem: true
|
|
44
|
+
allowPrivilegeEscalation: false
|
|
45
|
+
capabilities:
|
|
46
|
+
drop:
|
|
47
|
+
- ALL
|
|
48
|
+
ports:
|
|
49
|
+
- containerPort: 3000
|
|
50
|
+
name: http
|
|
51
|
+
envFrom:
|
|
52
|
+
- configMapRef:
|
|
53
|
+
name: vibecarbon-config
|
|
54
|
+
env:
|
|
55
|
+
- name: NODE_ENV
|
|
56
|
+
value: production
|
|
57
|
+
- name: SUPABASE_URL
|
|
58
|
+
valueFrom:
|
|
59
|
+
configMapKeyRef:
|
|
60
|
+
name: vibecarbon-config
|
|
61
|
+
key: KONG_URL
|
|
62
|
+
- name: SITE_URL
|
|
63
|
+
valueFrom:
|
|
64
|
+
configMapKeyRef:
|
|
65
|
+
name: vibecarbon-config
|
|
66
|
+
key: SITE_URL
|
|
67
|
+
- name: SUPABASE_ANON_KEY
|
|
68
|
+
valueFrom:
|
|
69
|
+
secretKeyRef:
|
|
70
|
+
name: vibecarbon-secrets
|
|
71
|
+
key: ANON_KEY
|
|
72
|
+
- name: SUPABASE_SERVICE_ROLE_KEY
|
|
73
|
+
valueFrom:
|
|
74
|
+
secretKeyRef:
|
|
75
|
+
name: vibecarbon-secrets
|
|
76
|
+
key: SERVICE_ROLE_KEY
|
|
77
|
+
resources:
|
|
78
|
+
requests:
|
|
79
|
+
cpu: 100m
|
|
80
|
+
memory: 256Mi
|
|
81
|
+
limits:
|
|
82
|
+
cpu: 1000m
|
|
83
|
+
memory: 512Mi
|
|
84
|
+
startupProbe:
|
|
85
|
+
httpGet:
|
|
86
|
+
path: /api/health
|
|
87
|
+
port: http
|
|
88
|
+
failureThreshold: 5
|
|
89
|
+
periodSeconds: 1
|
|
90
|
+
livenessProbe:
|
|
91
|
+
httpGet:
|
|
92
|
+
path: /api/health
|
|
93
|
+
port: http
|
|
94
|
+
initialDelaySeconds: 10
|
|
95
|
+
periodSeconds: 30
|
|
96
|
+
timeoutSeconds: 5
|
|
97
|
+
failureThreshold: 5
|
|
98
|
+
readinessProbe:
|
|
99
|
+
httpGet:
|
|
100
|
+
path: /api/health/ready
|
|
101
|
+
port: http
|
|
102
|
+
initialDelaySeconds: 0
|
|
103
|
+
periodSeconds: 3
|
|
104
|
+
timeoutSeconds: 3
|
|
105
|
+
failureThreshold: 3
|
|
106
|
+
lifecycle:
|
|
107
|
+
preStop:
|
|
108
|
+
exec:
|
|
109
|
+
command:
|
|
110
|
+
- sh
|
|
111
|
+
- -c
|
|
112
|
+
- sleep 5
|
|
113
|
+
volumeMounts:
|
|
114
|
+
- name: tmp
|
|
115
|
+
mountPath: /tmp
|
|
116
|
+
volumes:
|
|
117
|
+
- name: tmp
|
|
118
|
+
emptyDir: {}
|
|
119
|
+
affinity:
|
|
120
|
+
podAntiAffinity:
|
|
121
|
+
preferredDuringSchedulingIgnoredDuringExecution:
|
|
122
|
+
- weight: 100
|
|
123
|
+
podAffinityTerm:
|
|
124
|
+
labelSelector:
|
|
125
|
+
matchLabels:
|
|
126
|
+
app: vibecarbon-app
|
|
127
|
+
topologyKey: kubernetes.io/hostname
|
|
128
|
+
securityContext:
|
|
129
|
+
seccompProfile:
|
|
130
|
+
type: RuntimeDefault
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
apiVersion: autoscaling/v2
|
|
2
|
+
kind: HorizontalPodAutoscaler
|
|
3
|
+
metadata:
|
|
4
|
+
name: app
|
|
5
|
+
labels:
|
|
6
|
+
app: vibecarbon-app
|
|
7
|
+
component: application
|
|
8
|
+
spec:
|
|
9
|
+
scaleTargetRef:
|
|
10
|
+
apiVersion: apps/v1
|
|
11
|
+
kind: Deployment
|
|
12
|
+
name: app
|
|
13
|
+
minReplicas: 2
|
|
14
|
+
maxReplicas: 10
|
|
15
|
+
metrics:
|
|
16
|
+
- type: Resource
|
|
17
|
+
resource:
|
|
18
|
+
name: cpu
|
|
19
|
+
target:
|
|
20
|
+
type: Utilization
|
|
21
|
+
averageUtilization: 70
|
|
22
|
+
- type: Resource
|
|
23
|
+
resource:
|
|
24
|
+
name: memory
|
|
25
|
+
target:
|
|
26
|
+
type: Utilization
|
|
27
|
+
averageUtilization: 80
|
|
28
|
+
behavior:
|
|
29
|
+
scaleUp:
|
|
30
|
+
stabilizationWindowSeconds: 60
|
|
31
|
+
policies:
|
|
32
|
+
- type: Pods
|
|
33
|
+
value: 4
|
|
34
|
+
periodSeconds: 60
|
|
35
|
+
- type: Percent
|
|
36
|
+
value: 100
|
|
37
|
+
periodSeconds: 60
|
|
38
|
+
selectPolicy: Max
|
|
39
|
+
scaleDown:
|
|
40
|
+
stabilizationWindowSeconds: 300
|
|
41
|
+
policies:
|
|
42
|
+
- type: Pods
|
|
43
|
+
value: 1
|
|
44
|
+
periodSeconds: 120
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
apiVersion: networking.k8s.io/v1
|
|
2
|
+
kind: NetworkPolicy
|
|
3
|
+
metadata:
|
|
4
|
+
name: app-policy
|
|
5
|
+
namespace: vibecarbon
|
|
6
|
+
spec:
|
|
7
|
+
podSelector:
|
|
8
|
+
matchLabels:
|
|
9
|
+
app: vibecarbon-app
|
|
10
|
+
policyTypes:
|
|
11
|
+
- Ingress
|
|
12
|
+
- Egress
|
|
13
|
+
ingress:
|
|
14
|
+
# Allow traffic from Traefik ingress controller (runs in same namespace)
|
|
15
|
+
- from:
|
|
16
|
+
- podSelector:
|
|
17
|
+
matchLabels:
|
|
18
|
+
app: vibecarbon-traefik
|
|
19
|
+
ports:
|
|
20
|
+
- protocol: TCP
|
|
21
|
+
port: 3000
|
|
22
|
+
egress:
|
|
23
|
+
# Allow connection to Kong (Supabase API gateway)
|
|
24
|
+
- to:
|
|
25
|
+
- podSelector:
|
|
26
|
+
matchLabels:
|
|
27
|
+
app: vibecarbon-kong
|
|
28
|
+
ports:
|
|
29
|
+
- protocol: TCP
|
|
30
|
+
port: 8000
|
|
31
|
+
# Allow connection to database (direct queries)
|
|
32
|
+
- to:
|
|
33
|
+
- podSelector:
|
|
34
|
+
matchLabels:
|
|
35
|
+
app: vibecarbon-postgres
|
|
36
|
+
ports:
|
|
37
|
+
- protocol: TCP
|
|
38
|
+
port: 5432
|
|
39
|
+
# Allow access to Kubernetes API server for reading pod logs (admin dashboard)
|
|
40
|
+
# 10.43.0.1:443 = ClusterIP via kube-proxy DNAT (works on worker nodes)
|
|
41
|
+
- to:
|
|
42
|
+
- ipBlock:
|
|
43
|
+
cidr: 10.43.0.1/32
|
|
44
|
+
ports:
|
|
45
|
+
- protocol: TCP
|
|
46
|
+
port: 443
|
|
47
|
+
# 0.0.0.0/0:6443 = apiserver, dial-anywhere on apiserver-protocol port.
|
|
48
|
+
# See carbon/k8s/base/traefik/network-policy.yaml for the full RCA. tl;dr:
|
|
49
|
+
# kube-proxy DNATs 10.43.0.1 to the master's node IP at the OUTPUT chain
|
|
50
|
+
# BEFORE the CNI evaluates egress, so the policy sees the post-NAT IP.
|
|
51
|
+
# With --node-ip=public (master-init.sh) and the CCM HCLOUD_NETWORK patch
|
|
52
|
+
# reverted (kubelet cert SAN), the master IP is public — outside any
|
|
53
|
+
# private CIDR we could list. Allow any destination on 6443; deny-by-
|
|
54
|
+
# default is preserved on every other port.
|
|
55
|
+
- to:
|
|
56
|
+
- ipBlock:
|
|
57
|
+
cidr: 0.0.0.0/0
|
|
58
|
+
ports:
|
|
59
|
+
- protocol: TCP
|
|
60
|
+
port: 6443
|
|
61
|
+
# Allow outbound HTTPS (Stripe, SMTP provider, external APIs)
|
|
62
|
+
- to:
|
|
63
|
+
- ipBlock:
|
|
64
|
+
cidr: 0.0.0.0/0
|
|
65
|
+
except:
|
|
66
|
+
- 10.0.0.0/8
|
|
67
|
+
- 172.16.0.0/12
|
|
68
|
+
- 192.168.0.0/16
|
|
69
|
+
ports:
|
|
70
|
+
- protocol: TCP
|
|
71
|
+
port: 443
|
|
72
|
+
# Allow connection to Redis (if configured)
|
|
73
|
+
- to:
|
|
74
|
+
- podSelector:
|
|
75
|
+
matchLabels:
|
|
76
|
+
app: redis
|
|
77
|
+
ports:
|
|
78
|
+
- protocol: TCP
|
|
79
|
+
port: 6379
|
|
80
|
+
# Allow health checks to optional services (n8n, metabase, observability)
|
|
81
|
+
# These are only used for the admin services-status API; unused rules are harmless.
|
|
82
|
+
- to:
|
|
83
|
+
- podSelector:
|
|
84
|
+
matchLabels:
|
|
85
|
+
app: vibecarbon-n8n
|
|
86
|
+
ports:
|
|
87
|
+
- protocol: TCP
|
|
88
|
+
port: 5678
|
|
89
|
+
- to:
|
|
90
|
+
- podSelector:
|
|
91
|
+
matchLabels:
|
|
92
|
+
app: metabase
|
|
93
|
+
ports:
|
|
94
|
+
- protocol: TCP
|
|
95
|
+
port: 3000
|
|
96
|
+
- to:
|
|
97
|
+
- podSelector:
|
|
98
|
+
matchLabels:
|
|
99
|
+
app: vibecarbon-prometheus
|
|
100
|
+
ports:
|
|
101
|
+
- protocol: TCP
|
|
102
|
+
port: 9090
|
|
103
|
+
- to:
|
|
104
|
+
- podSelector:
|
|
105
|
+
matchLabels:
|
|
106
|
+
app: vibecarbon-grafana
|
|
107
|
+
ports:
|
|
108
|
+
- protocol: TCP
|
|
109
|
+
port: 3000
|
|
110
|
+
- to:
|
|
111
|
+
- podSelector:
|
|
112
|
+
matchLabels:
|
|
113
|
+
app: vibecarbon-loki
|
|
114
|
+
ports:
|
|
115
|
+
- protocol: TCP
|
|
116
|
+
port: 3100
|
|
117
|
+
# Allow health checks to Studio (for admin services-status API)
|
|
118
|
+
- to:
|
|
119
|
+
- podSelector:
|
|
120
|
+
matchLabels:
|
|
121
|
+
app: vibecarbon-studio
|
|
122
|
+
ports:
|
|
123
|
+
- protocol: TCP
|
|
124
|
+
port: 3000
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
apiVersion: policy/v1
|
|
2
|
+
kind: PodDisruptionBudget
|
|
3
|
+
metadata:
|
|
4
|
+
name: app
|
|
5
|
+
labels:
|
|
6
|
+
app: vibecarbon-app
|
|
7
|
+
component: application
|
|
8
|
+
spec:
|
|
9
|
+
# Ensure at least 1 pod is available during voluntary disruptions
|
|
10
|
+
# (e.g., node upgrades, cluster maintenance, kubectl drain)
|
|
11
|
+
minAvailable: 1
|
|
12
|
+
selector:
|
|
13
|
+
matchLabels:
|
|
14
|
+
app: vibecarbon-app
|