cover-letter-llm

Terraform Setup Guide

This guide will help you set up and deploy the Cover Letter LLM application infrastructure using Terraform.

Prerequisites

Required Tools

Local Testing (No Cloud Required)

Before deploying to the cloud, you can test your Terraform configuration locally:

1. Check Terraform Installation

terraform version

2. Navigate to Development Environment

cd terraform/environments/development

3. Create Configuration File

cp terraform.tfvars.example terraform.tfvars

4. Edit Configuration for Local Testing

Edit terraform.tfvars and set:

# Required: Use any placeholder value for local testing
project_id = "test-project-local"

# Optional: Keep other values as-is for testing
region = "us-central1"
zone   = "us-central1-a"
container_image = "gcr.io/test-project-local/cover-letter-llm:latest"

5. Initialize and Test

# Initialize Terraform
terraform init

# Validate configuration syntax
terraform validate

# Format code
terraform fmt -recursive

# Test configuration (will show plan but won't create resources)
terraform plan

Expected Result: You should see a plan showing resources to be created, ending with a Google credentials error. This is normal for local testing and confirms your configuration is valid.

Next Steps and Purpose

Current Status: ✅ Local Terraform Testing Complete

You’ve successfully validated that your Terraform configuration is syntactically correct and structurally sound.

Next Steps (In Order):

1. Container Image Preparation

Purpose: Your Terraform creates Cloud Run services that need a container image to deploy.

Steps:

cd /home/elreyuno/cover-letter-llm/CoverLetterApp
docker build -t cover-letter-llm:latest .

Why: Cloud Run needs a containerized application to run. Without this, your infrastructure will deploy but have nothing to serve.

2. Choose Deployment Strategy

Purpose: Decide how you want to deploy - locally controlled vs automated CI/CD.

Options:

3. Google Cloud Project Setup

Purpose: Create the actual cloud environment where your infrastructure will live.

Steps:

# Create project
gcloud projects create your-project-id

# Enable billing and required APIs
gcloud services enable compute.googleapis.com run.googleapis.com sql-component.googleapis.com

Why: You need a real GCP project to deploy actual resources that users can access.

4. Authentication Setup

Purpose: Give Terraform permission to create resources in your GCP project.

Steps:

gcloud auth application-default login
# OR
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

Why: Terraform needs credentials to interact with Google Cloud APIs.

5. Remote State Backend

Purpose: Store Terraform state securely and enable team collaboration.

Steps:

# Create GCS bucket for state
gsutil mb gs://your-project-terraform-state

Why: Local state files get lost and can’t be shared. Remote state enables collaboration and recovery.

6. First Real Deployment

Purpose: Deploy your actual infrastructure to the cloud.

Steps:

cd terraform/environments/development
terraform apply

Why: This creates the actual infrastructure users will interact with.

7. Application Deployment

Purpose: Deploy your Rails application to the created infrastructure.

Why: Infrastructure without the application is just empty servers.

8. Domain and SSL Setup

Purpose: Make your application accessible via a proper domain name with HTTPS.

Why: Users need a memorable URL and secure connections.

Overall Purpose:

You’re building a complete, production-ready deployment pipeline that:

Which step would you like to tackle next?

Google Cloud Setup (For Actual Deployment)

1. Create Google Cloud Projects (one for each environment):

  1. Enable required APIs in each project:
    gcloud services enable compute.googleapis.com
    gcloud services enable run.googleapis.com
    gcloud services enable sql-component.googleapis.com
    gcloud services enable redis.googleapis.com
    gcloud services enable secretmanager.googleapis.com
    gcloud services enable storage-component.googleapis.com
    gcloud services enable monitoring.googleapis.com
    gcloud services enable logging.googleapis.com
    gcloud services enable servicenetworking.googleapis.com
    
  2. Create service accounts for Terraform:
    # For each environment
    gcloud iam service-accounts create terraform-deployer \
      --description="Service account for Terraform deployments" \
      --display-name="Terraform Deployer"
       
    # Grant necessary permissions
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:terraform-deployer@PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/editor"
       
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member="serviceAccount:terraform-deployer@PROJECT_ID.iam.gserviceaccount.com" \
      --role="roles/secretmanager.admin"
       
    # Generate service account keys
    gcloud iam service-accounts keys create terraform-key.json \
      --iam-account=terraform-deployer@PROJECT_ID.iam.gserviceaccount.com
    
  3. Create a Google Cloud Storage bucket for Terraform state:
    gsutil mb gs://your-company-terraform-state
    gsutil versioning set on gs://your-company-terraform-state
    

Quick Start

1. Clone and Setup

git clone https://github.com/yourusername/cover-letter-llm.git
cd cover-letter-llm
git checkout terraform-infrastructure

2. Configure Environment Variables

# Set your Google Cloud project
export GOOGLE_PROJECT="your-company-coverllm-dev"
export GOOGLE_APPLICATION_CREDENTIALS="path/to/terraform-key.json"

3. Configure Terraform Variables

cd terraform/environments/development
cp terraform.tfvars.example terraform.tfvars
# Edit terraform.tfvars with your project details

4. Deploy Infrastructure

# Format and validate
../../../terraform/deploy.sh development fmt
../../../terraform/deploy.sh development validate

# Initialize Terraform
../../../terraform/deploy.sh development init

# Plan deployment
../../../terraform/deploy.sh development plan

# Apply changes
../../../terraform/deploy.sh development apply

Environment Configuration

Development Environment

Configuration:

# terraform/environments/development/terraform.tfvars
project_id = "your-company-coverllm-dev"
container_image = "gcr.io/your-company-coverllm-dev/cover-letter-llm:latest"
region = "us-central1"

Staging Environment

Configuration:

# terraform/environments/staging/terraform.tfvars
project_id = "your-company-coverllm-staging"
container_image = "gcr.io/your-company-coverllm-staging/cover-letter-llm:staging"
domain_name = "staging.coverletter.yourcompany.com"
region = "us-central1"

Production Environment

Configuration:

# terraform/environments/production/terraform.tfvars
project_id = "your-company-coverllm-prod"
container_image = "gcr.io/your-company-coverllm-prod/cover-letter-llm:latest"
domain_name = "coverletter.yourcompany.com"
region = "us-central1"
notification_channels = ["projects/PROJECT_ID/notificationChannels/CHANNEL_ID"]

Manual Secrets Setup

Before deploying, you need to manually create some secrets:

1. Rails Master Key

# Generate a new master key in your Rails app
cd CoverLetterApp
bundle exec rails credentials:edit

# Copy the master key and create the secret
gcloud secrets create cover-letter-llm-development-rails-master-key \
  --data-file=config/master.key

2. Google API Key

# Create secret for your Google AI API key
echo "your-google-ai-api-key" | gcloud secrets create cover-letter-llm-development-google-api-key \
  --data-file=-

3. Secret Key Base (Production)

# Generate a secret key base
SECRET_KEY_BASE=$(bundle exec rails secret)
echo $SECRET_KEY_BASE | gcloud secrets create cover-letter-llm-production-secret-key-base \
  --data-file=-

GitHub Actions Setup

Repository Secrets

Add these secrets to your GitHub repository:

Development:

Staging:

Production:

Repository Variables

Deployment Workflow

Development Deployment

  1. Push to terraform-infrastructure branch
  2. Automatic deployment happens via GitHub Actions
  3. Access: Use the Cloud Run URL provided in the output

Staging Deployment

  1. Merge PR to main branch
  2. Automatic deployment to staging
  3. Testing: Perform QA on staging environment

Production Deployment

  1. Manual trigger via GitHub Actions workflow dispatch
  2. Review and approve in GitHub environment
  3. Monitor deployment and application health

Monitoring and Alerting

Dashboards

Alerts

Automatic alerts are configured for:

Logs

Cost Optimization

Development

Staging

Production

Troubleshooting

Common Issues

1. Terraform State Lock

# If state is locked, force unlock (use carefully)
terraform force-unlock LOCK_ID

2. Service Account Permissions

# Check current permissions
gcloud projects get-iam-policy PROJECT_ID \
  --flatten="bindings[].members" \
  --format="table(bindings.role)" \
  --filter="bindings.members:terraform-deployer@PROJECT_ID.iam.gserviceaccount.com"

3. API Not Enabled

# Enable all required APIs
gcloud services enable compute.googleapis.com run.googleapis.com sqladmin.googleapis.com redis.googleapis.com secretmanager.googleapis.com storage.googleapis.com monitoring.googleapis.com logging.googleapis.com servicenetworking.googleapis.com

4. Insufficient Quota

5. Docker Build Issues

# Build and test locally
cd CoverLetterApp
docker build -t cover-letter-llm .
docker run -p 3000:3000 cover-letter-llm

Getting Help

Cleanup

Destroy Environment

# Destroy development environment
./terraform/deploy.sh development destroy --auto-approve

# Destroy staging environment
./terraform/deploy.sh staging destroy --auto-approve

# Destroy production environment (be very careful!)
./terraform/deploy.sh production destroy --auto-approve

Remove State Files

# Remove state files from GCS bucket
gsutil rm -r gs://your-company-terraform-state/cover-letter-llm/

Security Considerations

  1. Service Account Keys: Store securely, rotate regularly
  2. Secrets: Use Secret Manager, never commit to code
  3. Network Security: Use private networks, firewall rules
  4. Database: Private IP, encrypted at rest and in transit
  5. Monitoring: Enable audit logging, set up alerts
  6. Access Control: Use least privilege principles