-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
This page covers all environment variable configuration needed for your TableSlayer self-hosted deployment. Proper configuration is critical for all features to work correctly.
Create the production environment file:
# Navigate to deployment directory
cd apps/web/deployment
# Create production environment file
cp .env.example .env.production
# Edit the production file
nano .env.productionCopy this template into your .env.production file and replace all placeholder values:
# =================================================================
# DATABASE CONFIGURATION
# =================================================================
# Get these from: turso db show YOUR_DATABASE_NAME
# and: turso db tokens create YOUR_DATABASE_NAME
TURSO_API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
TURSO_APP_DB_AUTH_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
TURSO_APP_DB_URL=libsql://your-database-name.aws-eu-west-1.turso.io
# Leave these empty for single database setup
TURSO_GS_PARENT_DB_URL=
TURSO_GS_PARENT_DB_AUTH_TOKEN=
# =================================================================
# EMAIL CONFIGURATION
# =================================================================
# Get from: resend.com → API Keys
RESEND_TOKEN=re_123456789_abcdefghijklmnopqrstuvwxyz
DEV_EMAIL=admin@yourdomain.com
# =================================================================
# CLOUDFLARE R2 STORAGE CONFIGURATION
# =================================================================
# Get these from: Cloudflare Dashboard → R2 → Manage R2 API tokens
CLOUDFLARE_ACCOUNT_ID=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
CLOUDFLARE_R2_ACCESS_KEY=your_r2_access_key_id
CLOUDFLARE_R2_SECRET_KEY=your_r2_secret_access_key
CLOUDFLARE_R2_BUCKET_NAME=your-tableslayer-files
# Your custom R2 domain (setup in R2 bucket settings)
CLOUDFLARE_R2_PUBLIC_URL=https://files.yourdomain.com
PUBLIC_CLOUDFLARE_R2_URL=https://files.yourdomain.com
# =================================================================
# APPLICATION CONFIGURATION
# =================================================================
# Your primary domain
BASE_URL=https://yourdomain.com
# File upload size limit
BODY_SIZE_LIMIT=20M
# =================================================================
# GOOGLE OAUTH CONFIGURATION
# =================================================================
# Get from: Google Cloud Console → APIs & Services → Credentials
GOOGLE_CLIENT_ID=123456789012-abcdefghijklmnopqrstuvwxyz.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-AbCdEfGhIjKlMnOpQrStUvWxYz
# =================================================================
# PARTYKIT REAL-TIME CONFIGURATION
# =================================================================
# Get from: partykit deploy output
PUBLIC_PARTYKIT_HOST=your-project-name.your-username.partykit.dev
# =================================================================
# OPTIONAL: STRIPE PAYMENT CONFIGURATION
# =================================================================
# Leave dummy values if not using payments
STRIPE_API_KEY=sk_test_dummy_key_for_build_purposes_only
STRIPE_WEBHOOK_KEY=whsec_dummy_webhook_key
STRIPE_PRICE_ID_LIFETIME=price_dummy_lifetime_id
STRIPE_PRICE_ID_MONTHLY=price_dummy_monthly_id
STRIPE_PRICE_ID_YEARLY=price_dummy_yearly_id
# =================================================================
# OPTIONAL: MONITORING AND ANALYTICS
# =================================================================
# Sentry error tracking (optional)
SENTRY_DSN=
SENTRY_AUTH_TOKEN=
# =================================================================
# NODE.JS CONFIGURATION
# =================================================================
# Production environment
NODE_ENV=production
# Memory optimization (already set in Docker)
NODE_OPTIONS=--max-old-space-size=4096Required Values:
TURSO_API_TOKEN= # From: turso auth login
TURSO_APP_DB_AUTH_TOKEN= # From: turso db tokens create YOUR_DB
TURSO_APP_DB_URL= # From: turso db show YOUR_DBHow to Get These:
# Get API token (login token)
turso auth login
turso auth token
# Get database URL and create auth token
turso db show tableslayer-production
turso db tokens create tableslayer-productionRequired Values:
CLOUDFLARE_ACCOUNT_ID= # From R2 dashboard sidebar
CLOUDFLARE_R2_ACCESS_KEY= # From API tokens
CLOUDFLARE_R2_SECRET_KEY= # From API tokens
CLOUDFLARE_R2_BUCKET_NAME= # Your bucket name
CLOUDFLARE_R2_PUBLIC_URL= # Your custom domainFinding Account ID:
- Go to Cloudflare Dashboard
- Select your domain
- Look in the right sidebar for "Account ID"
Required Value:
PUBLIC_PARTYKIT_HOST=your-project.your-username.partykit.devHow to Get This:
cd apps/web
partykit deploy
# The deploy command outputs the URL
# Example: "Deployed to your-project.your-username.partykit.dev"Required Values:
GOOGLE_CLIENT_ID= # From Google Cloud Console
GOOGLE_CLIENT_SECRET= # From Google Cloud ConsoleFinding These Values:
- Go to Google Cloud Console
- Navigate to APIs & Services → Credentials
- Click on your OAuth 2.0 Client ID
- Copy Client ID and Client Secret
Secure your environment file:
# Set restrictive permissions
chmod 600 .env.production
# Verify permissions
ls -la .env.production
# Should show: -rw------- (600)# Create encrypted backup of environment file
gpg -c .env.production
# Creates: .env.production.gpg
# Store backup securely and delete original if neededCreate a validation script to check configuration:
File: scripts/validate-env.js
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const envFile = path.join(__dirname, '../apps/web/deployment/.env.production');
if (!fs.existsSync(envFile)) {
console.error('❌ .env.production file not found');
process.exit(1);
}
const envContent = fs.readFileSync(envFile, 'utf8');
const requiredVars = [
'TURSO_API_TOKEN',
'TURSO_APP_DB_AUTH_TOKEN',
'TURSO_APP_DB_URL',
'RESEND_TOKEN',
'CLOUDFLARE_ACCOUNT_ID',
'CLOUDFLARE_R2_ACCESS_KEY',
'CLOUDFLARE_R2_SECRET_KEY',
'CLOUDFLARE_R2_BUCKET_NAME',
'CLOUDFLARE_R2_PUBLIC_URL',
'BASE_URL',
'GOOGLE_CLIENT_ID',
'GOOGLE_CLIENT_SECRET',
'PUBLIC_PARTYKIT_HOST'
];
const missingVars = [];
const emptyVars = [];
requiredVars.forEach(varName => {
const regex = new RegExp(`^${varName}=(.*)$`, 'm');
const match = envContent.match(regex);
if (!match) {
missingVars.push(varName);
} else if (!match[1] || match[1].trim() === '' || match[1].includes('your_') || match[1].includes('yourdomain.com')) {
emptyVars.push(varName);
}
});
console.log('🔍 Environment Validation Results');
console.log('================================');
if (missingVars.length === 0 && emptyVars.length === 0) {
console.log('✅ All required environment variables are configured');
} else {
if (missingVars.length > 0) {
console.log('❌ Missing variables:');
missingVars.forEach(v => console.log(` - ${v}`));
}
if (emptyVars.length > 0) {
console.log('⚠️ Empty or placeholder variables:');
emptyVars.forEach(v => console.log(` - ${v}`));
}
console.log('\n💡 Please update your .env.production file before deployment');
process.exit(1);
}Run validation:
node scripts/validate-env.jsFor development, create .env.development:
# Development overrides
BASE_URL=http://localhost:5174
PUBLIC_PARTYKIT_HOST=localhost:1999
CLOUDFLARE_R2_PUBLIC_URL=http://localhost:3000/dev-files
# Keep production values for external services
TURSO_APP_DB_URL=libsql://dev-database.turso.io
# ... other production service configsFor staging/production separation:
Staging (.env.staging):
BASE_URL=https://staging.yourdomain.com
TURSO_APP_DB_URL=libsql://tableslayer-staging.turso.io
# ... staging-specific configsProduction (.env.production):
BASE_URL=https://yourdomain.com
TURSO_APP_DB_URL=libsql://tableslayer-production.turso.io
# ... production configsSymptoms: Can't connect to Turso database Solutions:
- Verify database URL format:
libsql://name.region.turso.io - Check auth token hasn't expired:
turso auth token - Ensure database exists:
turso db list
Symptoms: Images won't upload or display Solutions:
- Check R2 credentials are correct
- Verify bucket name matches exactly
- Ensure custom domain DNS is propagated
- Check CORS policy allows your domain
Symptoms: "OAuth error" during login Solutions:
- Verify redirect URIs match exactly (including https://)
- Check Google+ API is enabled
- Ensure client ID/secret are correct
Symptoms: Changes don't sync between users Solutions:
- Verify PartyKit host URL is accessible
- Check PartyKit deployment succeeded
- Ensure WebSocket connections aren't blocked
Symptoms: No signup/password reset emails Solutions:
- Check Resend API key is valid
- Verify domain is verified in Resend
- Check DEV_EMAIL is set to admin email
Test each service connection:
# Test Turso connection
turso db shell your-database "SELECT 1 as test;"
# Test R2 connection
curl -I https://files.yourdomain.com
# Test PartyKit connection
curl https://your-project.your-username.partykit.dev
# Test Resend (replace API_KEY)
curl -X POST https://api.resend.com/emails \
-H "Authorization: Bearer YOUR_RESEND_TOKEN" \
-H "Content-Type: application/json" \
-d '{"from":"test@yourdomain.com","to":"admin@yourdomain.com","subject":"Test","text":"Test"}'After deployment, verify health:
# Check application health endpoint
curl https://yourdomain.com/healthcheck
# Should return: {"status": "healthy"}Once configuration is complete and validated, proceed to Deployment to build and deploy your TableSlayer instance.
🔒 Security Reminder: Never commit .env.production to version control. Add it to your .gitignore file.