diff --git a/frontend/providers/invite/deploy/Kubefile b/frontend/providers/invite/deploy/Kubefile
new file mode 100644
index 00000000000..ec1504e7dfb
--- /dev/null
+++ b/frontend/providers/invite/deploy/Kubefile
@@ -0,0 +1,13 @@
+FROM scratch
+
+USER 65532:65532
+
+COPY registry registry
+COPY manifests manifests
+
+ENV cloudDomain="127.0.0.1.nip.io"
+ENV cloudPort=""
+ENV certSecretName="wildcard-cert"
+ENV lafBaseUrl=""
+
+CMD ["kubectl apply -f manifests"]
diff --git a/frontend/providers/invite/deploy/manifests/appcr.yaml.tmpl b/frontend/providers/invite/deploy/manifests/appcr.yaml.tmpl
new file mode 100644
index 00000000000..83ebd04f712
--- /dev/null
+++ b/frontend/providers/invite/deploy/manifests/appcr.yaml.tmpl
@@ -0,0 +1,19 @@
+apiVersion: app.sealos.io/v1
+kind: App
+metadata:
+ name: invite
+ namespace: app-system
+spec:
+ data:
+ desc: invite
+ url: "https://invite.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
+ icon: "https://invite.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}/logo.svg"
+ menuData:
+ helpDropDown: false
+ nameColor: text-black
+ name: invite
+ type: iframe
+ displayType: normal
+ i18n:
+ zh:
+ name: 邀请注册
diff --git a/frontend/providers/invite/deploy/manifests/deploy.yaml.tmpl b/frontend/providers/invite/deploy/manifests/deploy.yaml.tmpl
new file mode 100644
index 00000000000..87565615a60
--- /dev/null
+++ b/frontend/providers/invite/deploy/manifests/deploy.yaml.tmpl
@@ -0,0 +1,86 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+ labels:
+ app: invite-frontend
+ name: invite-frontend
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: invite-frontend-config
+ namespace: invite-frontend
+data:
+ config.yaml: |-
+ addr: :3000
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: invite-frontend
+ namespace: invite-frontend
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: invite-frontend
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxUnavailable: 25%
+ maxSurge: 25%
+ template:
+ metadata:
+ labels:
+ app: invite-frontend
+ spec:
+ containers:
+ - name: invite-frontend
+ env:
+ - name: SEALOS_DOMAIN
+ value: {{ .cloudDomain }}
+ - name: LAF_BASE_URL
+ value: {{ .lafBaseUrl }}
+ - name: GIFT_RATIO
+ value: "0.1"
+ securityContext:
+ runAsNonRoot: true
+ runAsUser: 1001
+ allowPrivilegeEscalation: false
+ capabilities:
+ drop:
+ - 'ALL'
+ resources:
+ limits:
+ cpu: 1000m
+ memory: 1024Mi
+ requests:
+ cpu: 10m
+ memory: 128Mi
+ # do not modify this image, it is used for CI/CD
+ image: ghcr.io/labring/sealos-invite-frontend:latest
+ imagePullPolicy: Always
+ volumeMounts:
+ - name: invite-frontend-volume
+ mountPath: /config.yaml
+ subPath: config.yaml
+ volumes:
+ - name: invite-frontend-volume
+ configMap:
+ name: invite-frontend-config
+---
+apiVersion: v1
+kind: Service
+metadata:
+ labels:
+ app: invite-frontend
+ name: invite-frontend
+ namespace: invite-frontend
+spec:
+ ports:
+ - name: http
+ port: 3000
+ protocol: TCP
+ targetPort: 3000
+ selector:
+ app: invite-frontend
diff --git a/frontend/providers/invite/deploy/manifests/ingress.yaml.tmpl b/frontend/providers/invite/deploy/manifests/ingress.yaml.tmpl
new file mode 100644
index 00000000000..76f93d40ea2
--- /dev/null
+++ b/frontend/providers/invite/deploy/manifests/ingress.yaml.tmpl
@@ -0,0 +1,51 @@
+# Copyright © 2023 sealos.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: nginx
+ nginx.ingress.kubernetes.io/enable-cors: "true"
+ nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
+ nginx.ingress.kubernetes.io/cors-allow-origin: "https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}, https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
+ nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
+ nginx.ingress.kubernetes.io/cors-max-age: "600"
+ nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
+ nginx.ingress.kubernetes.io/configuration-snippet: |
+ more_clear_headers "X-Frame-Options:";
+ more_set_headers "Content-Security-Policy: default-src * blob: data: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .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: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; img-src * data: blob: resource: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}; connect-src * wss: blob: resource:; style-src 'self' 'unsafe-inline' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource:; script-src 'self' 'unsafe-inline' 'unsafe-eval' blob: *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} resource: *.baidu.com *.bdstatic.com https://js.stripe.com; frame-src 'self' *.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} {{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} mailto: tel: weixin: mtt: *.baidu.com https://js.stripe.com; frame-ancestors 'self' https://{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }} https://*.{{ .cloudDomain }}{{ if .cloudPort }}:{{ .cloudPort }}{{ end }}"
+ X-Xss-Protection "1; mode=block"
+ name: invite-frontend
+ namespace: invite-frontend
+spec:
+ rules:
+ - host: invite.{{ .cloudDomain }}
+ http:
+ paths:
+ - pathType: Prefix
+ path: /
+ backend:
+ service:
+ name: invite-frontend
+ port:
+ number: 3000
+ tls:
+ - hosts:
+ - invite.{{ .cloudDomain }}
+ secretName: {{ .certSecretName }}
diff --git a/frontend/providers/invite/public/favicon.ico b/frontend/providers/invite/public/favicon.ico
index aaf5a412ae6..ef088be6928 100644
Binary files a/frontend/providers/invite/public/favicon.ico and b/frontend/providers/invite/public/favicon.ico differ
diff --git a/frontend/providers/invite/public/logo.svg b/frontend/providers/invite/public/logo.svg
index e189b86ba3e..f0e94b8b16b 100644
--- a/frontend/providers/invite/public/logo.svg
+++ b/frontend/providers/invite/public/logo.svg
@@ -1,9 +1,29 @@
-
+
\ No newline at end of file