Skip to content
This repository was archived by the owner on Jun 15, 2026. It is now read-only.

Commit 4d8b393

Browse files
committed
feat: add tf file for GCP
1 parent c2ba691 commit 4d8b393

12 files changed

Lines changed: 410 additions & 0 deletions

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,17 @@ yarn-error.log*
3636

3737
# Schema Spy
3838
schemaspy/output/
39+
40+
# Terraform
41+
.terraform/
42+
*.tfstate
43+
*.tfstate.backup
44+
*.tfvars
45+
*.tfvars.json
46+
override.tf
47+
override.tf.json
48+
_override.tf
49+
_override.tf.json
50+
.terraformrc
51+
terraform.rc
52+

terraform-gcp/.terraform.lock.hcl

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

terraform-gcp/cloudrun.tf

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
resource "google_cloud_run_v2_service" "backend" {
2+
name = "tasknote-api"
3+
location = var.region
4+
ingress = "INGRESS_TRAFFIC_ALL"
5+
6+
depends_on = [google_project_service.run]
7+
8+
template {
9+
service_account = google_service_account.cloudrun_sa.email
10+
vpc_access {
11+
connector = google_vpc_access_connector.connector.id
12+
egress = "ALL_TRAFFIC"
13+
}
14+
15+
containers {
16+
image = var.backend_image
17+
ports {
18+
container_port = 8585
19+
}
20+
env {
21+
name = "POSTGRES_DB"
22+
value = var.db_name
23+
}
24+
env {
25+
name = "POSTGRES_HOST"
26+
value = google_sql_database_instance.instance.private_ip_address
27+
}
28+
env {
29+
name = "POSTGRES_USER"
30+
value = var.db_user
31+
}
32+
env {
33+
name = "POSTGRES_PASSWORD"
34+
value = var.db_password
35+
}
36+
env {
37+
name = "POSTGRES_PORT"
38+
value = "5432"
39+
}
40+
env {
41+
name = "CORS_ALLOWED_ORIGINS"
42+
value = var.cors_allowed_origins
43+
}
44+
env {
45+
name = "SERVER_SERVLET_CONTEXT_PATH"
46+
value = "/"
47+
}
48+
env {
49+
name = "TARGET_ENV"
50+
value = "production"
51+
}
52+
env {
53+
name = "SECURITY_KEY"
54+
value_source {
55+
secret_key_ref {
56+
secret = google_secret_manager_secret.security_key.secret_id
57+
version = "latest"
58+
}
59+
}
60+
}
61+
env {
62+
name = "MAILGUN_APIKEY"
63+
value_source {
64+
secret_key_ref {
65+
secret = google_secret_manager_secret.mailgun_apikey.secret_id
66+
version = "latest"
67+
}
68+
}
69+
}
70+
}
71+
}
72+
}
73+
74+
resource "google_cloud_run_v2_service" "frontend" {
75+
name = "tasknote-app"
76+
location = var.region
77+
ingress = "INGRESS_TRAFFIC_ALL"
78+
79+
depends_on = [google_project_service.run]
80+
81+
template {
82+
service_account = google_service_account.cloudrun_sa.email
83+
84+
containers {
85+
image = var.frontend_image
86+
ports {
87+
container_port = 5000
88+
}
89+
env {
90+
name = "VITE_BACKEND_SERVER"
91+
value = google_cloud_run_v2_service.backend.uri
92+
}
93+
}
94+
}
95+
}
96+
97+
# Allow unauthenticated access to both services
98+
resource "google_cloud_run_service_iam_member" "backend_public" {
99+
location = google_cloud_run_v2_service.backend.location
100+
service = google_cloud_run_v2_service.backend.name
101+
role = "roles/run.invoker"
102+
member = "allUsers"
103+
}
104+
105+
resource "google_cloud_run_service_iam_member" "frontend_public" {
106+
location = google_cloud_run_v2_service.frontend.location
107+
service = google_cloud_run_v2_service.frontend.name
108+
role = "roles/run.invoker"
109+
member = "allUsers"
110+
}
111+
112+
# Grant Cloud SQL Client role to the service account
113+
resource "google_project_iam_member" "cloudsql_client" {
114+
project = var.project_id
115+
role = "roles/cloudsql.client"
116+
member = "serviceAccount:${google_service_account.cloudrun_sa.email}"
117+
}

terraform-gcp/database.tf

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
resource "google_sql_database_instance" "instance" {
2+
name = "tasknote-db-instance"
3+
region = var.region
4+
database_version = "POSTGRES_15"
5+
6+
depends_on = [
7+
google_service_networking_connection.private_vpc_connection,
8+
google_project_service.sqladmin,
9+
google_project_service.servicenetworking
10+
]
11+
12+
settings {
13+
tier = "db-f1-micro" # Smallest tier for dev/small app
14+
ip_configuration {
15+
ipv4_enabled = false
16+
private_network = google_compute_network.vpc_network.id
17+
}
18+
}
19+
20+
deletion_protection = false # Set to true for production
21+
}
22+
23+
resource "google_sql_database" "database" {
24+
name = var.db_name
25+
instance = google_sql_database_instance.instance.name
26+
}
27+
28+
resource "google_sql_user" "users" {
29+
name = var.db_user
30+
instance = google_sql_database_instance.instance.name
31+
password = var.db_password
32+
}

terraform-gcp/network.tf

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
resource "google_compute_network" "vpc_network" {
2+
name = "tasknote-vpc"
3+
auto_create_subnetworks = false
4+
}
5+
6+
resource "google_compute_subnetwork" "subnet" {
7+
name = "tasknote-subnet"
8+
ip_cidr_range = "10.0.0.0/24"
9+
region = var.region
10+
network = google_compute_network.vpc_network.id
11+
}
12+
13+
# Private IP for Cloud SQL
14+
resource "google_compute_global_address" "private_ip_address" {
15+
name = "tasknote-private-ip"
16+
purpose = "VPC_PEERING"
17+
address_type = "INTERNAL"
18+
prefix_length = 16
19+
network = google_compute_network.vpc_network.id
20+
}
21+
22+
resource "google_service_networking_connection" "private_vpc_connection" {
23+
network = google_compute_network.vpc_network.id
24+
service = "servicenetworking.googleapis.com"
25+
reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
26+
}
27+
28+
# Serverless VPC Access Connector
29+
resource "google_vpc_access_connector" "connector" {
30+
name = "tasknote-vpc-connector"
31+
region = var.region
32+
ip_cidr_range = "10.8.0.0/28"
33+
network = google_compute_network.vpc_network.name
34+
depends_on = [google_project_service.vpcaccess, google_project_service.compute]
35+
}

terraform-gcp/outputs.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
output "backend_url" {
2+
value = google_cloud_run_v2_service.backend.uri
3+
}
4+
5+
output "frontend_url" {
6+
value = google_cloud_run_v2_service.frontend.uri
7+
}
8+
9+
output "cloud_sql_instance_ip" {
10+
value = google_sql_database_instance.instance.private_ip_address
11+
}
12+
13+
output "artifact_registry_repo" {
14+
value = google_artifact_registry_repository.repo.name
15+
}

terraform-gcp/providers.tf

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
terraform {
2+
required_providers {
3+
google = {
4+
source = "hashicorp/google"
5+
version = "~> 5.0"
6+
}
7+
}
8+
9+
backend "s3" {
10+
bucket = "tasknote"
11+
key = "gcp/terraform.tfstate"
12+
region = "auto"
13+
endpoints = { s3 = "https://d17eb09b6bce2f90e16e800bb2a6baf9.r2.cloudflarestorage.com" }
14+
skip_credentials_validation = true
15+
skip_region_validation = true
16+
skip_requesting_account_id = true
17+
skip_metadata_api_check = true
18+
skip_s3_checksum = true
19+
}
20+
}
21+
22+
provider "google" {
23+
project = var.project_id
24+
region = var.region
25+
}

terraform-gcp/registry.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
resource "google_artifact_registry_repository" "repo" {
2+
location = var.region
3+
repository_id = "tasknote-repo"
4+
description = "Docker repository for TaskNote images"
5+
format = "DOCKER"
6+
depends_on = [google_project_service.artifactregistry]
7+
}

terraform-gcp/secrets.tf

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
resource "google_service_account" "cloudrun_sa" {
2+
account_id = "tasknote-cloudrun-sa"
3+
display_name = "TaskNote Cloud Run Service Account"
4+
}
5+
6+
resource "google_secret_manager_secret" "security_key" {
7+
secret_id = "security-key"
8+
replication {
9+
user_managed {
10+
replicas {
11+
location = var.region
12+
}
13+
}
14+
}
15+
}
16+
17+
resource "google_secret_manager_secret_version" "security_key_version" {
18+
secret = google_secret_manager_secret.security_key.id
19+
secret_data = var.security_key
20+
}
21+
22+
resource "google_secret_manager_secret" "mailgun_apikey" {
23+
secret_id = "mailgun-apikey"
24+
replication {
25+
user_managed {
26+
replicas {
27+
location = var.region
28+
}
29+
}
30+
}
31+
depends_on = [google_project_service.secretmanager]
32+
}
33+
34+
resource "google_secret_manager_secret_version" "mailgun_apikey_version" {
35+
secret = google_secret_manager_secret.mailgun_apikey.id
36+
secret_data = var.mailgun_apikey
37+
}
38+
39+
resource "google_secret_manager_secret_iam_member" "security_key_access" {
40+
secret_id = google_secret_manager_secret.security_key.id
41+
role = "roles/secretmanager.secretAccessor"
42+
member = "serviceAccount:${google_service_account.cloudrun_sa.email}"
43+
}
44+
45+
resource "google_secret_manager_secret_iam_member" "mailgun_apikey_access" {
46+
secret_id = google_secret_manager_secret.mailgun_apikey.id
47+
role = "roles/secretmanager.secretAccessor"
48+
member = "serviceAccount:${google_service_account.cloudrun_sa.email}"
49+
}

terraform-gcp/services.tf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
resource "google_project_service" "compute" {
2+
service = "compute.googleapis.com"
3+
disable_on_destroy = false
4+
}
5+
6+
resource "google_project_service" "sqladmin" {
7+
service = "sqladmin.googleapis.com"
8+
disable_on_destroy = false
9+
}
10+
11+
resource "google_project_service" "run" {
12+
service = "run.googleapis.com"
13+
disable_on_destroy = false
14+
}
15+
16+
resource "google_project_service" "secretmanager" {
17+
service = "secretmanager.googleapis.com"
18+
disable_on_destroy = false
19+
}
20+
21+
resource "google_project_service" "vpcaccess" {
22+
service = "vpcaccess.googleapis.com"
23+
disable_on_destroy = false
24+
}
25+
26+
resource "google_project_service" "artifactregistry" {
27+
service = "artifactregistry.googleapis.com"
28+
disable_on_destroy = false
29+
}
30+
31+
resource "google_project_service" "servicenetworking" {
32+
service = "servicenetworking.googleapis.com"
33+
disable_on_destroy = false
34+
}

0 commit comments

Comments
 (0)