Skip to content

Commit

Permalink
Add CGP Cloud Run deployment documentation
Browse files Browse the repository at this point in the history
* Add docs for gcp cloud run

* terraform gcp cloud run

* Edit GCP Clound Run documentation for clarity

---------

Co-authored-by: Christopher Charbonneau Wells <10456740+cdubz@users.noreply.github.com>
  • Loading branch information
NissesSenap and cdubz committed Dec 22, 2023
1 parent 9d3501d commit d053050
Show file tree
Hide file tree
Showing 5 changed files with 282 additions and 11 deletions.
43 changes: 32 additions & 11 deletions docs/setup/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,30 @@ for your instance of babybuddy.
After that, you just have to push babybuddy code repository to the Git
deployment URL of your Clever Cloud Python application.

## GCP Cloud Run

Baby Buddy can be hosted serverless in GCP Cloud Run using configuration provided at
`terraform/gcp-cloud-run`. The configuration scales down to zero for cost effectiveness.
With this approach initial requests to the service after a long period will be slow but
subsequent requests will be much faster. A [billing account](https://cloud.google.com/billing/docs/how-to/create-billing-account)
mut be configured in GCP to use the configuration.

The terraform code isn't production ready and is meant to be a good way of getting started.
No state strage is configured. See [storage options](https://cloud.google.com/run/docs/storage-options)
for information about how to configure persistant storage.

Run `terraform init` from the configurtion directory to get started:

```shell
git clone https://github.com/babybuddy/babybuddy.git
cd babybuddy/terraform/gcp-cloud-run
terraform init
terraform apply -var project_id=<project-id> -var project_name=<project-name> -var billing_account=<billing-account-id>
```

## Manual

There are many ways to deploy Baby Buddy manually to any server/VPS. The basic
There are many ways to deploy Baby Buddy manually to any server/VPS. The basic
requirements are Python, a web server, an application server, and a database.

### Requirements
Expand Down Expand Up @@ -139,7 +160,7 @@ and any number of children).
```shell
cd /var/www/babybuddy/public
```

6. Initiate and enter a Python environment with Pipenv locally.

```shell
Expand Down Expand Up @@ -183,18 +204,18 @@ and any number of children).
plugins = python3
project = babybuddy
base_dir = /var/www/babybuddy

chdir = %(base_dir)/public
virtualenv = %(chdir)/.venv
module = %(project).wsgi:application
env = DJANGO_SETTINGS_MODULE=%(project).settings.production
master = True
vacuum = True
```

See the [uWSGI documentation](http://uwsgi-docs.readthedocs.io/en/latest/)
for more advanced configuration details.

See [Subdirectory configuration](subdirectory.md) for additional configuration
required if Baby Buddy will be hosted in a subdirectory of another server.

Expand All @@ -212,30 +233,30 @@ and any number of children).
```

Example config:

```nginx
upstream babybuddy {
server unix:///var/run/uwsgi/app/babybuddy/socket;
}
server {
listen 80;
server_name babybuddy.example.com;
location / {
uwsgi_pass babybuddy;
include uwsgi_params;
}
location /media {
alias /var/www/babybuddy/data/media;
}
}
```

See the [nginx documentation](https://nginx.org/en/docs/) for more advanced
configuration details.

See [Subdirectory configuration](subdirectory.md) for additional configuration
required if Baby Buddy will be hosted in a subdirectory of another server.

Expand Down
40 changes: 40 additions & 0 deletions terraform/gcp-cloud-run/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

187 changes: 187 additions & 0 deletions terraform/gcp-cloud-run/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
provider "google" {
region = var.region
}

resource "google_project" "baby_buddy" {
name = var.project_name
project_id = var.project_id
billing_account = var.billing_account
auto_create_network = false
}

locals {
services = toset(["run.googleapis.com",
"sqladmin.googleapis.com",
"sql-component.googleapis.com",
"secretmanager.googleapis.com"
])
}

resource "google_project_service" "project_services" {
for_each = local.services
project = google_project.baby_buddy.project_id
service = each.value
disable_on_destroy = true
disable_dependent_services = true
}

resource "random_password" "root_password" {
min_lower = 1
min_numeric = 1
min_upper = 1
length = 19
special = true
min_special = 1
lifecycle {
ignore_changes = [
min_lower, min_upper, min_numeric, special, min_special, length
]
}
}

resource "random_password" "django_secret_key" {
min_lower = 1
min_numeric = 1
min_upper = 1
length = 20
special = true
min_special = 1
lifecycle {
ignore_changes = [
min_lower, min_upper, min_numeric, special, min_special, length
]
}
}

resource "google_sql_database_instance" "baby_buddy" {
name = "babybuddy"
database_version = "POSTGRES_15"
root_password = random_password.root_password.result
settings {
tier = "db-f1-micro"
disk_autoresize = false
deletion_protection_enabled = false
insights_config {
query_insights_enabled = false
}
maintenance_window {
day = 1
hour = 0
}
}

deletion_protection = "true"
}

resource "google_secret_manager_secret" "postgres_password" {
secret_id = "postgres-password"
project = google_project.baby_buddy.project_id
replication {
auto {}
}
}

resource "google_secret_manager_secret_version" "postgres_password" {
secret = google_secret_manager_secret.postgres_password.name
secret_data = google_sql_database_instance.baby_buddy.root_password
}

resource "google_secret_manager_secret_iam_member" "postgres_password" {
secret_id = google_secret_manager_secret.postgres_password.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_project.baby_buddy.number}-compute@developer.gserviceaccount.com"
depends_on = [google_secret_manager_secret.postgres_password]
}

resource "google_secret_manager_secret" "django_secret_key" {
secret_id = "django-secret-key"
project = google_project.baby_buddy.project_id
replication {
auto {}
}
}

resource "google_secret_manager_secret_version" "django_secret_key" {
secret = google_secret_manager_secret.django_secret_key.name
secret_data = random_password.django_secret_key.result
}

resource "google_secret_manager_secret_iam_member" "django_secret_key" {
secret_id = google_secret_manager_secret.django_secret_key.name
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_project.baby_buddy.number}-compute@developer.gserviceaccount.com"
depends_on = [google_secret_manager_secret.django_secret_key]
}

resource "google_cloud_run_v2_service" "baby_buddy" {
name = "babybuddy"
location = var.region
ingress = "INGRESS_TRAFFIC_ALL"
project = google_project.baby_buddy.project_id

template {
scaling {
max_instance_count = 2
}

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

containers {
name = "babybuddy-1"
image = "docker.io/linuxserver/babybuddy:latest"

env {
name = "DB_HOST"
value = "/cloudsql/${google_project.baby_buddy.project_id}:${var.region}:${google_sql_database_instance.baby_buddy.name}"
}
env {
name = "DB_USER"
value = "postgres"
}
env {
name = "DB_NAME"
value = "postgres"
}
env {
name = "DB_ENGINE"
value = "django.db.backends.postgresql"
}
env {
name = "DB_PASSWORD"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.postgres_password.secret_id
version = google_secret_manager_secret_version.postgres_password.version
}
}
}
env {
name = "SECRET_KEY"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.django_secret_key.secret_id
version = google_secret_manager_secret_version.django_secret_key.version
}
}
}
volume_mounts {
name = "cloudsql"
mount_path = "/cloudsql"
}
}
}

annotations = {
"foo" = "bar"
}
traffic {
type = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
percent = 100
}
depends_on = [google_secret_manager_secret_version.postgres_password, google_secret_manager_secret_version.django_secret_key]
}
3 changes: 3 additions & 0 deletions terraform/gcp-cloud-run/output.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "url" {
value = google_cloud_run_v2_service.baby_buddy.uri
}
20 changes: 20 additions & 0 deletions terraform/gcp-cloud-run/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
variable "project_name" {
description = "project name"
type = string
}

variable "project_id" {
description = "project id, remember the project id has to be unique"
type = string
}

variable "billing_account" {
description = "value of the billing account id"
type = string

}
variable "region" {
description = "which region to deploy to"
type = string
default = "europe-north1"
}

0 comments on commit d053050

Please sign in to comment.