From 8ffe18aaee98068070dccf7659da30c8da330716 Mon Sep 17 00:00:00 2001 From: Shunsuke Hayashi Date: Mon, 26 Jan 2026 13:08:57 +0900 Subject: [PATCH] feat(aws): migrate Discord token to Secrets Manager and fix infrastructure - Add Secrets Manager integration for Discord bot token - Add aws_account_id and discord_token_secret_name variables - Update ECS task definition to use Secrets Manager - Add IAM policy for Secrets Manager access - Fix Dockerfile .buildstamp generation for Linux compatibility - Change VPC CIDR to 100.64.0.0/16 to avoid conflicts - Add deployment documentation and .env.example Co-Authored-By: Claude --- Dockerfile | 4 +- workers/clawdbot-aws/.env.example | 33 +++++ workers/clawdbot-aws/terraform/README.md | 135 ++++++++++++++++++++ workers/clawdbot-aws/terraform/ecs.tf | 2 +- workers/clawdbot-aws/terraform/iam.tf | 17 +++ workers/clawdbot-aws/terraform/secrets.tf | 8 ++ workers/clawdbot-aws/terraform/variables.tf | 15 ++- workers/clawdbot-aws/terraform/vpc.tf | 4 +- 8 files changed, 212 insertions(+), 6 deletions(-) create mode 100644 workers/clawdbot-aws/.env.example create mode 100644 workers/clawdbot-aws/terraform/README.md create mode 100644 workers/clawdbot-aws/terraform/secrets.tf diff --git a/Dockerfile b/Dockerfile index 77d97f52a..fed40b114 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,8 @@ RUN pnpm install --frozen-lockfile COPY . . RUN pnpm build -# Create .buildstamp to prevent runtime rebuild -RUN mkdir -p dist && echo "$(date +%s%N)" > dist/.buildstamp +# Create .buildstamp to prevent runtime rebuild (portable timestamp) +RUN mkdir -p dist && echo "$(date +%s)000000000" > dist/.buildstamp # Force pnpm for UI build (Bun may fail on ARM/Synology architectures) ENV CLAWDBOT_PREFER_PNPM=1 RUN pnpm ui:install diff --git a/workers/clawdbot-aws/.env.example b/workers/clawdbot-aws/.env.example new file mode 100644 index 000000000..1bf4426cb --- /dev/null +++ b/workers/clawdbot-aws/.env.example @@ -0,0 +1,33 @@ +# AWS Terraform Variables for Clawdbot ECS Fargate Deployment +# Copy this file to terraform.tfvars and fill in the values + +# AWS Configuration +aws_region = "ap-northeast-1" +aws_account_id = "123456789012" # Your AWS account ID + +# Environment +environment = "production" +project_name = "clawdbot" + +# ECS Configuration +ecs_task_cpu = 256 # 0.25 vCPU +ecs_task_memory = 2048 # 2 GB +ecs_service_desired_count = 1 + +# Discord Token (DEPRECATED - Use Secrets Manager instead) +# discord_token = "your_bot_token_here" # DO NOT use in production + +# Secrets Manager Secret Name for Discord Bot Token +discord_token_secret_name = "clawdbot/discord-token" +# Create the secret in AWS Secrets Manager before running Terraform: +# aws secretsmanager create-secret \ +# --name clawdbot/discord-token \ +# --secret-string "your_bot_token_here" + +# DynamoDB Tables +sessions_table_name = "clawdbot-sessions" +artifacts_table_name = "clawdbot-artifacts" + +# S3 Bucket +artifacts_bucket_name = "clawdbot-artifacts" +artifacts_bucket_ttl_days = 7 diff --git a/workers/clawdbot-aws/terraform/README.md b/workers/clawdbot-aws/terraform/README.md new file mode 100644 index 000000000..6e7bf1de5 --- /dev/null +++ b/workers/clawdbot-aws/terraform/README.md @@ -0,0 +1,135 @@ +# Clawdbot AWS Deployment + +ECS Fargateを使用したClawdbotのAWSデプロイメント設定 + +## 前提条件 + +- AWS CLI設定済み +- Terraformインストール済み +- Dockerインストール済み + +## セットアップ手順 + +### 1. Discord Bot TokenをSecrets Managerに保存 + +```bash +# Secrets Managerにシークレットを作成 +aws secretsmanager create-secret \ + --name clawdbot/discord-token \ + --description "Discord Bot Token for Clawdbot" \ + --secret-string "your_discord_bot_token_here" + +# シークレットを確認 +aws secretsmanager get-secret-value --secret-id clawdbot/discord-token +``` + +### 2. Terraform変数の設定 + +`.env.example`をコピーして`terraform.tfvars`を作成: + +```bash +cp .env.example terraform.tfvars +``` + +`terraform.tfvars`を編集して以下の値を設定: +- `aws_account_id`: AWSアカウントID +- `discord_token_secret_name`: Secrets Managerのシークレット名(デフォルト: `clawdbot/discord-token`) + +### 3. Terraformの実行 + +```bash +# Terraform初期化 +terraform init + +# 設定確認 +terraform plan + +# デプロイ実行 +terraform apply +``` + +### 4. Dockerイメージのプッシュ + +```bash +# ECRログイン +aws ecr get-login-password --region ap-northeast-1 | \ + docker login --username AWS --password-stdin .dkr.ecr.ap-northeast-1.amazonaws.com + +# イメージビルド +docker build -t clawdbot . + +# タグ付け +docker tag clawdbot:latest .dkr.ecr.ap-northeast-1.amazonaws.com/clawdbot:latest + +# プッシュ +docker push .dkr.ecr.ap-northeast-1.amazonaws.com/clawdbot:latest +``` + +### 5. ECSサービスの更新 + +```bash +# 新しいタスク定義でECSサービスを更新 +aws ecs update-service \ + --cluster clawdbot-cluster \ + --service clawdbot-service \ + --force-new-deployment +``` + +## セキュリティベストプラクティス + +- ✅ Discord Bot TokenはAWS Secrets Managerに保存 +- ✅ IAMロールで最小権限の原則を適用 +- ✅ S3バケットでAES256暗号化を有効化 +- ✅ DynamoDBでPITR(Point-in-Time Recovery)を有効化 +- ✅ VPC内にプライベートサブネットを配置 + +## コスト最適化 + +- ECS Fargate: 256 CPU, 2048 MBメモリ(最小構成) +- CloudWatch Logs: 7日間保持 +- S3ライフサイクル: 7日間で古いアーティファクトを自動削除 + +## 監視とログ + +### CloudWatch Logs + +```bash +# ログストリーム確認 +aws logs tail /ecs/clawdbot --follow +``` + +### ECSタスクの状態確認 + +```bash +# サービス状態 +aws ecs describe-services --cluster clawdbot-cluster --services clawdbot-service + +# タスク一覧 +aws ecs list-tasks --cluster clawdbot-cluster +``` + +## トラブルシューティング + +### コンテナが起動しない場合 + +1. CloudWatch Logsでエラーを確認 +2. タスク定義の環境変数を確認 +3. Secrets Managerからシークレットが取得できているか確認 + +### Discord Botが応答しない場合 + +1. ECSタスクが実行中か確認 +2. セキュリティグループでアウトバウンド通信が許可されているか確認 +3. Discord Bot Tokenが正しいか確認 + +## クリーンアップ + +```bash +terraform destroy +``` + +注意: Secrets Managerのシークレットは手動で削除する必要があります: + +```bash +aws secretsmanager delete-secret --secret-id clawdbot/discord-token +``` diff --git a/workers/clawdbot-aws/terraform/ecs.tf b/workers/clawdbot-aws/terraform/ecs.tf index f1b42d326..dc241eab3 100644 --- a/workers/clawdbot-aws/terraform/ecs.tf +++ b/workers/clawdbot-aws/terraform/ecs.tf @@ -81,7 +81,7 @@ resource "aws_ecs_task_definition" "clawdbot" { }, { name = "DISCORD_BOT_TOKEN" - value = var.discord_token + value = data.aws_secretsmanager_secret_version.discord_token.secret_string }, { name = "CLAWDBOT_FORCE_BUILD" diff --git a/workers/clawdbot-aws/terraform/iam.tf b/workers/clawdbot-aws/terraform/iam.tf index 1ecf6cd1d..8447bf78d 100644 --- a/workers/clawdbot-aws/terraform/iam.tf +++ b/workers/clawdbot-aws/terraform/iam.tf @@ -81,3 +81,20 @@ resource "aws_iam_role_policy" "ecs_task_s3" { ] }) } + +# Task Role Policy: Secrets Manager access for Discord token +resource "aws_iam_role_policy" "ecs_task_secrets" { + name = "${var.project_name}-secrets-access" + role = aws_iam_role.ecs_task_role.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = ["secretsmanager:GetSecretValue"] + Resource = "arn:aws:secretsmanager:${var.aws_region}:${var.aws_account_id}:secret:${var.discord_token_secret_name}-??????*" + } + ] + }) +} diff --git a/workers/clawdbot-aws/terraform/secrets.tf b/workers/clawdbot-aws/terraform/secrets.tf new file mode 100644 index 000000000..4630a275b --- /dev/null +++ b/workers/clawdbot-aws/terraform/secrets.tf @@ -0,0 +1,8 @@ +/** + * AWS Secrets Manager Data Sources + */ + +# Discord Bot Token from Secrets Manager +data "aws_secretsmanager_secret_version" "discord_token" { + secret_id = var.discord_token_secret_name +} diff --git a/workers/clawdbot-aws/terraform/variables.tf b/workers/clawdbot-aws/terraform/variables.tf index 38075ca03..b11a16edc 100644 --- a/workers/clawdbot-aws/terraform/variables.tf +++ b/workers/clawdbot-aws/terraform/variables.tf @@ -4,6 +4,11 @@ variable "aws_region" { default = "ap-northeast-1" } +variable "aws_account_id" { + description = "AWS account ID (for Secrets Manager ARN)" + type = string +} + variable "environment" { description = "Environment name (e.g., production, staging)" type = string @@ -59,8 +64,16 @@ variable "ecs_service_desired_count" { default = 1 } +variable "discord_token_secret_name" { + description = "AWS Secrets Manager secret name for Discord bot token" + type = string + default = "clawdbot/discord-token" +} + +# DEPRECATED: Use discord_token_secret_name with AWS Secrets Manager instead variable "discord_token" { - description = "Discord bot token (DISCORD_BOT_TOKEN) - sensitive, do not commit to version control" + description = "DEPRECATED: Discord bot token (use Secrets Manager instead)" type = string sensitive = true + default = null } diff --git a/workers/clawdbot-aws/terraform/vpc.tf b/workers/clawdbot-aws/terraform/vpc.tf index 6a6f0b462..79b0b92d0 100644 --- a/workers/clawdbot-aws/terraform/vpc.tf +++ b/workers/clawdbot-aws/terraform/vpc.tf @@ -3,9 +3,9 @@ * Discord bot requires outbound internet access for WebSocket connections */ -# VPC +# VPC (using 100.64.0.0/16 to avoid conflicts with default 10.0.0.0/8) resource "aws_vpc" "clawdbot" { - cidr_block = "10.0.0.0/16" + cidr_block = "100.64.0.0/16" enable_dns_hostnames = true enable_dns_support = true