はじめに
FramePack は lllyasviel 氏が開発した動画生成モデルで、1枚の画像からプロンプトに沿った短い動画を生成できます。GPU が必要なため、手元に GPU マシンがない場合は EC2 の GPU インスタンスを使うのが手軽です。
この記事では Terraform を使って EC2 環境を一発構築し、SSH トンネル経由で Gradio UI にアクセスするまでの手順をまとめます。インフラのコード化により、使い終わったら terraform destroy で即削除できるのがメリットです。
構成
| 項目 | 値 |
|---|---|
| インスタンスタイプ | g6.2xlarge(NVIDIA L4 GPU) |
| AMI | Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.10 (Ubuntu 24.04) |
| リージョン | ap-northeast-1 |
| ストレージ | gp3 150GB(暗号化) |
| FramePack | lllyasviel/FramePack + kustomzone/FramePack-eichi |
| PyTorch | 2.6.0 + CUDA 12.6 |
| 起動方法 | systemd サービス(ポート 7860、localhost のみ) |
セキュリティグループは SSH(22番)を自分のIPからのみ許可し、Gradio は 127.0.0.1:7860 にバインドして外部公開しない設計にしています。
前提条件
- Terraform >= 1.5.0
- AWS CLI が設定済み(
aws configure済み) - EC2 キーペアが作成済み
- g6.2xlarge が利用可能な AZ を確認済み(東京リージョンは
ap-northeast-1aで利用可)
g6 系インスタンスはサービスクォータのデフォルト上限に引っかかる場合があります。初回利用時は Running On-Demand G and VT instances のクォータを引き上げておいてください(vcpu換算で8必要)。
ファイル構成
framepack/
├── main.tf
├── variables.tf
├── terraform.tfvars # 実際の値(git 管理しない)
├── terraform.tfvars.example # サンプル
└── userdata.sh.tftpl # EC2 起動時の自動セットアップスクリプト
Terraform コード
variables.tf
variable "aws_region" {
type = string
default = "ap-northeast-1"
}
variable "key_name" {
type = string
description = "EC2 key pair name"
}
variable "my_ip_cidr" {
type = string
description = "Your IP address in CIDR notation (e.g., 123.456.789.0/32)"
}
variable "eichi_github_username" {
type = string
default = "x-access-token"
}
variable "eichi_github_token" {
type = string
default = ""
sensitive = true
}
main.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.aws_region
}
locals {
instance_type = "g6.2xlarge"
vpc_cidr = "10.0.0.0/16"
az = "${var.aws_region}a"
}
# g6.2xlarge が指定 AZ で利用可能かチェック
data "aws_ec2_instance_type_offerings" "g6" {
filter {
name = "instance-type"
values = [local.instance_type]
}
location_type = "availability-zone"
}
# VPC
resource "aws_vpc" "framepack" {
cidr_block = local.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = { Name = "framepack-vpc" }
}
resource "aws_internet_gateway" "framepack" {
vpc_id = aws_vpc.framepack.id
tags = { Name = "framepack-igw" }
}
resource "aws_route_table" "public" {
vpc_id = aws_vpc.framepack.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.framepack.id
}
tags = { Name = "framepack-public-rt" }
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.framepack.id
cidr_block = "10.0.1.0/24"
availability_zone = local.az
map_public_ip_on_launch = true
tags = { Name = "framepack-public-subnet" }
}
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
# AMI(最新の Deep Learning AMI を自動取得)
data "aws_ami" "dlami" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.10 (Ubuntu 24.04) *"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "state"
values = ["available"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# セキュリティグループ(SSH のみ)
resource "aws_security_group" "framepack" {
name = "framepack-sg"
description = "FramePack SSH access"
vpc_id = aws_vpc.framepack.id
ingress {
description = "SSH from my IP"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [var.my_ip_cidr]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = { Name = "framepack-sg" }
}
# EC2 インスタンス
resource "aws_instance" "framepack" {
ami = data.aws_ami.dlami.id
instance_type = local.instance_type
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.framepack.id]
associate_public_ip_address = true
key_name = var.key_name
user_data = templatefile("${path.module}/userdata.sh.tftpl", {
eichi_github_username = var.eichi_github_username
eichi_github_token = var.eichi_github_token
})
root_block_device {
volume_type = "gp3"
volume_size = 150
encrypted = true
}
tags = { Name = "framepack" }
lifecycle {
precondition {
condition = contains(data.aws_ec2_instance_type_offerings.g6.locations, local.az)
error_message = "指定した AZ ${local.az} では g6.2xlarge が利用できません。"
}
}
}
output "public_ip" { value = aws_instance.framepack.public_ip }
output "public_dns" { value = aws_instance.framepack.public_dns }
output "ami_id" { value = data.aws_ami.dlami.id }
AMI は data "aws_ami" で毎回最新を自動取得します。また lifecycle.precondition で g6.2xlarge が対象 AZ で利用可能かを terraform apply 前に確認しています。
userdata.sh.tftpl
EC2 起動直後に自動実行されるセットアップスクリプトです。
#!/bin/bash
set -euxo pipefail
exec > /var/log/framepack-eichi-userdata.log 2>&1
export DEBIAN_FRONTEND=noninteractive
APP_DIR=/home/ubuntu/FramePack
VENV_DIR=/home/ubuntu/FramePack/.venv
EICHI_SRC_DIR=/home/ubuntu/FramePack-eichi-src
EICHI_TOKEN='${eichi_github_token}'
EICHI_GITHUB_USERNAME='${eichi_github_username}'
apt-get update
apt-get install -y git python3.11 python3.11-venv ffmpeg rsync
# FramePack 本体をクローン
if [ ! -d "$APP_DIR/.git" ]; then
runuser -u ubuntu -- git clone https://github.com/lllyasviel/FramePack.git "$APP_DIR"
fi
# FramePack-eichi をクローン(GitHub Token があれば private repo にも対応)
if [ ! -d "$EICHI_SRC_DIR/.git" ]; then
if [ -n "$EICHI_TOKEN" ]; then
runuser -u ubuntu -- git clone \
"https://${EICHI_GITHUB_USERNAME}:${EICHI_TOKEN}@github.com/kustomzone/FramePack-eichi.git" \
"$EICHI_SRC_DIR"
else
runuser -u ubuntu -- git clone \
"https://github.com/kustomzone/FramePack-eichi.git" \
"$EICHI_SRC_DIR"
fi
fi
# eichi の webui と起動スクリプトを FramePack に上書き
if [ -d "$EICHI_SRC_DIR/webui" ]; then
runuser -u ubuntu -- rsync -a "$EICHI_SRC_DIR/webui/" "$APP_DIR/"
fi
for f in endframe_ichi.py endframe_ichi_f1.py oneframe_ichi.py; do
if [ -f "$EICHI_SRC_DIR/$f" ]; then
runuser -u ubuntu -- cp "$EICHI_SRC_DIR/$f" "$APP_DIR/$f"
fi
done
# Python 仮想環境を作成し、PyTorch (CUDA 12.6) をインストール
runuser -u ubuntu -- python3.11 -m venv "$VENV_DIR"
runuser -u ubuntu -- "$VENV_DIR/bin/pip" install --upgrade pip
runuser -u ubuntu -- "$VENV_DIR/bin/pip" uninstall -y torch torchvision torchaudio || true
runuser -u ubuntu -- "$VENV_DIR/bin/pip" install \
torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 \
--index-url https://download.pytorch.org/whl/cu126
runuser -u ubuntu -- "$VENV_DIR/bin/pip" install -r "$APP_DIR/requirements.txt"
# Hugging Face キャッシュ用ディレクトリ
mkdir -p /home/ubuntu/hf_cache
chown -R ubuntu:ubuntu /home/ubuntu/hf_cache
# systemd サービスとして登録
cat > /etc/systemd/system/framepack-eichi.service << 'EOF'
[Unit]
Description=FramePack-eichi Gradio
After=network-online.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/FramePack
Environment=PYTHONUNBUFFERED=1
Environment=HF_HOME=/home/ubuntu/hf_cache
ExecStart=/home/ubuntu/FramePack/.venv/bin/python \
/home/ubuntu/FramePack/endframe_ichi.py \
--server 127.0.0.1 --port 7860
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable framepack-eichi.service
systemctl restart framepack-eichi.service
ポイントは以下の通りです。
-
runuser -u ubuntu --で各コマンドを ubuntu ユーザーとして実行し、ファイルの所有者が root にならないようにしています - PyTorch は DLAMI にプリインストールされているものとバージョンが合わない可能性があるため、一度 uninstall してから cu126 対応版を明示的に入れ直しています
- Gradio は
--server 127.0.0.1でローカルホストのみにバインドし、外部から直接アクセスできない構成にしています
terraform.tfvars
key_name = "your-key-pair-name"
my_ip_cidr = "x.x.x.x/32" # curl ifconfig.me で確認
# FramePack-eichi を private fork から使う場合のみ設定
# eichi_github_username = "x-access-token"
# eichi_github_token = "ghp_xxxxxxxxxxxxxxxxxxxx"
my_ip_cidr は curl ifconfig.me で取得した自分のグローバル IP を /32 で指定してください。
デプロイ手順
cd framepack/
terraform init
terraform plan
terraform apply
apply が完了すると以下のような出力が得られます。
Outputs:
ami_id = "ami-xxxxxxxxxxxxxxxxx"
public_dns = "ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com"
public_ip = "xx.xx.xx.xx"
初回起動時は userdata スクリプトが裏で動いています。完了まで 10〜15分程度かかります。進捗は SSH してログで確認できます。
ssh -i your-key.pem ubuntu@$(terraform output -raw public_ip)
tail -f /var/log/framepack-eichi-userdata.log
systemctl status framepack-eichi.service が active (running) になっていれば準備完了です。
SSH トンネルで接続する
Gradio は localhost にしかバインドしていないため、SSH トンネルでポートフォワードします。
# ローカルの 7860 を EC2 の 127.0.0.1:7860 に転送
ssh -i your-key.pem \
-L 7860:127.0.0.1:7860 \
ubuntu@$(terraform output -raw public_dns)
このターミナルを開いたまま、ブラウザで以下にアクセスします。
http://127.0.0.1:7860
FramePack-eichi の Gradio UI が表示されれば成功です。
使い終わったら削除する
GPU インスタンスは従量課金なので、使い終わったら必ず削除してください。g6.2xlarge のオンデマンド料金は東京リージョンで 約 $1.0/時間です。
terraform destroy
まとめ
- Terraform でVPC・EC2・セキュリティグループをまとめて管理することで、環境構築と削除を冪等に行えます
- userdata でセットアップを自動化しているため、
terraform applyから15分程度でブラウザからアクセスできる状態になります - セキュリティグループで SSH のみ許可し、Gradio を localhost バインドにすることで外部公開しない安全な構成にしています
- スポットインスタンスを使えばコストを 60〜70% 削減できます(中断リスクとのトレードオフ)