GCEでブログを構築した話
ブログを作るにあたって、せっかくなのでインフラもコードで管理したいと思い、TerraformとGCEを使って構築しました。この記事ではどんな構成にしたか、実際のコードを交えて紹介します。
構成概要
| 項目 | 内容 |
|---|---|
| インフラ管理 | Terraform |
| クラウド | Google Cloud Platform |
| サーバー | GCE(e2-micro) |
| OS | Debian 12 |
| リージョン | asia-northeast1(東京) |
| Webサーバー | Nginx |
| フロントエンド | Astro v6(静的サイト生成) |
| パッケージマネージャ | pnpm |
GCEのe2-microは無料枠の対象なので、コストをほぼゼロに抑えられます。
Terraformの構成
Terraformのファイル構成はシンプルにしています。
terraform/
├── main.tf # リソース定義
├── variables.tf # 変数定義
└── outputs.tf # 出力値
ネットワーク
専用VPCとサブネットを作成しています。デフォルトVPCは使わない方針です。
resource "google_compute_network" "blog_vpc" {
name = "blog-vpc"
auto_create_subnetworks = false
}
resource "google_compute_subnetwork" "blog_subnet" {
name = "blog-subnet"
ip_cidr_range = "10.0.1.0/24"
region = var.region
network = google_compute_network.blog_vpc.id
}
ファイアウォール
SSHはIAP(Identity-Aware Proxy)経由のみ許可しています。外部から22番ポートを直接開けないので、セキュリティ的に安心です。
# SSHはIAPのIPレンジのみ許可
resource "google_compute_firewall" "allow_ssh" {
name = "blog-allow-ssh"
network = google_compute_network.blog_vpc.name
allow {
protocol = "tcp"
ports = ["22"]
}
source_ranges = ["35.235.240.0/20"]
target_tags = ["blog-server"]
}
# HTTP/HTTPSは全公開
resource "google_compute_firewall" "allow_http" {
name = "blog-allow-http"
network = google_compute_network.blog_vpc.name
allow {
protocol = "tcp"
ports = ["80", "443"]
}
source_ranges = ["0.0.0.0/0"]
target_tags = ["blog-server"]
}
GCEインスタンス
インスタンスのOSはDebian 12を選択しました。スタートアップスクリプトでNginxのインストールと設定、Let’s Encryptの証明書取得まで自動で行います。
resource "google_compute_instance" "blog" {
name = "blog-server"
machine_type = "e2-micro"
zone = var.zone
tags = ["blog-server"]
boot_disk {
initialize_params {
image = "debian-cloud/debian-12"
size = 20
}
}
network_interface {
network = google_compute_network.blog_vpc.name
subnetwork = google_compute_subnetwork.blog_subnet.name
access_config {
nat_ip = google_compute_address.blog_ip.address
}
}
metadata = {
enable-oslogin = "TRUE"
}
}
enable-oslogin = "TRUE" を設定することで、OS Loginが有効になります。SSHの公開鍵管理をGCPのIAMに任せられるので、鍵ファイルを手で管理しなくて済みます。
スタートアップスクリプト
metadata_startup_script に起動時の初期設定を書いています。Nginxのインストール、設定ファイルの配置、certbotによるHTTPS化まで一気に終わります。
apt-get update
apt-get install -y nginx certbot python3-certbot-nginx
mkdir -p /var/www/blog
chown -R www-data:www-data /var/www/blog
# Nginx設定を配置
cat > /etc/nginx/sites-available/blog <<'NGINX'
server {
listen 80;
server_name nagiho.xyz;
root /var/www/blog;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 静的ファイルのキャッシュ設定
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
gzip on;
gzip_types text/plain text/css application/javascript application/json image/svg+xml;
}
NGINX
ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/blog
rm -f /etc/nginx/sites-enabled/default
systemctl enable nginx && systemctl restart nginx
# Let's Encryptで証明書取得+HTTPSリダイレクト設定
certbot --nginx -d nagiho.xyz --non-interactive --agree-tos \
--email your@email.com --redirect
terraform apply 一発でサーバーが立ち上がり、NginxとHTTPS設定まで完了します。
フロントエンド(Astro)
ブログ本体はAstroで作っています。pnpm build でHTMLを静的生成し、生成したファイルをGCEに転送するだけで公開できます。
# ビルド
pnpm build
# GCEに転送(IAP経由)
gcloud compute scp --recurse dist/* blog-server:/var/www/blog/ \
--zone=asia-northeast1-a \
--project=YOUR_PROJECT_ID \
--tunnel-through-iap
静的ファイルをNginxで配信するだけなので、構成がシンプルで把握しやすいです。
まとめ
TerraformとGCEを使うことで、インフラの構成をコードとして管理できるようになりました。terraform apply で再現可能な状態にしておくと、万が一サーバーが壊れてもすぐに作り直せるので安心感があります。
Astroによる静的サイト生成と組み合わせることで、シンプルかつ低コストなブログ環境ができました。