> ## Documentation Index
> Fetch the complete documentation index at: https://help.teable.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 在 AWS 上部署

> 分步指引：在 AWS 上使用 ECS、RDS PostgreSQL、ElastiCache 与 S3 部署 Teable

<Callout type="info">
  **推荐场景**：50+ 用户的生产环境
</Callout>

## 架构概览

```mermaid theme={null}
graph TB
    ECS["AWS ECS<br/>(Fargate 或 EC2)<br/>Teable 应用: 4+ 副本<br/>Sandbox: 2+ 副本 (可选)"]
    
    RDS["Amazon RDS<br/>Aurora PostgreSQL"]
    ElastiCache["Amazon ElastiCache<br/>(Valkey/Redis)<br/>队列 & 缓存"]
    S3["Amazon S3<br/>Public + Private 双桶"]
    
    ECS --> RDS
    ECS --> ElastiCache
    ECS --> S3
    
    style ECS fill:#ff9900,stroke:#cc7a00,color:#fff
    style RDS fill:#527fff,stroke:#3d5fd9,color:#fff
    style ElastiCache fill:#c925d1,stroke:#a01ba8,color:#fff
    style S3 fill:#569a31,stroke:#3f7224,color:#fff
```

## 前置要求

* 已安装并配置 AWS CLI
* AWS 账号具备 ECS、RDS、ElastiCache、S3、IAM 权限
* Docker 镜像仓库访问权（或 ECR）

***

## 步骤 1：创建 AWS 资源

### 1.1 创建 RDS PostgreSQL

```bash theme={null}
aws rds create-db-instance \
  --db-instance-identifier teable-db \
  --db-instance-class db.t3.medium \
  --engine postgres \
  --engine-version 16 \
  --master-username teableadmin \
  --master-user-password '<你的强密码>' \
  --allocated-storage 100 \
  --vpc-security-group-ids sg-xxxxxx \
  --db-subnet-group-name your-subnet-group \
  --publicly-accessible false
```

<Note>
  等待实例状态变为 `available`。获取 endpoint：

  ```bash theme={null}
  aws rds describe-db-instances \
    --db-instance-identifier teable-db \
    --query 'DBInstances[0].Endpoint.Address' --output text
  ```
</Note>

### 1.2 创建 ElastiCache Redis（用于队列）

```bash theme={null}
aws elasticache create-cache-cluster \
  --cache-cluster-id teable-cache \
  --engine redis \
  --cache-node-type cache.t3.small \
  --num-cache-nodes 1 \
  --engine-version 7.0 \
  --security-group-ids sg-xxxxxx \
  --cache-subnet-group-name your-subnet-group
```

<Note>
  获取 endpoint：

  ```bash theme={null}
  aws elasticache describe-cache-clusters \
    --cache-cluster-id teable-cache \
    --show-cache-node-info \
    --query 'CacheClusters[0].CacheNodes[0].Endpoint.Address' --output text
  ```
</Note>

### 1.3 创建 S3 bucket（public + private）

```bash theme={null}
# 创建 public bucket
aws s3api create-bucket \
  --bucket teable-public-<你的唯一后缀> \
  --region us-west-2 \
  --create-bucket-configuration LocationConstraint=us-west-2

# 创建 private bucket
aws s3api create-bucket \
  --bucket teable-private-<你的唯一后缀> \
  --region us-west-2 \
  --create-bucket-configuration LocationConstraint=us-west-2
```

**必做：配置 public bucket**

1. **Public read 策略**：

```bash theme={null}
cat > public-bucket-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::teable-public-<你的唯一后缀>/*"
    }
  ]
}
EOF

aws s3api put-bucket-policy \
  --bucket teable-public-<你的唯一后缀> \
  --policy file://public-bucket-policy.json
```

2. **关闭 public bucket 的"阻止公共访问"**：

```bash theme={null}
aws s3api put-public-access-block \
  --bucket teable-public-<你的唯一后缀> \
  --public-access-block-configuration \
    BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false
```

3. **CORS 配置**（允许任意跨域）：

```bash theme={null}
cat > cors.json <<EOF
{
  "CORSRules": [
    {
      "AllowedHeaders": ["*"],
      "AllowedMethods": ["GET", "HEAD", "PUT"],
      "AllowedOrigins": ["*"],
      "ExposeHeaders": ["ETag"],
      "MaxAgeSeconds": 3000
    }
  ]
}
EOF

aws s3api put-bucket-cors \
  --bucket teable-public-<你的唯一后缀> \
  --cors-configuration file://cors.json
```

<Callout type="warning">
  **安全提醒**：public bucket 必须允许公开读。请确保符合你们公司的安全规范。private bucket 保持私有即可。
</Callout>

### 1.4 创建 IAM 用户/角色用于 S3 访问

```bash theme={null}
# 创建 IAM 用户
aws iam create-user --user-name teable-s3-user

# 附加 S3 完全访问策略（或创建自定义策略）
aws iam attach-user-policy \
  --user-name teable-s3-user \
  --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

# 创建访问密钥
aws iam create-access-key --user-name teable-s3-user
```

<Note>
  保存输出中的 `AccessKeyId` 和 `SecretAccessKey`。
</Note>

***

## 步骤 2：准备环境变量

创建 `.env` 文件（或 ECS 任务定义的环境变量）：

```bash theme={null}
# Core
PUBLIC_ORIGIN=https://teable.yourcompany.com
SECRET_KEY=<生成32位随机字符串>

# Database
PRISMA_DATABASE_URL=postgresql://teableadmin:<password>@<rds-endpoint>:5432/teable

# Redis（队列依赖）
BACKEND_CACHE_PROVIDER=redis
BACKEND_CACHE_REDIS_URI=redis://<elasticache-endpoint>:6379/0

# 性能缓存（可选；可指向同一个 Redis 或单独集群）
BACKEND_PERFORMANCE_CACHE=redis://<elasticache-endpoint>:6379/0

# Storage（S3 双桶）
BACKEND_STORAGE_PROVIDER=s3
BACKEND_STORAGE_S3_REGION=us-west-2
BACKEND_STORAGE_S3_ENDPOINT=https://s3.us-west-2.amazonaws.com
BACKEND_STORAGE_S3_ACCESS_KEY=<步骤1.4的access-key>
BACKEND_STORAGE_S3_SECRET_KEY=<步骤1.4的secret-key>
BACKEND_STORAGE_PUBLIC_BUCKET=teable-public-<你的唯一后缀>
BACKEND_STORAGE_PRIVATE_BUCKET=teable-private-<你的唯一后缀>
STORAGE_PREFIX=https://teable-public-<你的唯一后缀>.s3.us-west-2.amazonaws.com

# 可选：Sandbox 服务（如果单独部署）
# SANDBOX_URL=http://teable-sandbox:7070
```

<Tip>
  生成强 `SECRET_KEY`：

  ```bash theme={null}
  openssl rand -base64 32
  ```
</Tip>

***

## 步骤 3：部署到 ECS

### 方案 A：使用 ECS Fargate（推荐，简单）

1. **创建 ECS 集群**：

```bash theme={null}
aws ecs create-cluster --cluster-name teable-cluster
```

2. **创建任务定义** (`teable-task.json`)：

```json theme={null}
{
  "family": "teable",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "2048",
  "memory": "4096",
  "containerDefinitions": [
    {
      "name": "teable",
      "image": "ghcr.io/teableio/teable:latest",
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {"name": "PUBLIC_ORIGIN", "value": "https://teable.yourcompany.com"},
        {"name": "SECRET_KEY", "value": "***REDACTED***"},
        {"name": "PRISMA_DATABASE_URL", "value": "postgresql://..."},
        {"name": "BACKEND_CACHE_PROVIDER", "value": "redis"},
        {"name": "BACKEND_CACHE_REDIS_URI", "value": "redis://..."},
        {"name": "BACKEND_STORAGE_PROVIDER", "value": "s3"},
        {"name": "BACKEND_STORAGE_S3_REGION", "value": "us-west-2"},
        {"name": "BACKEND_STORAGE_S3_ENDPOINT", "value": "https://s3.us-west-2.amazonaws.com"},
        {"name": "BACKEND_STORAGE_S3_ACCESS_KEY", "value": "***"},
        {"name": "BACKEND_STORAGE_S3_SECRET_KEY", "value": "***"},
        {"name": "BACKEND_STORAGE_PUBLIC_BUCKET", "value": "teable-public-xxx"},
        {"name": "BACKEND_STORAGE_PRIVATE_BUCKET", "value": "teable-private-xxx"},
        {"name": "STORAGE_PREFIX", "value": "https://teable-public-xxx.s3.us-west-2.amazonaws.com"}
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/teable",
          "awslogs-region": "us-west-2",
          "awslogs-stream-prefix": "teable"
        }
      }
    }
  ]
}
```

3. **注册任务定义**：

```bash theme={null}
aws ecs register-task-definition --cli-input-json file://teable-task.json
```

4. **创建 ECS 服务**：

```bash theme={null}
aws ecs create-service \
  --cluster teable-cluster \
  --service-name teable-service \
  --task-definition teable \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-xxx,subnet-yyy],securityGroups=[sg-xxx],assignPublicIp=ENABLED}" \
  --load-balancers "targetGroupArn=arn:aws:elasticloadbalancing:...,containerName=teable,containerPort=3000"
```

<Note>
  你需要单独创建 Application Load Balancer (ALB) 和目标组，然后在 `--load-balancers` 中引用。
</Note>

***

## 步骤 4：验证部署

1. **检查 ECS 服务状态**：

```bash theme={null}
aws ecs describe-services \
  --cluster teable-cluster \
  --services teable-service
```

2. **查看日志**：

```bash theme={null}
aws logs tail /ecs/teable --follow
```

3. **访问健康检查**：

```bash theme={null}
curl https://teable.yourcompany.com/health
```

预期返回：

```json theme={null}
{"status":"ok"}
```

4. **浏览器访问 Teable**：`https://teable.yourcompany.com`

***

## 故障排查

### 数据库连接错误

* 验证 RDS 安全组允许来自 ECS 任务的流量
* 检查 `PRISMA_DATABASE_URL` 格式：`postgresql://user:pass@endpoint:5432/dbname`

### Redis 连接错误

* 验证 ElastiCache 安全组允许来自 ECS 的流量
* 使用 **主节点 endpoint**（不是只读副本）

### S3 访问错误

* 验证 IAM 用户具有 `s3:GetObject`、`s3:PutObject`、`s3:DeleteObject` 权限
* 检查 bucket 名称在 `BACKEND_STORAGE_PUBLIC_BUCKET` / `BACKEND_STORAGE_PRIVATE_BUCKET` 中完全匹配
* 确保 public bucket 已配置 public read 策略与 CORS

### 容器启动失败

* 检查 CloudWatch Logs：`/ecs/teable`
* 验证所有必需环境变量已设置
* 确保 `SECRET_KEY` 已设置（不为空）

***

## 生产环境最佳实践

<Tip>
  详细的生产环境建议（包括配置、高可用、扩展策略）请参考 [私有化部署概览](/zh/deploy/production-overview)。
</Tip>

**AWS 特定建议**：

* 使用 AWS Secrets Manager 存储敏感值
* 启用 RDS 静态加密
* 使用 VPC endpoint 访问 S3/ECR 避免公网流量
* 启用 CloudWatch Container Insights for ECS

***

## 相关文档

* [私有化部署概览](/zh/deploy/production-overview) — 架构、配置与扩展
* [环境变量参考](/zh/deploy/env)
* [对象存储（S3-compatible）](/zh/deploy/storage)
