Premium System Setup Guide
This guide covers the complete setup process for the Aleteia Premium subscription system, including all external services, environment variables, and local development configuration.
Prerequisites
Before starting, ensure you have:
- Ruby 3.3.9 or later
- Rails 7.0 or later
- PostgreSQL 14+
- Redis 6+
- Go 1.21+ (for compiling the Firebase link binary)
- Node.js 22+ (for frontend assets)
Quick Start
# 1. Start infrastructure services
docker compose up -d postgres redis firestore
# 2. Install dependencies
bundle install
# 3. Compile Go binary
cd firebase-link && ./compile-firebase && cd ..
# 4. Configure environment
cp example.env .env
# Edit .env with your credentials
# 5. Start the application
foreman start -f Procfile.dev
Environment Variables
Complete Reference
| Variable | Required | Description | Example |
|---|---|---|---|
STRIPE_SECRET_KEY | Yes | Stripe API secret key | sk_test_... or sk_live_... |
STRIPE_WEBHOOK_SECRET_V2 | Yes | Webhook signing secret | whsec_... |
GOOGLE_APPLICATION_CREDENTIALS | Yes* | Firebase/GCP credentials | See below |
GOOGLE_PROJECT_ID | Alt | Firebase project ID | aleteia-subscriptions |
GOOGLE_CLIENT_EMAIL | Alt | Service account email | [email protected] |
GOOGLE_PRIVATE_KEY | Alt | Service account private key | -----BEGIN PRIVATE KEY-----\n... |
FIRESTORE_PROJECT | No | Firestore project (defaults to Firebase project) | aleteia-subscriptions |
FIRESTORE_EMULATOR_HOST | No | Local emulator host | localhost:8000 |
SENDGRID_API_KEY | Yes | SendGrid API key | SG.xxx... |
FIREBASE_CONTINUE_URL | No | Password reset redirect URL | https://aleteia.org/login |
*Either GOOGLE_APPLICATION_CREDENTIALS OR the three GOOGLE_* variables must be set.
Example .env File
# Stripe Configuration
STRIPE_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET_V2=whsec_xxxxxxxxxxxxxxxxxxxxx
# Firebase/Google Cloud (Method 1: Inline JSON)
GOOGLE_APPLICATION_CREDENTIALS='{"type":"service_account","project_id":"aleteia-subscriptions","private_key_id":"abc123","private_key":"-----BEGIN PRIVATE KEY-----\nMIIEvgIBAD...\n-----END PRIVATE KEY-----\n","client_email":"[email protected]","client_id":"123456789","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token"}'
# OR Firebase/Google Cloud (Method 2: File path)
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json
# OR Firebase/Google Cloud (Method 3: Separate variables)
# GOOGLE_PROJECT_ID=aleteia-subscriptions
# GOOGLE_CLIENT_EMAIL=premium@aleteia-subscriptions.iam.gserviceaccount.com
# GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvgIBAD...\n-----END PRIVATE KEY-----\n"
# SendGrid
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxx
# Firebase Password Reset
FIREBASE_CONTINUE_URL=https://aleteia.org/login
# Development only
FIRESTORE_EMULATOR_HOST=localhost:8000
External Service Setup
1. Stripe Configuration
Create Webhook Endpoint
- Go to Stripe Dashboard > Developers > Webhooks
- Click Add endpoint
- Enter your webhook URL:
https://your-domain.com/stripe-webhook - Select events to listen for:
customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deleted
- Click Add endpoint
- Copy the Signing secret and set as
STRIPE_WEBHOOK_SECRET_V2
Configure Products
- Go to Products in Stripe Dashboard
- Create a new product for each plan tier
- Add required metadata:
{
"platform": "premium",
"tier": "essential",
"name": "Premium Essential",
"locale": "it"
}
- Create a price for the product (monthly/yearly)
2. Firebase Project Setup
Create Firebase Project
- Go to Firebase Console
- Click Add project
- Enter project name:
aleteia-subscriptions - Disable Google Analytics (optional)
- Click Create project
Enable Authentication
- In Firebase Console, go to Authentication
- Click Get started
- Enable Email/Password provider
- Configure Authorized domains:
- Add your production domain
- Add
localhostfor development
Create Service Account
- Go to Project Settings > Service accounts
- Click Generate new private key
- Save the JSON file securely
- Use contents for
GOOGLE_APPLICATION_CREDENTIALS
Configure Password Reset Template
- Go to Authentication > Templates
- Select Password reset
- Customize the email template
- Set Action URL (handled automatically by Firebase)
3. Firestore Setup
Enable Firestore
- In Firebase Console, go to Firestore Database
- Click Create database
- Select Start in production mode
- Choose a location (e.g.,
europe-west1)
Security Rules
Deploy these security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Users collection - only service account can write
match /users/{userId} {
// Allow read for authenticated users matching the document
allow read: if request.auth != null && request.auth.uid == userId;
// Only allow writes from server (service account)
allow write: if false;
}
}
}
Create Index
For querying users by email, create an index:
- Go to Firestore > Indexes
- Click Add index
- Collection:
users - Field:
email(Ascending)
4. SendGrid Setup
Create API Key
- Go to SendGrid Dashboard
- Navigate to Settings > API Keys
- Click Create API Key
- Select Full Access or Restricted Access with:
- Mail Send: Full Access
- Template Engine: Read Access
- Copy the API key and set as
SENDGRID_API_KEY
Create Dynamic Templates
Create templates following the naming convention:
| Template Name | Purpose |
|---|---|
PREMIUM-WELCOME-EN | English welcome email |
PREMIUM-WELCOME-IT | Italian welcome email |
PREMIUM-WELCOME-FR | French welcome email |
PREMIUM-GOODBYE-EN | English goodbye email |
PREMIUM-GOODBYE-IT | Italian goodbye email |
PREMIUM-GOODBYE-FR | French goodbye email |
For template content, see Email Notifications.
Local Development Setup
Docker Services
Start required services:
docker compose up -d postgres redis firestore
The docker-compose.yml includes:
services:
postgres:
image: postgres:14
ports:
- '5432:5432'
environment:
POSTGRES_PASSWORD: postgres
redis:
image: redis:7
ports:
- '6379:6379'
firestore:
image: gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators
command: gcloud emulators firestore start --host-port=0.0.0.0:8000
ports:
- '8000:8000'
environment:
FIRESTORE_PROJECT_ID: aleteia-subscriptions
Compile Go Binary
cd firebase-link
./compile-firebase
This creates bin/firebase-link used for password reset link generation.
Stripe CLI
For local webhook testing:
# Install Stripe CLI (macOS)
brew install stripe/stripe-cli/stripe
# Login
stripe login
# Forward webhooks
stripe listen --forward-to localhost:3000/stripe-webhook
The Stripe CLI is included in Procfile.dev:
web: bin/rails server
worker: bundle exec sidekiq
stripe: stripe listen --forward-to localhost:3000/stripe-webhook
Start Development Server
foreman start -f Procfile.dev
This starts:
- Rails server on port 3000
- Sidekiq for background jobs
- Stripe CLI for webhook forwarding
Production Deployment
Heroku Configuration
Set environment variables:
# Stripe
heroku config:set STRIPE_SECRET_KEY=sk_live_xxx
heroku config:set STRIPE_WEBHOOK_SECRET_V2=whsec_xxx
# Firebase (inline JSON for Heroku)
heroku config:set GOOGLE_APPLICATION_CREDENTIALS='{"type":"service_account",...}'
# SendGrid
heroku config:set SENDGRID_API_KEY=SG.xxx
# Firebase password reset
heroku config:set FIREBASE_CONTINUE_URL=https://aleteia.org/login
Verify Webhook Endpoint
After deploying:
- Go to Stripe Dashboard > Webhooks
- Select your endpoint
- Click Send test webhook
- Choose
customer.subscription.created - Verify successful delivery
Post-Deployment Checklist
- Environment variables set correctly
- Stripe webhook endpoint configured
- Firebase project configured
- Firestore security rules deployed
- SendGrid templates created
- Test subscription flow end-to-end
Troubleshooting
Common Issues
Webhook Signature Verification Failed
Symptom: Stripe::SignatureVerificationError
Solutions:
- Verify
STRIPE_WEBHOOK_SECRET_V2matches Stripe Dashboard - Check webhook URL is correct
- Ensure raw request body is not modified by middleware
Firebase Authentication Failed
Symptom: Google::Auth::CredentialsError
Solutions:
- Check
GOOGLE_APPLICATION_CREDENTIALSformat - Verify service account has required permissions
- For inline JSON, ensure proper escaping of newlines in private key
Firestore Connection Failed
Symptom: GRPC::Unavailable
Solutions:
- Check
FIRESTORE_EMULATOR_HOSTfor local development - Verify Firestore is enabled in Firebase Console
- Check service account has Firestore access
Password Reset Link Generation Failed
Symptom: TTY::Command::ExitError
Solutions:
- Verify
bin/firebase-linkexists and is executable - Check Go binary was compiled correctly
- Verify credentials can access Firebase Auth
Debug Mode
Enable verbose logging:
# Rails console
Rails.logger.level = :debug
# Or in .env
LOG_LEVEL=debug
Health Checks
Verify services are running:
# Rails console
# Check Stripe
Stripe::Account.retrieve
# => #<Stripe::Account id=acct_xxx>
# Check Firebase
firebase = Firebase::Admin::Auth.new
firebase.get_user_by_email('[email protected]')
# => #<Firebase::Admin::UserRecord> or raises NotFound
# Check Firestore
firestore = Google::Cloud::Firestore.new
firestore.col('users').limit(1).get
# => #<Google::Cloud::Firestore::QuerySnapshot>
# Check SendGrid
client = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'])
response = client.client.templates.get
# => #<SendGrid::Response>
Security Checklist
- All credentials stored in environment variables
-
.envfile in.gitignore - Stripe webhook signature verification enabled
- Firebase security rules restrict access
- Service account has minimal required permissions
- Production uses HTTPS
- Sensitive data not logged
Related Documentation
- Overview - System architecture overview
- Firebase Integration - Firebase details
- Stripe Integration - Stripe webhook handling
- Email Notifications - SendGrid templates