支持
快速入门

使用 Terraform 和 CI 以代码方式管理重定向

直接回答

RedirHub 在 Terraform Registry 上提供官方 Terraform provider:redirhub/redirhub。每个链接都是一个 redirhub_link 资源:域名重定向、网站迁移映射、品牌短链接和二维码。域名使用 redirhub_domain,并包含所需的 DNS 记录。你可以在拉取请求中将更改作为计划进行审查,并使用 API token 从 CI 中应用它们。它适用于所有包含 API 的套餐:Core、Pro 和 Enterprise。

1. 设置 provider#

按照 创建和管理 API token 中的说明创建一个 token。该 token 属于一个工作区,而 Terraform 管理该工作区。请通过 REDIRHUB_API_TOKEN 环境变量传入,而不要写在文件中。

hclterraform {
  required_providers {
    redirhub = {
      source  = "redirhub/redirhub"
      version = "~> 0.1"
    }
  }
}

# 从 REDIRHUB_API_TOKEN 读取 token。
provider "redirhub" {}
bashexport REDIRHUB_API_TOKEN="your-token"
terraform init

2. 添加重定向、短链接和二维码#

handler 说明链接类型:redirect、migration、short-url 或 qr。重定向和迁移映射使用 url,即它们响应的来源。短链接和二维码使用 host,也就是你的短链接域名,以及可选的别名。其他属性与 API 中的字段相同:destinations、type、forward_path、forward_query、status、tags 和 utm。

hcl# 将整个域名重定向到新站点,包括路径和查询参数。
resource "redirhub_link" "old_domain" {
  handler       = "redirect"
  url           = "old-site.com"
  destinations  = ["https://new-site.com"]
  type          = "301"
  forward_path  = true
  forward_query = true
}

# 网站迁移:每个旧页面对应一条映射,存放在配置旁边的 CSV 中。
resource "redirhub_link" "migration" {
  for_each = { for row in csvdecode(file("${path.module}/redirects.csv")) : row.from => row }

  handler      = "migration"
  url          = each.value.from
  destinations = [each.value.to]
  type         = "301"
}

# 品牌短链接和动态二维码。
resource "redirhub_link" "spring" {
  handler      = "short-url"
  host         = "go.example.com"
  alias        = "spring"
  destinations = ["https://example.com/campaigns/spring"]
  utm          = { source = "newsletter", campaign = "spring" }
}

resource "redirhub_link" "menu" {
  handler      = "qr"
  host         = "go.example.com"
  alias        = "menu"
  destinations = ["https://example.com/menu"]
  qr           = { theme = "dark", logo = true }
}

运行 terraform plan 查看将发生的更改,再运行 terraform apply 进行更改。Terraform 会在发送任何内容之前检查每个链接的字段,因此缺少 url 的重定向或缺少 host 的二维码会在计划阶段失败。如果某个套餐不包含 tags 或多个 destinations 等限制项,计划也会返回与控制台中相同的消息。

3. 连接域名及其 DNS 在同一次 apply 中完成#

redirhub_domain 会连接一个域名,并在 dns_records 中返回它需要的 DNS 记录。将这些记录交给你的 DNS 提供商的 Terraform 资源。redirhub_domain_verification 随后会等待直到记录生效,因此使用该域名的链接只会在它响应后才发布。默认等待 10 分钟;如果你的 DNS 较慢,可以增加超时时间。

hclresource "redirhub_domain" "go" {
  host        = "go.example.com"
  short_links = true
}

# 这里以 Cloudflare 为例;任何带有 Terraform record 资源的 DNS 提供商都同样适用。
resource "cloudflare_dns_record" "redirhub" {
  for_each = { for r in redirhub_domain.go.dns_records : "${r.type}-${r.name}" => r }

  zone_id = var.cloudflare_zone_id
  name    = each.value.name
  type    = each.value.type
  content = each.value.value
  ttl     = 300
}

resource "redirhub_domain_verification" "go" {
  host       = redirhub_domain.go.host
  depends_on = [cloudflare_dns_record.redirhub]
}

resource "redirhub_link" "launch" {
  handler      = "short-url"
  host         = redirhub_domain_verification.go.host
  alias        = "launch"
  destinations = ["https://example.com/launch"]
}

4. 将现有链接纳入 Terraform 管理#

你在仪表板中创建的链接会继续正常工作。要用 Terraform 管理某个链接,请按其 id 导入,例如 link_7bXmR4,也就是仪表板和 API 中显示的 id。按其主机名导入域名。redirhub_links 数据源会以与 API 相同的筛选条件列出 id,例如 handler、host 和 tags。

hcldata "redirhub_links" "old_site" {
  handler = "redirect,migration"
  host    = "old-site.com"
}

output "old_site_ids" {
  value = { for l in data.redirhub_links.old_site.links : l.url => l.id }
}

# Terraform 1.5 及更高版本:先在计划中导入,然后照常管理。
import {
  to = redirhub_link.old_domain
  id = "link_7bXmR4"
}

之后如果有人在仪表板中做出更改,会在下一次 plan 中体现出来,而 terraform apply 会将其改回你文件中定义的内容。若从文件中移除某个链接,它会在下一次 apply 时被删除。

5. 在拉取请求中进行计划,在合并时应用#

将配置保存在仓库中的一个文件夹里,并把 Terraform state 存在远程后端,例如 S3 或 HCP Terraform。把 token 作为 CI 密钥保存。这个 GitHub Actions 工作流会在每个拉取请求时发布 plan,并在拉取请求合并时执行 apply。GitLab CI pipeline 见 提供商的示例。

yaml# .github/workflows/redirects.yml
name: Redirects
on:
  pull_request:
    paths: ['redirects/**']
  push:
    branches: [main]
    paths: ['redirects/**']
permissions:
  contents: read
  pull-requests: write
concurrency: redirects
jobs:
  terraform:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash
        working-directory: redirects
    env:
      REDIRHUB_API_TOKEN: ${{ secrets.REDIRHUB_API_TOKEN }}
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_wrapper: false
      - run: terraform init -input=false
      - run: terraform plan -input=false -no-color -out=tfplan | tee plan.txt
      - if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const plan = require('fs').readFileSync('redirects/plan.txt', 'utf8');
            await github.rest.issues.createComment({ ...context.repo, issue_number: context.issue.number, body: '```\n' + plan.slice(-60000) + '\n```' });
      - if: github.event_name == 'push'
        run: terraform apply -input=false tfplan

再次运行也安全#

CI 作业会超时并重试。提供程序创建的每个链接都带有一个 Idempotency-Key,因此当响应在返回途中丢失时,重试会拿到 RedirHub 已经创建好的链接,而不是第二个副本。速率限制和临时服务器错误会自动重试。你自己的脚本也可以这样做:在 POST 的 Idempotency-Key 标头中发送任意唯一值,同一个键在 24 小时内会返回第一次响应,并标记为 Idempotent-Replayed: true。

bashcurl -X POST "https://api.redirhub.com/v1/links" \
  -H "Authorization: Bearer $REDIRHUB_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"handler": "redirect", "url": "old-site.com", "destination": "https://new-site.com"}'

每个属性都列在 Terraform Registry 上的提供程序文档 中。若要在不使用 Terraform 的情况下编写一次性任务,请参见 使用 API 批量创建、更新和删除重定向。

常见问题

是的。官方 provider 是 Terraform Registry 上的 redirhub/redirhub。它可管理重定向、网站迁移映射、品牌短链接、二维码和域名。

所有包含 API 的套餐:Core、Pro 和 Enterprise。标签或多个目标等套餐限制与控制面板中的规则一致。

可以。可按各自的 id 导入每个链接,或按 hostname 导入每个域名。redirhub_links 数据源会列出某个域名下或带有某个标签的链接 id。

不会重复创建任何内容。如果文件没有变化,第二次 apply 不会改变任何东西;而重试的创建会携带相同的 Idempotency-Key,因此 RedirHub 会返回它已经创建好的链接。

OpenTofu 可以使用 source = "registry.terraform.io/redirhub/redirhub" 这个 provider。对于 Pulumi 和其他工具,请使用 API:它是在 HTTPS 上通过 Bearer token 传输的纯 JSON。

相关帮助

查看全部文章