A complete, production-ready subscription content platform (OnlyFans-style) that you can host yourself
- What is StarNest?
- Features
- Tech Stack
- Prerequisites
- Installation Guide
- Configuration
- Usage Guide
- Deployment Options
- Troubleshooting
- Security
- Support
StarNest is a self-hosted subscription content platform that allows creators to monetize their content through paid subscriptions. Think of it as your own OnlyFans-style platform that you completely control and host yourself.
- Creator: The person who creates and sells content
- Subscriber: People who pay to access the creator's content
- Admin: Platform administrator who manages users and settings
- Free Content: Posts that anyone can view
- Paid Content: Posts that only paying subscribers can access
- 📝 Content Management: Create, edit, and schedule posts
- 🎥 Video Upload: Upload videos that are automatically converted to streaming format
- 🖼️ Image Support: Upload images to your posts
- 💬 Direct Messaging: Chat with your subscribers in real-time
- 📊 Analytics: View subscriber count and revenue statistics
- 🔒 Content Control: Mark content as free or paid
- 📱 Feed: Browse free and paid content (after subscribing)
- 💳 Easy Subscription: One-click subscription via Stripe
- 💬 Direct Chat: Message the creator directly
- 📺 Video Streaming: Watch videos with adaptive quality (auto-adjusts to your internet speed)
- 👥 User Management: View all users, ban/unban accounts
- 📈 Revenue Tracking: Monitor subscription revenue
- 🔐 Email 2FA: Secure admin access with email-based two-factor authentication
- 📋 Audit Logs: Track all admin actions
- 🛡️ Moderation Tools: Manage content and users
- 🔒 Row Level Security: Database-level security ensuring users only see what they should
- 🔐 Signed Video URLs: Videos are protected with time-limited, signed URLs
- ⚡ Real-time Chat: Instant messaging using WebSocket technology
- 🎬 HLS Video Streaming: Professional video streaming with multiple quality options
- 📧 Email Integration: Send emails for 2FA codes and notifications
- 🐳 Docker Ready: Everything runs in containers for easy deployment
- Next.js 14 - React framework with App Router
- TypeScript - Type-safe JavaScript
- Tailwind CSS - Utility-first CSS framework
- shadcn/ui - Beautiful, accessible UI components
- hls.js - HLS video player library
- Next.js API Routes - Server-side API endpoints
- Supabase (Self-hosted) - Authentication, database, storage, and real-time features
- GoTrue - Authentication service
- PostgREST - Auto-generated REST API
- Realtime - WebSocket-based real-time features
- Storage API - File storage service
- PostgreSQL 15 - Relational database
- Kong - API Gateway
- Docker & Docker Compose - Containerization
- Nginx - Web server for video streaming
- FFmpeg - Video transcoding (converts videos to streaming format)
- SMTP Server - Email delivery (MailHog for development)
- Stripe - Subscription and payment processing
- Row Level Security (RLS) - Database-level access control
- HMAC-Signed URLs - Secure video access
- Email 2FA - Two-factor authentication for admins
- JWT Tokens - Secure authentication tokens
Before you begin, make sure you have:
-
Docker Desktop (or Docker Engine + Docker Compose)
- Windows/Mac: Download from docker.com
- Linux: Install Docker Engine and Docker Compose
- Verify installation: Open terminal and run
docker --versionanddocker compose version
-
Git (to clone the repository)
- Download from git-scm.com
- Verify: Run
git --versionin terminal
-
A Text Editor (to edit configuration files)
- VS Code, Notepad++, or any text editor
-
Stripe Account (for payments)
- Sign up at stripe.com
- You'll need API keys from the Stripe Dashboard
-
Email Service (for production - optional for testing)
- Gmail, SendGrid, Mailgun, or any SMTP service
- For testing, MailHog is included (no setup needed)
- RAM: Minimum 4GB (8GB+ recommended)
- Storage: At least 20GB free space
- CPU: 2+ cores recommended
- Internet: Stable connection for downloading Docker images
Option A: Using Git (Recommended)
git clone https://github.com/yourusername/StarNest.git
cd StarNestOption B: Download ZIP
- Click "Code" → "Download ZIP" on GitHub
- Extract the ZIP file
- Open terminal/command prompt in the extracted folder
- Find the file named
.env.examplein the project folder - Copy it and rename the copy to
.env- Windows: Right-click → Copy → Paste → Rename to
.env - Mac/Linux: Run
cp .env.example .envin terminal
- Windows: Right-click → Copy → Paste → Rename to
Open the .env file in a text editor. You'll see many variables. Here's what you need to set:
# Database Password (generate a strong password)
POSTGRES_PASSWORD=your-very-secure-password-here-min-32-characters
# JWT Secret (generate a random string)
SUPABASE_JWT_SECRET=generate-random-string-here-at-least-32-characters
# Video Signing Secret (generate a random string)
VIDEO_SIGNING_SECRET=another-random-string-here-at-least-32-charactersHow to Generate Random Strings:
Windows (PowerShell):
-join ((65..90) + (97..122) + (48..57) | Get-Random -Count 32 | % {[char]$_})Mac/Linux:
openssl rand -base64 32Online Tool: Use random.org to generate random strings
- Go to Stripe Dashboard
- Click "Developers" → "API keys"
- Copy your keys:
STRIPE_SECRET_KEY=sk_test_... (or sk_live_... for production)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_... (or pk_live_... for production)- Create a product and price:
- Go to "Products" → "Add product"
- Set price (e.g., $9.99/month)
- Copy the Price ID (starts with
price_)
STRIPE_PRICE_ID=price_xxxxxxxxxxxxx- Set up webhook (after deployment):
- Go to "Developers" → "Webhooks"
- Add endpoint:
https://your-domain.com/api/stripe/webhook - Select events:
checkout.session.completed,customer.subscription.updated,customer.subscription.deleted - Copy webhook secret:
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxUsing Gmail:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password # Use App Password, not regular password
SMTP_FROM_EMAIL=your-email@gmail.comUsing SendGrid:
SMTP_HOST=smtp.sendgrid.net
SMTP_PORT=587
SMTP_USER=apikey
SMTP_PASSWORD=your-sendgrid-api-key
SMTP_FROM_EMAIL=noreply@yourdomain.comFor Testing (MailHog - No Configuration Needed):
SMTP_HOST=smtp-server
SMTP_PORT=587
SMTP_USER=noreply@starnest.local
SMTP_PASSWORD=any-password
SMTP_FROM_EMAIL=noreply@starnest.localSITE_NAME=StarNest
SITE_DOMAIN=localhost # Change to your domain for production
SITE_LOGO_URL=/logo.png
SITE_PRIMARY_COLOR=#6366f1CREATOR_DISPLAY_NAME=Your Creator Name
CREATOR_BIO=Welcome to my exclusive content!
CREATOR_AVATAR_URL=/avatar.jpg
CREATOR_BANNER_URL=/banner.jpgADMIN_EMAIL=admin@yourdomain.com
ADMIN_2FA_CODE_EXPIRY_SECONDS=600 # 10 minutesYou need to generate Supabase keys. For now, use these placeholder values (we'll explain how to generate proper ones):
SUPABASE_URL=http://supabase-kong:8000
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IUNote: These are example keys. In production, generate unique keys matching your JWT secret.
NEXT_PUBLIC_SUPABASE_URL=http://localhost:8000
NEXT_PUBLIC_SUPABASE_ANON_KEY=same-as-SUPABASE_ANON_KEY-above-
Open Terminal/Command Prompt in the StarNest folder
-
Start all services:
docker compose up -dThis command:
- Downloads all required Docker images (may take 5-10 minutes first time)
- Starts all services (database, API, frontend, etc.)
- Sets up the database automatically
- Wait for services to start (check status):
docker compose psAll services should show "Up" status. If any show "Restarting" or "Exited", check logs:
docker compose logs [service-name]- Check if services are running:
docker psYou should see containers named:
starnest-postgresstarnest-authstarnest-storagestarnest-realtimestarnest-reststarnest-kongstarnest-nextjsstarnest-nginxstarnest-ffmpegstarnest-smtp
-
Access the platform:
- Open browser: http://localhost:3000
- You should see the login page
-
Check MailHog (for testing emails):
- Open: http://localhost:8025
- This is where test emails will appear
-
Sign up via the web interface:
- Go to http://localhost:3000/auth/login
- Click "Sign up" (if available) or use the API
-
Or create via API:
curl -X POST http://localhost:8000/auth/v1/signup \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "SecurePassword123!"
}'- Set admin role:
# Windows (PowerShell)
docker exec -it starnest-postgres psql -U postgres -d postgres -c "UPDATE profiles SET role = 'admin' WHERE email = 'admin@example.com';"
# Mac/Linux
docker exec -it starnest-postgres psql -U postgres -d postgres -c "UPDATE profiles SET role = 'admin' WHERE email = 'admin@example.com';"-
Sign up creator account (same as admin, but different email)
-
Set creator role:
docker exec -it starnest-postgres psql -U postgres -d postgres -c "UPDATE profiles SET role = 'creator' WHERE email = 'creator@example.com';"Migrations run automatically on first start. To manually run:
# Check if migrations ran
docker exec -it starnest-postgres psql -U postgres -d postgres -c "\dt"
# You should see tables: profiles, posts, media, subscriptions, conversations, messages, etc.- Go to http://localhost:3000/auth/login
- Enter your admin email and password
- You'll receive a 6-digit code via email (check MailHog at http://localhost:8025)
- Enter the code to access admin dashboard
- User Management: View all users, see subscription status, ban/unban users
- Revenue Tracking: See total subscriptions and revenue
- Audit Logs: View all admin actions
- Go to Admin Dashboard
- Find the user in the list
- Click "Ban" button
- Optionally add a reason
- User will immediately lose access to all content
- Go to http://localhost:3000/auth/login
- Enter creator email and password
- You'll be redirected to Creator Dashboard
- Click "Create Post" button
- Enter title and content
- Choose "Free" or "Paid" content
- Upload images or videos
- Click "Save" or "Publish"
- When creating a post, click "Upload Video"
- Select video file (MP4, MOV, etc.)
- Video will be automatically:
- Uploaded to server
- Converted to streaming format (HLS)
- Available in multiple qualities (480p, 720p, 1080p)
- This process may take a few minutes depending on video size
- Go to "Messages" section in Creator Dashboard
- See list of conversations with subscribers
- Click on a conversation to open chat
- Type and send messages
- Messages are delivered in real-time
- Go to http://localhost:3000/auth/login
- Click "Sign up" (if available)
- Enter email and password
- Verify email (check MailHog)
- Go to Feed page
- Click "Subscribe" button
- You'll be redirected to Stripe checkout
- Enter payment details (use test card:
4242 4242 4242 4242) - Complete payment
- You now have access to paid content!
- Free Posts: Visible to everyone
- Paid Posts: Only visible after subscribing
- Videos: Click to play, quality adjusts automatically
- After subscribing, go to Feed page
- Click "Message Creator" or similar button
- Start conversation
- Messages are real-time
Perfect for VPS providers like DigitalOcean, Linode, Vultr, etc.
- VPS with Ubuntu 20.04+ or similar Linux distribution
- At least 4GB RAM, 2 CPU cores, 50GB storage
- Domain name (optional but recommended)
- Connect to your VPS:
ssh root@your-server-ip- Install Docker:
# Update system
apt update && apt upgrade -y
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
# Install Docker Compose
apt install docker-compose-plugin -y
# Verify
docker --version
docker compose version- Clone StarNest:
git clone https://github.com/yourusername/StarNest.git
cd StarNest- Configure environment:
cp .env.example .env
nano .env # Edit with your valuesImportant changes for production:
SITE_DOMAIN=yourdomain.com
SMTP_HOST=smtp.gmail.com # Or your SMTP provider
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
# ... other production values- Set up SSL with Nginx Reverse Proxy:
Install Nginx:
apt install nginx certbot python3-certbot-nginx -yCreate Nginx config (/etc/nginx/sites-available/starnest):
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}Enable site:
ln -s /etc/nginx/sites-available/starnest /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginxGet SSL certificate:
certbot --nginx -d yourdomain.com- Start StarNest:
docker compose up -d- Set up automatic backups (recommended):
# Create backup script
cat > /root/backup-starnest.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/root/backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Backup database
docker exec starnest-postgres pg_dump -U postgres postgres > $BACKUP_DIR/db_$DATE.sql
# Backup volumes (optional)
# docker run --rm -v starnest_postgres_data:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/volumes_$DATE.tar.gz /data
# Keep only last 7 days
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
EOF
chmod +x /root/backup-starnest.sh
# Add to crontab (daily at 2 AM)
(crontab -l 2>/dev/null; echo "0 2 * * * /root/backup-starnest.sh") | crontab -Coolify is a self-hosted alternative to Vercel/Netlify that makes deployment easier.
- A server with Docker installed
- Coolify installed (see coolify.io/docs)
-
Create New Project in Coolify:
- Go to your Coolify dashboard
- Click "New Project"
- Name it "StarNest"
-
Add New Resource → Docker Compose:
- Click "Add Resource" → "Docker Compose"
- Connect your Git repository or upload files
-
Configure Environment Variables:
- In Coolify, go to your project settings
- Add all environment variables from
.env.example - Set production values
-
Deploy:
- Click "Deploy"
- Coolify will build and start all containers
- Access via the provided domain
-
Set up Domain:
- In Coolify, go to "Domains"
- Add your custom domain
- SSL will be automatically configured
-
Configure Stripe Webhook:
- Use Coolify's provided domain:
https://your-app.coolify-domain.com/api/stripe/webhook - Add this URL in Stripe Dashboard → Webhooks
- Use Coolify's provided domain:
Railway is a cloud platform that makes deployment simple.
-
Create Railway Account:
- Sign up at railway.app
- Connect GitHub account
-
Create New Project:
- Click "New Project"
- Select "Deploy from GitHub repo"
- Choose StarNest repository
-
Add Docker Compose:
- Railway will detect
docker-compose.yml - Configure environment variables in Railway dashboard
- Railway will detect
-
Deploy:
- Railway will automatically deploy
- Get your domain from Railway dashboard
- Create Account: Sign up at digitalocean.com
- Create App: Go to App Platform → Create App
- Connect Repository: Link your GitHub repo
- Configure:
- Select "Docker Compose" as source
- Add environment variables
- Set resource limits
- Deploy: Click "Deploy"
Problem: Containers keep restarting or won't start
Solution:
# Check logs
docker compose logs
# Check specific service
docker compose logs postgres
docker compose logs nextjs
# Common issues:
# 1. Port already in use
# Solution: Change ports in docker-compose.yml or stop conflicting services
# 2. Environment variables missing
# Solution: Check .env file has all required variables
# 3. Database connection failed
# Solution: Verify POSTGRES_PASSWORD matches in all servicesProblem: http://localhost:3000 shows error or won't load
Solution:
# Check if Next.js container is running
docker ps | grep nextjs
# Check Next.js logs
docker logs starnest-nextjs
# Restart Next.js
docker compose restart nextjsProblem: "Connection refused" or "Authentication failed"
Solution:
# Check PostgreSQL is running
docker ps | grep postgres
# Test connection
docker exec -it starnest-postgres psql -U postgres -d postgres -c "SELECT 1;"
# Check password
# Verify POSTGRES_PASSWORD in .env matches in docker-compose.ymlProblem: Video player shows error or won't load
Solution:
# Check FFmpeg transcoding
docker logs starnest-ffmpeg
# Check if HLS files exist
docker exec -it starnest-ffmpeg ls -la /processed/
# Check Nginx
docker logs starnest-nginx
# Verify video upload completed
# Check uploads directory
docker exec -it starnest-nextjs ls -la /app/uploadsProblem: 2FA codes not received
Solution:
# Check SMTP container
docker logs starnest-smtp
# For testing, check MailHog: http://localhost:8025
# For production, verify SMTP settings:
# - SMTP_HOST is correct
# - SMTP_PORT is correct (587 for TLS, 465 for SSL)
# - SMTP_USER and SMTP_PASSWORD are correct
# - For Gmail, use App Password, not regular passwordProblem: Subscriptions not activating after payment
Solution:
-
Verify webhook URL:
- Must be accessible from internet
- Use HTTPS in production
- Format:
https://yourdomain.com/api/stripe/webhook
-
Check webhook secret:
- Copy from Stripe Dashboard → Webhooks → Your endpoint → Signing secret
- Must match
STRIPE_WEBHOOK_SECRETin.env
-
Check webhook logs:
docker logs starnest-nextjs | grep webhook -
Test webhook:
- In Stripe Dashboard → Webhooks → Your endpoint → "Send test webhook"
Problem: Containers crash with memory errors
Solution:
# Check memory usage
docker stats
# Increase Docker memory limit:
# Docker Desktop → Settings → Resources → Memory
# Set to at least 4GB (8GB recommended)
# Or reduce resource usage:
# - Limit video file sizes
# - Reduce number of concurrent transcodesProblem: "Port is already allocated" error
Solution:
# Find what's using the port
# Windows
netstat -ano | findstr :3000
# Mac/Linux
lsof -i :3000
# Stop the conflicting service or change port in docker-compose.yml- Changed all default passwords
- Generated unique, strong secrets (32+ characters)
- Set up production SMTP (not MailHog)
- Configured SSL/TLS certificates
- Set up firewall rules (only allow ports 80, 443, 22)
- Enabled automatic security updates
- Set up regular database backups
- Configured rate limiting
- Reviewed and tested RLS policies
- Set secure CORS policies
- Disabled debug mode in production
- Set up monitoring and alerts
-
Keep Secrets Secret:
- Never commit
.envfile to Git - Use environment variables, not hardcoded values
- Rotate secrets regularly
- Never commit
-
Database Security:
- Use strong PostgreSQL password
- Limit database access to application only
- Regular backups
-
Network Security:
- Use firewall to restrict access
- Only expose necessary ports
- Use VPN for admin access if possible
-
Application Security:
- Keep Docker images updated
- Regularly update dependencies
- Monitor logs for suspicious activity
- ARCHITECTURE.md - Detailed system architecture
- SETUP.md - Advanced setup instructions
- QUICKSTART.md - Quick start guide
- PROJECT_STRUCTURE.md - File structure explanation
# View all logs
docker compose logs -f
# Restart all services
docker compose restart
# Stop all services
docker compose down
# Stop and remove volumes (WARNING: deletes data)
docker compose down -v
# Update and restart
git pull
docker compose build
docker compose up -d
# Backup database
docker exec starnest-postgres pg_dump -U postgres postgres > backup.sql
# Restore database
docker exec -i starnest-postgres psql -U postgres postgres < backup.sql-
Check Logs First:
docker compose logs [service-name]
-
Check Documentation:
- Read ARCHITECTURE.md for system details
- Read SETUP.md for advanced configuration
-
Common Issues:
- See Troubleshooting section above
- Check GitHub Issues (if public)
This project is proprietary. All rights reserved.
Built with:
- Next.js
- Supabase
- Stripe
- Docker
- And many other open-source projects
Made with ❤️ for creators who want control