feat: add tf file for GCP
This commit is contained in:
+14
@@ -36,3 +36,17 @@ yarn-error.log*
|
||||
|
||||
# Schema Spy
|
||||
schemaspy/output/
|
||||
|
||||
# Terraform
|
||||
.terraform/
|
||||
*.tfstate
|
||||
*.tfstate.backup
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
override.tf
|
||||
override.tf.json
|
||||
_override.tf
|
||||
_override.tf.json
|
||||
.terraformrc
|
||||
terraform.rc
|
||||
|
||||
|
||||
Generated
+22
@@ -0,0 +1,22 @@
|
||||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/google" {
|
||||
version = "5.45.2"
|
||||
constraints = "~> 5.0"
|
||||
hashes = [
|
||||
"h1:k8taQAdfHrv2F/AiGV5BZBZfI+1uaq8g6O8dWzjx42c=",
|
||||
"zh:0d09c8f20b556305192cdbe0efa6d333ceebba963a8ba91f9f1714b5a20c4b7a",
|
||||
"zh:117143fc91be407874568df416b938a6896f94cb873f26bba279cedab646a804",
|
||||
"zh:16ccf77d18dd2c5ef9c0625f9cf546ebdf3213c0a452f432204c69feed55081e",
|
||||
"zh:3e555cf22a570a4bd247964671f421ed7517970cd9765ceb46f335edc2c6f392",
|
||||
"zh:688bd5b05a75124da7ae6e885b2b92bd29f4261808b2b78bd5f51f525c1052ca",
|
||||
"zh:6db3ef37a05010d82900bfffb3261c59a0c247e0692049cb3eb8c2ef16c9d7bf",
|
||||
"zh:70316fde75f6a15d72749f66d994ccbdde5f5ed4311b6d06b99850f698c9bbf9",
|
||||
"zh:84b8e583771a4f2bd514e519d98ed7fd28dce5efe0634e973170e1cfb5556fb4",
|
||||
"zh:9d4b8ef0a9b6677935c604d94495042e68ff5489932cfd1ec41052e094a279d3",
|
||||
"zh:a2089dd9bd825c107b148dd12d6b286f71aa37dfd4ca9c35157f2dcba7bc19d8",
|
||||
"zh:f03d795c0fd9721e59839255ee7ba7414173017dc530b4ce566daf3802a0d6dd",
|
||||
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
resource "google_cloud_run_v2_service" "backend" {
|
||||
name = "tasknote-api"
|
||||
location = var.region
|
||||
ingress = "INGRESS_TRAFFIC_ALL"
|
||||
|
||||
depends_on = [google_project_service.run]
|
||||
|
||||
template {
|
||||
service_account = google_service_account.cloudrun_sa.email
|
||||
vpc_access {
|
||||
connector = google_vpc_access_connector.connector.id
|
||||
egress = "ALL_TRAFFIC"
|
||||
}
|
||||
|
||||
containers {
|
||||
image = var.backend_image
|
||||
ports {
|
||||
container_port = 8585
|
||||
}
|
||||
env {
|
||||
name = "POSTGRES_DB"
|
||||
value = var.db_name
|
||||
}
|
||||
env {
|
||||
name = "POSTGRES_HOST"
|
||||
value = google_sql_database_instance.instance.private_ip_address
|
||||
}
|
||||
env {
|
||||
name = "POSTGRES_USER"
|
||||
value = var.db_user
|
||||
}
|
||||
env {
|
||||
name = "POSTGRES_PASSWORD"
|
||||
value = var.db_password
|
||||
}
|
||||
env {
|
||||
name = "POSTGRES_PORT"
|
||||
value = "5432"
|
||||
}
|
||||
env {
|
||||
name = "CORS_ALLOWED_ORIGINS"
|
||||
value = var.cors_allowed_origins
|
||||
}
|
||||
env {
|
||||
name = "SERVER_SERVLET_CONTEXT_PATH"
|
||||
value = "/"
|
||||
}
|
||||
env {
|
||||
name = "TARGET_ENV"
|
||||
value = "production"
|
||||
}
|
||||
env {
|
||||
name = "SECURITY_KEY"
|
||||
value_source {
|
||||
secret_key_ref {
|
||||
secret = google_secret_manager_secret.security_key.secret_id
|
||||
version = "latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
env {
|
||||
name = "MAILGUN_APIKEY"
|
||||
value_source {
|
||||
secret_key_ref {
|
||||
secret = google_secret_manager_secret.mailgun_apikey.secret_id
|
||||
version = "latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_cloud_run_v2_service" "frontend" {
|
||||
name = "tasknote-app"
|
||||
location = var.region
|
||||
ingress = "INGRESS_TRAFFIC_ALL"
|
||||
|
||||
depends_on = [google_project_service.run]
|
||||
|
||||
template {
|
||||
service_account = google_service_account.cloudrun_sa.email
|
||||
|
||||
containers {
|
||||
image = var.frontend_image
|
||||
ports {
|
||||
container_port = 5000
|
||||
}
|
||||
env {
|
||||
name = "VITE_BACKEND_SERVER"
|
||||
value = google_cloud_run_v2_service.backend.uri
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Allow unauthenticated access to both services
|
||||
resource "google_cloud_run_service_iam_member" "backend_public" {
|
||||
location = google_cloud_run_v2_service.backend.location
|
||||
service = google_cloud_run_v2_service.backend.name
|
||||
role = "roles/run.invoker"
|
||||
member = "allUsers"
|
||||
}
|
||||
|
||||
resource "google_cloud_run_service_iam_member" "frontend_public" {
|
||||
location = google_cloud_run_v2_service.frontend.location
|
||||
service = google_cloud_run_v2_service.frontend.name
|
||||
role = "roles/run.invoker"
|
||||
member = "allUsers"
|
||||
}
|
||||
|
||||
# Grant Cloud SQL Client role to the service account
|
||||
resource "google_project_iam_member" "cloudsql_client" {
|
||||
project = var.project_id
|
||||
role = "roles/cloudsql.client"
|
||||
member = "serviceAccount:${google_service_account.cloudrun_sa.email}"
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
resource "google_sql_database_instance" "instance" {
|
||||
name = "tasknote-db-instance"
|
||||
region = var.region
|
||||
database_version = "POSTGRES_15"
|
||||
|
||||
depends_on = [
|
||||
google_service_networking_connection.private_vpc_connection,
|
||||
google_project_service.sqladmin,
|
||||
google_project_service.servicenetworking
|
||||
]
|
||||
|
||||
settings {
|
||||
tier = "db-f1-micro" # Smallest tier for dev/small app
|
||||
ip_configuration {
|
||||
ipv4_enabled = false
|
||||
private_network = google_compute_network.vpc_network.id
|
||||
}
|
||||
}
|
||||
|
||||
deletion_protection = false # Set to true for production
|
||||
}
|
||||
|
||||
resource "google_sql_database" "database" {
|
||||
name = var.db_name
|
||||
instance = google_sql_database_instance.instance.name
|
||||
}
|
||||
|
||||
resource "google_sql_user" "users" {
|
||||
name = var.db_user
|
||||
instance = google_sql_database_instance.instance.name
|
||||
password = var.db_password
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
resource "google_compute_network" "vpc_network" {
|
||||
name = "tasknote-vpc"
|
||||
auto_create_subnetworks = false
|
||||
}
|
||||
|
||||
resource "google_compute_subnetwork" "subnet" {
|
||||
name = "tasknote-subnet"
|
||||
ip_cidr_range = "10.0.0.0/24"
|
||||
region = var.region
|
||||
network = google_compute_network.vpc_network.id
|
||||
}
|
||||
|
||||
# Private IP for Cloud SQL
|
||||
resource "google_compute_global_address" "private_ip_address" {
|
||||
name = "tasknote-private-ip"
|
||||
purpose = "VPC_PEERING"
|
||||
address_type = "INTERNAL"
|
||||
prefix_length = 16
|
||||
network = google_compute_network.vpc_network.id
|
||||
}
|
||||
|
||||
resource "google_service_networking_connection" "private_vpc_connection" {
|
||||
network = google_compute_network.vpc_network.id
|
||||
service = "servicenetworking.googleapis.com"
|
||||
reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
|
||||
}
|
||||
|
||||
# Serverless VPC Access Connector
|
||||
resource "google_vpc_access_connector" "connector" {
|
||||
name = "tasknote-vpc-connector"
|
||||
region = var.region
|
||||
ip_cidr_range = "10.8.0.0/28"
|
||||
network = google_compute_network.vpc_network.name
|
||||
depends_on = [google_project_service.vpcaccess, google_project_service.compute]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
output "backend_url" {
|
||||
value = google_cloud_run_v2_service.backend.uri
|
||||
}
|
||||
|
||||
output "frontend_url" {
|
||||
value = google_cloud_run_v2_service.frontend.uri
|
||||
}
|
||||
|
||||
output "cloud_sql_instance_ip" {
|
||||
value = google_sql_database_instance.instance.private_ip_address
|
||||
}
|
||||
|
||||
output "artifact_registry_repo" {
|
||||
value = google_artifact_registry_repository.repo.name
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = "~> 5.0"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {
|
||||
bucket = "tasknote"
|
||||
key = "gcp/terraform.tfstate"
|
||||
region = "auto"
|
||||
endpoints = { s3 = "https://d17eb09b6bce2f90e16e800bb2a6baf9.r2.cloudflarestorage.com" }
|
||||
skip_credentials_validation = true
|
||||
skip_region_validation = true
|
||||
skip_requesting_account_id = true
|
||||
skip_metadata_api_check = true
|
||||
skip_s3_checksum = true
|
||||
}
|
||||
}
|
||||
|
||||
provider "google" {
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
resource "google_artifact_registry_repository" "repo" {
|
||||
location = var.region
|
||||
repository_id = "tasknote-repo"
|
||||
description = "Docker repository for TaskNote images"
|
||||
format = "DOCKER"
|
||||
depends_on = [google_project_service.artifactregistry]
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
resource "google_service_account" "cloudrun_sa" {
|
||||
account_id = "tasknote-cloudrun-sa"
|
||||
display_name = "TaskNote Cloud Run Service Account"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret" "security_key" {
|
||||
secret_id = "security-key"
|
||||
replication {
|
||||
user_managed {
|
||||
replicas {
|
||||
location = var.region
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "security_key_version" {
|
||||
secret = google_secret_manager_secret.security_key.id
|
||||
secret_data = var.security_key
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret" "mailgun_apikey" {
|
||||
secret_id = "mailgun-apikey"
|
||||
replication {
|
||||
user_managed {
|
||||
replicas {
|
||||
location = var.region
|
||||
}
|
||||
}
|
||||
}
|
||||
depends_on = [google_project_service.secretmanager]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "mailgun_apikey_version" {
|
||||
secret = google_secret_manager_secret.mailgun_apikey.id
|
||||
secret_data = var.mailgun_apikey
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "security_key_access" {
|
||||
secret_id = google_secret_manager_secret.security_key.id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloudrun_sa.email}"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "mailgun_apikey_access" {
|
||||
secret_id = google_secret_manager_secret.mailgun_apikey.id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloudrun_sa.email}"
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
resource "google_project_service" "compute" {
|
||||
service = "compute.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_project_service" "sqladmin" {
|
||||
service = "sqladmin.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_project_service" "run" {
|
||||
service = "run.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_project_service" "secretmanager" {
|
||||
service = "secretmanager.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_project_service" "vpcaccess" {
|
||||
service = "vpcaccess.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_project_service" "artifactregistry" {
|
||||
service = "artifactregistry.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
resource "google_project_service" "servicenetworking" {
|
||||
service = "servicenetworking.googleapis.com"
|
||||
disable_on_destroy = false
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
project_id = "your-gcp-project-id"
|
||||
region = "us-central1"
|
||||
db_user = "tasknoteuser"
|
||||
db_password = "your-db-password"
|
||||
db_name = "tasknote"
|
||||
security_key = "your-security-key"
|
||||
mailgun_apikey = "your-mailgun-apikey"
|
||||
backend_image = "ghcr.io/rmcampos/tasknote/api:latest"
|
||||
frontend_image = "ghcr.io/rmcampos/tasknote/app:latest"
|
||||
cors_allowed_origins = "*"
|
||||
@@ -0,0 +1,50 @@
|
||||
variable "project_id" {
|
||||
type = string
|
||||
description = "The GCP Project ID"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
type = string
|
||||
default = "us-central1"
|
||||
description = "The GCP region to deploy resources"
|
||||
}
|
||||
|
||||
variable "db_user" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_password" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
type = string
|
||||
default = "tasknote"
|
||||
}
|
||||
|
||||
variable "security_key" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "mailgun_apikey" {
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "backend_image" {
|
||||
type = string
|
||||
default = "ghcr.io/rmcampos/tasknote/api:latest"
|
||||
}
|
||||
|
||||
variable "frontend_image" {
|
||||
type = string
|
||||
default = "ghcr.io/rmcampos/tasknote/app:latest"
|
||||
}
|
||||
|
||||
variable "cors_allowed_origins" {
|
||||
type = string
|
||||
default = "*"
|
||||
}
|
||||
Reference in New Issue
Block a user