Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions frontend/providers/devbox/deploy/Kubefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ FROM scratch
USER 65532:65532

COPY registry registry
COPY manifests manifests
COPY charts charts
COPY devbox-frontend-entrypoint.sh devbox-frontend-entrypoint.sh

ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV registryAddr="sealos.hub:5000"

CMD ["kubectl apply -f manifests"]
CMD ["bash devbox-frontend-entrypoint.sh"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: devbox-frontend
description: Sealos Devbox Frontend Helm Chart
type: application
version: 1.0.0
appVersion: "latest"
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# User-customizable values for devbox frontend.

devboxConfig:
tlsRejectUnauthorized: "1"
documentUrlZH: https://sealos.run/docs/overview/intro
documentUrlEN: https://sealos.io/docs/overview/intro
privacyUrlZH: https://sealos.run/docs/msa/privacy-policy
privacyUrlEN: https://sealos.io/docs/msa/privacy-policy
monitorURL: http://launchpad-monitor.sealos.svc.cluster.local:8428
accountURL: http://account-service.account-system.svc.cluster.local:2333
rootRuntimeNamespace: devbox-system
currencySymbol: usd
gpuEnable: "false"
retagSvcURL: http://devbox-service.devbox-system.svc.cluster.local:8092
devboxAffinityEnable: "true"
squashEnable: "false"
enableImportFeature: "false"
enableWebideFeature: "false"
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "devbox-frontend.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "devbox-frontend.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "devbox-frontend.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "devbox-frontend.labels" -}}
helm.sh/chart: {{ include "devbox-frontend.chart" . }}
{{ include "devbox-frontend.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "devbox-frontend.selectorLabels" -}}
app.kubernetes.io/name: {{ include "devbox-frontend.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
External hostname without scheme.
*/}}
{{- define "devbox-frontend.externalHost" -}}
{{- $host := .Values.ingress.host | default (printf "devbox.%s" .Values.devboxConfig.cloudDomain) -}}
{{- $port := toString .Values.devboxConfig.cloudPort -}}
{{- if and $port (ne $port "") -}}
{{- printf "%s:%s" $host $port -}}
{{- else -}}
{{- $host -}}
{{- end -}}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{{- if .Values.app.enabled }}
apiVersion: app.sealos.io/v1
kind: App
metadata:
name: {{ .Values.app.name }}
namespace: {{ .Values.app.namespace }}
spec:
data:
desc: Devbox
url: {{ printf "https://%s" (include "devbox-frontend.externalHost" .) | quote }}
icon: {{ printf "https://%s/logo.svg" (include "devbox-frontend.externalHost" .) | quote }}
i18n:
zh:
name: Devbox
zh-Hans:
name: Devbox
name: {{ .Values.app.name }}
type: {{ .Values.app.type }}
displayType: {{ .Values.app.displayType }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "devbox-frontend.fullname" . }}-config
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
data:
config.yaml: |-
addr: :3000
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "devbox-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "devbox-frontend.selectorLabels" . | nindent 6 }}
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template:
metadata:
labels:
{{- include "devbox-frontend.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: devbox-frontend-init
image: "{{ .Values.image }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
env:
- name: DATABASE_URL
value: {{ .Values.devboxConfig.databaseURL | quote }}
- name: DATABASE_PROVIDER
value: {{ .Values.global.featureConfigs.database.type | quote }}
command:
- sh
- -c
args:
- |-
cd /app/providers/devbox
DB_PROVIDER="${DATABASE_PROVIDER:-cockroachdb}"
SCHEMA_PATH="./prisma/cockroach/schema.prisma"
if [ "$DB_PROVIDER" = "postgresql" ] || [ "$DB_PROVIDER" = "postgres" ] || [ "$DB_PROVIDER" = "pg" ]; then
SCHEMA_PATH="./prisma/postgresql/schema.prisma"
HAS_UUID_FN=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_proc WHERE proname='gen_random_uuid' LIMIT 1;")
if [ "$HAS_UUID_FN" != "1" ]; then
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 -c 'CREATE OR REPLACE FUNCTION public.gen_random_uuid() RETURNS uuid LANGUAGE SQL VOLATILE AS $func$ SELECT md5(random()::text || clock_timestamp()::text || txid_current()::text)::uuid; $func$;'
fi
MIGRATION="20260125094114_add_template_repository_kind"
HAS_MIGRATION=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM _prisma_migrations WHERE migration_name='${MIGRATION}' AND rolled_back_at IS NULL LIMIT 1;")
if [ "$HAS_MIGRATION" = "1" ]; then
prisma migrate deploy --schema "$SCHEMA_PATH"
exit 0
fi
HAS_ENUM=$(psql "$DATABASE_URL" -tAc "SELECT 1 FROM pg_enum e JOIN pg_type t ON t.oid = e.enumtypid WHERE t.typname IN ('TemplateRepositoryKind','template_repository_kind') AND e.enumlabel = 'SERVICE' LIMIT 1;")
if [ "$HAS_ENUM" = "1" ]; then
prisma migrate resolve --schema "$SCHEMA_PATH" --applied "$MIGRATION"
fi
fi
prisma migrate deploy --schema "$SCHEMA_PATH"
containers:
- name: {{ include "devbox-frontend.name" . }}
image: "{{ .Values.image }}"
imagePullPolicy: {{ .Values.imagePullPolicy }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
env:
- name: NODE_TLS_REJECT_UNAUTHORIZED
value: {{ .Values.devboxConfig.tlsRejectUnauthorized | quote }}
- name: DOCUMENT_URL_ZH
value: {{ .Values.devboxConfig.documentUrlZH | quote }}
- name: DOCUMENT_URL_EN
value: {{ .Values.devboxConfig.documentUrlEN | quote }}
- name: PRIVACY_URL_ZH
value: {{ .Values.devboxConfig.privacyUrlZH | quote }}
- name: PRIVACY_URL_EN
value: {{ .Values.devboxConfig.privacyUrlEN | quote }}
- name: SEALOS_DOMAIN
value: {{ .Values.devboxConfig.cloudDomain | quote }}
- name: INGRESS_SECRET
value: {{ .Values.devboxConfig.certSecretName | quote }}
- name: REGISTRY_ADDR
value: {{ .Values.devboxConfig.registryAddr | quote }}
- name: DEVBOX_AFFINITY_ENABLE
value: {{ .Values.devboxConfig.devboxAffinityEnable | quote }}
- name: MONITOR_URL
value: {{ .Values.devboxConfig.monitorURL | quote }}
- name: SQUASH_ENABLE
value: {{ .Values.devboxConfig.squashEnable | quote }}
- name: ACCOUNT_URL
value: {{ .Values.devboxConfig.accountURL | quote }}
- name: ROOT_RUNTIME_NAMESPACE
value: {{ .Values.devboxConfig.rootRuntimeNamespace | quote }}
- name: INGRESS_DOMAIN
value: {{ default .Values.devboxConfig.cloudDomain .Values.devboxConfig.ingressDomain | quote }}
- name: CURRENCY_SYMBOL
value: {{ .Values.devboxConfig.currencySymbol | quote }}
- name: GPU_ENABLE
value: {{ .Values.devboxConfig.gpuEnable | quote }}
- name: PRIVACY_URL
value: {{ .Values.devboxConfig.privacyUrlZH | quote }}
- name: RETAG_SVC_URL
value: {{ .Values.devboxConfig.retagSvcURL | quote }}
- name: JWT_SECRET
value: {{ .Values.devboxConfig.jwtInternal | quote }}
- name: REGION_UID
value: {{ .Values.devboxConfig.regionUID | quote }}
- name: DATABASE_URL
value: {{ .Values.devboxConfig.databaseURL | quote }}
- name: DATABASE_PROVIDER
value: {{ .Values.global.featureConfigs.database.type | quote }}
- name: ENABLE_IMPORT_FEATURE
value: {{ .Values.devboxConfig.enableImportFeature | quote }}
- name: ENABLE_WEBIDE_FEATURE
value: {{ .Values.devboxConfig.enableWebideFeature | quote }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: devbox-frontend-volume
mountPath: /config.yaml
subPath: config.yaml
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: devbox-frontend-volume
configMap:
name: {{ include "devbox-frontend.fullname" . }}-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "devbox-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
nginx.ingress.kubernetes.io/configuration-snippet: |
more_clear_headers "X-Frame-Options:";
more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }}; img-src * data: blob: resource: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} https://*.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }}";
more_set_headers "X-Xss-Protection: 1; mode=block";
higress.io/response-header-control-remove: X-Frame-Options
higress.io/response-header-control-update: |
Content-Security-Policy "default-src * blob: data: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }}; img-src * data: blob: resource: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} resource: *.baidu.com *.bdstatic.com; frame-src 'self' {{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} mailto: tel: weixin: mtt: *.baidu.com; frame-ancestors 'self' https://{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }} https://*.{{ .Values.devboxConfig.cloudDomain }}{{- if .Values.devboxConfig.cloudPort -}}:{{ .Values.devboxConfig.cloudPort }}{{- end }}"
X-Xss-Protection "1; mode=block"
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ .Values.ingress.host | default (printf "devbox.%s" .Values.devboxConfig.cloudDomain) | quote }}
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: {{ include "devbox-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
tls:
- hosts:
- {{ .Values.ingress.host | default (printf "devbox.%s" .Values.devboxConfig.cloudDomain) | quote }}
secretName: {{ .Values.ingress.certSecretName | quote }}
---
{{- if .Values.ingress.challenge.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: devbox-challenge
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
annotations:
kubernetes.io/ingress.class: {{ .Values.ingress.className | quote }}
spec:
ingressClassName: {{ .Values.ingress.className | quote }}
rules:
- host: {{ .Values.ingress.challenge.host | quote }}
http:
paths:
- pathType: Prefix
path: {{ .Values.ingress.challenge.path | quote }}
backend:
service:
name: {{ include "devbox-frontend.fullname" . }}
port:
number: {{ .Values.service.port }}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "devbox-frontend.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "devbox-frontend.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- name: http
port: {{ .Values.service.port }}
protocol: TCP
targetPort: {{ .Values.service.port }}
selector:
{{- include "devbox-frontend.selectorLabels" . | nindent 4 }}
Loading
Loading