All Products
Search
Document Center

Resource Orchestration Service:ALIYUN::SAE::Application

Last Updated:Jun 05, 2026

You can use the ALIYUN::SAE::Application resource type to create a Serverless App Engine (SAE) application.

Syntax

{
  "Type": "ALIYUN::SAE::Application",
  "Properties": {
    "Timezone": String,
    "AppDescription": String,
    "MountDesc": String,
    "NasId": String,
    "WarStartOptions": String,
    "Liveness": String,
    "Memory": Integer,
    "WebContainer": String,
    "SlsConfigs": String,
    "Cpu": Integer,
    "Deploy": Boolean,
    "PackageVersion": String,
    "AppName": String,
    "Jdk": String,
    "JarStartArgs": String,
    "PreStop": String,
    "Readiness": String,
    "PackageType": String,
    "CommandArgs": String,
    "Envs": String,
    "VSwitchId": String,
    "ImageUrl": String,
    "PostStart": String,
    "JarStartOptions": String,
    "MountHost": String,
    "Replicas": Integer,
    "CustomHostAlias": String,
    "VpcId": String,
    "Tags": List,
    "SecurityGroupId": String,
    "Command": String,
    "EdasContainerVersion": String,
    "PackageUrl": String,
    "NamespaceId": String,
    "AssociateEip": Boolean,
    "AcrInstanceId": String,
    "OssAkId": String,
    "ProgrammingLanguage": String,
    "OssAkSecret": String,
    "Python": String,
    "BaseAppId": String,
    "EnableEbpf": String,
    "PhpArmsConfigLocation": String,
    "PhpConfig": String,
    "MicroRegistrationConfig": String,
    "TerminationGracePeriodSeconds": Integer,
    "ConfigMapMountDesc": String,
    "PvtzDiscoverySvc": String,
    "AcrAssumeRoleArn": String,
    "TomcatConfig": String,
    "AppSource": String,
    "PythonModules": String,
    "NasConfigs": String,
    "MicroRegistration": String,
    "ServiceTags": String,
    "ImagePullSecrets": String,
    "AutoConfig": Boolean,
    "KafkaConfigs": String,
    "Php": String,
    "OssMountDescs": List,
    "PhpConfigLocation": String,
    "SaeVersion": String,
    "NewSaeVersion": String,
    "EnableNewArms": Boolean,
    "EnableSidecarResourceIsolated": Boolean,
    "SidecarContainersConfig": List,
    "InitContainersConfig": List
  }
}

Properties

Property Name

Type

Required

Update allowed

Description

Constraints

AppName

String

Yes

No

The application name.

The name can be up to 36 characters in length. It must start with a letter and can contain letters, digits, and hyphens (-).

Cpu

Integer

Yes

No

The CPU required for each instance. Only defined specifications are supported.

Valid values:

  • 500

  • 1000

  • 2000

  • 4000

  • 8000

  • 16000

  • 32000

Unit: millicores.

Memory

Integer

Yes

No

The memory required for each instance. Only defined specifications are supported.

It has a one-to-one correspondence with the CPU and currently supports only the following specifications:

  • 1024: corresponds to 500 millicores of CPU.

  • 2048: corresponds to 500 and 1000 millicores of CPU.

  • 4096: corresponds to 1000 and 2000 millicores of CPU.

  • 8192: corresponds to 2000 and 4000 millicores of CPU.

  • 16384: corresponds to 4000 and 8000 millicores of CPU.

  • 32768: corresponds to 16000 millicores of CPU.

  • 65536: corresponds to 8000, 16000, and 32000 millicores of CPU.

  • 131072: corresponds to 32000 millicores of CPU.

Unit: MB.

Replicas

Integer

Yes

No

The initial number of instances.

None

PackageType

String

Yes

No

The application package type.

Valid values:

  • FatJar

  • War

  • Image

Timezone

String

No

Yes

The time zone.

Default value: Asia/Shanghai.

AppDescription

String

No

No

The application description.

The description can be up to 1024 characters in length.

MountDesc

String

No

Yes

The mount description.

None

NasId

String

No

Yes

The ID of the mounted NAS file system.

The NAS file system must have an available mount target quota, or its mount target must be on a vSwitch in the VPC. If you do not specify this parameter but specify the MountDesc parameter, a NAS file system is automatically purchased and mounted to the vSwitch in the VPC.

WarStartOptions

String

No

Yes

The options for starting the application in a WAR package.

The default startup command for the application is java $JAVA_OPTS $CATALINA_OPTS -Options org.apache.catalina.startup.Bootstrap "$@" start.

Liveness

String

No

Yes

The container health check. A container that fails the health check is restarted.

Only commands that are run in the container are supported. Example: {"exec":{"command":["sleep","5s"]},"initialDelaySeconds":10,"timeoutSeconds":11}.

WebContainer

String

No

Yes

The Tomcat version that the deployment package depends on.

The image does not support this parameter.

SlsConfigs

String

No

Yes

The configuration for file log collection.

None

Deploy

Boolean

No

No

Specifies whether to deploy the application immediately.

Valid values:

  • true: Deploy immediately.

  • false (default): Do not deploy immediately.

Tags

List

No

Yes

The tags.

A maximum of 20 tags are supported.

For more information, see Tags syntax and Tags properties.

PackageVersion

String

No

Yes

The version number of the deployed package.

This parameter is required when PackageType is set to War or FatJar.

Jdk

String

No

Yes

The JDK version that the deployment package depends on.

The image does not support this parameter.

JarStartArgs

String

No

Yes

The parameters for starting the application in a JAR package.

The default startup command for the application is $JAVA_HOME/bin/java $JarStartOptions -jar $CATALINA_OPTS "$package_path" $JarStartArgs.

PreStop

String

No

Yes

The script to execute before the container is deleted.

The script to execute before the container is deleted. Example: {"exec":{"command":"cat","/etc/group"}}.

Readiness

String

No

Yes

The application startup status check script.

The application startup status check script. Example: {"exec":{"command":["sleep","6s"]},"initialDelaySeconds":15,"timeoutSeconds":12}.

A container that fails the health check multiple times is restarted. No traffic from Server Load Balancer (SLB) is routed to a container that fails the health check.

CommandArgs

String

No

Yes

The parameters for the image startup command.

None

Envs

String

No

Yes

The environment variables of the container.

The format for the container environment variable parameter is: [{"name":"envtmp","value":"0"}].

  • name: The name of the environment variable.

  • value: The value of the environment variable or an environment variable reference.

VSwitchId

String

No

No

The vSwitch to which the elastic network interface (ENI) of the application instance is connected.

The vSwitch must be in the specified VPC. The vSwitch is bound to the EDAS namespace. If you do not specify this parameter, the vSwitch that is bound to the namespace is used.

ImageUrl

String

No

Yes

The image address.

You can configure an image address only for applications of the Image type.

PostStart

String

No

Yes

The script to execute after the container starts.

The script to execute after the container starts. Example: {"exec":{"command":"cat","/etc/group"}}.

JarStartOptions

String

No

Yes

The options for starting the application in a JAR package.

The default startup command for the application is $JAVA_HOME/bin/java $JarStartOptions -jar $CATALINA_OPTS "$package_path" $JarStartArgs.

MountHost

String

No

Yes

The mount target of the NAS file system in the VPC.

None

CustomHostAlias

String

No

Yes

The custom host mapping in the container.

The custom host mapping in the container. The format is [{"hostName":"samplehost","ip":"127.0.XX.XX"}] .

  • hostName: The domain name or hostname.

  • ip: The IP address.

VpcId

String

No

No

The VPC that corresponds to the SAE namespace.

In SAE, a namespace can be bound to only one VPC. The binding cannot be changed. The binding is created when you create the first SAE application in the namespace. Multiple namespaces can be bound to the same VPC. If you do not specify this parameter, the VPC that is bound to the namespace is used.

SecurityGroupId

String

No

No

The security group ID.

None

Command

String

No

Yes

The image startup command.

The command must be an executable object that exists in the container. For example, sleep.

Setting this command overwrites the original startup command of the image.

EdasContainerVersion

String

No

Yes

The runtime environment used by the EDAS Pandora application.

None

PackageUrl

String

No

Yes

The address of the deployment package.

This parameter is valid when PackageType is set to War or FatJar.

NamespaceId

String

Yes

No

The ID of the EDAS namespace.

Only namespaces whose names contain lowercase letters and hyphens (-) are supported. The name must start with a lowercase letter.

AssociateEip

Boolean

No

No

Specifies whether to bind an EIP.

Valid values:

  • true: Bind an EIP.

  • false: Do not bind an EIP.

AcrInstanceId

String

No

Yes

The ID of the ACR Enterprise instance.

None

OssAkId

String

No

No

The AccessKey ID for OSS read and write operations.

None

ProgrammingLanguage

String

No

No

The programming language of the technology stack for the application.

Valid values:

  • java: Java language.

  • php: PHP language.

  • other: Multiple languages, such as Python, C++, Go, and Node.js.

OssAkSecret

String

No

No

The AccessKey secret for OSS read and write operations.

None

Python

String

No

No

The Python environment.

PYTHON 3.9.15 is supported.

BaseAppId

String

No

No

The base application ID.

None

EnableEbpf

String

No

No

Enables application monitoring for non-Java applications based on eBPF technology.

Valid values:

  • true: Enable.

  • false: Disable. This is the default value.

PhpArmsConfigLocation

String

No

No

The mount path for PHP application monitoring. Ensure that the PHP server loads the configuration file from this path.

You do not need to pay attention to the configuration content. SAE automatically renders the correct configuration file.

PhpConfig

String

No

No

The content of the PHP configuration file.

None

MicroRegistrationConfig

String

No

No

The configuration information for the service registry.

None

TerminationGracePeriodSeconds

Integer

No

No

The graceful shutdown timeout period.

The default value is 30. Unit: seconds. Valid values: 1 to 300.

ConfigMapMountDesc

String

No

No

The description of the ConfigMap mount.

Use the configuration items created on the Configurations page of the namespace to inject configuration information into the container. The parameters are described as follows:

  • configMapId: The ID of the ConfigMap instance.

  • key: The key.

  • mountPath: The mount path.

Note

You can pass the sae-sys-configmap-all parameter to mount all keys.

PvtzDiscoverySvc

String

No

No

Enables K8s Service registration and discovery.

The parameters are described as follows:

  • serviceName: The service name. The format is Custom-Namespace ID. The -Namespace ID suffix cannot be customized. You must specify the suffix based on the namespace of the application. For example, if you select the default namespace in the China (Beijing) region, the suffix is -cn-beijing-default.

  • namespaceId: The namespace ID.

  • portProtocols: The ports and protocols. The port number must be in the range of [1, 65535]. The supported protocols are TCP and UDP.

  • portAndProtocol: The port and protocol. The port number must be in the range of [1, 65535]. The supported protocols are TCP and UDP. The portProtocols parameter is recommended. If you set portProtocols, only portProtocols takes effect.

  • enable: Enables K8s Service registration and discovery.

AcrAssumeRoleArn

String

No

No

The Alibaba Cloud Resource Name (ARN) of the RAM role required to pull images across accounts.

For more information, see Grant permissions to a RAM role.

TomcatConfig

String

No

No

The Tomcat file configuration.

Set the value to "" or "{}" to delete the configuration:

  • port: The port number. Valid values: 1024 to 65535. Ports smaller than 1024 require root permissions. Because the container is configured with administrator permissions, specify a port number greater than 1024. If you do not configure this parameter, the default port 8080 is used.

  • contextPath: The access path. The default value is the root directory "/".

  • maxThreads: The maximum number of connections in the connection pool. The default value is 400.

  • uriEncoding: The encoding format for Tomcat, including UTF-8, ISO-8859-1, GBK, and GB2312. If you do not set this parameter, the default value ISO-8859-1 is used.

  • useBodyEncodingForUri: Specifies whether to use BodyEncoding for URL. The default value is true.

AppSource

String

No

No

The microservice application.

Valid values:

  • micro_service

PythonModules

String

No

No

Module dependencies for custom installation.

By default, the dependencies defined in the requirements.txt file in the root directory are installed. If no configuration or custom software package is available, you can specify the dependencies to be installed.

NasConfigs

String

No

No

The configurations for mounting a NAS file system.

The parameters are described as follows:

  • mountPath: The container mount path.

  • readOnly: If the value is false, you have read and write permissions.

  • nasId: The NAS ID.

  • mountDomain: The container mount target address. For more information, see DescribeMountTargets.

  • nasPath: The relative path of the NAS file.

MicroRegistration

String

No

No

Select the Nacos service registry.

Valid values:

  • 0: SAE built-in Nacos.

  • 1: User-created Nacos.

  • 2: MSE Commercial Nacos.

ServiceTags

String

No

No

The grayscale tags configured for the application.

None

ImagePullSecrets

String

No

No

The ID of the corresponding secret.

None

AutoConfig

Boolean

No

No

Specifies whether to automatically configure the network environment.

Valid values:

  • true: SAE automatically configures the network environment when you create the application. The values of NamespaceId, VpcId, vSwitchId, and SecurityGroupId are ignored.

  • false: Manually configure the network environment when creating the application in SAE.

Note

If you set this parameter to true, other passed NamespaceId values are ignored.

KafkaConfigs

String

No

No

The summary of configurations for collecting logs to Kafka.

The parameters are described as follows:

  • kafkaEndpoint: The service endpoint of the Kafka API.

  • kafkaInstanceId: The Kafka instance ID.

  • kafkaConfigs: The summary of configurations for one or more logs. For more information about the valid values, see the request parameter KafkaConfigs in this topic.

Php

String

No

No

The PHP version that the PHP deployment package depends on.

None.

OssMountDescs

List

No

No

The description of the OSS mount.

The parameters are described as follows:

  • bucketName: The bucket name.

  • bucketPath: The directory or OSS object you created in OSS. If the OSS mount directory does not exist, an exception is triggered.

  • mountPath: The container path in SAE. If the path exists, it is overwritten. If the path does not exist, it is created.

  • readOnly: Specifies whether the container path has read-only permission for the mounted directory resources. Valid values:

    • true: Read-only permission.

    • false: Read and write permissions.

PhpConfigLocation

String

No

No

The mount path for the PHP application startup configuration.

Ensure that the PHP server starts using this configuration file.

SaeVersion

String

No

No

The SAE version.

Supported versions:

  • v1

  • v2

NewSaeVersion

String

No

No

The new SAE version.

Valid values:

  • lite

  • std

  • pro

EnableNewArms

Boolean

No

No

Specifies whether to enable the new Arms feature.

Valid values:

  • true: Enable

  • false: Disable

EnableSidecarResourceIsolated

Boolean

No

Yes

Specifies whether to enable resource isolation for the sidecar container.

Valid values:

  • true: Isolate resources.

  • false: Do not isolate resources.

SidecarContainersConfig

List

No

Yes

The list of container configuration information.

For more information, see SidecarContainersConfig properties.

InitContainersConfig

List

No

Yes

The list of init container configurations.

For more information, see InitContainersConfig properties.

SidecarContainersConfig syntax

"SidecarContainersConfig": [
  {
    "CommandArgs": String,
    "AcrInstanceId": String,
    "Memory": Integer,
    "Name": String,
    "EmptyDirDesc": String,
    "Command": String,
    "ImageUrl": String,
    "Cpu": Integer,
    "Envs": String,
    "ConfigMapMountDesc": String
  }
]  

SidecarContainersConfig properties

Property Name

Type

Required

Update allowed

Description

Constraints

CommandArgs

String

No

Yes

The parameters of the command to run in the init container.

None

AcrInstanceId

String

No

Yes

The ID of the ACR instance.

None

Memory

Integer

Yes

Yes

The amount of memory to allocate to the sidecar container.

None

Name

String

Yes

Yes

The name of the sidecar container.

None

EmptyDirDesc

String

No

Yes

The EMPTYDIR mount description.

None

Command

String

No

Yes

The command to run in the init container.

None

ImageUrl

String

No

Yes

The image address.

You can configure an image address only for applications of the Image type.

Cpu

Integer

Yes

Yes

The number of CPU cores to allocate to the sidecar container.

None

Envs

String

No

Yes

The environment variables of the container.

Example:

[{ "name": "envtmp", "value": "0"}]

ConfigMapMountDesc

String

No

Yes

The ConfigMap mount description.

None

InitContainersConfig syntax

"InitContainersConfig": [
  {
    "Command": String,
    "ConfigMapMountDesc": String,
    "ImageUrl": String,
    "CommandArgs": String,
    "Envs": String,
    "Name": String
  }
]  

InitContainersConfig properties

Property name

Type

Required

Update allowed

Description

Constraints

Command

String

No

Yes

The command to run in the init container.

None

ConfigMapMountDesc

String

No

No

The ConfigMap mount description.

None

ImageUrl

String

No

Yes

The image address.

You can configure an image address only for applications of the Image type.

CommandArgs

String

No

Yes

The parameters of the command to run in the init container.

None

Envs

String

No

Yes

The environment variables of the container.

Example:

[{ "name": "envtmp", "value": "0"}]

Name

String

Yes

Yes

The name of the init container.

None

Tags syntax

"Tags": [
  {
    "Key": String,
    "Value": String
  }
]  

Tags properties

Property name

Type

Required

Update allowed

Description

Constraints

Key

String

Yes

No

The tag key.

The tag key can be 1 to 128 characters in length. It cannot start with aliyun or acs:, and cannot contain http:// or https://.

Value

String

No

No

The tag value.

The tag value can be 0 to 128 characters in length. It cannot start with aliyun or acs:, and cannot contain http:// or https://.

Return values

Fn::GetAtt

  • AppId: The application ID.

  • ChangeOrderId: The ID of the change order. You can use this ID to query the task execution status.

Examples

Scenario 1: Create an SAE application

Create Now

ROSTemplateFormatVersion: '2015-09-01'
Parameters:
  NamespaceId:
    Type: String
    Description: |-
      The ID of the EDAS namespace. The name of the namespace can contain only lowercase letters and hyphens (-). It must start with a lowercase letter.
      You can obtain the namespace from the DescribeNamespaceList operation.
  VpcId:
    Type: String
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
  VSwitchId:
    Type: String
    AssociationProperty: ALIYUN::ECS::VSwitch::VSwitchId
    AssociationPropertyMetadata:
      VpcId: ${VpcId}
  SecurityGroupId:
    Type: String
    AssociationProperty: ALIYUN::ECS::SecurityGroup::SecurityGroupId
    AssociationPropertyMetadata:
      VpcId: ${VpcId}
Resources:
  Application:
    Type: ALIYUN::SAE::Application
    Properties:
      AppName: TestApp
      NamespaceId:
        Ref: NamespaceId
      VpcId:
        Ref: VpcId
      VSwitchId:
        Ref: VSwitchId
      SecurityGroupId:
        Ref: SecurityGroupId
      Cpu: 500
      Memory: 1024
      Replicas: 2
      PackageType: War
      Deploy: true
      Timezone: Asia/Shanghai
Outputs: {}
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Parameters": {
    "NamespaceId": {
      "Type": "String",
      "Description": "The ID of the EDAS namespace. The name of the namespace can contain only lowercase letters and hyphens (-). It must start with a lowercase letter.\nYou can obtain the namespace from the DescribeNamespaceList operation."
    },
    "VpcId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::VPC::VPCId"
    },
    "VSwitchId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::VSwitch::VSwitchId",
      "AssociationPropertyMetadata": {
        "VpcId": "${VpcId}"
      }
    },
    "SecurityGroupId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::SecurityGroup::SecurityGroupId",
      "AssociationPropertyMetadata": {
        "VpcId": "${VpcId}"
      }
    }
  },
  "Resources": {
    "Application": {
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "TestApp",
        "NamespaceId": {
          "Ref": "NamespaceId"
        },
        "VpcId": {
          "Ref": "VpcId"
        },
        "VSwitchId": {
          "Ref": "VSwitchId"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroupId"
        },
        "Cpu": 500,
        "Memory": 1024,
        "Replicas": 2,
        "PackageType": "War",
        "Deploy": true,
        "Timezone": "Asia/Shanghai"
      }
    }
  },
  "Outputs": {
  }
}

Scenario 2: Create an SAE application and a namespace, and bind an SLB instance

Create Now

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: Creates an SAE application and a namespace, binds an SLB instance, configures ECS resources and load balancing, and automates the deployment of a containerized application.
  en: Create SAE applications, namespaces, and SLB bindings, configure ECS resources
    with load balancing, and automate the deployment of containerized applications.
Parameters:
  ZoneId:
    Type: String
    AssociationProperty: ALIYUN::ECS::Instance:ZoneId
  VpcId:
    Type: String
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
  VSwitchId:
    Type: String
    AssociationProperty: ALIYUN::ECS::VSwitch::VSwitchId
    AssociationPropertyMetadata:
      VpcId: VpcId
      ZoneId: ZoneId
  SecurityGroupId:
    Type: String
    AssociationProperty: ALIYUN::ECS::SecurityGroup::SecurityGroupId
    AssociationPropertyMetadata:
      VpcId: VpcId
  NamespaceName:
    Type: String
    Description: The namespace name.
    Default: mytest
  NamespaceId:
    Type: String
    Description: The namespace ID.
    Default: mytest
  Description:
    Type: String
    Description: The description of the namespace.
    Default: null
  AppName:
    Type: String
    Description: The application name.
    Default: test
  LoadBalancerSpec:
    Type: String
    Description: The specification of the SLB instance.
    Default: slb.s2.medium
Resources:
  LoadBalancer:
    Type: ALIYUN::SLB::LoadBalancer
    Properties:
      MasterZoneId:
        Ref: ZoneId
      LoadBalancerSpec:
        Ref: LoadBalancerSpec
  Namespace:
    Type: ALIYUN::SAE::Namespace
    Properties:
      NamespaceName:
        Ref: NamespaceName
      NamespaceId:
        Fn::Sub: ${ALIYUN::Region}:${NamespaceId}
      NamespaceDescription:
        Ref: Description
    DependsOn: LoadBalancer
  SaeApp:
    Type: ALIYUN::SAE::Application
    Properties:
      VpcId:
        Ref: VpcId
      VSwitchId:
        Ref: VSwitchId
      SecurityGroupId:
        Ref: SecurityGroupId
      AppName:
        Ref: AppName
      NamespaceId:
        Fn::GetAtt:
        - Namespace
        - NamespaceId
      Cpu: 500
      Memory: 1024
      Replicas: 2
      Deploy: true
      Timezone: Asia/Shanghai
      SaeVersion: v2
      AutoConfig: false

      PackageType: Image
      Jdk: Dragonwell 21
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:web-springboot-hellosae-v1.0
      ProgrammingLanguage: java
      AppSource: micro_service
    DependsOn:
    - Namespace
  BindSlb:
    Type: ALIYUN::SAE::SlbBinding
    Properties:
      AppId:
        Ref: SaeApp
      Intranet: '[{"port": 80, "targetPort": 8080, "protocol": "TCP"}]'
      InternetSlbId:
        Ref: LoadBalancer
    DependsOn:
    - LoadBalancer
    - SaeApp
Outputs:
  AppId:
    Value:
      Fn::GetAtt:
      - SaeApp
      - AppId
  ChangeOrderId:
    Value:
      Fn::GetAtt:
      - SaeApp
      - ChangeOrderId
  NamespaceId:
    Value:
      Fn::GetAtt:
      - Namespace
      - NamespaceId
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": {
    "zh-cn": "Creates an SAE application and a namespace, binds an SLB instance, configures ECS resources and load balancing, and automates the deployment of a containerized application.",
    "en": "Create SAE applications, namespaces, and SLB bindings, configure ECS resources with load balancing, and automate the deployment of containerized applications."
  },
  "Parameters": {
    "ZoneId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::Instance:ZoneId"
    },
    "VpcId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::VPC::VPCId"
    },
    "VSwitchId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::VSwitch::VSwitchId",
      "AssociationPropertyMetadata": {
        "VpcId": "VpcId",
        "ZoneId": "ZoneId"
      }
    },
    "SecurityGroupId": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::SecurityGroup::SecurityGroupId",
      "AssociationPropertyMetadata": {
        "VpcId": "VpcId"
      }
    },
    "NamespaceName": {
      "Type": "String",
      "Description": "The namespace name.",
      "Default": "mytest"
    },
    "NamespaceId": {
      "Type": "String",
      "Description": "The namespace ID.",
      "Default": "mytest"
    },
    "Description": {
      "Type": "String",
      "Description": "The description of the namespace.",
      "Default": null
    },
    "AppName": {
      "Type": "String",
      "Description": "The application name.",
      "Default": "test"
    },
    "LoadBalancerSpec": {
      "Type": "String",
      "Description": "The specification of the SLB instance.",
      "Default": "slb.s2.medium"
    }
  },
  "Resources": {
    "LoadBalancer": {
      "Type": "ALIYUN::SLB::LoadBalancer",
      "Properties": {
        "MasterZoneId": {
          "Ref": "ZoneId"
        },
        "LoadBalancerSpec": {
          "Ref": "LoadBalancerSpec"
        }
      }
    },
    "Namespace": {
      "Type": "ALIYUN::SAE::Namespace",
      "Properties": {
        "NamespaceName": {
          "Ref": "NamespaceName"
        },
        "NamespaceId": {
          "Fn::Sub": "${ALIYUN::Region}:${NamespaceId}"
        },
        "NamespaceDescription": {
          "Ref": "Description"
        }
      },
      "DependsOn": "LoadBalancer"
    },
    "SaeApp": {
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "VpcId": {
          "Ref": "VpcId"
        },
        "VSwitchId": {
          "Ref": "VSwitchId"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroupId"
        },
        "AppName": {
          "Ref": "AppName"
        },
        "NamespaceId": {
          "Fn::GetAtt": [
            "Namespace",
            "NamespaceId"
          ]
        },
        "Cpu": 500,
        "Memory": 1024,
        "Replicas": 2,
        "Deploy": true,
        "Timezone": "Asia/Shanghai",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "PackageType": "Image",
        "Jdk": "Dragonwell 21",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:web-springboot-hellosae-v1.0"
        },
        "ProgrammingLanguage": "java",
        "AppSource": "micro_service"
      },
      "DependsOn": [
        "Namespace"
      ]
    },
    "BindSlb": {
      "Type": "ALIYUN::SAE::SlbBinding",
      "Properties": {
        "AppId": {
          "Ref": "SaeApp"
        },
        "Intranet": "[{\"port\": 80, \"targetPort\": 8080, \"protocol\": \"TCP\"}]",
        "InternetSlbId": {
          "Ref": "LoadBalancer"
        }
      },
      "DependsOn": [
        "LoadBalancer",
        "SaeApp"
      ]
    }
  },
  "Outputs": {
    "AppId": {
      "Value": {
        "Fn::GetAtt": [
          "SaeApp",
          "AppId"
        ]
      }
    },
    "ChangeOrderId": {
      "Value": {
        "Fn::GetAtt": [
          "SaeApp",
          "ChangeOrderId"
        ]
      }
    },
    "NamespaceId": {
      "Value": {
        "Fn::GetAtt": [
          "Namespace",
          "NamespaceId"
        ]
      }
    }
  }
}

Scenario 3: Deploy a production Dify platform using SAE

Create Now

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: Deploys a production Dify platform using Serverless App Engine.
  en: Deploys a production Dify platform using Serverless App Engine.
Parameters:
  CommonName:
    Type: String
    Default: Dify
  NamespaceName:
    Type: String
    Label:
      en: Namespace Name
      zh-cn: Namespace Name
    Description:
      zh-cn: The namespace name. Only lowercase letters and numbers are supported.
      en: The namespace name. Only lowercase letters and numbers are supported.
    AllowedPattern: '^[a-z0-9]+$'
    AssociationProperty: AutoCompleteInput
    AssociationPropertyMetadata:
      Length: 3
      Prefix: dify
      CharacterClasses:
        - Class: lowercase
          min: 2
        - Class: "number"
          min: 1
  ZoneId1:
    Type: String
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    AssociationPropertyMetadata:
      ExclusiveTo:
        - ZoneId2
    Label:
      en: Availability Zone 1
      zh-cn: Availability Zone 1
  ZoneId2:
    Type: String
    AssociationProperty: 'ALIYUN::ECS::Instance::ZoneId'
    AssociationPropertyMetadata:
      ExclusiveTo:
        - ZoneId1
    Label:
      en: Availability Zone 2
      zh-cn: Availability Zone 2
  InstanceType:
    Type: String
    AssociationProperty: 'ALIYUN::ECS::Instance::InstanceType'
    AssociationPropertyMetadata:
      InstanceChargeType: PostPaid
      SystemDiskCategory: cloud_essd
      ZoneId: ${ZoneId1}
    Label:
      en: Instance Type
      zh-cn: Instance Type
  ADBPGAccount:
    Default: dify
    Type: String
    Label:
      zh-cn: DB Account
      en: DB Account
  ADBPGPassword:
    NoEcho: true
    Type: String
    Label:
      zh-cn: DB Account Password
      en: DB Account Password
    AssociationProperty: ALIYUN::RDS::Instance::AccountPassword
  InstancePassword:
    Type: String
    Label:
      en: Logon Password
      zh-cn: Logon Password
    Description:
      en: The logon password of the server. The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters are ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/
      zh-cn: The logon password of the server. The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters are ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/
    AssociationProperty: ALIYUN::ECS::Instance::Password
  RedisInstancePassword:
    Type: String
    Label:
      en: Instance Password
      zh-cn: Instance Password
    Description:
      en: The Redis password for Dify. The password must be 8 to 32 characters in length and can contain only uppercase letters, lowercase letters, and digits. Do not use other characters.
      zh-cn: The Redis password for Dify. The password must be 8 to 32 characters in length and can contain only uppercase letters, lowercase letters, and digits. Do not use other characters.
    ConstraintDescription:
      en: The Redis password for Dify. The password must be 8 to 32 characters in length and can contain only uppercase letters, lowercase letters, and digits. Do not use other characters.
      zh-cn: The Redis password for Dify. The password must be 8 to 32 characters in length and can contain only uppercase letters, lowercase letters, and digits. Do not use other characters.
    AllowedPattern: ^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?\d)[A-Za-z0-9]{8,32}$
    MinLength: '8'
    MaxLength: '32'
    NoEcho: true
  DBInstanceClass:
    Type: String
    Label:
      en: Instance Type
      zh-cn: Instance Type
    Default: pg.n4m.2c.2m
    Required: true
    AssociationProperty: ALIYUN::RDS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      EngineVersion: '17.0'
      Engine: PostgreSQL
      Category: HighAvailability
      InstanceChargeType: Postpaid
      DBInstanceStorageType: cloud_essd
      CommodityCode: bards
  PostgreSQLPassword:
    Type: String
    NoEcho: true
    Label:
      en: Database Account Password
      zh-cn: Database Account Password
    AssociationProperty: ALIYUN::RDS::Instance::AccountPassword
  PostgreSQLUserName:
    Type: String
    Label:
      en: Database Account
      zh-cn: Database Account
    # This rule applies to MySQL 5.7 and 8.0.
    AllowedPattern: ^(?!dbo\b|login\b|admin\b|administrator\b|adminsys\b|alimail\b|aliyun\b|apache\b|appadmin\b|apsara\b|aurora\b|bulkadmin\b|cangjie\b|cdn\b|client\b|cm\b|dataengine\b|dayu\b|dba\b|dbcreator\b|developer\b|diskadmin\b|distribution\b|dns\b|download\b|eagleye\b|f5\b|faq\b|fuxi\b|galaxy\b|gongcao\b|gongming\b|groupon\b|ha\b|help\b|host\b|hostmaster\b|houyi\b|hr\b|info\b|information_schema\b|kuafu\b|lvs\b|manager\b|master\b|meituan\b|model\b|monitor\b|msdb\b|mssqld\b|mssqlsystemresource\b|mysql\b|nas\b|net\b|netops\b|netweb\b|news\b|no-reply\b|ntp\b|nuwa\b|nvwa\b|operator\b|opr\b|ops\b|opsdb\b|oracle\b|pangu\b|pe\b|post\b|postmaster\b|processadmin\b|public\b|qq\b|replicator\b|reply\b|root\b|sa\b|sales\b|san\b|security\b|securityadmin\b|serveradmin\b|services\b|setupadmin\b|shennong\b|siteops\b|sqlengine\b|sqlonline\b|squid\b|ssladmin\b|support\b|sys\b|sysadmin\b|syslog\b|system\b|taoyun\b|tempdb\b|test\b|tianyun\b|wangwang\b|eb\b|webmaster\b|webnet\b|xtrabak\b|youchao\b|yum\b|yunti\b|zhongkui\b|database\b|add\b|except\b|percent\b|all\b|exec\b|plan\b|alter\b|execute\b|precision\b|and\b|exists\b|primary\b|any\b|exit\b|print\b|as\b|fetch\b|proc\b|asc\b|file\b|procedure\b|authorization\b|fillfactor\b|public\b|backup\b|for\b|raiserror\b|begin\b|foreign\b|read\b|between\b|freetext\b|readtext\b|break\b|freetexttable\b|reconfigure\b|browse\b|from\b|references\b|bulk\b|full\b|replication\b|by\b|function\b|restore\b|cascade\b|goto\b|restrict\b|case\b|grant\b|return\b|check\b|group\b|revoke\b|checkpoint\b|having\b|right\b|close\b|holdlock\b|rollback\b|clustered\b|identity\b|rowcount\b|coalesce\b|identity_insert\b|rowguidcol\b|collate\b|identitycol\b|rule\b|column\b|if\b|save\b|commit\b|in\b|schema\b|compute\b|index\b|select\b|constraint\b|inner\b|session_user\b|contains\b|insert\b|set\b|containstable\b|intersect\b|setuser\b|continue\b|into\b|shutdown\b|convert\b|is\b|some\b|create\b|join\b|statistics\b|cross\b|key\b|system_user\b|current\b|kill\b|table\b|current_date\b|left\b|textsize\b|current_time\b|like\b|then\b|current_timestamp\b|lineno\b|to\b|current_user\b|load\b|top\b|cursor\b|national\b|tran\b|database\b|nocheck\b|transaction\b|dbcc\b|nonclustered\b|trigger\b|deallocate\b|not\b|truncate\b|declare\b|null\b|tsequal\b|default\b|nullif\b|union\b|delete\b|of\b|unique\b|deny\b|off\b|update\b|desc\b|offsets\b|updatetext\b|disk\b|on\b|use\b|distinct\b|open\b|user\b|distributed\b|opendatasource\b|values\b|double\b|openquery\b|varying\b|drop\b|openrowset\b|view\b|dummy\b|openxml\b|waitfor\b|dump\b|option\b|when\b|else\b|or\b|where\b|end\b|order\b|while\b|errlvl\b|outer\b|with\b|escape\b|over\b|writetext\b|add\b|analyze\b|asc\b|between\b|blob\b|call\b|change\b|check\b|condition\b|continue\b|cross\b|current_timestamp\b|database\b|day_microsecond\b|dec\b|default\b|desc\b|distinct\b|double\b|each\b|enclosed\b|exit\b|fetch\b|float8\b|foreign\b|goto\b|having\b|hour_minute\b|ignore\b|infile\b|insensitive\b|int1\b|int4\b|interval\b|iterate\b|keys\b|leading\b|like\b|lines\b|localtimestamp\b|longblob\b|low_priority\b|mediumint\b|minute_microsecond\b|modifies\b|no_write_to_binlog\b|on\b|optionally\b|out\b|precision\b|purge\b|read\b|references\b|rename\b|require\b|revoke\b|schema\b|select\b|set\b|spatial\b|sqlexception\b|sql_big_result\b|ssl\b|table\b|tinyblob\b|to\b|true\b|unique\b|update\b|using\b|utc_timestamp\b|varchar\b|when\b|with\b|xor\b|all\b|and\b|asensitive\b|bigint\b|both\b|cascade\b|char\b|collate\b|connection\b|convert\b|current_date\b|current_user\b|databases\b|day_minute\b|decimal\b|delayed\b|describe\b|distinctrow\b|drop\b|else\b|escaped\b|explain\b|float\b|for\b|from\b|grant\b|high_priority\b|hour_second\b|in\b|inner\b|insert\b|int2\b|int8\b|into\b|join\b|kill\b|leave\b|limit\b|load\b|lock\b|longtext\b|match\b|mediumtext\b|minute_second\b|natural\b|null\b|optimize\b|or\b|outer\b|primary\b|raid0\b|reads\b|regexp\b|repeat\b|restrict\b|right\b|schemas\b|sensitive\b|show\b|specific\b|sqlstate\b|sql_calc_found_rows\b|starting\b|terminated\b|tinyint\b|trailing\b|undo\b|unlock\b|usage\b|utc_date\b|values\b|varcharacter\b|where\b|write\b|year_month\b|alter\b|as\b|before\b|binary\b|by\b|case\b|character\b|column\b|constraint\b|create\b|current_time\b|cursor\b|day_hour\b|day_second\b|declare\b|delete\b|deterministic\b|div\b|dual\b|elseif\b|exists\b|false\b|float4\b|force\b|fulltext\b|group\b|hour_microsecond\b|if\b|index\b|inout\b|int\b|int3\b|integer\b|is\b|key\b|label\b|left\b|linear\b|localtime\b|long\b|loop\b|mediumblob\b|middleint\b|mod\b|not\b|numeric\b|option\b|order\b|outfile\b|procedure\b|range\b|real\b|release\b|replace\b|return\b|rlike\b|second_microsecond\b|separator\b|smallint\b|sql\b|sqlwarning\b|sql_small_result\b|straight_join\b|then\b|tinytext\b|trigger\b|union\b|unsigned\b|use\b|utc_time\b|varbinary\b|varying\b|while\b|x509\b|zerofill)([a-zA-Z][a-zA-Z0-9_]{0,30}[a-zA-Z0-9])$
    ConstraintDescription:
      en: The value must be up to 32 characters in length and can contain lowercase letters, uppercase letters, digits, and underscores (_). It must start with a letter and end with a letter or digit. For more information about invalid characters, see <a href="https://www.alibabacloud.com/help/zh/rds/developer-reference/forbidden-keywords" target="_blank">Forbidden keywords table</a>.
      zh-cn: The value must be up to 32 characters in length and can contain lowercase letters, uppercase letters, digits, and underscores (_). It must start with a letter and end with a letter or digit. For more information about invalid characters, see <a href="https://www.alibabacloud.com/help/zh/rds/developer-reference/forbidden-keywords" target="_blank">Forbidden keywords table</a>.
    Default: db_user
Resources:
  Vpc:
    Type: 'ALIYUN::ECS::VPC'
    Properties:
      CidrBlock: 192.168.0.0/16
      VpcName:
        Fn::Sub: ${CommonName}-VPC_HZ
  VSwitch1:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VpcId:
        Ref: Vpc
      CidrBlock: 192.168.1.0/24
      ZoneId:
        Ref: ZoneId1
      VSwitchName:
        Fn::Sub: ${CommonName}-vsw_001
  VSwitch2:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VpcId:
        Ref: Vpc
      CidrBlock: 192.168.2.0/24
      ZoneId:
        Ref: ZoneId2
      VSwitchName:
        Fn::Sub: ${CommonName}-vsw_002
  Sleep:
    DependsOn:
      - VSwitch1
      - VSwitch2
    Type: ALIYUN::ROS::Sleep
    Properties:
      DeleteDuration: 300
  SecurityGroup:
    Type: 'ALIYUN::ECS::SecurityGroup'
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupName:
        Fn::Sub: ${CommonName}-SecurityGroup_1
      SecurityGroupIngress:
        - PortRange: 80/80
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 3000/3000
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 5001/5001
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 5002/5002
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 5003/5003
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
        - PortRange: 8080/8080
          Priority: 1
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
  EcsInstance:
    Type: 'ALIYUN::ECS::InstanceGroup'
    Properties:
      VpcId:
        Ref: Vpc
      ZoneId:
        Ref: ZoneId1
      VSwitchId:
        Ref: VSwitch1
      SecurityGroupId:
        Ref: SecurityGroup
      ImageId: aliyun_3_x64_20G_alibase_
      InstanceName:
        Fn::Sub: ${CommonName}-ecs
      InstanceType:
        Ref: InstanceType
      SystemDiskCategory: cloud_essd
      MaxAmount: 1
      SystemDiskSize: 40
      InternetMaxBandwidthOut: 5
      Password:
        Ref: InstancePassword
  RunCommand:
    Type: ALIYUN::ECS::RunCommand
    Properties:
      CommandContent:
        Fn::Sub:
          |
          #!/bin/sh
          echo "sk-$(openssl rand -hex 16)"
      Type: RunShellScript
      InstanceIds:
        - Ref: EcsInstance
  RunCommand2:
    DependsOn:
      - RunCommand
    Type: ALIYUN::ECS::RunCommand
    Properties:
      CommandContent:
        Fn::Sub:
          |
          #!/bin/sh
          export ROS_DEPLOY=true
          curl -fsSL https://help-static-aliyun-doc.aliyuncs.com/install-script/dify/sae/install.sh | bash
      Type: RunShellScript
      InstanceIds:
        - Ref: EcsInstance
  RedisInstance:
    Type: ALIYUN::REDIS::Instance
    Properties:
      ZoneId:
        Ref: ZoneId1
      SecondaryZoneId:
        Ref: ZoneId2
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch1
      InstanceClass: redis.shard.large.y.ee
      EvictionPolicy: noeviction
      InstanceName:
        Fn::Sub: ${CommonName}-Redis
      EngineVersion: '7.0'
      Password:
        Ref: RedisInstancePassword
  REDISWhitelist:
    Type: ALIYUN::REDIS::Whitelist
    Properties:
      InstanceId:
        Ref: RedisInstance
      SecurityIps: 192.168.0.0/16
  ADBPGInstance:
    Type: ALIYUN::GPDB::DBInstance
    Properties:
      EngineVersion: '7.0'
      VectorConfigurationStatus: True
      InstanceSpec: 4C32G
      ZoneId:
        Ref: ZoneId1
      VSwitchId:
        Ref: VSwitch1
      SegNodeNum: 4
      SegStorageType: cloud_essd
      SegDiskPerformanceLevel: pl1
      StorageSize: 50
      VPCId:
        Ref: Vpc
      SecurityIPList: 192.168.0.0/16
      DBInstanceDescription:
        Fn::Sub: ${CommonName}
      PayType: Postpaid
      DBInstanceCategory: HighAvailability
      DBInstanceMode: StorageElastic
      ProdType: standard
  GPDBAccount:
    Type: ALIYUN::GPDB::Account
    Properties:
      DBInstanceId:
        Fn::GetAtt:
          - ADBPGInstance
          - DBInstanceId
      AccountPassword:
        Ref: ADBPGPassword
      AccountName:
        Ref: ADBPGAccount
  SaeNamespace:
    DependsOn:
      - PostgreSQLInstance
      - RedisInstance
      - ADBPGInstance
      - PluginNas
      - APINas
    Type: ALIYUN::SAE::Namespace
    Properties:
      NamespaceName:
        Ref: NamespaceName
      NamespaceId:
        Fn::Sub: ${ALIYUN::Region}:${NamespaceName}
      VpcId:
        Ref: Vpc
  PostgreSQLInstance:
    Type: ALIYUN::RDS::DBInstance
    Properties:
      ZoneId:
        Ref: ZoneId1
      SlaveZoneIds:
        - Ref: ZoneId2
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch1
      DBInstanceClass:
        Ref: DBInstanceClass
      DBInstanceStorage: 50
      Engine: PostgreSQL
      EngineVersion: '17.0'
      SecurityIPList: 192.168.0.0/16
      Category: HighAvailability
      MasterUserType: Super
      MasterUserPassword:
        Ref: PostgreSQLPassword
      MasterUsername:
        Ref: PostgreSQLUserName
      DBInstanceStorageType: cloud_essd
  DifyDataBase:
    Type: ALIYUN::RDS::Database
    Properties:
      CharacterSetName: utf8
      DBInstanceId:
        Fn::GetAtt:
          - PostgreSQLInstance
          - DBInstanceId
      DBName: dify
  DifySetUpDataBase:
    Type: ALIYUN::RDS::Database
    DependsOn: DifyDataBase
    Properties:
      CharacterSetName: UTF8
      DBInstanceId:
        Fn::GetAtt:
          - PostgreSQLInstance
          - DBInstanceId
      DBName: dify_setups
  RdsAccountPrivilege:
    Type: ALIYUN::RDS::AccountPrivilege
    DependsOn: DifySetUpDataBase
    Properties:
      AccountPrivilege: DBOwner
      DBInstanceId:
        Ref: PostgreSQLInstance
      DBName: dify
      AccountName:
        Ref: PostgreSQLUserName
  NatGateway:
    Type: ALIYUN::VPC::NatGateway
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch1
      NatGatewayName:
        Fn::Sub: ${CommonName}-nat
      InternetChargeType: PayByLcu
      EipBindMode: NAT
  Eip:
    Type: 'ALIYUN::VPC::EIP'
    Properties:
      DeletionProtection: false
      Isp: BGP
      Bandwidth: 200
      InternetChargeType: PayByTraffic
  EipAssociation:
    Type: 'ALIYUN::VPC::EIPAssociation'
    Properties:
      InstanceId:
        Ref: NatGateway
      AllocationId:
        Ref: Eip
  SNat:
    Type: 'ALIYUN::VPC::SnatEntry'
    DependsOn: EipAssociation
    Properties:
      SnatTableId:
        Fn::GetAtt:
          - NatGateway
          - SNatTableId
      SnatEntryName:
        Fn::Sub: ${CommonName}-snat
      SourceVSwitchIds:
        - Ref: VSwitch1
        - Ref: VSwitch2
      SnatIp:
        Fn::GetAtt:
          - Eip
          - EipAddress
  APINas:
    Type: ALIYUN::NAS::FileSystem
    Properties:
      ProtocolType: NFS
      FileSystemType: standard
      DeletionForce: true
      StorageType: Performance
      Description:
        Fn::Sub: ${CommonName}-API-NAS
  APINasMountTarget:
    Type: ALIYUN::NAS::MountTarget
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch1
      NetworkType: Vpc
      AccessGroupName: DEFAULT_VPC_GROUP_NAME
      FileSystemId:
        Ref: APINas
  PluginNas:
    Type: ALIYUN::NAS::FileSystem
    Properties:
      ProtocolType: NFS
      FileSystemType: standard
      DeletionForce: true
      StorageType: Performance
      Description:
        Fn::Sub: ${CommonName}-Plugin-NAS
  PluginNasMountTarget:
    Type: ALIYUN::NAS::MountTarget
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch1
      NetworkType: Vpc
      AccessGroupName: DEFAULT_VPC_GROUP_NAME
      FileSystemId:
        Ref: PluginNas
  SuperOpsUser:
    Type: 'ALIYUN::RAM::User'
    Properties:
      UserName:
        Fn::Sub: SuperOps-${ALIYUN::StackId}
      Policies:
        - PolicyName:
            'Fn::Join':
              - '-'
              - - DifySuperOpsPolicy
                - Ref: 'ALIYUN::StackName'
          PolicyDocument:
            Version: '1'
            Statement:
              - Effect: Allow
                Action:
                  - 'gpdb:*'
                Resource:
                  - '*'
      PolicyAttachments:
        System:
          - AliyunSTSAssumeRoleAccess
          - AliyunRAMReadOnlyAccess
  AccessKey:
    Type: 'ALIYUN::RAM::AccessKey'
    Properties:
      UserName:
        'Fn::GetAtt':
          - SuperOpsUser
          - UserName
  DifyApiConfigMap:
    Type: ALIYUN::SAE::ConfigMap
    Properties:
      Data:
        MAIL_DEFAULT_SEND_FROM: 'YOUR EMAIL FROM (eg: no-reply <no-reply@dify.ai>)'
        SENTRY_PROFILES_SAMPLE_RATE: '1'
        MARKETPLACE_ENABLED: 'true'
        DB_PORT: '5432'
        VECTOR_STORE: analyticdb
        LOG_LEVEL: INFO
        DB_DATABASE: dify
        REDIS_USE_SSL: 'false'
        STORAGE_LOCAL_PATH: /app/api/storage
        SENTRY_TRACES_SAMPLE_RATE: '1'
        MODE: api
        WEB_API_CORS_ALLOW_ORIGINS: '*'
        RESEND_API_URL: https://api.resend.com
        ANALYTICDB_INSTANCE_ID:
          Fn::GetAtt:
            - ADBPGInstance
            - DBInstanceId
        CODE_EXECUTION_ENDPOINT: http://dify-sandbox:8194
        REDIS_HOST:
          Fn::GetAtt:
            - RedisInstance
            - ConnectionDomain
        REDIS_DB: '0'
        REDIS_PORT: '6379'
        MAIL_TYPE: resend
        ANALYTICDB_REGION_ID:
          Ref: ALIYUN::Region
        MIGRATION_ENABLED: 'true'
        CONSOLE_CORS_ALLOW_ORIGINS: '*'
        PLUGIN_DAEMON_URL: http://dify-plugin-daemon:5002
        STORAGE_TYPE: local
        DB_HOST:
          Fn::GetAtt:
            - PostgreSQLInstance
            - InnerConnectionString
      NamespaceId:
        Ref: SaeNamespace
      Name: dify-api
  DifyApiSecret:
    Type: 'ALIYUN::SAE::Secret'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      SecretName: dify-api
      SecretType: Opaque
      SecretData:
        ANALYTICDB_ACCOUNT:
          Ref: ADBPGAccount
        ANALYTICDB_KEY_ID:
          Fn::GetAtt:
            - AccessKey
            - AccessKeyId
        ANALYTICDB_KEY_SECRET:
          Fn::GetAtt:
            - AccessKey
            - AccessKeySecret
        ANALYTICDB_NAMESPACE: difyns
        ANALYTICDB_NAMESPACE_PASSWORD:
          Ref: ADBPGPassword
        ANALYTICDB_PASSWORD:
          Ref: ADBPGPassword
        CELERY_BROKER_URL:
          Fn::Sub:
            - redis://:${REDIS_PASSWORD}@${REDIS_HOST}:6379/0
            - REDIS_PASSWORD:
                Ref: RedisInstancePassword
              REDIS_HOST:
                Fn::GetAtt:
                  - RedisInstance
                  - ConnectionDomain
        CODE_EXECUTION_API_KEY: dify-sandbox
        DB_PASSWORD:
          Ref: PostgreSQLPassword
        DB_USERNAME:
          Ref: PostgreSQLUserName
        INNER_API_KEY_FOR_PLUGIN: QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
        PLUGIN_DAEMON_KEY: lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi
        REDIS_PASSWORD:
          Ref: RedisInstancePassword
        REDIS_USERNAME: default
        RESEND_API_KEY: xxxx
        SECRET_KEY:
          !Base64Decode
          Fn::Jq:
            - First
            - .[0].Output
            - Fn::GetAtt:
                - RunCommand
                - InvokeResults
  DifyWorkerConfigMap:
    Type: ALIYUN::SAE::ConfigMap
    Properties:
      Data:
        MAIL_DEFAULT_SEND_FROM: 'YOUR EMAIL FROM (eg: no-reply <no-reply@dify.ai>)'
        SENTRY_PROFILES_SAMPLE_RATE: '1'
        MARKETPLACE_ENABLED: 'true'
        DB_PORT: '5432'
        VECTOR_STORE: analyticdb
        LOG_LEVEL: INFO
        DB_DATABASE: dify
        REDIS_USE_SSL: 'false'
        STORAGE_LOCAL_PATH: /app/api/storage
        SENTRY_TRACES_SAMPLE_RATE: '1'
        MODE: worker
        WEB_API_CORS_ALLOW_ORIGINS: '*'
        RESEND_API_URL: https://api.resend.com
        ANALYTICDB_INSTANCE_ID:
          Fn::GetAtt:
            - ADBPGInstance
            - DBInstanceId
        REDIS_HOST:
          Fn::GetAtt:
            - RedisInstance
            - ConnectionDomain
        REDIS_DB: '0'
        REDIS_PORT: '6379'
        MAIL_TYPE: resend
        ANALYTICDB_REGION_ID:
          Ref: ALIYUN::Region
        MIGRATION_ENABLED: 'true'
        CONSOLE_CORS_ALLOW_ORIGINS: '*'
        PLUGIN_DAEMON_URL: http://dify-plugin-daemon:5002
        STORAGE_TYPE: local
        DB_HOST:
          Fn::GetAtt:
            - PostgreSQLInstance
            - InnerConnectionString
      NamespaceId:
        Ref: SaeNamespace
      Name: dify-worker

  DifyWorkerSecret:
    Type: 'ALIYUN::SAE::Secret'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      SecretName: dify-worker
      SecretType: Opaque
      SecretData:
        ANALYTICDB_ACCOUNT:
          Ref: ADBPGAccount
        ANALYTICDB_KEY_ID:
          Fn::GetAtt:
            - AccessKey
            - AccessKeyId
        ANALYTICDB_KEY_SECRET:
          Fn::GetAtt:
            - AccessKey
            - AccessKeySecret
        ANALYTICDB_NAMESPACE: difyns
        ANALYTICDB_NAMESPACE_PASSWORD:
          Ref: ADBPGPassword
        ANALYTICDB_PASSWORD:
          Ref: ADBPGPassword
        CELERY_BROKER_URL:
          Fn::Sub:
            - redis://:${REDIS_PASSWORD}@${REDIS_HOST}:6379/0
            - REDIS_PASSWORD:
                Ref: RedisInstancePassword
              REDIS_HOST:
                Fn::GetAtt:
                  - RedisInstance
                  - ConnectionDomain
        DB_PASSWORD:
          Ref: PostgreSQLPassword
        DB_USERNAME:
          Ref: PostgreSQLUserName
        INNER_API_KEY_FOR_PLUGIN: QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
        PLUGIN_DAEMON_KEY: lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi
        REDIS_PASSWORD:
          Ref: RedisInstancePassword
        REDIS_USERNAME: default
        RESEND_API_KEY: xxxx
        SECRET_KEY:
          !Base64Decode
          Fn::Jq:
            - First
            - .[0].Output
            - Fn::GetAtt:
                - RunCommand
                - InvokeResults
  DifyPluginDaemonConfigMap:
    Type: 'ALIYUN::SAE::ConfigMap'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      Name: dify-plugin-daemon
      Data:
        SERVER_PORT: "5002"
        PLUGIN_REMOTE_INSTALLING_HOST: "0.0.0.0"
        REDIS_DB: "0"
        REDIS_HOST:
          Fn::GetAtt:
            - RedisInstance
            - ConnectionDomain
        MARKETPLACE_ENABLED: "true"
        DB_PORT: "5432"
        REDIS_USE_SSL: "false"
        PLUGIN_WORKING_PATH: /app/storage/cwd
        DB_HOST:
          Fn::GetAtt:
            - PostgreSQLInstance
            - InnerConnectionString
        PIP_MIRROR_URL: http://mirrors.aliyun.com/pypi/simple/
        REDIS_PORT: "6379"
        PLUGIN_REMOTE_INSTALLING_PORT: "5003"
        MAX_PLUGIN_PACKAGE_SIZE: "52428800"
        DB_DATABASE: dify_plugin
        DIFY_INNER_API_URL: http://dify-api:5001
  DifyPluginDaemonSecret:
    Type: 'ALIYUN::SAE::Secret'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      SecretName: dify-plugin-daemon
      SecretType: Opaque
      SecretData:
        DB_PASSWORD:
          Ref: PostgreSQLPassword
        DB_USERNAME:
          Ref: PostgreSQLUserName
        DIFY_INNER_API_KEY: QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
        REDIS_PASSWORD:
          Ref: RedisInstancePassword
        REDIS_USERNAME: default
        SERVER_KEY: lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi
  DifySandboxConfigMap:
    Type: 'ALIYUN::SAE::ConfigMap'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      Name: dify-sandbox
      Data:
        GIN_MODE: release
        SANDBOX_PORT: "8194"
  DifySandboxSecret:
    Type: 'ALIYUN::SAE::Secret'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      SecretName: dify-sandbox
      SecretType: Opaque
      SecretData:
        API_KEY: dify-sandbox
  DifyWebConfigMap:
    Type: 'ALIYUN::SAE::ConfigMap'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      Name: dify-web
      Data:
        MARKETPLACE_ENABLED: "true"
        MARKETPLACE_URL: https://marketplace.dify.ai
        MARKETPLACE_API_URL: https://marketplace.dify.ai
  DifyNginxConfigMap:
    Type: 'ALIYUN::SAE::ConfigMap'
    Properties:
      NamespaceId:
        Ref: SaeNamespace
      Name: dify-nginx
      Data:
        default.conf: |-
          server {
                  listen 80;
                  server_name _;

                  location /console/api {
                    proxy_pass http://dify-api:5001;
                    include proxy.conf;
                  }

                  location /api {
                    proxy_pass http://dify-api:5001;
                    include proxy.conf;
                  }

                  location /v1 {
                    proxy_pass http://dify-api:5001;
                    include proxy.conf;
                  }

                  location /files {
                    proxy_pass http://dify-api:5001;
                    include proxy.conf;
                  }

                  location /explore {
                    proxy_pass http://dify-web:3000;
                    proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;
                    include proxy.conf;
                  }

                  location /e/ {
                    proxy_pass http://dify-plugin-daemon:5002;
                    proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;
                    include proxy.conf;
                  }

                  location / {
                    proxy_pass http://dify-web:3000;
                    include proxy.conf;
                  }
              }
        nginx.conf: |-
          user  nginx;
              worker_processes  auto;
              pid        /var/run/nginx.pid;


              events {
                  worker_connections  1024;
              }


              http {
                  include       /etc/nginx/mime.types;
                  default_type  application/octet-stream;

                  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                                    '$status $body_bytes_sent "$http_referer" '
                                    '"$http_user_agent" "$http_x_forwarded_for"';

                  sendfile        on;
                  #tcp_nopush     on;

                  keepalive_timeout  65;

                  #gzip  on;
                  client_max_body_size 15M;

                  include /etc/nginx/conf.d/*.conf;
              }
        proxy.conf: |-
          proxy_set_header Host $host;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header X-Forwarded-Proto $scheme;
          proxy_set_header X-Forwarded-Port $server_port;
          proxy_http_version 1.1;
          proxy_set_header Connection "";
          proxy_buffering off;
          proxy_read_timeout 3600s;
          proxy_send_timeout 3600s;
  DifyApiApp:
    DependsOn:
      - SaeNamespace
      - DifyApiConfigMap
      - DifyApiSecret
      - ADBPGInstance
    Type: 'ALIYUN::SAE::Application'
    Properties:
      AppName: dify-api
      SaeVersion: v2
      AutoConfig: false
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: SecurityGroup
      VSwitchId:
        Fn::Sub:
          - '${VSwitch1},${VSwitch2}'
          - VSwitch1:
              Ref: VSwitch1
            VSwitch2:
              Ref: VSwitch2
      Replicas: 1
      NamespaceId:
        Ref: SaeNamespace
      Cpu: 1000
      Memory: 2048
      PackageType: Image
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-api-v1.6.0
      ProgrammingLanguage: python
      AppSource: micro_service
      Timezone: Asia/Shanghai
      NasConfigs:
        Fn::Sub:
          - '[{"mountDomain":"${MOUNT_DOMAIN}","mountPath":"/app/api/storage","nasId":"${NAS_ID}","nasPath":"dify-api","readOnly":false,"volumeName":"nas-1"}]'
          - MOUNT_DOMAIN:
              Fn::GetAtt:
                - APINasMountTarget
                - MountTargetDomain
            NAS_ID:
              Fn::GetAtt:
                - APINas
                - FileSystemId
      PvtzDiscoverySvc:
        Fn::Sub:
          - '{"enable":"true","namespaceId":"${REGION_ID}:${NAMESPACE}","portAndProtocol":{"5001:TCP":"5001"},"portProtocols":[],"pvtzDiscoveryName":"${REGION_ID}-${USER_ID}","serviceName":"dify-api.${NAMESPACE}"}'
          - NAMESPACE:
              Ref: NamespaceName
            USER_ID:
              Ref: ALIYUN::TenantId
            REGION_ID:
              Ref: ALIYUN::Region
      Envs:
        Fn::Sub:
          - '[{"name":"APP_WEB_URL"},{"name":"FILES_URL"},{"name":"CODE_MAX_DEPTH","value":"5"},{"name":"CODE_MAX_OBJECT_ARRAY_LENGTH","value":"30"},{"name":"CHECK_UPDATE_URL"},{"name":"CODE_MAX_STRING_ARRAY_LENGTH","value":"30"},{"name":"SERVICE_API_URL"},{"name":"sae-sys-secret-all-dify-api","valueFrom":{"secretRef":{"secretId":${SECRET_ID},"key":""}}},{"name":"CODE_MAX_PRECISION","value":"20"},{"name":"CONSOLE_API_URL"},{"name":"TEMPLATE_TRANSFORM_MAX_LENGTH","value":"80000"},{"name":"CODE_MAX_NUMBER","value":"9223372036854775807"},{"name":"CODE_MAX_NUMBER_ARRAY_LENGTH","value":"1000"},{"name":"CONSOLE_WEB_URL"},{"name":"CODE_MIN_NUMBER","value":"-9223372036854775808"},{"name":"CODE_MAX_STRING_LENGTH","value":"80000"},{"name":"SENTRY_DSN"},{"name":"CODE_EXECUTION_API_KEY","valueFrom":{"secretRef":{"secretId":${SANDBOX_SECRET_ID},"key":"API_KEY"}}},{"name":"sae-sys-configmap-all-dify-api","valueFrom":{"configMapRef":{"configMapId":${CONFIGMAP_ID},"key":""}}}]'
          - CONFIGMAP_ID:
              Fn::GetAtt:
                - DifyApiConfigMap
                - ConfigMapId
            SECRET_ID:
              Fn::GetAtt:
                - DifyApiSecret
                - SecretId
            SANDBOX_SECRET_ID:
              Fn::GetAtt:
                - DifySandboxSecret
                - SecretId
  DifyWorkerApp:
    DependsOn:
      - SaeNamespace
      - DifyWorkerConfigMap
      - DifyWorkerSecret
    Type: 'ALIYUN::SAE::Application'
    Properties:
      AppName: dify-worker
      SaeVersion: v2
      AutoConfig: false
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: SecurityGroup
      VSwitchId:
        Fn::Sub:
          - '${VSwitch1},${VSwitch2}'
          - VSwitch1:
              Ref: VSwitch1
            VSwitch2:
              Ref: VSwitch2
      Replicas: 1
      NamespaceId:
        Ref: SaeNamespace
      Cpu: 1000
      Memory: 2048
      PackageType: Image
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-api-v1.6.0
      ProgrammingLanguage: python
      AppSource: micro_service
      Timezone: Asia/Shanghai
      NasConfigs:
        Fn::Sub:
          - '[{"mountDomain":"${MOUNT_DOMAIN}","mountPath":"/app/api/storage","nasId":"${NAS_ID}","nasPath":"dify-api","readOnly":false,"volumeName":"nas-1"}]'
          - MOUNT_DOMAIN:
              Fn::GetAtt:
                - APINasMountTarget
                - MountTargetDomain
            NAS_ID:
              Fn::GetAtt:
                - APINas
                - FileSystemId
      Envs:
        Fn::Sub:
          - '[{"name":"sae-sys-secret-all-dify-worker","valueFrom":{"secretRef":{"secretId":${SECRET_ID},"key":""}}},{"name":"sae-sys-configmap-all-dify-worker","valueFrom":{"configMapRef":{"configMapId":${CONFIGMAP_ID},"key":""}}},{"name":"CONSOLE_WEB_URL"}]'
          - CONFIGMAP_ID:
              Fn::GetAtt:
                - DifyWorkerConfigMap
                - ConfigMapId
            SECRET_ID:
              Fn::GetAtt:
                - DifyWorkerSecret
                - SecretId
  DifyPluginDaemonApp:
    DependsOn:
      - SaeNamespace
      - DifyPluginDaemonConfigMap
      - DifyPluginDaemonSecret
    Type: 'ALIYUN::SAE::Application'
    Properties:
      AppName: dify-plugin-daemon
      SaeVersion: v2
      AutoConfig: false
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: SecurityGroup
      VSwitchId:
        Fn::Sub:
          - '${VSwitch1},${VSwitch2}'
          - VSwitch1:
              Ref: VSwitch1
            VSwitch2:
              Ref: VSwitch2
      Replicas: 1
      NamespaceId:
        Ref: SaeNamespace
      Cpu: 1000
      Memory: 2048
      PackageType: Image
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-plugin-daemon-v0.1.3-local
      ProgrammingLanguage: golang
      AppSource: micro_service
      Timezone: Asia/Shanghai
      NasConfigs:
        Fn::Sub:
          - '[{"mountDomain":"${MOUNT_DOMAIN}","mountPath":"/app/storage","nasId":"${NAS_ID}","nasPath":"dify-plugin-daemon","readOnly":false,"volumeName":"nas-1"}]'
          - MOUNT_DOMAIN:
              Fn::GetAtt:
                - PluginNasMountTarget
                - MountTargetDomain
            NAS_ID:
              Fn::GetAtt:
                - PluginNas
                - FileSystemId
      PvtzDiscoverySvc:
        Fn::Sub:
          - '{"enable":"true","namespaceId":"${REGION_ID}:${NAMESPACE}","portAndProtocol":{"5003:TCP":"5003","5002:TCP":"5002"},"portProtocols":[],"pvtzDiscoveryName":"${REGION_ID}-${USER_ID}","serviceName":"dify-plugin-daemon.${NAMESPACE}"}'
          - NAMESPACE:
              Ref: NamespaceName
            USER_ID:
              Ref: ALIYUN::TenantId
            REGION_ID:
              Ref: ALIYUN::Region
      Envs:
        Fn::Sub:
          - '[{"name":"sae-sys-secret-all-dify-plugin-daemon","valueFrom":{"secretRef":{"secretId":${SECRET_ID},"key":""}}},{"name":"sae-sys-configmap-all-dify-plugin-daemon","valueFrom":{"configMapRef":{"configMapId":${CONFIGMAP_ID},"key":""}}}]'
          - CONFIGMAP_ID:
              Fn::GetAtt:
                - DifyPluginDaemonConfigMap
                - ConfigMapId
            SECRET_ID:
              Fn::GetAtt:
                - DifyPluginDaemonSecret
                - SecretId
  DifySandboxApp:
    DependsOn:
      - SaeNamespace
      - DifySandboxConfigMap
      - DifySandboxSecret
    Type: 'ALIYUN::SAE::Application'
    Properties:
      AppName: dify-sandbox
      SaeVersion: v2
      AutoConfig: false
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: SecurityGroup
      VSwitchId:
        Fn::Sub:
          - '${VSwitch1},${VSwitch2}'
          - VSwitch1:
              Ref: VSwitch1
            VSwitch2:
              Ref: VSwitch2
      Replicas: 1
      NamespaceId:
        Ref: SaeNamespace
      Cpu: 1000
      Memory: 2048
      PackageType: Image
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-sandbox-v0.2.12
      ProgrammingLanguage: golang
      AppSource: micro_service
      Timezone: Asia/Shanghai
      PvtzDiscoverySvc:
        Fn::Sub:
          - '{"enable":"true","namespaceId":"${REGION_ID}:${NAMESPACE}","portAndProtocol":{"8194:TCP":"8194"},"portProtocols":[],"pvtzDiscoveryName":"${REGION_ID}-${USER_ID}","serviceName":"dify-sandbox.${NAMESPACE}"}'
          - NAMESPACE:
              Ref: NamespaceName
            USER_ID:
              Ref: ALIYUN::TenantId
            REGION_ID:
              Ref: ALIYUN::Region
      Envs:
        Fn::Sub:
          - '[{"name":"sae-sys-secret-all-dify-sandbox","valueFrom":{"secretRef":{"secretId":${SECRET_ID},"key":""}}},{"name":"WORKER_TIMEOUT","value":"15"},{"name":"sae-sys-configmap-all-dify-sandbox","valueFrom":{"configMapRef":{"configMapId":${CONFIGMAP_ID},"key":""}}}]'
          - CONFIGMAP_ID:
              Fn::GetAtt:
                - DifySandboxConfigMap
                - ConfigMapId
            SECRET_ID:
              Fn::GetAtt:
                - DifySandboxSecret
                - SecretId
  DifyWebApp:
    DependsOn:
      - SaeNamespace
      - DifyWebConfigMap
    Type: 'ALIYUN::SAE::Application'
    Properties:
      AppName: dify-web
      SaeVersion: v2
      AutoConfig: false
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: SecurityGroup
      VSwitchId:
        Fn::Sub:
          - '${VSwitch1},${VSwitch2}'
          - VSwitch1:
              Ref: VSwitch1
            VSwitch2:
              Ref: VSwitch2
      Replicas: 1
      NamespaceId:
        Ref: SaeNamespace
      Cpu: 1000
      Memory: 2048
      PackageType: Image
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-web-v1.6.0
      ProgrammingLanguage: other
      AppSource: micro_service
      Timezone: Asia/Shanghai
      PvtzDiscoverySvc:
        Fn::Sub:
          - '{"enable":"true","namespaceId":"${REGION_ID}:${NAMESPACE}","portAndProtocol":{"3000:TCP":"3000"},"portProtocols":[],"pvtzDiscoveryName":"${REGION_ID}-${USER_ID}","serviceName":"dify-web.${NAMESPACE}"}'
          - NAMESPACE:
              Ref: NamespaceName
            USER_ID:
              Ref: ALIYUN::TenantId
            REGION_ID:
              Ref: ALIYUN::Region
      Envs:
        Fn::Sub:
          - '[{"name":"sae-sys-configmap-all-dify-web","valueFrom":{"configMapRef":{"configMapId":${CONFIGMAP_ID},"key":""}}},{"name":"APP_API_URL"},{"name":"CONSOLE_API_URL"},{"name":"EDITION","value":"SELF_HOSTED"}]'
          - CONFIGMAP_ID:
              Fn::GetAtt:
                - DifyWebConfigMap
                - ConfigMapId
  DifyNginxApp:
    DependsOn:
      - SaeNamespace
      - DifyNginxConfigMap
    Type: 'ALIYUN::SAE::Application'
    Properties:
      AppName: dify-nginx
      SaeVersion: v2
      AutoConfig: false
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: SecurityGroup
      VSwitchId:
        Fn::Sub:
          - '${VSwitch1},${VSwitch2}'
          - VSwitch1:
              Ref: VSwitch1
            VSwitch2:
              Ref: VSwitch2
      Replicas: 1
      NamespaceId:
        Ref: SaeNamespace
      Cpu: 1000
      Memory: 2048
      PackageType: Image
      ImageUrl:
        Fn::Sub: registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:nginx-v1.23.4
      ProgrammingLanguage: other
      AppSource: micro_service
      Timezone: Asia/Shanghai
      ConfigMapMountDesc:
        Fn::Sub:
          - '[{"MountPath":"/etc/nginx/conf.d/default.conf","ConfigMapId":${CONFIGMAP_ID},"ConfigMapName":"dify-nginx","Key":"default.conf"},{"MountPath":"/etc/nginx/nginx.conf","ConfigMapId":${CONFIGMAP_ID},"ConfigMapName":"dify-nginx","Key":"nginx.conf"},{"MountPath":"/etc/nginx/proxy.conf","ConfigMapId":${CONFIGMAP_ID},"ConfigMapName":"dify-nginx","Key":"proxy.conf"}]'
          - CONFIGMAP_ID:
              Fn::GetAtt:
                - DifyNginxConfigMap
                - ConfigMapId
  InternetClb:
    Type: ALIYUN::SLB::LoadBalancer
    Properties:
      LoadBalancerName:
        Ref: ALIYUN::StackName
      LoadBalancerSpec: slb.s2.medium
      AddressType: internet
  BackendAppBindClb:
    Type: 'ALIYUN::SAE::SlbBinding'
    DependsOn:
      - DifyNginxApp
      - InternetClb
    Properties:
      InternetSlbId:
        Fn::GetAtt:
          - InternetClb
          - LoadBalancerId
      Internet: '[{"port": 80, "targetPort": 80, "protocol": "TCP"}]'
      AppId:
        Fn::GetAtt:
          - DifyNginxApp
          - AppId
Outputs:
  DifyAddress:
    Label:
      zh-cn: Dify service address.
      en: Dify service address.
    Description:
      zh-cn: Dify service address.
      en: Dify service address.
    Value:
      Fn::Sub:
        - http://${ServerAddress}:80
        - ServerAddress:
            Fn::GetAtt:
              - InternetClb
              - IpAddress
  PostgresName:
    Label:
      zh-cn: Postgres username
      en: Postgres username
    Description:
      zh-cn: The username of AnalyticDB for PostgreSQL.
      en: The username of AnalyticDB for PostgreSQL.
    Value:
      Ref: ADBPGAccount
  PostgresPassword:
    Label:
      zh-cn: Postgres password
      en: Postgres password
    Description:
      zh-cn: The password of AnalyticDB for PostgreSQL.
      en: The password of AnalyticDB for PostgreSQL.
    NoEcho: true
    Value:
      Ref: ADBPGPassword
  PostgresConnectionString:
    Label:
      zh-cn: Postgres database address
      en: Postgres database address
    Description:
      zh-cn: The internal endpoint of AnalyticDB for PostgreSQL.
      en: The internal endpoint of AnalyticDB for PostgreSQL.
    Value:
      Fn::GetAtt:
        - ADBPGInstance
        - ConnectionString
  APINasFileSystemId:
    Label:
      zh-cn: API NAS file system
      en: API NAS file system
    Description:
      zh-cn: NAS file system.
      en: NAS file system.
    Value:
      Ref: APINas
  APINasMountTarget:
    Label:
      zh-cn: API NAS mount target
      en: API NAS mount target
    Description:
      zh-cn: NAS mount target.
      en: NAS mount target.
    Value:
      Ref: APINasMountTarget
  PluginNasFileSystemId:
    Label:
      zh-cn: Plugin NAS file system
      en: Plugin NAS file system
    Description:
      zh-cn: NAS file system.
      en: NAS file system.
    Value:
      Ref: PluginNas
  PluginNasMountTarget:
    Label:
      zh-cn: Plugin NAS mount target
      en: Plugin NAS mount target
    Description:
      zh-cn: NAS mount target.
      en: NAS mount target.
    Value:
      Ref: PluginNasMountTarget
  RedisConnectionString:
    Label:
      zh-cn: Redis endpoint
      en: Redis endpoint
    Description:
      zh-cn: Redis endpoint.
      en: Redis endpoint.
    Value:
      Fn::GetAtt:
        - RedisInstance
        - ConnectionDomain
  RedisName:
    Label:
      zh-cn: Redis username
      en: Redis username
    Description:
      zh-cn: The username of Redis.
      en: The username of Redis.
    Value: default
  RedisInstancePassword:
    Label:
      zh-cn: Redis password
      en: Redis password
    Description:
      zh-cn: The password of Redis.
      en: The password of Redis.
    NoEcho: true
    Value:
      Ref: RedisInstancePassword
  PostgreSQLDBName:
    Label:
      zh-cn: Database Name
      en: Database Name
    Description:
      zh-cn: The database name of ApsaraDB RDS for PostgreSQL.
      en: The database name of ApsaraDB RDS for PostgreSQL.
    Value: dify
  PostgreSQLConnectionString:
    Label:
      zh-cn: RDS database address
      en: RDS database address
    Description:
      zh-cn: The internal endpoint of ApsaraDB RDS for PostgreSQL.
      en: The internal endpoint of ApsaraDB RDS for PostgreSQL.
    Value:
      Fn::GetAtt:
        - PostgreSQLInstance
        - InnerConnectionString
  PostgreSQLAccount:
    Label:
      zh-cn: RDS username
      en: RDS username
    Description:
      zh-cn: The username of ApsaraDB RDS for PostgreSQL.
      en: The username of ApsaraDB RDS for PostgreSQL.
    Value:
      Ref: PostgreSQLUserName
  PostgreSQLPassword:
    Label:
      zh-cn: RDS password
      en: RDS password
    Description:
      zh-cn: The password of ApsaraDB RDS for PostgreSQL.
      en: The password of ApsaraDB RDS for PostgreSQL.
    NoEcho: true
    Value:
      Ref: PostgreSQLPassword
  NameSpace:
    Label:
      zh-cn: Namespace
      en: Namespace
    Description:
      zh-cn: Namespace.
      en: Namespace.
    Value:
      Fn::Sub: ${ALIYUN::Region}:${NamespaceName}
  Vpc:
    Label:
      zh-cn: VPC ID
      en: VPC ID
    Description:
      zh-cn: VPC ID.
      en: VPC ID.
    Value:
      Ref: Vpc
  Vsw:
    Label:
      zh-cn: vSwitch ID
      en: vSwitch ID
    Description:
      zh-cn: vSwitch ID.
      en: vSwitch ID.
    Value:
      Ref: VSwitch1
  Sg:
    Label:
      zh-cn: Security Group ID
      en: Security Group ID
    Description:
        zh-cn: Security Group ID.
        en: Security Group ID.
    Value:
        Ref: SecurityGroup
  SecretKey:
    Label:
      zh-cn: Secret Key
      en: Secret Key
    Description:
      zh-cn: Used for secure signatures and encrypting sensitive information in the database.
      en: Used for secure signatures and encrypting sensitive information in the database.
    NoEcho: true
    Value:
      !Base64Decode
        Fn::Jq:
          - First
          - .[0].Output
          - Fn::GetAtt:
              - RunCommand
              - InvokeResults
  dify-nginx:
    Label:
      zh-cn: The application address of dify-nginx
      en: The application address of dify-nginx
    Description:
      zh-cn: The application address of dify-nginx. In the application access settings, view the public endpoint based on SLB access.
      en: The application address of dify-nginx. In the application access settings, view the public endpoint based on SLB access.
    Value:
      Fn::Sub: https://sae.console.alibabacloud.com/${ALIYUN::Region}/app-list/${DifyNginxApp.AppId}/micro-app/base?name=dify-nginx
  ECSInstanceId:
    Label:
      zh-cn: ECS instance ID
      en: ECS instance ID
    Description:
      zh-cn: ECS instance ID. This instance deploys the sample e-commerce system.
      en: ECS instance ID. This instance deploys the sample e-commerce system.
    Value:
      Fn::Select:
        - 0
        - Fn::GetAtt:
            - EcsInstance
            - InstanceIds
  Console@DemoUrl:
    Description:
      zh-cn: The application access domain name, which is the address of the e-commerce system in this solution.
      en: The application access domain name, which is the address of the e-commerce system in this solution.
    Value:
      Fn::Sub:
        - http://${PublicIp}
        - PublicIp:
            Fn::Select:
              - 0
              - Fn::GetAtt:
                  - EcsInstance
                  - PublicIps
Metadata:
  'ALIYUN::ROS::Interface':
    Outputs:
      - DifyAddress
      - ECSInstanceId
      - Console@DemoUrl
      - dify-nginx
      - NameSpace
      - Vpc
      - Vsw
      - Sg
      - PostgreSQLDBName
      - PostgreSQLConnectionString
      - PostgreSQLAccount
      - PostgreSQLPassword
      - PostgresName
      - PostgresPassword
      - PostgresConnectionString
      - APINasFileSystemId
      - APINasMountTarget
      - PluginNasFileSystemId
      - PluginNasMountTarget
      - RedisConnectionString
      - RedisName
      - RedisInstancePassword
      - SecretKey
    ParameterGroups:
      - Parameters:
          - ZoneId1
          - ZoneId2
        Label:
          default:
            en: Availability Zone
            zh-cn: Availability Zone
      - Parameters:
          - InstanceType
          - InstancePassword
        Label:
          default:
            en: Elastic Compute Service (ECS)
            zh-cn: Elastic Compute Service (ECS)
      - Parameters:
          - RedisInstancePassword
        Label:
          default:
            en: ApsaraDB for Tair (compatible with Redis)
            zh-cn: ApsaraDB for Tair (compatible with Redis)
      - Parameters:
          - ADBPGAccount
          - ADBPGPassword
        Label:
          default:
            en: Cloud-native data warehouse AnalyticDB for PostgreSQL
            zh-cn: Cloud-native data warehouse AnalyticDB for PostgreSQL
      - Parameters:
          - DBInstanceClass
          - RdsDatabaseName
          - PostgreSQLUserName
          - PostgreSQLPassword
        Label:
          default:
            en: ApsaraDB RDS for PostgreSQL
            zh-cn: ApsaraDB RDS for PostgreSQL
      - Parameters:
          - NamespaceName
        Label:
          default:
            en: Serverless App Engine (SAE)
            zh-cn: Serverless App Engine (SAE)
    TemplateTags:
      - acs:technical-solution:internet-application-development:Deploy a production Dify platform using Serverless App Engine-tech_solu_251
    Hidden:
      - CommonName
{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": {
    "zh-cn": "Deploys a production Dify platform using Serverless App Engine.",
    "en": "Deploy the production environment Dify platform through the Serverless application engine."
  },
  "Parameters": {
    "CommonName": {
      "Type": "String",
      "Default": "Dify"
    },
    "NamespaceName": {
      "Type": "String",
      "Label": {
        "en": "Namespace Name",
        "zh-cn": "Namespace Name"
      },
      "Description": {
        "zh-cn": "The namespace name. Only lowercase letters and numbers are supported.",
        "en": "Namespace name, only lowercase letters and numbers are supported."
      },
      "AllowedPattern": "^[a-z0-9]+$",
      "AssociationProperty": "AutoCompleteInput",
      "AssociationPropertyMetadata": {
        "Length": 3,
        "Prefix": "dify",
        "CharacterClasses": [
          {
            "Class": "lowercase",
            "min": 2
          },
          {
            "Class": "number",
            "min": 1
          }
        ]
      }
    },
    "ZoneId1": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::Instance::ZoneId",
      "AssociationPropertyMetadata": {
        "ExclusiveTo": [
          "ZoneId2"
        ]
      },
      "Label": {
        "en": "Availability Zone 1",
        "zh-cn": "Availability Zone 1"
      }
    },
    "ZoneId2": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::Instance::ZoneId",
      "AssociationPropertyMetadata": {
        "ExclusiveTo": [
          "ZoneId1"
        ]
      },
      "Label": {
        "en": "Availability Zone 2",
        "zh-cn": "Availability Zone 2"
      }
    },
    "InstanceType": {
      "Type": "String",
      "AssociationProperty": "ALIYUN::ECS::Instance::InstanceType",
      "AssociationPropertyMetadata": {
        "InstanceChargeType": "PostPaid",
        "SystemDiskCategory": "cloud_essd",
        "ZoneId": "${ZoneId1}"
      },
      "Label": {
        "en": "Instance Type",
        "zh-cn": "Instance Type"
      }
    },
    "ADBPGAccount": {
      "Default": "dify",
      "Type": "String",
      "Label": {
        "zh-cn": "DB Account",
        "en": "DB Account"
      }
    },
    "ADBPGPassword": {
      "NoEcho": true,
      "Type": "String",
      "Label": {
        "zh-cn": "DB Account Password",
        "en": "DB Account Password"
      },
      "AssociationProperty": "ALIYUN::RDS::Instance::AccountPassword"
    },
    "InstancePassword": {
      "Type": "String",
      "Label": {
        "en": "Server login Password",
        "zh-cn": "Logon Password"
      },
      "Description": {
        "en": "Server login password, Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in)",
        "zh-cn": "The logon password of the server. The password must be 8 to 30 characters in length and contain at least three of the following character types: uppercase letters, lowercase letters, digits, and special characters. Special characters are ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/"
      },
      "AssociationProperty": "ALIYUN::ECS::Instance::Password"
    },
    "RedisInstancePassword": {
      "Type": "String",
      "Label": {
        "en": "Instance Password",
        "zh-cn": "Instance Password"
      },
      "Description": {
        "en": "The Redis password used by Dify should be 8 to 32 characters. It only supports a combination of upper and lower case English and numbers. Please do not use any other characters.",
        "zh-cn": "The Redis password for Dify. The password must be 8 to 32 characters in length and can contain only uppercase letters, lowercase letters, and digits. Do not use other characters."
      },
      "ConstraintDescription": {
        "en": "The Redis password used by Dify should be 8 to 32 characters. It only supports a combination of upper and lower case English and numbers. Please do not use any other characters.",
        "zh-cn": "The Redis password for Dify. The password must be 8 to 32 characters in length and can contain only uppercase letters, lowercase letters, and digits. Do not use other characters."
      },
      "AllowedPattern": "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?\\d)[A-Za-z0-9]{8,32}$",
      "MinLength": "8",
      "MaxLength": "32",
      "NoEcho": true
    },
    "DBInstanceClass": {
      "Type": "String",
      "Label": {
        "en": "Instance Class",
        "zh-cn": "Instance Type"
      },
      "Default": "pg.n4m.2c.2m",
      "Required": true,
      "AssociationProperty": "ALIYUN::RDS::Instance::InstanceType",
      "AssociationPropertyMetadata": {
        "ZoneId": "${ZoneId}",
        "EngineVersion": "17.0",
        "Engine": "PostgreSQL",
        "Category": "HighAvailability",
        "InstanceChargeType": "Postpaid",
        "DBInstanceStorageType": "cloud_essd",
        "CommodityCode": "bards"
      }
    },
    "PostgreSQLPassword": {
      "Type": "String",
      "NoEcho": true,
      "Label": {
        "en": "Database Account Password",
        "zh-cn": "Database Account Password"
      },
      "AssociationProperty": "ALIYUN::RDS::Instance::AccountPassword"
    },
    "PostgreSQLUserName": {
      "Type": "String",
      "Label": {
        "en": "Database Account",
        "zh-cn": "Database Account"
      },
      "AllowedPattern": "^(?!dbo\\b|login\\b|admin\\b|administrator\\b|adminsys\\b|alimail\\b|aliyun\\b|apache\\b|appadmin\\b|apsara\\b|aurora\\b|bulkadmin\\b|cangjie\\b|cdn\\b|client\\b|cm\\b|dataengine\\b|dayu\\b|dba\\b|dbcreator\\b|developer\\b|diskadmin\\b|distribution\\b|dns\\b|download\\b|eagleye\\b|f5\\b|faq\\b|fuxi\\b|galaxy\\b|gongcao\\b|gongming\\b|groupon\\b|ha\\b|help\\b|host\\b|hostmaster\\b|houyi\\b|hr\\b|info\\b|information_schema\\b|kuafu\\b|lvs\\b|manager\\b|master\\b|meituan\\b|model\\b|monitor\\b|msdb\\b|mssqld\\b|mssqlsystemresource\\b|mysql\\b|nas\\b|net\\b|netops\\b|netweb\\b|news\\b|no-reply\\b|ntp\\b|nuwa\\b|nvwa\\b|operator\\b|opr\\b|ops\\b|opsdb\\b|oracle\\b|pangu\\b|pe\\b|post\\b|postmaster\\b|processadmin\\b|public\\b|qq\\b|replicator\\b|reply\\b|root\\b|sa\\b|sales\\b|san\\b|security\\b|securityadmin\\b|serveradmin\\b|services\\b|setupadmin\\b|shennong\\b|siteops\\b|sqlengine\\b|sqlonline\\b|squid\\b|ssladmin\\b|support\\b|sys\\b|sysadmin\\b|syslog\\b|system\\b|taoyun\\b|tempdb\\b|test\\b|tianyun\\b|wangwang\\b|eb\\b|webmaster\\b|webnet\\b|xtrabak\\b|youchao\\b|yum\\b|yunti\\b|zhongkui\\b|database\\b|add\\b|except\\b|percent\\b|all\\b|exec\\b|plan\\b|alter\\b|execute\\b|precision\\b|and\\b|exists\\b|primary\\b|any\\b|exit\\b|print\\b|as\\b|fetch\\b|proc\\b|asc\\b|file\\b|procedure\\b|authorization\\b|fillfactor\\b|public\\b|backup\\b|for\\b|raiserror\\b|begin\\b|foreign\\b|read\\b|between\\b|freetext\\b|readtext\\b|break\\b|freetexttable\\b|reconfigure\\b|browse\\b|from\\b|references\\b|bulk\\b|full\\b|replication\\b|by\\b|function\\b|restore\\b|cascade\\b|goto\\b|restrict\\b|case\\b|grant\\b|return\\b|check\\b|group\\b|revoke\\b|checkpoint\\b|having\\b|right\\b|close\\b|holdlock\\b|rollback\\b|clustered\\b|identity\\b|rowcount\\b|coalesce\\b|identity_insert\\b|rowguidcol\\b|collate\\b|identitycol\\b|rule\\b|column\\b|if\\b|save\\b|commit\\b|in\\b|schema\\b|compute\\b|index\\b|select\\b|constraint\\b|inner\\b|session_user\\b|contains\\b|insert\\b|set\\b|containstable\\b|intersect\\b|setuser\\b|continue\\b|into\\b|shutdown\\b|convert\\b|is\\b|some\\b|create\\b|join\\b|statistics\\b|cross\\b|key\\b|system_user\\b|current\\b|kill\\b|table\\b|current_date\\b|left\\b|textsize\\b|current_time\\b|like\\b|then\\b|current_timestamp\\b|lineno\\b|to\\b|current_user\\b|load\\b|top\\b|cursor\\b|national\\b|tran\\b|database\\b|nocheck\\b|transaction\\b|dbcc\\b|nonclustered\\b|trigger\\b|deallocate\\b|not\\b|truncate\\b|declare\\b|null\\b|tsequal\\b|default\\b|nullif\\b|union\\b|delete\\b|of\\b|unique\\b|deny\\b|off\\b|update\\b|desc\\b|offsets\\b|updatetext\\b|disk\\b|on\\b|use\\b|distinct\\b|open\\b|user\\b|distributed\\b|opendatasource\\b|values\\b|double\\b|openquery\\b|varying\\b|drop\\b|openrowset\\b|view\\b|dummy\\b|openxml\\b|waitfor\\b|dump\\b|option\\b|when\\b|else\\b|or\\b|where\\b|end\\b|order\\b|while\\b|errlvl\\b|outer\\b|with\\b|escape\\b|over\\b|writetext\\b|add\\b|analyze\\b|asc\\b|between\\b|blob\\b|call\\b|change\\b|check\\b|condition\\b|continue\\b|cross\\b|current_timestamp\\b|database\\b|day_microsecond\\b|dec\\b|default\\b|desc\\b|distinct\\b|double\\b|each\\b|enclosed\\b|exit\\b|fetch\\b|float8\\b|foreign\\b|goto\\b|having\\b|hour_minute\\b|ignore\\b|infile\\b|insensitive\\b|int1\\b|int4\\b|interval\\b|iterate\\b|keys\\b|leading\\b|like\\b|lines\\b|localtimestamp\\b|longblob\\b|low_priority\\b|mediumint\\b|minute_microsecond\\b|modifies\\b|no_write_to_binlog\\b|on\\b|optionally\\b|out\\b|precision\\b|purge\\b|read\\b|references\\b|rename\\b|require\\b|revoke\\b|schema\\b|select\\b|set\\b|spatial\\b|sqlexception\\b|sql_big_result\\b|ssl\\b|table\\b|tinyblob\\b|to\\b|true\\b|unique\\b|update\\b|using\\b|utc_timestamp\\b|varchar\\b|when\\b|with\\b|xor\\b|all\\b|and\\b|asensitive\\b|bigint\\b|both\\b|cascade\\b|char\\b|collate\\b|connection\\b|convert\\b|current_date\\b|current_user\\b|databases\\b|day_minute\\b|decimal\\b|delayed\\b|describe\\b|distinctrow\\b|drop\\b|else\\b|escaped\\b|explain\\b|float\\b|for\\b|from\\b|grant\\b|high_priority\\b|hour_second\\b|in\\b|inner\\b|insert\\b|int2\\b|int8\\b|into\\b|join\\b|kill\\b|leave\\b|limit\\b|load\\b|lock\\b|longtext\\b|match\\b|mediumtext\\b|minute_second\\b|natural\\b|null\\b|optimize\\b|or\\b|outer\\b|primary\\b|raid0\\b|reads\\b|regexp\\b|repeat\\b|restrict\\b|right\\b|schemas\\b|sensitive\\b|show\\b|specific\\b|sqlstate\\b|sql_calc_found_rows\\b|starting\\b|terminated\\b|tinyint\\b|trailing\\b|undo\\b|unlock\\b|usage\\b|utc_date\\b|values\\b|varcharacter\\b|where\\b|write\\b|year_month\\b|alter\\b|as\\b|before\\b|binary\\b|by\\b|case\\b|character\\b|column\\b|constraint\\b|create\\b|current_time\\b|cursor\\b|day_hour\\b|day_second\\b|declare\\b|delete\\b|deterministic\\b|div\\b|dual\\b|elseif\\b|exists\\b|false\\b|float4\\b|force\\b|fulltext\\b|group\\b|hour_microsecond\\b|if\\b|index\\b|inout\\b|int\\b|int3\\b|integer\\b|is\\b|key\\b|label\\b|left\\b|linear\\b|localtime\\b|long\\b|loop\\b|mediumblob\\b|middleint\\b|mod\\b|not\\b|numeric\\b|option\\b|order\\b|outfile\\b|procedure\\b|range\\b|real\\b|release\\b|replace\\b|return\\b|rlike\\b|second_microsecond\\b|separator\\b|smallint\\b|sql\\b|sqlwarning\\b|sql_small_result\\b|straight_join\\b|then\\b|tinytext\\b|trigger\\b|union\\b|unsigned\\b|use\\b|utc_time\\b|varbinary\\b|varying\\b|while\\b|x509\\b|zerofill)([a-zA-Z][a-zA-Z0-9_]{0,30}[a-zA-Z0-9])$",
      "ConstraintDescription": {
        "en": "The value can be up to 32 characters in length and can contain letters, digits, and underscores (_). The value must start with a letter and end with a letter or digit.  For more information about invalid characters, see <a href=\"https://www.alibabacloud.com/help/zh/rds/developer-reference/forbidden-keywords\" target=\"_blank\">Forbidden keywords table</a>.",
        "zh-cn": "The value must be up to 32 characters in length and can contain lowercase letters, uppercase letters, digits, and underscores (_). It must start with a letter and end with a letter or digit. For more information about invalid characters, see <a href=\"https://www.alibabacloud.com/help/zh/rds/developer-reference/forbidden-keywords\" target=\"_blank\">Forbidden keywords table</a>."
      },
      "Default": "db_user"
    }
  },
  "Resources": {
    "Vpc": {
      "Type": "ALIYUN::ECS::VPC",
      "Properties": {
        "CidrBlock": "192.168.0.0/16",
        "VpcName": {
          "Fn::Sub": "${CommonName}-VPC_HZ"
        }
      }
    },
    "VSwitch1": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "CidrBlock": "192.168.1.0/24",
        "ZoneId": {
          "Ref": "ZoneId1"
        },
        "VSwitchName": {
          "Fn::Sub": "${CommonName}-vsw_001"
        }
      }
    },
    "VSwitch2": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "CidrBlock": "192.168.2.0/24",
        "ZoneId": {
          "Ref": "ZoneId2"
        },
        "VSwitchName": {
          "Fn::Sub": "${CommonName}-vsw_002"
        }
      }
    },
    "Sleep": {
      "DependsOn": [
        "VSwitch1",
        "VSwitch2"
      ],
      "Type": "ALIYUN::ROS::Sleep",
      "Properties": {
        "DeleteDuration": 300
      }
    },
    "SecurityGroup": {
      "Type": "ALIYUN::ECS::SecurityGroup",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupName": {
          "Fn::Sub": "${CommonName}-SecurityGroup_1"
        },
        "SecurityGroupIngress": [
          {
            "PortRange": "80/80",
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          },
          {
            "PortRange": "3000/3000",
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          },
          {
            "PortRange": "5001/5001",
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          },
          {
            "PortRange": "5002/5002",
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          },
          {
            "PortRange": "5003/5003",
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          },
          {
            "PortRange": "8080/8080",
            "Priority": 1,
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "tcp"
          }
        ]
      }
    },
    "EcsInstance": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "ZoneId": {
          "Ref": "ZoneId1"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "ImageId": "aliyun_3_x64_20G_alibase_",
        "InstanceName": {
          "Fn::Sub": "${CommonName}-ecs"
        },
        "InstanceType": {
          "Ref": "InstanceType"
        },
        "SystemDiskCategory": "cloud_essd",
        "MaxAmount": 1,
        "SystemDiskSize": 40,
        "InternetMaxBandwidthOut": 5,
        "Password": {
          "Ref": "InstancePassword"
        }
      }
    },
    "RunCommand": {
      "Type": "ALIYUN::ECS::RunCommand",
      "Properties": {
        "CommandContent": {
          "Fn::Sub": "#!/bin/sh\necho \"sk-$(openssl rand -hex 16)\"\n"
        },
        "Type": "RunShellScript",
        "InstanceIds": [
          {
            "Ref": "EcsInstance"
          }
        ]
      }
    },
    "RunCommand2": {
      "DependsOn": [
        "RunCommand"
      ],
      "Type": "ALIYUN::ECS::RunCommand",
      "Properties": {
        "CommandContent": {
          "Fn::Sub": "#!/bin/sh\nexport ROS_DEPLOY=true\ncurl -fsSL https://help-static-aliyun-doc.aliyuncs.com/install-script/dify/sae/install.sh | bash\n"
        },
        "Type": "RunShellScript",
        "InstanceIds": [
          {
            "Ref": "EcsInstance"
          }
        ]
      }
    },
    "RedisInstance": {
      "Type": "ALIYUN::REDIS::Instance",
      "Properties": {
        "ZoneId": {
          "Ref": "ZoneId1"
        },
        "SecondaryZoneId": {
          "Ref": "ZoneId2"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "InstanceClass": "redis.shard.large.y.ee",
        "EvictionPolicy": "noeviction",
        "InstanceName": {
          "Fn::Sub": "${CommonName}-Redis"
        },
        "EngineVersion": "7.0",
        "Password": {
          "Ref": "RedisInstancePassword"
        }
      }
    },
    "REDISWhitelist": {
      "Type": "ALIYUN::REDIS::Whitelist",
      "Properties": {
        "InstanceId": {
          "Ref": "RedisInstance"
        },
        "SecurityIps": "192.168.0.0/16"
      }
    },
    "ADBPGInstance": {
      "Type": "ALIYUN::GPDB::DBInstance",
      "Properties": {
        "EngineVersion": "7.0",
        "VectorConfigurationStatus": true,
        "InstanceSpec": "4C32G",
        "ZoneId": {
          "Ref": "ZoneId1"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "SegNodeNum": 4,
        "SegStorageType": "cloud_essd",
        "SegDiskPerformanceLevel": "pl1",
        "StorageSize": 50,
        "VPCId": {
          "Ref": "Vpc"
        },
        "SecurityIPList": "192.168.0.0/16",
        "DBInstanceDescription": {
          "Fn::Sub": "${CommonName}"
        },
        "PayType": "Postpaid",
        "DBInstanceCategory": "HighAvailability",
        "DBInstanceMode": "StorageElastic",
        "ProdType": "standard"
      }
    },
    "GPDBAccount": {
      "Type": "ALIYUN::GPDB::Account",
      "Properties": {
        "DBInstanceId": {
          "Fn::GetAtt": [
            "ADBPGInstance",
            "DBInstanceId"
          ]
        },
        "AccountPassword": {
          "Ref": "ADBPGPassword"
        },
        "AccountName": {
          "Ref": "ADBPGAccount"
        }
      }
    },
    "SaeNamespace": {
      "DependsOn": [
        "PostgreSQLInstance",
        "RedisInstance",
        "ADBPGInstance",
        "PluginNas",
        "APINas"
      ],
      "Type": "ALIYUN::SAE::Namespace",
      "Properties": {
        "NamespaceName": {
          "Ref": "NamespaceName"
        },
        "NamespaceId": {
          "Fn::Sub": "${ALIYUN::Region}:${NamespaceName}"
        },
        "VpcId": {
          "Ref": "Vpc"
        }
      }
    },
    "PostgreSQLInstance": {
      "Type": "ALIYUN::RDS::DBInstance",
      "Properties": {
        "ZoneId": {
          "Ref": "ZoneId1"
        },
        "SlaveZoneIds": [
          {
            "Ref": "ZoneId2"
          }
        ],
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "DBInstanceClass": {
          "Ref": "DBInstanceClass"
        },
        "DBInstanceStorage": 50,
        "Engine": "PostgreSQL",
        "EngineVersion": "17.0",
        "SecurityIPList": "192.168.0.0/16",
        "Category": "HighAvailability",
        "MasterUserType": "Super",
        "MasterUserPassword": {
          "Ref": "PostgreSQLPassword"
        },
        "MasterUsername": {
          "Ref": "PostgreSQLUserName"
        },
        "DBInstanceStorageType": "cloud_essd"
      }
    },
    "DifyDataBase": {
      "Type": "ALIYUN::RDS::Database",
      "Properties": {
        "CharacterSetName": "utf8",
        "DBInstanceId": {
          "Fn::GetAtt": [
            "PostgreSQLInstance",
            "DBInstanceId"
          ]
        },
        "DBName": "dify"
      }
    },
    "DifySetUpDataBase": {
      "Type": "ALIYUN::RDS::Database",
      "DependsOn": "DifyDataBase",
      "Properties": {
        "CharacterSetName": "UTF8",
        "DBInstanceId": {
          "Fn::GetAtt": [
            "PostgreSQLInstance",
            "DBInstanceId"
          ]
        },
        "DBName": "dify_setups"
      }
    },
    "RdsAccountPrivilege": {
      "Type": "ALIYUN::RDS::AccountPrivilege",
      "DependsOn": "DifySetUpDataBase",
      "Properties": {
        "AccountPrivilege": "DBOwner",
        "DBInstanceId": {
          "Ref": "PostgreSQLInstance"
        },
        "DBName": "dify",
        "AccountName": {
          "Ref": "PostgreSQLUserName"
        }
      }
    },
    "NatGateway": {
      "Type": "ALIYUN::VPC::NatGateway",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "NatGatewayName": {
          "Fn::Sub": "${CommonName}-nat"
        },
        "InternetChargeType": "PayByLcu",
        "EipBindMode": "NAT"
      }
    },
    "Eip": {
      "Type": "ALIYUN::VPC::EIP",
      "Properties": {
        "DeletionProtection": false,
        "Isp": "BGP",
        "Bandwidth": 200,
        "InternetChargeType": "PayByTraffic"
      }
    },
    "EipAssociation": {
      "Type": "ALIYUN::VPC::EIPAssociation",
      "Properties": {
        "InstanceId": {
          "Ref": "NatGateway"
        },
        "AllocationId": {
          "Ref": "Eip"
        }
      }
    },
    "SNat": {
      "Type": "ALIYUN::VPC::SnatEntry",
      "DependsOn": "EipAssociation",
      "Properties": {
        "SnatTableId": {
          "Fn::GetAtt": [
            "NatGateway",
            "SNatTableId"
          ]
        },
        "SnatEntryName": {
          "Fn::Sub": "${CommonName}-snat"
        },
        "SourceVSwitchIds": [
          {
            "Ref": "VSwitch1"
          },
          {
            "Ref": "VSwitch2"
          }
        ],
        "SnatIp": {
          "Fn::GetAtt": [
            "Eip",
            "EipAddress"
          ]
        }
      }
    },
    "APINas": {
      "Type": "ALIYUN::NAS::FileSystem",
      "Properties": {
        "ProtocolType": "NFS",
        "FileSystemType": "standard",
        "DeletionForce": true,
        "StorageType": "Performance",
        "Description": {
          "Fn::Sub": "${CommonName}-API-NAS"
        }
      }
    },
    "APINasMountTarget": {
      "Type": "ALIYUN::NAS::MountTarget",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "NetworkType": "Vpc",
        "AccessGroupName": "DEFAULT_VPC_GROUP_NAME",
        "FileSystemId": {
          "Ref": "APINas"
        }
      }
    },
    "PluginNas": {
      "Type": "ALIYUN::NAS::FileSystem",
      "Properties": {
        "ProtocolType": "NFS",
        "FileSystemType": "standard",
        "DeletionForce": true,
        "StorageType": "Performance",
        "Description": {
          "Fn::Sub": "${CommonName}-Plugin-NAS"
        }
      }
    },
    "PluginNasMountTarget": {
      "Type": "ALIYUN::NAS::MountTarget",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchId": {
          "Ref": "VSwitch1"
        },
        "NetworkType": "Vpc",
        "AccessGroupName": "DEFAULT_VPC_GROUP_NAME",
        "FileSystemId": {
          "Ref": "PluginNas"
        }
      }
    },
    "SuperOpsUser": {
      "Type": "ALIYUN::RAM::User",
      "Properties": {
        "UserName": {
          "Fn::Sub": "SuperOps-${ALIYUN::StackId}"
        },
        "Policies": [
          {
            "PolicyName": {
              "Fn::Join": [
                "-",
                [
                  "DifySuperOpsPolicy",
                  {
                    "Ref": "ALIYUN::StackName"
                  }
                ]
              ]
            },
            "PolicyDocument": {
              "Version": "1",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "gpdb:*"
                  ],
                  "Resource": [
                    "*"
                  ]
                }
              ]
            }
          }
        ],
        "PolicyAttachments": {
          "System": [
            "AliyunSTSAssumeRoleAccess",
            "AliyunRAMReadOnlyAccess"
          ]
        }
      }
    },
    "AccessKey": {
      "Type": "ALIYUN::RAM::AccessKey",
      "Properties": {
        "UserName": {
          "Fn::GetAtt": [
            "SuperOpsUser",
            "UserName"
          ]
        }
      }
    },
    "DifyApiConfigMap": {
      "Type": "ALIYUN::SAE::ConfigMap",
      "Properties": {
        "Data": {
          "MAIL_DEFAULT_SEND_FROM": "YOUR EMAIL FROM (eg: no-reply <no-reply@dify.ai>)",
          "SENTRY_PROFILES_SAMPLE_RATE": "1",
          "MARKETPLACE_ENABLED": "true",
          "DB_PORT": "5432",
          "VECTOR_STORE": "analyticdb",
          "LOG_LEVEL": "INFO",
          "DB_DATABASE": "dify",
          "REDIS_USE_SSL": "false",
          "STORAGE_LOCAL_PATH": "/app/api/storage",
          "SENTRY_TRACES_SAMPLE_RATE": "1",
          "MODE": "api",
          "WEB_API_CORS_ALLOW_ORIGINS": "*",
          "RESEND_API_URL": "https://api.resend.com",
          "ANALYTICDB_INSTANCE_ID": {
            "Fn::GetAtt": [
              "ADBPGInstance",
              "DBInstanceId"
            ]
          },
          "CODE_EXECUTION_ENDPOINT": "http://dify-sandbox:8194",
          "REDIS_HOST": {
            "Fn::GetAtt": [
              "RedisInstance",
              "ConnectionDomain"
            ]
          },
          "REDIS_DB": "0",
          "REDIS_PORT": "6379",
          "MAIL_TYPE": "resend",
          "ANALYTICDB_REGION_ID": {
            "Ref": "ALIYUN::Region"
          },
          "MIGRATION_ENABLED": "true",
          "CONSOLE_CORS_ALLOW_ORIGINS": "*",
          "PLUGIN_DAEMON_URL": "http://dify-plugin-daemon:5002",
          "STORAGE_TYPE": "local",
          "DB_HOST": {
            "Fn::GetAtt": [
              "PostgreSQLInstance",
              "InnerConnectionString"
            ]
          }
        },
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Name": "dify-api"
      }
    },
    "DifyApiSecret": {
      "Type": "ALIYUN::SAE::Secret",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "SecretName": "dify-api",
        "SecretType": "Opaque",
        "SecretData": {
          "ANALYTICDB_ACCOUNT": {
            "Ref": "ADBPGAccount"
          },
          "ANALYTICDB_KEY_ID": {
            "Fn::GetAtt": [
              "AccessKey",
              "AccessKeyId"
            ]
          },
          "ANALYTICDB_KEY_SECRET": {
            "Fn::GetAtt": [
              "AccessKey",
              "AccessKeySecret"
            ]
          },
          "ANALYTICDB_NAMESPACE": "difyns",
          "ANALYTICDB_NAMESPACE_PASSWORD": {
            "Ref": "ADBPGPassword"
          },
          "ANALYTICDB_PASSWORD": {
            "Ref": "ADBPGPassword"
          },
          "CELERY_BROKER_URL": {
            "Fn::Sub": [
              "redis://:${REDIS_PASSWORD}@${REDIS_HOST}:6379/0",
              {
                "REDIS_PASSWORD": {
                  "Ref": "RedisInstancePassword"
                },
                "REDIS_HOST": {
                  "Fn::GetAtt": [
                    "RedisInstance",
                    "ConnectionDomain"
                  ]
                }
              }
            ]
          },
          "CODE_EXECUTION_API_KEY": "dify-sandbox",
          "DB_PASSWORD": {
            "Ref": "PostgreSQLPassword"
          },
          "DB_USERNAME": {
            "Ref": "PostgreSQLUserName"
          },
          "INNER_API_KEY_FOR_PLUGIN": "QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1",
          "PLUGIN_DAEMON_KEY": "lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi",
          "REDIS_PASSWORD": {
            "Ref": "RedisInstancePassword"
          },
          "REDIS_USERNAME": "default",
          "RESEND_API_KEY": "xxxx",
          "SECRET_KEY": {
            "Fn::Base64Decode": {
              "Fn::Jq": [
                "First",
                ".[0].Output",
                {
                  "Fn::GetAtt": [
                    "RunCommand",
                    "InvokeResults"
                  ]
                }
              ]
            }
          }
        }
      }
    },
    "DifyWorkerConfigMap": {
      "Type": "ALIYUN::SAE::ConfigMap",
      "Properties": {
        "Data": {
          "MAIL_DEFAULT_SEND_FROM": "YOUR EMAIL FROM (eg: no-reply <no-reply@dify.ai>)",
          "SENTRY_PROFILES_SAMPLE_RATE": "1",
          "MARKETPLACE_ENABLED": "true",
          "DB_PORT": "5432",
          "VECTOR_STORE": "analyticdb",
          "LOG_LEVEL": "INFO",
          "DB_DATABASE": "dify",
          "REDIS_USE_SSL": "false",
          "STORAGE_LOCAL_PATH": "/app/api/storage",
          "SENTRY_TRACES_SAMPLE_RATE": "1",
          "MODE": "worker",
          "WEB_API_CORS_ALLOW_ORIGINS": "*",
          "RESEND_API_URL": "https://api.resend.com",
          "ANALYTICDB_INSTANCE_ID": {
            "Fn::GetAtt": [
              "ADBPGInstance",
              "DBInstanceId"
            ]
          },
          "REDIS_HOST": {
            "Fn::GetAtt": [
              "RedisInstance",
              "ConnectionDomain"
            ]
          },
          "REDIS_DB": "0",
          "REDIS_PORT": "6379",
          "MAIL_TYPE": "resend",
          "ANALYTICDB_REGION_ID": {
            "Ref": "ALIYUN::Region"
          },
          "MIGRATION_ENABLED": "true",
          "CONSOLE_CORS_ALLOW_ORIGINS": "*",
          "PLUGIN_DAEMON_URL": "http://dify-plugin-daemon:5002",
          "STORAGE_TYPE": "local",
          "DB_HOST": {
            "Fn::GetAtt": [
              "PostgreSQLInstance",
              "InnerConnectionString"
            ]
          }
        },
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Name": "dify-worker"
      }
    },
    "DifyWorkerSecret": {
      "Type": "ALIYUN::SAE::Secret",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "SecretName": "dify-worker",
        "SecretType": "Opaque",
        "SecretData": {
          "ANALYTICDB_ACCOUNT": {
            "Ref": "ADBPGAccount"
          },
          "ANALYTICDB_KEY_ID": {
            "Fn::GetAtt": [
              "AccessKey",
              "AccessKeyId"
            ]
          },
          "ANALYTICDB_KEY_SECRET": {
            "Fn::GetAtt": [
              "AccessKey",
              "AccessKeySecret"
            ]
          },
          "ANALYTICDB_NAMESPACE": "difyns",
          "ANALYTICDB_NAMESPACE_PASSWORD": {
            "Ref": "ADBPGPassword"
          },
          "ANALYTICDB_PASSWORD": {
            "Ref": "ADBPGPassword"
          },
          "CELERY_BROKER_URL": {
            "Fn::Sub": [
              "redis://:${REDIS_PASSWORD}@${REDIS_HOST}:6379/0",
              {
                "REDIS_PASSWORD": {
                  "Ref": "RedisInstancePassword"
                },
                "REDIS_HOST": {
                  "Fn::GetAtt": [
                    "RedisInstance",
                    "ConnectionDomain"
                  ]
                }
              }
            ]
          },
          "DB_PASSWORD": {
            "Ref": "PostgreSQLPassword"
          },
          "DB_USERNAME": {
            "Ref": "PostgreSQLUserName"
          },
          "INNER_API_KEY_FOR_PLUGIN": "QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1",
          "PLUGIN_DAEMON_KEY": "lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi",
          "REDIS_PASSWORD": {
            "Ref": "RedisInstancePassword"
          },
          "REDIS_USERNAME": "default",
          "RESEND_API_KEY": "xxxx",
          "SECRET_KEY": {
            "Fn::Base64Decode": {
              "Fn::Jq": [
                "First",
                ".[0].Output",
                {
                  "Fn::GetAtt": [
                    "RunCommand",
                    "InvokeResults"
                  ]
                }
              ]
            }
          }
        }
      }
    },
    "DifyPluginDaemonConfigMap": {
      "Type": "ALIYUN::SAE::ConfigMap",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Name": "dify-plugin-daemon",
        "Data": {
          "SERVER_PORT": "5002",
          "PLUGIN_REMOTE_INSTALLING_HOST": "0.0.0.0",
          "REDIS_DB": "0",
          "REDIS_HOST": {
            "Fn::GetAtt": [
              "RedisInstance",
              "ConnectionDomain"
            ]
          },
          "MARKETPLACE_ENABLED": "true",
          "DB_PORT": "5432",
          "REDIS_USE_SSL": "false",
          "PLUGIN_WORKING_PATH": "/app/storage/cwd",
          "DB_HOST": {
            "Fn::GetAtt": [
              "PostgreSQLInstance",
              "InnerConnectionString"
            ]
          },
          "PIP_MIRROR_URL": "http://mirrors.aliyun.com/pypi/simple/",
          "REDIS_PORT": "6379",
          "PLUGIN_REMOTE_INSTALLING_PORT": "5003",
          "MAX_PLUGIN_PACKAGE_SIZE": "52428800",
          "DB_DATABASE": "dify_plugin",
          "DIFY_INNER_API_URL": "http://dify-api:5001"
        }
      }
    },
    "DifyPluginDaemonSecret": {
      "Type": "ALIYUN::SAE::Secret",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "SecretName": "dify-plugin-daemon",
        "SecretType": "Opaque",
        "SecretData": {
          "DB_PASSWORD": {
            "Ref": "PostgreSQLPassword"
          },
          "DB_USERNAME": {
            "Ref": "PostgreSQLUserName"
          },
          "DIFY_INNER_API_KEY": "QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1",
          "REDIS_PASSWORD": {
            "Ref": "RedisInstancePassword"
          },
          "REDIS_USERNAME": "default",
          "SERVER_KEY": "lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi"
        }
      }
    },
    "DifySandboxConfigMap": {
      "Type": "ALIYUN::SAE::ConfigMap",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Name": "dify-sandbox",
        "Data": {
          "GIN_MODE": "release",
          "SANDBOX_PORT": "8194"
        }
      }
    },
    "DifySandboxSecret": {
      "Type": "ALIYUN::SAE::Secret",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "SecretName": "dify-sandbox",
        "SecretType": "Opaque",
        "SecretData": {
          "API_KEY": "dify-sandbox"
        }
      }
    },
    "DifyWebConfigMap": {
      "Type": "ALIYUN::SAE::ConfigMap",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Name": "dify-web",
        "Data": {
          "MARKETPLACE_ENABLED": "true",
          "MARKETPLACE_URL": "https://marketplace.dify.ai",
          "MARKETPLACE_API_URL": "https://marketplace.dify.ai"
        }
      }
    },
    "DifyNginxConfigMap": {
      "Type": "ALIYUN::SAE::ConfigMap",
      "Properties": {
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Name": "dify-nginx",
        "Data": {
          "default.conf": "server {\n        listen 80;\n        server_name _;\n\n        location /console/api {\n          proxy_pass http://dify-api:5001;\n          include proxy.conf;\n        }\n\n        location /api {\n          proxy_pass http://dify-api:5001;\n          include proxy.conf;\n        }\n\n        location /v1 {\n          proxy_pass http://dify-api:5001;\n          include proxy.conf;\n        }\n\n        location /files {\n          proxy_pass http://dify-api:5001;\n          include proxy.conf;\n        }\n\n        location /explore {\n          proxy_pass http://dify-web:3000;\n          proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;\n          include proxy.conf;\n        }\n\n        location /e/ {\n          proxy_pass http://dify-plugin-daemon:5002;\n          proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;\n          include proxy.conf;\n        }\n\n        location / {\n          proxy_pass http://dify-web:3000;\n          include proxy.conf;\n        }\n    }",
          "nginx.conf": "user  nginx;\n    worker_processes  auto;\n    pid        /var/run/nginx.pid;\n\n\n    events {\n        worker_connections  1024;\n    }\n\n\n    http {\n        include       /etc/nginx/mime.types;\n        default_type  application/octet-stream;\n\n        log_format  main  '$remote_addr - $remote_user [$time_local] \"$request\" '\n                          '$status $body_bytes_sent \"$http_referer\" '\n                          '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n        sendfile        on;\n        #tcp_nopush     on;\n\n        keepalive_timeout  65;\n\n        #gzip  on;\n        client_max_body_size 15M;\n\n        include /etc/nginx/conf.d/*.conf;\n    }",
          "proxy.conf": "proxy_set_header Host $host;\nproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\nproxy_set_header X-Forwarded-Proto $scheme;\nproxy_set_header X-Forwarded-Port $server_port;\nproxy_http_version 1.1;\nproxy_set_header Connection \"\";\nproxy_buffering off;\nproxy_read_timeout 3600s;\nproxy_send_timeout 3600s;"
        }
      }
    },
    "DifyApiApp": {
      "DependsOn": [
        "SaeNamespace",
        "DifyApiConfigMap",
        "DifyApiSecret",
        "ADBPGInstance"
      ],
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "dify-api",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "VSwitchId": {
          "Fn::Sub": [
            "${VSwitch1},${VSwitch2}",
            {
              "VSwitch1": {
                "Ref": "VSwitch1"
              },
              "VSwitch2": {
                "Ref": "VSwitch2"
              }
            }
          ]
        },
        "Replicas": 1,
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Cpu": 1000,
        "Memory": 2048,
        "PackageType": "Image",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-api-v1.6.0"
        },
        "ProgrammingLanguage": "python",
        "AppSource": "micro_service",
        "Timezone": "Asia/Shanghai",
        "NasConfigs": {
          "Fn::Sub": [
            "[{\"mountDomain\":\"${MOUNT_DOMAIN}\",\"mountPath\":\"/app/api/storage\",\"nasId\":\"${NAS_ID}\",\"nasPath\":\"dify-api\",\"readOnly\":false,\"volumeName\":\"nas-1\"}]",
            {
              "MOUNT_DOMAIN": {
                "Fn::GetAtt": [
                  "APINasMountTarget",
                  "MountTargetDomain"
                ]
              },
              "NAS_ID": {
                "Fn::GetAtt": [
                  "APINas",
                  "FileSystemId"
                ]
              }
            }
          ]
        },
        "PvtzDiscoverySvc": {
          "Fn::Sub": [
            "{\"enable\":\"true\",\"namespaceId\":\"${REGION_ID}:${NAMESPACE}\",\"portAndProtocol\":{\"5001:TCP\":\"5001\"},\"portProtocols\":[],\"pvtzDiscoveryName\":\"${REGION_ID}-${USER_ID}\",\"serviceName\":\"dify-api.${NAMESPACE}\"}",
            {
              "NAMESPACE": {
                "Ref": "NamespaceName"
              },
              "USER_ID": {
                "Ref": "ALIYUN::TenantId"
              },
              "REGION_ID": {
                "Ref": "ALIYUN::Region"
              }
            }
          ]
        },
        "Envs": {
          "Fn::Sub": [
            "[{\"name\":\"APP_WEB_URL\"},{\"name\":\"FILES_URL\"},{\"name\":\"CODE_MAX_DEPTH\",\"value\":\"5\"},{\"name\":\"CODE_MAX_OBJECT_ARRAY_LENGTH\",\"value\":\"30\"},{\"name\":\"CHECK_UPDATE_URL\"},{\"name\":\"CODE_MAX_STRING_ARRAY_LENGTH\",\"value\":\"30\"},{\"name\":\"SERVICE_API_URL\"},{\"name\":\"sae-sys-secret-all-dify-api\",\"valueFrom\":{\"secretRef\":{\"secretId\":${SECRET_ID},\"key\":\"\"}}},{\"name\":\"CODE_MAX_PRECISION\",\"value\":\"20\"},{\"name\":\"CONSOLE_API_URL\"},{\"name\":\"TEMPLATE_TRANSFORM_MAX_LENGTH\",\"value\":\"80000\"},{\"name\":\"CODE_MAX_NUMBER\",\"value\":\"9223372036854775807\"},{\"name\":\"CODE_MAX_NUMBER_ARRAY_LENGTH\",\"value\":\"1000\"},{\"name\":\"CONSOLE_WEB_URL\"},{\"name\":\"CODE_MIN_NUMBER\",\"value\":\"-9223372036854775808\"},{\"name\":\"CODE_MAX_STRING_LENGTH\",\"value\":\"80000\"},{\"name\":\"SENTRY_DSN\"},{\"name\":\"CODE_EXECUTION_API_KEY\",\"valueFrom\":{\"secretRef\":{\"secretId\":${SANDBOX_SECRET_ID},\"key\":\"API_KEY\"}}},{\"name\":\"sae-sys-configmap-all-dify-api\",\"valueFrom\":{\"configMapRef\":{\"configMapId\":${CONFIGMAP_ID},\"key\":\"\"}}}]",
            {
              "CONFIGMAP_ID": {
                "Fn::GetAtt": [
                  "DifyApiConfigMap",
                  "ConfigMapId"
                ]
              },
              "SECRET_ID": {
                "Fn::GetAtt": [
                  "DifyApiSecret",
                  "SecretId"
                ]
              },
              "SANDBOX_SECRET_ID": {
                "Fn::GetAtt": [
                  "DifySandboxSecret",
                  "SecretId"
                ]
              }
            }
          ]
        }
      }
    },
    "DifyWorkerApp": {
      "DependsOn": [
        "SaeNamespace",
        "DifyWorkerConfigMap",
        "DifyWorkerSecret"
      ],
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "dify-worker",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "VSwitchId": {
          "Fn::Sub": [
            "${VSwitch1},${VSwitch2}",
            {
              "VSwitch1": {
                "Ref": "VSwitch1"
              },
              "VSwitch2": {
                "Ref": "VSwitch2"
              }
            }
          ]
        },
        "Replicas": 1,
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Cpu": 1000,
        "Memory": 2048,
        "PackageType": "Image",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-api-v1.6.0"
        },
        "ProgrammingLanguage": "python",
        "AppSource": "micro_service",
        "Timezone": "Asia/Shanghai",
        "NasConfigs": {
          "Fn::Sub": [
            "[{\"mountDomain\":\"${MOUNT_DOMAIN}\",\"mountPath\":\"/app/api/storage\",\"nasId\":\"${NAS_ID}\",\"nasPath\":\"dify-api\",\"readOnly\":false,\"volumeName\":\"nas-1\"}]",
            {
              "MOUNT_DOMAIN": {
                "Fn::GetAtt": [
                  "APINasMountTarget",
                  "MountTargetDomain"
                ]
              },
              "NAS_ID": {
                "Fn::GetAtt": [
                  "APINas",
                  "FileSystemId"
                ]
              }
            }
          ]
        },
        "Envs": {
          "Fn::Sub": [
            "[{\"name\":\"sae-sys-secret-all-dify-worker\",\"valueFrom\":{\"secretRef\":{\"secretId\":${SECRET_ID},\"key\":\"\"}}},{\"name\":\"sae-sys-configmap-all-dify-worker\",\"valueFrom\":{\"configMapRef\":{\"configMapId\":${CONFIGMAP_ID},\"key\":\"\"}}},{\"name\":\"CONSOLE_WEB_URL\"}]",
            {
              "CONFIGMAP_ID": {
                "Fn::GetAtt": [
                  "DifyWorkerConfigMap",
                  "ConfigMapId"
                ]
              },
              "SECRET_ID": {
                "Fn::GetAtt": [
                  "DifyWorkerSecret",
                  "SecretId"
                ]
              }
            }
          ]
        }
      }
    },
    "DifyPluginDaemonApp": {
      "DependsOn": [
        "SaeNamespace",
        "DifyPluginDaemonConfigMap",
        "DifyPluginDaemonSecret"
      ],
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "dify-plugin-daemon",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "VSwitchId": {
          "Fn::Sub": [
            "${VSwitch1},${VSwitch2}",
            {
              "VSwitch1": {
                "Ref": "VSwitch1"
              },
              "VSwitch2": {
                "Ref": "VSwitch2"
              }
            }
          ]
        },
        "Replicas": 1,
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Cpu": 1000,
        "Memory": 2048,
        "PackageType": "Image",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-plugin-daemon-v0.1.3-local"
        },
        "ProgrammingLanguage": "golang",
        "AppSource": "micro_service",
        "Timezone": "Asia/Shanghai",
        "NasConfigs": {
          "Fn::Sub": [
            "[{\"mountDomain\":\"${MOUNT_DOMAIN}\",\"mountPath\":\"/app/storage\",\"nasId\":\"${NAS_ID}\",\"nasPath\":\"dify-plugin-daemon\",\"readOnly\":false,\"volumeName\":\"nas-1\"}]",
            {
              "MOUNT_DOMAIN": {
                "Fn::GetAtt": [
                  "PluginNasMountTarget",
                  "MountTargetDomain"
                ]
              },
              "NAS_ID": {
                "Fn::GetAtt": [
                  "PluginNas",
                  "FileSystemId"
                ]
              }
            }
          ]
        },
        "PvtzDiscoverySvc": {
          "Fn::Sub": [
            "{\"enable\":\"true\",\"namespaceId\":\"${REGION_ID}:${NAMESPACE}\",\"portAndProtocol\":{\"5003:TCP\":\"5003\",\"5002:TCP\":\"5002\"},\"portProtocols\":[],\"pvtzDiscoveryName\":\"${REGION_ID}-${USER_ID}\",\"serviceName\":\"dify-plugin-daemon.${NAMESPACE}\"}",
            {
              "NAMESPACE": {
                "Ref": "NamespaceName"
              },
              "USER_ID": {
                "Ref": "ALIYUN::TenantId"
              },
              "REGION_ID": {
                "Ref": "ALIYUN::Region"
              }
            }
          ]
        },
        "Envs": {
          "Fn::Sub": [
            "[{\"name\":\"sae-sys-secret-all-dify-plugin-daemon\",\"valueFrom\":{\"secretRef\":{\"secretId\":${SECRET_ID},\"key\":\"\"}}},{\"name\":\"sae-sys-configmap-all-dify-plugin-daemon\",\"valueFrom\":{\"configMapRef\":{\"configMapId\":${CONFIGMAP_ID},\"key\":\"\"}}}]",
            {
              "CONFIGMAP_ID": {
                "Fn::GetAtt": [
                  "DifyPluginDaemonConfigMap",
                  "ConfigMapId"
                ]
              },
              "SECRET_ID": {
                "Fn::GetAtt": [
                  "DifyPluginDaemonSecret",
                  "SecretId"
                ]
              }
            }
          ]
        }
      }
    },
    "DifySandboxApp": {
      "DependsOn": [
        "SaeNamespace",
        "DifySandboxConfigMap",
        "DifySandboxSecret"
      ],
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "dify-sandbox",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "VSwitchId": {
          "Fn::Sub": [
            "${VSwitch1},${VSwitch2}",
            {
              "VSwitch1": {
                "Ref": "VSwitch1"
              },
              "VSwitch2": {
                "Ref": "VSwitch2"
              }
            }
          ]
        },
        "Replicas": 1,
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Cpu": 1000,
        "Memory": 2048,
        "PackageType": "Image",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-sandbox-v0.2.12"
        },
        "ProgrammingLanguage": "golang",
        "AppSource": "micro_service",
        "Timezone": "Asia/Shanghai",
        "PvtzDiscoverySvc": {
          "Fn::Sub": [
            "{\"enable\":\"true\",\"namespaceId\":\"${REGION_ID}:${NAMESPACE}\",\"portAndProtocol\":{\"8194:TCP\":\"8194\"},\"portProtocols\":[],\"pvtzDiscoveryName\":\"${REGION_ID}-${USER_ID}\",\"serviceName\":\"dify-sandbox.${NAMESPACE}\"}",
            {
              "NAMESPACE": {
                "Ref": "NamespaceName"
              },
              "USER_ID": {
                "Ref": "ALIYUN::TenantId"
              },
              "REGION_ID": {
                "Ref": "ALIYUN::Region"
              }
            }
          ]
        },
        "Envs": {
          "Fn::Sub": [
            "[{\"name\":\"sae-sys-secret-all-dify-sandbox\",\"valueFrom\":{\"secretRef\":{\"secretId\":${SECRET_ID},\"key\":\"\"}}},{\"name\":\"WORKER_TIMEOUT\",\"value\":\"15\"},{\"name\":\"sae-sys-configmap-all-dify-sandbox\",\"valueFrom\":{\"configMapRef\":{\"configMapId\":${CONFIGMAP_ID},\"key\":\"\"}}}]",
            {
              "CONFIGMAP_ID": {
                "Fn::GetAtt": [
                  "DifySandboxConfigMap",
                  "ConfigMapId"
                ]
              },
              "SECRET_ID": {
                "Fn::GetAtt": [
                  "DifySandboxSecret",
                  "SecretId"
                ]
              }
            }
          ]
        }
      }
    },
    "DifyWebApp": {
      "DependsOn": [
        "SaeNamespace",
        "DifyWebConfigMap"
      ],
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "dify-web",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "VpcId": {
          "Ref": "V"Ref": "SecurityGroup"
        },
        "VSwitchId": {
          "Fn::Sub": [
            "${VSwitch1},${VSwitch2}",
            {
              "VSwitch1": {
                "Ref": "VSwitch1"
              },
              "VSwitch2": {
                "Ref": "VSwitch2"
              }
            }
          ]
        },
        "Replicas": 1,
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Cpu": 1000,
        "Memory": 2048,
        "PackageType": "Image",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:dify-web-v1.6.0"
        },
        "ProgrammingLanguage": "other",
        "AppSource": "micro_service",
        "Timezone": "Asia/Shanghai",
        "PvtzDiscoverySvc": {
          "Fn::Sub": [
            "{\"enable\":\"true\",\"namespaceId\":\"${REGION_ID}:${NAMESPACE}\",\"portAndProtocol\":{\"3000:TCP\":\"3000\"},\"portProtocols\":[],\"pvtzDiscoveryName\":\"${REGION_ID}-${USER_ID}\",\"serviceName\":\"dify-web.${NAMESPACE}\"}",
            {
              "NAMESPACE": {
                "Ref": "NamespaceName"
              },
              "USER_ID": {
                "Ref": "ALIYUN::TenantId"
              },
              "REGION_ID": {
                "Ref": "ALIYUN::Region"
              }
            }
          ]
        },
        "Envs": {
          "Fn::Sub": [
            "[{\"name\":\"sae-sys-configmap-all-dify-web\",\"valueFrom\":{\"configMapRef\":{\"configMapId\":${CONFIGMAP_ID},\"key\":\"\"}}},{\"name\":\"APP_API_URL\"},{\"name\":\"CONSOLE_API_URL\"},{\"name\":\"EDITION\",\"value\":\"SELF_HOSTED\"}]",
            {
              "CONFIGMAP_ID": {
                "Fn::GetAtt": [
                  "DifyWebConfigMap",
                  "ConfigMapId"
                ]
              }
            }
          ]
        }
      }
    },
    "DifyNginxApp": {
      "DependsOn": [
        "SaeNamespace",
        "DifyNginxConfigMap"
      ],
      "Type": "ALIYUN::SAE::Application",
      "Properties": {
        "AppName": "dify-nginx",
        "SaeVersion": "v2",
        "AutoConfig": false,
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupId": {
          "Ref": "SecurityGroup"
        },
        "VSwitchId": {
          "Fn::Sub": [
            "${VSwitch1},${VSwitch2}",
            {
              "VSwitch1": {
                "Ref": "VSwitch1"
              },
              "VSwitch2": {
                "Ref": "VSwitch2"
              }
            }
          ]
        },
        "Replicas": 1,
        "NamespaceId": {
          "Ref": "SaeNamespace"
        },
        "Cpu": 1000,
        "Memory": 2048,
        "PackageType": "Image",
        "ImageUrl": {
          "Fn::Sub": "registry.${ALIYUN::Region}.aliyuncs.com/sae-serverless-demo/sae-demo:nginx-v1.23.4"
        },
        "ProgrammingLanguage": "other",
        "AppSource": "micro_service",
        "Timezone": "Asia/Shanghai",
        "ConfigMapMountDesc": {
          "Fn::Sub": [
            "[{\"MountPath\":\"/etc/nginx/conf.d/default.conf\",\"ConfigMapId\":${CONFIGMAP_ID},\"ConfigMapName\":\"dify-nginx\",\"Key\":\"default.conf\"},{\"MountPath\":\"/etc/nginx/nginx.conf\",\"ConfigMapId\":${CONFIGMAP_ID},\"ConfigMapName\":\"dify-nginx\",\"Key\":\"nginx.conf\"},{\"MountPath\":\"/etc/nginx/proxy.conf\",\"ConfigMapId\":${CONFIGMAP_ID},\"ConfigMapName\":\"dify-nginx\",\"Key\":\"proxy.conf\"}]",
            {
              "CONFIGMAP_ID": {
                "Fn::GetAtt": [
                  "DifyNginxConfigMap",
                  "ConfigMapId"
                ]
              }
            }
          ]
        }
      }
    },
    "InternetClb": {
      "Type": "ALIYUN::SLB::LoadBalancer",
      "Properties": {
        "LoadBalancerName": {
          "Ref": "ALIYUN::StackName"
        },
        "LoadBalancerSpec": "slb.s2.medium",
        "AddressType": "internet"
      }
    },
    "BackendAppBindClb": {
      "Type": "ALIYUN::SAE::SlbBinding",
      "DependsOn": [
        "DifyNginxApp",
        "InternetClb"
      ],
      "Properties": {
        "InternetSlbId": {
          "Fn::GetAtt": [
            "InternetClb",
            "LoadBalancerId"
          ]
        },
        "Internet": "[{\"port\": 80, \"targetPort\": 80, \"protocol\": \"TCP\"}]",
        "AppId": {
          "Fn::GetAtt": [
            "DifyNginxApp",
            "AppId"
          ]
        }
      }
    }
  },
  "Outputs": {
    "DifyAddress": {
      "Label": {
        "zh-cn": "Dify service address.",
        "en": "Dify service address."
      },
      "Description": {
        "zh-cn": "Dify service address.",
        "en": "Dify service address."
      },
      "Value": {
        "Fn::Sub": [
          "http://${ServerAddress}:80",
          {
            "ServerAddress": {
              "Fn::GetAtt": [
                "InternetClb",
                "IpAddress"
              ]
            }
          }
        ]
      }
    },
    "PostgresName": {
      "Label": {
        "zh-cn": "Postgres username",
        "en": "Postgres username"
      },
      "Description": {
        "zh-cn": "The username of AnalyticDB for PostgreSQL.",
        "en": "The username of AnalyticDB PostgreSQL."
      },
      "Value": {
        "Ref": "ADBPGAccount"
      }
    },
    "PostgresPassword": {
      "Label": {
        "zh-cn": "Postgres password",
        "en": "Postgres password"
      },
      "Description": {
        "zh-cn": "The password of AnalyticDB for PostgreSQL.",
        "en": "The password of AnalyticDB PostgreSQL."
      },
      "NoEcho": true,
      "Value": {
        "Ref": "ADBPGPassword"
      }
    },
    "PostgresConnectionString": {
      "Label": {
        "zh-cn": "Postgres database address",
        "en": "Postgres database address"
      },
      "Description": {
        "zh-cn": "The internal endpoint of AnalyticDB for PostgreSQL.",
        "en": "The internal network connection address of AnalyticDB PostgreSQL."
      },
      "Value": {
        "Fn::GetAtt": [
          "ADBPGInstance",
          "ConnectionString"
        ]
      }
    },
    "APINasFileSystemId": {
      "Label": {
        "zh-cn": "API NAS file system",
        "en": "API NAS file System"
      },
      "Description": {
        "zh-cn": "NAS file system.",
        "en": "NAS file System."
      },
      "Value": {
        "Ref": "APINas"
      }
    },
    "APINasMountTarget": {
      "Label": {
        "zh-cn": "API NAS mount target",
        "en": "API NAS MountTarget"
      },
      "Description": {
        "zh-cn": "NAS mount target.",
        "en": "NAS MountTarget."
      },
      "Value": {
        "Ref": "APINasMountTarget"
      }
    },
    "PluginNasFileSystemId": {
      "Label": {
        "zh-cn": "Plugin NAS file system",
        "en": "API NAS file System"
      },
      "Description": {
        "zh-cn": "NAS file system.",
        "en": "NAS file System."
      },
      "Value": {
        "Ref": "PluginNas"
      }
    },
    "PluginNasMountTarget": {
      "Label": {
        "zh-cn": "Plugin NAS mount target",
        "en": "API NAS MountTarget"
      },
      "Description": {
        "zh-cn": "NAS mount target.",
        "en": "NAS MountTarget."
      },
      "Value": {
        "Ref": "PluginNasMountTarget"
      }
    },
    "RedisConnectionString": {
      "Label": {
        "zh-cn": "Redis endpoint",
        "en": "Redis connection address"
      },
      "Description": {
        "zh-cn": "Redis endpoint.",
        "en": "Redis connection address."
      },
      "Value": {
        "Fn::GetAtt": [
          "RedisInstance",
          "ConnectionDomain"
        ]
      }
    },
    "RedisName": {
      "Label": {
        "zh-cn": "Redis username",
        "en": "Redis username"
      },
      "Description": {
        "zh-cn": "The username of Redis.",
        "en": "The username of Redis."
      },
      "Value": "default"
    },
    "RedisInstancePassword": {
      "Label": {
        "zh-cn": "Redis password",
        "en": "Redis password"
      },
      "Description": {
        "zh-cn": "The password of Redis.",
        "en": "The password of Redis."
      },
      "NoEcho": true,
      "Value": {
        "Ref": "RedisInstancePassword"
      }
    },
    "PostgreSQLDBName": {
      "Label": {
        "zh-cn": "Database Name",
        "en": "DBName"
      },
      "Description": {
        "zh-cn": "The database name of ApsaraDB RDS for PostgreSQL.",
        "en": "The database name of RDS PostgreSQL."
      },
      "Value": "dify"
    },
    "PostgreSQLConnectionString": {
      "Label": {
        "zh-cn": "RDS database address",
        "en": "RDS Database address"
      },
      "Description": {
        "zh-cn": "The internal endpoint of ApsaraDB RDS for PostgreSQL.",
        "en": "The internal network connection address of RDS PostgreSQL."
      },
      "Value": {
        "Fn::GetAtt": [
          "PostgreSQLInstance",
          "InnerConnectionString"
        ]
      }
    },
    "PostgreSQLAccount": {
      "Label": {
        "zh-cn": "RDS username",
        "en": "RDS Account"
      },
      "Description": {
        "zh-cn": "The username of ApsaraDB RDS for PostgreSQL.",
        "en": "The username of RDS PostgreSQL."
      },
      "Value": {
        "Ref": "PostgreSQLUserName"
      }
    },
    "PostgreSQLPassword": {
      "Label": {
        "zh-cn": "RDS password",
        "en": "RDS Password"
      },
      "Description": {
        "zh-cn": "The password of ApsaraDB RDS for PostgreSQL.",
        "en": "The password of RDS PostgreSQL."
      },
      "NoEcho": true,
      "Value": {
        "Ref": "PostgreSQLPassword"
      }
    },
    "NameSpace": {
      "Label": {
        "zh-cn": "Namespace",
        "en": "NameSpace"
      },
      "Description": {
        "zh-cn": "Namespace.",
        "en": "NameSpace."
      },
      "Value": {
        "Fn::Sub": "${ALIYUN::Region}:${NamespaceName}"
      }
    },
    "Vpc": {
      "Label": {
        "zh-cn": "VPC ID",
        "en": "Vpc ID"
      },
      "Description": {
        "zh-cn": "VPC ID.",
        "en": "Vpc ID."
      },
      "Value": {
        "Ref": "Vpc"
      }
    },
    "Vsw": {
      "Label": {
        "zh-cn": "vSwitch ID",
        "en": "Vsw ID"
      },
      "Description": {
        "zh-cn": "vSwitch ID.",
        "en": "Vsw ID."
      },
      "Value": {
        "Ref": "VSwitch1"
      }
    },
    "Sg": {
      "Label": {
        "zh-cn": "Security Group ID",
        "en": "Security Group ID"
      },
      "Description": {
        "zh-cn": "Security Group ID.",
        "en": "Security Group ID."
      },
      "Value": {
        "Ref": "SecurityGroup"
      }
    },
    "SecretKey": {
      "Label": {
        "zh-cn": "Secret Key",
        "en": "Secret Key"
      },
      "Description": {
        "zh-cn": "Used for secure signatures and encrypting sensitive information in the database.",
        "en": "Used for secure signatures and encrypting sensitive information in the database."
      },
      "NoEcho": true,
      "Value": {
        "Fn::Base64Decode": {
          "Fn::Jq": [
            "First",
            ".[0].Output",
            {
              "Fn::GetAtt": [
                "RunCommand",
                "InvokeResults"
              ]
            }
          ]
        }
      }
    },
    "dify-nginx": {
      "Label": {
        "zh-cn": "The application address of dify-nginx",
        "en": "The application address of dify-nginx"
      },
      "Description": {
        "zh-cn": "The application address of dify-nginx. In the application access settings, view the public endpoint based on CLB access.",
        "en": "The application address of dify-nginx,In the application access Settings, based on CLB access, view the public network access address."
      },
      "Value": {
        "Fn::Sub": "https://sae.console.alibabacloud.com/${ALIYUN::Region}/app-list/${DifyNginxApp.AppId}/micro-app/base?name=dify-nginx"
      }
    },
    "ECSInstanceId": {
      "Label": {
        "zh-cn": "ECS instance ID",
        "en": "The application address of dify-nginx"
      },
      "Description": {
        "zh-cn": "ECS instance ID. This instance deploys the sample e-commerce system.",
        "en": "ECS instance ID. This instance deploys the sample e-commerce system."
      },
      "Value": {
        "Fn::Select": [
          0,
          {
            "Fn::GetAtt": [
              "EcsInstance",
              "InstanceIds"
            ]
          }
        ]
      }
    },
    "Console@DemoUrl": {
      "Description": {
        "zh-cn": "The application access domain name, which is the address of the e-commerce system in this solution.",
        "en": "The application accesses the domain name, which is the address of the e-commerce system of this solution."
      },
      "Value": {
        "Fn::Sub": [
          "http://${PublicIp}",
          {
            "PublicIp": {
              "Fn::Select": [
                0,
                {
                  "Fn::GetAtt": [
                    "EcsInstance",
                    "PublicIps"
                  ]
                }
              ]
            }
          }
        ]
      }
    }
  },
  "Metadata": {
    "ALIYUN::ROS::Interface": {
      "Outputs": [
        "DifyAddress",
        "ECSInstanceId",
        "Console@DemoUrl",
        "dify-nginx",
        "NameSpace",
        "Vpc",
        "Vsw",
        "Sg",
        "PostgreSQLDBName",
        "PostgreSQLConnectionString",
        "PostgreSQLAccount",
        "PostgreSQLPassword",
        "PostgresName",
        "PostgresPassword",
        "PostgresConnectionString",
        "APINasFileSystemId",
        "APINasMountTarget",
        "PluginNasFileSystemId",
        "PluginNasMountTarget",
        "RedisConnectionString",
        "RedisName",
        "RedisInstancePassword",
        "SecretKey"
      ],
      "ParameterGroups": [
        {
          "Parameters": [
            "ZoneId1",
            "ZoneId2"
          ],
          "Label": {
            "default": {
              "en": "Availability Zone",
              "zh-cn": "Availability Zone"
            }
          }
        },
        {
          "Parameters": [
            "InstanceType",
            "InstancePassword"
          ],
          "Label": {
            "default": {
              "en": "Elastic Compute Service (ECS)",
              "zh-cn": "Elastic Compute Service (ECS)"
            }
          }
        },
        {
          "Parameters": [
            "RedisInstancePassword"
          ],
          "Label": {
            "default": {
              "en": "ApsaraDB for Tair (compatible with Redis)",
              "zh-cn": "ApsaraDB for Tair (compatible with Redis)"
            }
          }
        },
        {
          "Parameters": [
            "ADBPGAccount",
            "ADBPGPassword"
          ],
          "Label": {
            "default": {
              "en": "Cloud-native data warehouse AnalyticDB for PostgreSQL",
              "zh-cn": "Cloud-native data warehouse AnalyticDB for PostgreSQL"
            }
          }
        },
        {
          "Parameters": [
            "DBInstanceClass",
            "RdsDatabaseName",
            "PostgreSQLUserName",
            "PostgreSQLPassword"
          ],
          "Label": {
            "default": {
              "en": "ApsaraDB RDS for PostgreSQL",
              "zh-cn": "ApsaraDB RDS for PostgreSQL"
            }
          }
        },
        {
          "Parameters": [
            "NamespaceName"
          ],
          "Label": {
            "default": {
              "en": "Serverless App Engine (SAE)",
              "zh-cn": "Serverless App Engine (SAE)"
            }
          }
        }
      ],
      "TemplateTags": [
        "acs:technical-solution:internet-application-development:Deploy a production Dify platform using Serverless App Engine-tech_solu_251"
      ],
      "Hidden": [
        "CommonName"
      ]
    }
  }
}

For more examples, see Public templates that contain this resource.