provider "alicloud" {
region = var.region
}
variable "region" {
description = "阿里云地域"
type = string
default = "cn-hongkong"
}
variable "instance_type" {
description = "ECS实例规格"
type = string
default = "ecs.c9i.xlarge"
validation {
condition = can(regex("^ecs\\.", var.instance_type))
error_message = "实例规格必须以 'ecs.' 开头"
}
}
variable "system_disk_category" {
description = "系统盘类型"
type = string
default = "cloud_essd"
validation {
condition = contains(["cloud_efficiency", "cloud_ssd", "cloud_essd"], var.system_disk_category)
error_message = "系统盘类型必须是 cloud_efficiency, cloud_ssd 或 cloud_essd 之一"
}
}
variable "system_disk_size" {
description = "系统盘大小(GB)"
type = number
default = 40
validation {
condition = var.system_disk_size >= 20 && var.system_disk_size <= 500
error_message = "系统盘大小必须在 20-500 GB 之间"
}
}
variable "instance_password" {
description = "ECS实例密码 (至少8位,包含大小写字母和数字)"
type = string
sensitive = true
validation {
condition = (
length(var.instance_password) >= 8 &&
length(var.instance_password) <= 30 &&
can(regex("[a-z]", var.instance_password)) &&
can(regex("[A-Z]", var.instance_password)) &&
can(regex("[0-9]", var.instance_password))
)
error_message = "密码必须至少8位,包含大小写字母和数字"
}
}
variable "vpc_cidr" {
description = "VPC CIDR块"
type = string
default = "192.168.0.0/16"
}
variable "vswitch_cidr" {
description = "交换机 CIDR块"
type = string
default = "192.168.1.0/24"
}
variable "project_name" {
description = "项目名称,用于资源命名"
type = string
default = "dify-deployment"
}
variable "internet_max_bandwidth_out" {
description = "公网带宽上限(Mbps)"
type = number
default = 5
validation {
condition = var.internet_max_bandwidth_out >= 1 && var.internet_max_bandwidth_out <= 200
error_message = "公网带宽必须在 1-200 Mbps 之间"
}
}
data "alicloud_zones" "default" {
available_disk_category = var.system_disk_category
available_resource_creation = "VSwitch"
available_instance_type = var.instance_type
}
# 获取最新的CentOS 7镜像
data "alicloud_images" "centos" {
owners = "system"
name_regex = "^centos_7"
most_recent = true
instance_type = var.instance_type
}
# 创建VPC
resource "alicloud_vpc" "main" {
vpc_name = "${var.project_name}-vpc"
cidr_block = var.vpc_cidr
}
# 创建交换机
resource "alicloud_vswitch" "main" {
vpc_id = alicloud_vpc.main.id
cidr_block = var.vswitch_cidr
zone_id = data.alicloud_zones.default.zones.0.id
vswitch_name = "${var.project_name}-vswitch"
}
# 创建安全组
resource "alicloud_security_group" "main" {
security_group_name = "${var.project_name}-sg"
description = "Security group for Dify deployment"
vpc_id = alicloud_vpc.main.id
}
# 安全组规则 - HTTP
resource "alicloud_security_group_rule" "http" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = "80/80"
priority = 1
security_group_id = alicloud_security_group.main.id
cidr_ip = "0.0.0.0/0"
description = "Allow HTTP traffic"
}
# 安全组规则 - SSH
resource "alicloud_security_group_rule" "ssh" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = "22/22"
priority = 1
security_group_id = alicloud_security_group.main.id
cidr_ip = "0.0.0.0/0"
description = "Allow SSH traffic"
}
# 安全组规则 - HTTPS
resource "alicloud_security_group_rule" "https" {
type = "ingress"
ip_protocol = "tcp"
nic_type = "intranet"
policy = "accept"
port_range = "443/443"
priority = 1
security_group_id = alicloud_security_group.main.id
cidr_ip = "0.0.0.0/0"
description = "Allow HTTPS traffic"
}
# 创建ECS实例
resource "alicloud_instance" "dify" {
instance_name = "${var.project_name}-instance"
image_id = data.alicloud_images.centos.images[0].id
instance_type = var.instance_type
system_disk_category = var.system_disk_category
system_disk_size = var.system_disk_size
password = var.instance_password
vswitch_id = alicloud_vswitch.main.id
security_groups = [alicloud_security_group.main.id]
internet_max_bandwidth_out = var.internet_max_bandwidth_out
}
locals {
# 安装和配置Dify
deploy_dify = base64encode(<<-EOF
#!/bin/bash
# Dify 自动安装脚本
set -e
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> /var/log/dify-install.log
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# 错误处理
error_exit() {
log "ERROR: $1"
exit 1
}
log "更新系统包..."
yum update -y || error_exit "系统更新失败"
yum install -y git
log "安装Docker..."
sudo wget -O /etc/yum.repos.d/docker-ce.repo http://mirrors.cloud.aliyuncs.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's|https://mirrors.aliyun.com|http://mirrors.cloud.aliyuncs.com|g' /etc/yum.repos.d/docker-ce.repo
sudo yum -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
log "启动Docker服务..."
systemctl start docker || error_exit "Docker启动失败"
systemctl enable docker || error_exit "Docker自启动设置失败"
log "创建应用目录..."
mkdir -p /opt/dify
cd /opt/dify
git clone https://github.com/langgenius/dify.git . || error_exit "dify clone失败"
log "复制环境配置文件..."
cd docker
cp .env.example .env || error_exit "复制环境配置文件失败"
log "启动Dify服务..."
docker compose up -d || error_exit "启动Dify服务失败"
log "Dify安装完成!"
log "访问地址: http://$(curl -s ipinfo.io/ip):80"
log "默认管理员账户需要在首次访问时创建"
EOF
)
}
resource "alicloud_ecs_command" "deploy_dify" {
name = "deploy_dify"
type = "RunShellScript"
command_content = local.deploy_dify
timeout = 600
working_dir = "/root"
}
resource "alicloud_ecs_invocation" "invocation" {
instance_id = [alicloud_instance.dify.id]
command_id = alicloud_ecs_command.deploy_dify.id
timeouts {
create = "10m"
}
}
# 获取实例信息
data "alicloud_instances" "dify" {
ids = [alicloud_instance.dify.id]
depends_on = [alicloud_instance.dify]
}