FRONTEND_URL may hold a list of origins (e.g. CORS needs both
panel.abrban.com and abrban.com). The domain resolvers ran new URL()
on the whole string, so new URL('https://a,https://b').hostname became
"a,https" and leaked into ingress hosts, which k8s then rejected with
the generic "HTTP request failed" surfaced in the UI. CORS likewise
never split the list, so the second origin never matched.
Parse only the first URL for domain/preview-root resolution, and split
the list into an array for enableCors.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removing a custom domain left the Ingress with a stale custom-domain rule
and no preview host, so the platform preview URL 404'd. updateIngress now
resolves the app's stable preview number from its latest deployment and
re-emits the preview host (with cert-manager TLS) whenever no verified
custom domain is set, and removeCustomDomain re-applies the Ingress.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Derive the CNAME target shown to users from the site's public root
domain (PREVIEW_BASE_DOMAIN, e.g. 3fase.ir) instead of the internal
platform domain, which is not a valid public suffix and cannot get a
Let's Encrypt cert. On DNS verification, re-apply the Ingress so Traefik
routes the custom domain and cert-manager issues a cert via HTTP-01,
mirroring the preview-domain flow.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Ingress / preview URLs:
- Default the app Ingress class and ACME HTTP-01 solver to Traefik
(k3s default) via a new INGRESS_CLASS env, instead of hardcoding nginx —
fixes 404s on clusters without ingress-nginx.
- Only put public, real-TLD hosts (custom domain + preview) in the TLS
block; the internal *.apps.cloudhost.local host no longer poisons the
Let's Encrypt order, so certs actually issue.
- Make the per-app preview number stable across redeploys so URLs stop
breaking, and let PREVIEW_BASE_DOMAIN configure the base domain.
Registry pulls:
- Point the k3s registries.yaml mirror endpoint at the registry NodePort on
loopback so node containerd never depends on cluster DNS (image pulls
survive node restarts).
Builds:
- Pin the Kaniko image, use IfNotPresent pull policy, drop the dead build
queue/processor, and retry transient Kubernetes API errors while polling
build jobs.
Logs & apps list:
- fluent-bit reads log files from head so startup output reaches
Elasticsearch.
- Order joined deployments newest-first so the apps list shows the latest
deployment status.
Allocation:
- Reserve in-flight (pending/building) capacity and stop globally degrading
the cluster on a single allocation failure, so concurrent deploys don't
starve or wrongly report "no healthy cluster".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Introduce a catalog-driven Tools Management section under Clusters so
admins can install/uninstall infrastructure tools per cluster: cert-manager
(Helm/jetstack), ClusterIssuer (email + HTTP01 form, depends on cert-manager),
and central Elasticsearch. Cluster creation no longer auto-installs Elastic
or the cloudhost-node-cluster-dns DaemonSet; build bootstrap stays automatic.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Build hosts as <userPrefix>-<deploymentNumber>-preview.<rootDomain> from FRONTEND_URL, wire them through ingress/TLS, and open them from the preview API.
Co-authored-by: Cursor <cursoragent@cursor.com>
Auto port-forward using the registered cluster kubeconfig, default to loopback outside Kubernetes, route log APIs by app cluster, and document platform env settings.
Co-authored-by: Cursor <cursoragent@cursor.com>
Bootstrap configures systemd-resolved for *.cluster.local, installs k3s registries.yaml for the internal registry only, removes the legacy external-registry DaemonSet, and aligns Helm REGISTRY_PULL_URL with the in-cluster registry URL.
Co-authored-by: Cursor <cursoragent@cursor.com>
Assign unpredictable subdomains on create when no custom domain is set, and update deploy UI CNAME hints to reference the app Platform Domain after creation.
Co-authored-by: Cursor <cursoragent@cursor.com>
Remove external registry Ingress (repo.3fase.ir) and route Kaniko push and app pulls through the internal ClusterIP registry. Add RegistryService, ensure StorageClass and pull secrets on deploy, make Elasticsearch install/repair more resilient, and add per-cluster Deploy Elastic controls in admin UI.
Co-authored-by: Cursor <cursoragent@cursor.com>
Auto-reconnect Elasticsearch port-forward after cluster or API restarts, poll log status in the UI, and apply storage changes through billing upgrade for all workloads. Add Redis/RabbitMQ PVC resize, Helm ES credentials for Fluent Bit, and fix deploy progress overlay behavior.
Co-authored-by: Cursor <cursoragent@cursor.com>
Deploy backend, frontend, PostgreSQL, and Redis on Kubernetes with optional Ingress/TLS, SQL migration hooks, and public registry exposure at repo.3fase.ir.
Co-authored-by: Cursor <cursoragent@cursor.com>
Show minutes and local expiry for resource credits; add shared delete hook with row/card loading overlays, detail-page deleting modal, and disabled controls to prevent double-delete.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce product types for managed PostgreSQL, Redis, and RabbitMQ with a dedicated dashboard, Helm-only deploy pipeline, external access, snapshots with progress, and prorated resource or storage upgrades matching application billing rules. PVCs use an expandable StorageClass with automatic migration when legacy disks cannot resize in place.
Co-authored-by: Cursor <cursoragent@cursor.com>
Deployment success now reflects readiness across the application, database, and enabled add-on workloads so scheduling or resource failures do not appear as a running app.
Co-authored-by: Cursor <cursoragent@cursor.com>
Admins and technical staff can reset passwords via PATCH /users/:id/password with scoped permissions for technical users; deploy/source uploads allow up to 10GiB and block deploy when allocated storage is smaller than uploaded archive or DB dump, with an inline error modal.
Co-authored-by: Cursor <cursoragent@cursor.com>
Split optional pricing vs deploy defaults and move custom domain to its own card; parse Mi as decimal GB so fractional memory scales linearly with per-GB rates. Deploy wizard hides env and optional services for WordPress and sanitizes create payloads.
Co-authored-by: Cursor <cursoragent@cursor.com>
Users pick per-service CPU/memory/storage at deploy; admins manage unit rates and deploy defaults. PATCH sends only fields accepted by the pricing-catalog DTO.
Co-authored-by: Cursor <cursoragent@cursor.com>
Derive admin tabs and addon rows from enums, and add Redis/RabbitMQ/ES CPU/RAM/disk to deploy cost using the app runtime unit rates.
Co-authored-by: Cursor <cursoragent@cursor.com>
Store explicit hourly/monthly/yearly rates in pricing_rates and addon_rates, compute deploy costs without cycle conversion, and simplify admin UI and wallet payment to cycle-only.
Co-authored-by: Cursor <cursoragent@cursor.com>
When users delete an app before plan expiry, remaining resources become credits for a new deploy. The deploy calculator shows covered vs additional charges, prices optional services correctly, and prorates extras to days left on the credit.
Co-authored-by: Cursor <cursoragent@cursor.com>
Deploy cloudhost-logging on cluster registration, ship app and optional service logs to ES with owner isolation, and fix Kibana 8.12 auth via kibana_system.
Co-authored-by: Cursor <cursoragent@cursor.com>
Users can open temporary NodePort access with auto-revoke via Bull jobs and a dashboard UI to manage active grants.
Co-authored-by: Cursor <cursoragent@cursor.com>
Read live deployment replica counts from K8s before scaling to zero,
store them on the application as suspendedReplicas, and use that snapshot
when resuming so Start restores the pre-stop replica layout.
Co-authored-by: Cursor <cursoragent@cursor.com>
Use suspendApplication on stop so app, database, Redis, and RabbitMQ
deployments scale to zero. Start uses resumeApplication to bring the
full stack back. Deployment status is updated to stopped/running.
Co-authored-by: Cursor <cursoragent@cursor.com>
Inject APP_URL for Laravel/PHP apps when missing: on create from the
platform subdomain, on custom-domain verification from the verified host,
and at deploy time as a safety net. Never overwrites user-provided values.
Co-authored-by: Cursor <cursoragent@cursor.com>
Use php-cli matching phpVersion instead of composer:2 (PHP 8.5), skip
artisan during dump-autoload, and fail loudly on composer install instead
of swallowing lock-file/platform errors with || true.
Co-authored-by: Cursor <cursoragent@cursor.com>
Laravel images no longer bake config:cache at build time, which ignored
K8s DB env vars. Add DB_CONNECTION, clear config on boot, generate APP_KEY
when missing, run migrations, and rebuild caches at container start.
Co-authored-by: Cursor <cursoragent@cursor.com>
Set Laravel DB env vars in Helm and Kubernetes, fix default port to 80 with a storage-aware entrypoint, and let users upload a .env file during deploy.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace port-forward/netcat PVC upload with kubectl cp for integrity
- Add build cancellation API and session cleanup; deploy catches cancel
- Default port 80 for WordPress, PHP, and Laravel on create
- Build progress modal with cancel; Helm/K8s adjustments for deployments
- Update build and kubernetes specs
Co-authored-by: Cursor <cursoragent@cursor.com>
Add admin endpoints for stack deploy/status and user-facing logs
query API. Register controllers and service in KubernetesModule.
Co-authored-by: Cursor <cursoragent@cursor.com>
Deploy and manage central Elasticsearch + Kibana via K8s API, with
health checks, credentials, and per-user log query helpers.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add namespace, secrets, Elasticsearch StatefulSet, Kibana deployment,
and Fluent Bit RBAC for the central logging stack.
Co-authored-by: Cursor <cursoragent@cursor.com>
Add standalone DNS check endpoint and verify DNS on Next click in the
deploy wizard (step 2). Show error modal with CNAME instructions when
DNS is not configured instead of disabling the Next button. Also make
the custom domain clickable in the app detail header.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Cost calculation now reads custom domain price from PlatformSetting
as fallback when no CUSTOM_DOMAIN_ADDON pricing rule exists
- Convert all custom domain UI text from Persian to English
- Fix toggle switch overflow by adding shrink-0, min-w-0, and proper
absolute positioning
Co-authored-by: Cursor <cursoragent@cursor.com>
Users can assign a custom domain to their app with automatic SSL via
cert-manager. Includes DNS verification flow (CNAME check), Persian
instructions, admin-configurable pricing via PlatformSetting, and
integration into the deploy wizard cost calculation.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Replace k8s.Exec WebSocket with kubectl cp for binary file transfer to PVC
- Fix Python Dockerfile CMD: switch from JSON exec form to shell form to avoid
invalid JSON escape sequences (\|) causing shell parse errors
- Fix Django Dockerfile CMD with same shell form approach
- Add retry logic for ECONNRESET during build job polling
- Update seed.ts default admin email to match actual database
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add helm/kubectl binaries and chart directory to backend Dockerfile
- Extend Helm templates for MongoDB/MariaDB database support (env vars, probes, ports)
- Add Redis and RabbitMQ Helm templates (deployment, service, secret, PVC)
- Add generic app-storage PVC and Fluent Bit sidecar with ES authentication
- Fix imagePullSecrets in K8s API fallback, prevent secret regeneration on redeploy
- Clean up Redis/RabbitMQ/FluentBit resources on app deletion without removing shared secrets
- Fix HelmService chartPath resolution for production Docker builds
Co-authored-by: Cursor <cursoragent@cursor.com>