在腾讯云 COS 上部署静态网站服务
介绍如何利用腾讯云 COS 来部署静态网站,比如:博客,Next.js 前端资源部署等。 分为如下几个步骤:
这些步骤可以通过登录腾讯云控制台手动操作,但步骤繁琐。通过 IaC (Infrastructure as Code) 的方式部署更高效,不易出错。这里使用流行的 IaC 工具 Terraform 来部署。
首先了解如何安装和使用 Terraform。
设置 Terraform 基本信息
需要先在腾讯云控制台创建一个子账号供 Terraform 使用:
- 禁用密码登录。
- 仅供 API 调用使用。
复制密钥 secret 并填写到下面的 terraform.tfvars
文件中,
# terraform.tfvars
secret_id = "your_secret_id"
secret_key = "your_secret_key"
availability_region = "ap-singapore"
availability_zone = "ap-singapore-4"
$ echo 'terraform.tfvars' >> .gitignore # 在版本库中忽略该文件
在 variables.tf
文件中填写相关的变量,比如域名,CDN 配置。
# variables.tf
variable "secret_id" {
type = string
description = "Secret ID"
# sensitive = true
}
variable "secret_key" {
type = string
description = "Secret Key"
sensitive = true
}
variable "availability_region" {
type = string
description = "Region"
default = "ap-singapore"
}
variable "availability_zone" {
type = string
description = "Zone"
default = "ap-singapore-4"
}
variable "uin" {
type = string
default = "100000xxxxxx"
}
variable "sub_domain" {
type = string
default = "assets"
}
variable "domain" {
type = string
default = "redridgemountains.com"
}
variable "cdn_area" {
type = string
default = "overseas" # mainland, overseas
}
# provider.tf
terraform {
required_providers {
tencentcloud = {
source = "tencentcloudstack/tencentcloud"
# version = "1.81.82"
}
}
}
provider "tencentcloud" {
secret_id = var.secret_id
secret_key = var.secret_key
region = var.availability_region
}
# output.tf
output "bucket_endpoint" {
value = tencentcloud_cos_bucket.example.website.0.endpoint
}
创建 COS 存储桶
- 存储桶私有读写。
- 公开访问只能通过 CDN。
# infra_cos.tf
data "tencentcloud_user_info" "example" {}
locals {
# uin = data.tencentcloud_user_info.example.uin
uin = var.uin
app_id = data.tencentcloud_user_info.example.app_id
bucket_name = "${replace(var.sub_domain, ".", "-")}-${replace(var.domain, ".", "-")}-${local.app_id}"
}
# Bucket for static website
resource "tencentcloud_cos_bucket" "example" {
# Bucket format should be [custom name]-[appid].
bucket = local.bucket_name
acl = "private"
website {
index_document = "index.html"
error_document = "404.html"
}
# cors_rules {
# allowed_origins = ["http://*.redridgemountains.com"]
# allowed_methods = ["PUT", "POST"]
# allowed_headers = ["*"]
# max_age_seconds = 300
# expose_headers = ["Etag"]
# }
}
resource "tencentcloud_cos_bucket_policy" "example" {
depends_on = [ tencentcloud_cos_bucket.example ]
bucket = local.bucket_name
policy = <<EOF
{
"version": "2.0",
"Statement": [
{
"Principal": {
"qcs": [
"qcs::cam::uin/${local.uin}:service/cdn"
]
},
"Action": [
"name/cos:GetObject",
"name/cos:HeadObject",
"name/cos:OptionsObject"
],
"Effect": "Allow",
"Resource": [
"qcs::cos:${var.availability_region}:uid/${local.app_id}:${local.bucket_name}/*"
]
}
]
}
EOF
}
resource "tencentcloud_cos_bucket_object" "example" {
bucket = local.bucket_name
key = "404.html"
source = "404.html"
}
创建 404.html 文件,提供更友好的 404 页面:
$ echo '<html><head><title>404</title></head><body>Page not found.</body></html>' > 404.html
配置存储桶为静态网站
# infra_cdn.tf
locals {
cdn_domain = "${var.sub_domain}.${var.domain}"
}
resource "tencentcloud_cdn_domain" "example" {
domain = local.cdn_domain
service_type = "web"
area = var.cdn_area
cache_key {
full_url_cache = "off"
}
origin {
origin_type = "cos"
origin_list = [tencentcloud_cos_bucket.example.website.0.endpoint]
server_name = tencentcloud_cos_bucket.example.website.0.endpoint
origin_pull_protocol = "follow" # http, https and follow
cos_private_access = "on"
}
https_config {
https_switch = "off"
http2_switch = "off"
ocsp_stapling_switch = "off"
spdy_switch = "off"
verify_client = "off"
}
}
关联 CDN 并配置域名访问存储桶
# infra_dns_record.tf
# Create a dns record
resource "tencentcloud_dnspod_record" "example" {
depends_on = [ tencentcloud_cdn_domain.example ]
domain = var.domain
sub_domain = var.sub_domain
record_type = "CNAME"
record_line = "默认"
value = tencentcloud_cdn_domain.example.cname
# depends_on = [tencentcloud_cos_bucket.example]
}
# # Filter dns records
# data "tencentcloud_dnspod_records" "example" {
# domain = "example.com"
# subdomain = "www"
# depends_on = [tencentcloud_dnspod_record.example]
# }
# output "dns_record" {
# value = data.tencentcloud_dnspod_records.example.result
# }
运行 Terraform
$ terraform init
$ terraform plan
$ terraform apply --auto-approve
# $ terraform destroy --auto-approve
注意:每次创建新的存储桶时,要复制此目录,并删除 .tfstate 文件。不然就是在之前的桶上修改,而不是创建新的。