n8n + CloudRunで社内用n8nのテスト運用環境を作る
社内でn8nを使ってみようと思ってまずはローカルで試していたんですが
Slackなど、Webhookを使って連携する場合にローカルだと不便なので
さくっとCloudRunに立ててしまうことにしました。
n8n とは?
Flexible AI workflow automationfor technical teams
ということで、AIを使ったWorkflowを構築するアプリケーションです。
Best apps & software integrations | n8n
2025/06/17 時点で、 1039
個のIntegrationsがありました。
n8n Press | Automate without limits
Our name
It is "n8n" with all lower case letters. It can either be pronounced "n eight n" or "nodemation".While looking for a good name for the project with a free domain, Jan quickly realized that all the good ones he could think of were already taken. So, in the end, he chose nodemation. 'node-' in the sense that it uses a Node-View and that it uses Node.js and '-mation' for 'automation' which is what the project is supposed to help with. However, he did not like how long the name was and could not imagine writing something that long every time in the CLI. That is when he ended up on 'n8n'.
Node.js + Automation = nodemation
読み方は エヌエイトエヌ
or ノードメーション
らしいですね。
構成
- Database
- 今回はSQLiteでやります
- CloudRun
- n8nのコンテナを動かす
- GCS
- CloudRunにマウントして使います
- SQLiteもここに書き込むようにします
※今回はIAPで認証を入れてしまうと、そのままだとWebhookが受け取れなくなってしまうため、認証はn8nに任せることにします。
Terraform
今回はTerraformから環境構築とデプロイまでやってしまいます。
variable "gcp_project_id" {
type = string
}
variable "gcp_region" {
type = string
}
## ServiceAccount
resource "google_service_account" "n8n" {
project = var.gcp_project_id
account_id = "lecto-n8n"
display_name = "n8n ServiceAccount"
}
## GCS
resource "google_storage_bucket" "n8n_data" {
project = var.gcp_project_id
location = var.gcp_region
name = "lecto-n8n-data"
uniform_bucket_level_access = true
}
resource "google_storage_bucket_iam_member" "n8n_gcs_access" {
bucket = google_storage_bucket.n8n_data.name
role = "roles/storage.objectUser"
member = google_service_account.n8n.member
}
## CloudRun
locals {
n8n_name = "n8n"
n8n_port = 5678
n8n_user_folder = "/home/node/.n8n"
# 決定論的URL
# https://cloud.google.com/run/docs/triggering/https-request?hl=ja#deterministic
n8n_host = "${local.n8n_name}-${data.google_project.project.number}.${var.gcp_region}.run.app"
}
data "google_project" "project" {
project_id = var.gcp_project_id
}
resource "google_cloud_run_v2_service" "n8n" {
project = data.google_project.project.project_id
provider = google-beta
name = local.n8n_name
location = var.gcp_region
launch_stage = "GA" # IAP使うときは "BETA"
# iap_enabled = true # 後で設定
template {
containers {
image = "n8nio/n8n:1.98.1"
ports {
container_port = local.n8n_port
}
resources {
limits = {
cpu = "1"
memory = "2Gi"
}
}
env {
name = "DB_TYPE"
value = "sqlite" # postgresにする場合はここを変更
}
env {
name = "N8N_USER_FOLDER"
value = local.n8n_user_folder
}
env {
name = "N8N_PROTOCOL"
value = "https"
}
env {
name = "N8N_PORT"
value = local.n8n_port
}
env {
name = "N8N_HOST"
value = local.n8n_host
}
# デフォルトだとUI上に表示されるwebhookのURLにポート番号(5678)が入ってしまい、そのままコピーしても使えないので、ここで上書きする
env {
name = "WEBHOOK_URL"
value = "https://${local.n8n_host}"
}
volume_mounts {
name = "n8n-data"
mount_path = local.n8n_user_folder
}
}
service_account = google_service_account.n8n.email
# gcs volume
volumes {
name = "n8n-data"
gcs {
bucket = google_storage_bucket.n8n_data.name
}
}
scaling {
min_instance_count = 1
max_instance_count = 1
}
}
}
# 今回はIAPでの制限を入れないので、未認証でもアクセスできるようにします
# https://cloud.google.com/run/docs/authenticating/public?hl=ja#assign-allusers-iam-invoker
resource "google_cloud_run_service_iam_binding" "n8n" {
location = google_cloud_run_v2_service.n8n.location
service = google_cloud_run_v2_service.n8n.name
role = "roles/run.invoker"
members = [
"allUsers"
]
}
これを apply
します
n8nの初期ユーザー作成
https://{CloudRunのname}.{GCPプロジェクト番号}-{リージョン}.run.app
を開いて、初期ユーザーを作成します。
※EmailとPasswordを設定
TODO
-
ちゃんと運用するならオートスケールさせたいので、PostgreSQLに移行する
- Configuring queue mode | n8n Docs
- RedisをかませてWorkerを動かす方法もあるようだけど、ここまでいったらCloud版使う方が良さそう
- 入退社があると面倒なので、IAPで認証かけておく(IAPかけてもSlackなどのWebhookを受け取れるようにする)
Discussion