78731566c9
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
11 KiB
11 KiB
Migration Guide: Single-User to Multi-Tenant SaaS
This guide helps you migrate from the legacy single-user pop3_forwarder.py script to the new multi-tenant SaaS application.
Overview
The migration involves:
- Understanding the architectural changes
- Exporting existing configuration
- Setting up the new system
- Importing mail accounts
- Verifying functionality
- Decommissioning the old system
Architectural Changes
Before (Legacy)
- Single Docker container
- Environment variable configuration
- Direct POP3 fetching and SMTP forwarding
- No user accounts or authentication
- Limited to one Gmail destination
After (New System)
- Multi-container architecture (API, workers, database)
- Database-backed configuration
- User accounts with authentication
- Multiple users with separate configurations
- Web dashboard and API access
- Subscription tiers and limits
Prerequisites
- Access to existing
.envfile - Docker and Docker Compose installed
- Basic understanding of REST APIs
- Access to Google Cloud Console (for OAuth)
Step-by-Step Migration
Step 1: Backup Existing Configuration
# Save your existing .env file
cp .env .env.legacy.backup
# Document your mail accounts
cat .env | grep POP3_ACCOUNT
Step 2: Set Up New System
# Pull latest changes
git pull origin main
# Create new environment file
cp backend/.env.example backend/.env
# Generate secure keys
echo "SECRET_KEY=$(openssl rand -hex 32)" >> backend/.env
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> backend/.env
Step 3: Start New Services
# Start all services
docker-compose -f docker-compose.new.yml up -d
# Wait for services to be ready
sleep 10
# Run database migrations
docker-compose -f docker-compose.new.yml exec backend alembic upgrade head
Step 4: Create Your User Account
Option A: Via API
# Register a new user
curl -X POST http://localhost:8000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "your-email@example.com",
"password": "your-secure-password",
"full_name": "Your Name"
}'
# Login to get access token
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d "username=your-email@example.com&password=your-secure-password"
# Save the access_token from response
export TOKEN="your-access-token-here"
Option B: Via Google OAuth
- Set up Google OAuth credentials (see IMPLEMENTATION_GUIDE.md)
- Use the web interface or OAuth flow to register
Step 5: Import Mail Accounts
Create a migration script to import your existing accounts:
# Create migration script
cat > migrate_accounts.sh << 'EOF'
#!/bin/bash
TOKEN="your-access-token"
API_URL="http://localhost:8000/api/v1"
# Function to add a mail account
add_account() {
local name=$1
local host=$2
local port=$3
local user=$4
local pass=$5
local forward_to=$6
curl -X POST "$API_URL/mail-accounts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"name\": \"$name\",
\"email_address\": \"$user\",
\"protocol\": \"pop3_ssl\",
\"host\": \"$host\",
\"port\": $port,
\"use_ssl\": true,
\"use_tls\": false,
\"username\": \"$user\",
\"password\": \"$pass\",
\"forward_to\": \"$forward_to\",
\"is_enabled\": true,
\"check_interval_minutes\": 5,
\"max_emails_per_check\": 50,
\"delete_after_forward\": true
}"
echo ""
}
# Import accounts from old .env
# Account 1
add_account \
"My Email Account" \
"$POP3_ACCOUNT_1_HOST" \
"$POP3_ACCOUNT_1_PORT" \
"$POP3_ACCOUNT_1_USER" \
"$POP3_ACCOUNT_1_PASSWORD" \
"$GMAIL_DESTINATION"
# Account 2 (if exists)
if [ -n "$POP3_ACCOUNT_2_HOST" ]; then
add_account \
"Second Account" \
"$POP3_ACCOUNT_2_HOST" \
"$POP3_ACCOUNT_2_PORT" \
"$POP3_ACCOUNT_2_USER" \
"$POP3_ACCOUNT_2_PASSWORD" \
"$GMAIL_DESTINATION"
fi
# Add more accounts as needed...
EOF
chmod +x migrate_accounts.sh
# Source old environment and run migration
source .env.legacy.backup
./migrate_accounts.sh
Step 6: Verify Configuration
# List imported accounts
curl -X GET http://localhost:8000/api/v1/mail-accounts \
-H "Authorization: Bearer $TOKEN" | jq .
# Test connection for first account
curl -X POST http://localhost:8000/api/v1/mail-accounts/test \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d @test_connection.json
Step 7: Monitor Processing
# Check Celery worker logs
docker-compose -f docker-compose.new.yml logs -f celery-worker
# Watch for processing runs
watch -n 5 'curl -s -X GET http://localhost:8000/api/v1/mail-accounts \
-H "Authorization: Bearer $TOKEN" | jq ".[].last_check_at"'
Step 8: Parallel Testing (Recommended)
Run both systems in parallel for a few days:
# Keep old system running
docker-compose -f docker-compose.yml ps
# Run new system on different ports
# Edit docker-compose.new.yml to use port 8001 if needed
# Compare logs and results
diff <(docker-compose -f docker-compose.yml logs) \
<(docker-compose -f docker-compose.new.yml logs)
Step 9: Decommission Old System
Once confident the new system works:
# Stop old container
docker-compose -f docker-compose.yml down
# Archive old configuration
mkdir -p archive
mv pop3_forwarder.py archive/
mv .env.legacy.backup archive/
mv docker-compose.yml archive/docker-compose.legacy.yml
# Update main docker-compose
mv docker-compose.new.yml docker-compose.yml
Multi-User Migration
If migrating for multiple users (e.g., family members):
For Your Wife's Account
# She needs to register her own account
curl -X POST http://localhost:8000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "wife@example.com",
"password": "her-secure-password",
"full_name": "Wife Name"
}'
# She logs in to get her token
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d "username=wife@example.com&password=her-secure-password"
WIFE_TOKEN="her-access-token"
# Add her mail accounts using her token
curl -X POST http://localhost:8000/api/v1/mail-accounts \
-H "Authorization: Bearer $WIFE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Wife Email",
"email_address": "wife@provider.com",
"protocol": "pop3_ssl",
"host": "pop.provider.com",
"port": 995,
"use_ssl": true,
"username": "wife@provider.com",
"password": "her-email-password",
"forward_to": "wife@gmail.com",
"is_enabled": true
}'
Configuration Mapping
Environment Variables to Database
Legacy (.env) |
New System (Database) |
|---|---|
POP3_ACCOUNT_N_* |
mail_accounts table per user |
GMAIL_DESTINATION |
forward_to field in mail_accounts |
CHECK_INTERVAL_MINUTES |
Per-account check_interval_minutes |
MAX_EMAILS_PER_RUN |
Per-account max_emails_per_check |
SMTP_USER / SMTP_PASSWORD |
To be configured per user or globally |
Feature Mapping
| Legacy Feature | New Feature | Notes |
|---|---|---|
| Multiple POP3 accounts | Mail Accounts API | Per-user, unlimited (based on tier) |
| Single Gmail destination | Per-account forwarding | Each account can forward to different address |
| Fixed check interval | Configurable per account | More flexibility |
| Postmark notifications | Apprise notifications | More channels (Telegram, Slack, etc.) |
| Environment config | Database + Web UI | Easier management |
| No authentication | JWT + OAuth2 | Secure multi-user access |
| No user limits | Subscription tiers | Free: 1, Basic: 5, Pro: 20, Enterprise: 100 |
Troubleshooting Migration
Issue: Cannot connect to database
# Check database is running
docker-compose -f docker-compose.new.yml ps postgres
# Check connection
docker-compose -f docker-compose.new.yml exec postgres psql -U postgres -c "SELECT 1;"
Issue: Migrations fail
# Reset database (⚠️ deletes all data)
docker-compose -f docker-compose.new.yml down -v
docker-compose -f docker-compose.new.yml up -d postgres
sleep 5
docker-compose -f docker-compose.new.yml exec backend alembic upgrade head
Issue: Emails not being processed
# Check Celery worker
docker-compose -f docker-compose.new.yml logs celery-worker
# Manually trigger processing
curl -X POST http://localhost:8000/api/v1/admin/trigger-processing \
-H "Authorization: Bearer $TOKEN"
Issue: Authentication fails
# Verify token is valid
curl -X GET http://localhost:8000/api/v1/users/me \
-H "Authorization: Bearer $TOKEN"
# If expired, login again
curl -X POST http://localhost:8000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d "username=your-email&password=your-password"
Rollback Plan
If you need to rollback to the old system:
# Stop new system
docker-compose -f docker-compose.new.yml down
# Restore old configuration
cp archive/.env.legacy.backup .env
cp archive/docker-compose.legacy.yml docker-compose.yml
# Start old system
docker-compose up -d
# Verify it's working
docker-compose logs -f
Post-Migration Checklist
- All mail accounts imported and tested
- Email processing verified
- Notifications configured
- Old system stopped and archived
- Documentation updated
- Users trained on new interface
- Monitoring set up
- Backups configured
- SSL/TLS certificates installed (for production)
- OAuth credentials configured
Getting Help
If you encounter issues during migration:
- Check logs:
docker-compose -f docker-compose.new.yml logs - Review IMPLEMENTATION_GUIDE.md
- Check ARCHITECTURE.md for system overview
- Open an issue on GitHub with:
- Error messages
- Steps to reproduce
- Configuration (without passwords)
Benefits After Migration
- ✅ Multi-user support: Each user has own accounts
- ✅ Better security: Encrypted credentials, JWT auth
- ✅ Web interface: Easy configuration (when implemented)
- ✅ API access: Programmatic control
- ✅ Better monitoring: Statistics, logs per account
- ✅ Scalability: Can handle many users
- ✅ Subscription management: Monetization ready
- ✅ More protocols: POP3 and IMAP support
- ✅ Auto-detection: Server settings for common providers
- ✅ Flexible notifications: Multiple channels via Apprise
Need Help? Open an issue or discussion on GitHub!
Last Updated: 2026-02-01