Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions google-cloud-run/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Terraform script for deploying n8n on Google Cloud Run (Durable Mode)

This Terraform script provisions the necessary resources to deploy a durable instance of n8n on Google Cloud Run. The script is based on the "Durable mode" instructions in the [official n8n documentation](https://docs.n8n.io/hosting/installation/server-setups/google-cloud-run.html#durable-mode).

## Resources Created

This script will create the following resources in your Google Cloud project:

* **APIs:**
* Cloud Run API
* Cloud SQL Admin API
* Secret Manager API
* **Cloud SQL for PostgreSQL:**
* A PostgreSQL instance (`db-f1-micro`)
* A database named `n8n`
* A user named `n8n-user` with a randomly generated password
* **Secret Manager:**
* A secret to store the database password
* A secret to store the n8n encryption key (randomly generated)
* **Service Account:**
* A service account for the Cloud Run service
* IAM bindings to allow the service account to access the secrets and the Cloud SQL instance
* **Cloud Run:**
* A Cloud Run service that deplodes the latest `n8nio/n8n` container image

## Prerequisites

* [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) installed on your local machine.
* A Google Cloud project with billing enabled.
* The `gcloud` CLI installed and authenticated with your Google Cloud account.

## How to Use

1. **Clone this repository or download the files.**

2. **Update `terraform.tfvars`:**
Open the `terraform.tfvars` file and replace the placeholder values with your actual Google Cloud project ID and your desired region.

```hcl
project_id = "your-gcp-project-id"
region = "us-central1"
```

3. **Initialize Terraform:**
Open a terminal in the directory containing the Terraform files and run:

```bash
terraform init
```

4. **Apply the Terraform configuration:**
Run the following command to create the resources. You will be prompted to confirm the changes before they are applied.

```bash
terraform apply
```

5. **Access n8n:**
Once the `apply` command is complete, Terraform will output the URL of your n8n instance. You can use this URL to access your n8n deployment.

## Cleanup

To destroy all the resources created by this Terraform script, run the following command:

```bash
terraform destroy
```
256 changes: 256 additions & 0 deletions google-cloud-run/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@

# Terraform script for deploying n8n in "Durable mode" on Google Cloud Run
#
# This script is based on the instructions in the n8n documentation:
# https://docs.n8n.io/hosting/installation/server-setups/google-cloud-run.html#durable-mode

# Configure the Google Cloud provider
provider "google" {
project = var.project_id
region = var.region
}

# Enable necessary APIs
resource "google_project_service" "run" {
service = "run.googleapis.com"
}

resource "google_project_service" "sqladmin" {
service = "sqladmin.googleapis.com"
}

resource "google_project_service" "secretmanager" {
service = "secretmanager.googleapis.com"
}

# Create a random password for the database user
resource "random_password" "db_password" {
length = 16
special = true
}

# Create a random encryption key
resource "random_password" "encryption_key" {
length = 42
special = true
}

# Create the Cloud SQL for PostgreSQL instance
resource "google_sql_database_instance" "n8n_db_instance" {
name = "n8n-db"
database_version = "POSTGRES_13"
region = var.region

settings {
tier = "db-f1-micro"
availability_type = "ZONAL"
disk_size = 10
disk_type = "PD_HDD"
backup_configuration {
enabled = false
}
}

deletion_protection = false
}

# Create the n8n database
resource "google_sql_database" "n8n_database" {
name = "n8n"
instance = google_sql_database_instance.n8n_db_instance.name
}

# Create the n8n database user
resource "google_sql_user" "n8n_user" {
name = "n8n-user"
instance = google_sql_database_instance.n8n_db_instance.name
password = random_password.db_password.result
}

# Store the database password in Secret Manager
resource "google_secret_manager_secret" "n8n_db_password_secret" {
secret_id = "n8n-db-password"

replication {
auto {}
}
}

resource "google_secret_manager_secret_version" "n8n_db_password_secret_version" {
secret = google_secret_manager_secret.n8n_db_password_secret.id
secret_data = random_password.db_password.result
}

# Store the encryption key in Secret Manager
resource "google_secret_manager_secret" "n8n_encryption_key_secret" {
secret_id = "n8n-encryption-key"

replication {
auto {}
}
}

resource "google_secret_manager_secret_version" "n8n_encryption_key_secret_version" {
secret = google_secret_manager_secret.n8n_encryption_key_secret.id
secret_data = random_password.encryption_key.result
}

# Create a service account for the Cloud Run service
resource "google_service_account" "n8n_service_account" {
account_id = "n8n-service-account"
display_name = "n8n Service Account"
}

# Grant the service account access to the database password secret
resource "google_secret_manager_secret_iam_member" "n8n_db_password_secret_accessor" {
secret_id = google_secret_manager_secret.n8n_db_password_secret.secret_id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.n8n_service_account.email}"
}

# Grant the service account access to the encryption key secret
resource "google_secret_manager_secret_iam_member" "n8n_encryption_key_secret_accessor" {
secret_id = google_secret_manager_secret.n8n_encryption_key_secret.secret_id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.n8n_service_account.email}"
}

# Grant the service account the Cloud SQL Client role
resource "google_project_iam_member" "n8n_cloudsql_client" {
project = var.project_id
role = "roles/cloudsql.client"
member = "serviceAccount:${google_service_account.n8n_service_account.email}"
}

# Deploy the n8n Cloud Run service
resource "google_cloud_run_v2_service" "n8n_service" {
name = "n8n"
location = var.region
ingress = "INGRESS_TRAFFIC_ALL"
deletion_protection = false

template {
service_account = google_service_account.n8n_service_account.email

volumes {
name = "cloudsql"
cloud_sql_instance {
instances = [google_sql_database_instance.n8n_db_instance.connection_name]
}
}

containers {
image = "n8nio/n8n:latest"
command = ["/bin/sh"]
args = ["-c", "sleep 5; n8n start"]

ports {
container_port = 5678
}

volume_mounts {
name = "cloudsql"
mount_path = "/cloudsql"
}

resources {
limits = {
memory = "2Gi"
}
cpu_idle = false
}

env {
name = "N8N_PORT"
value = "5678"
}
env {
name = "N8N_PROTOCOL"
value = "https"
}
env {
name = "DB_TYPE"
value = "postgresdb"
}
env {
name = "DB_POSTGRESDB_DATABASE"
value = google_sql_database.n8n_database.name
}
env {
name = "DB_POSTGRESDB_USER"
value = google_sql_user.n8n_user.name
}
env {
name = "DB_POSTGRESDB_HOST"
value = "/cloudsql/${google_sql_database_instance.n8n_db_instance.connection_name}"
}
env {
name = "DB_POSTGRESDB_PORT"
value = "5432"
}
env {
name = "DB_POSTGRESDB_SCHEMA"
value = "public"
}
env {
name = "GENERIC_TIMEZONE"
value = "UTC"
}
env {
name = "QUEUE_HEALTH_CHECK_ACTIVE"
value = "true"
}
env {
name = "DB_POSTGRESDB_PASSWORD"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.n8n_db_password_secret.secret_id
version = "latest"
}
}
}
env {
name = "N8N_ENCRYPTION_KEY"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.n8n_encryption_key_secret.secret_id
version = "latest"
}
}
}
}
}

depends_on = [
google_project_service.run,
google_project_service.sqladmin,
google_project_service.secretmanager,
google_secret_manager_secret_iam_member.n8n_db_password_secret_accessor,
google_secret_manager_secret_iam_member.n8n_encryption_key_secret_accessor,
google_project_iam_member.n8n_cloudsql_client,
]
}

resource "google_cloud_run_v2_service_iam_member" "n8n_public_invoker" {
project = google_cloud_run_v2_service.n8n_service.project
location = google_cloud_run_v2_service.n8n_service.location
name = google_cloud_run_v2_service.n8n_service.name
role = "roles/run.invoker"
member = "allUsers"
}

# Define input variables
variable "project_id" {
description = "The Google Cloud project ID."
type = string
}

variable "region" {
description = "The Google Cloud region to deploy the resources in."
type = string
}

# Output the URL of the Cloud Run service
output "n8n_url" {
value = google_cloud_run_v2_service.n8n_service.uri
}
6 changes: 6 additions & 0 deletions google-cloud-run/terraform.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Terraform variables for the n8n deployment on Google Cloud Run
#
# Replace the placeholder values with your actual Google Cloud project ID and desired region.

project_id = "your-project"
region = "your-region"