Update wiki
This commit is contained in:
@@ -1,228 +0,0 @@
|
||||
---
|
||||
title: Database Setup
|
||||
description: Configure and manage your PostgreSQL database
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- PostgreSQL 14 or higher
|
||||
- Database created
|
||||
- Database user with permissions
|
||||
|
||||
## Installation
|
||||
|
||||
### Using Docker
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name plunk-postgres \
|
||||
-e POSTGRES_PASSWORD=your-password \
|
||||
-e POSTGRES_DB=plunk \
|
||||
-p 5432:5432 \
|
||||
-v postgres_data:/var/lib/postgresql/data \
|
||||
postgres:14
|
||||
```
|
||||
|
||||
### Using Package Manager
|
||||
|
||||
#### Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install postgresql postgresql-contrib
|
||||
```
|
||||
|
||||
#### macOS
|
||||
|
||||
```bash
|
||||
brew install postgresql@14
|
||||
brew services start postgresql@14
|
||||
```
|
||||
|
||||
## Database Creation
|
||||
|
||||
```sql
|
||||
CREATE DATABASE plunk;
|
||||
CREATE USER plunk WITH ENCRYPTED PASSWORD 'your-password';
|
||||
GRANT ALL PRIVILEGES ON DATABASE plunk TO plunk;
|
||||
```
|
||||
|
||||
## Connection String
|
||||
|
||||
```bash
|
||||
DATABASE_URL="postgresql://plunk:your-password@localhost:5432/plunk"
|
||||
DIRECT_DATABASE_URL="postgresql://plunk:your-password@localhost:5432/plunk"
|
||||
```
|
||||
|
||||
## Running Migrations
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
yarn workspace @plunk/db migrate:dev
|
||||
```
|
||||
|
||||
### Production
|
||||
|
||||
```bash
|
||||
yarn workspace @plunk/db migrate:prod
|
||||
```
|
||||
|
||||
## Database Schema
|
||||
|
||||
Plunk uses Prisma ORM. The schema is located at:
|
||||
```
|
||||
packages/db/prisma/schema.prisma
|
||||
```
|
||||
|
||||
### Core Tables
|
||||
|
||||
- **User**: User accounts
|
||||
- **Project**: Workspaces/tenants
|
||||
- **Membership**: User-project relationships
|
||||
- **Contact**: Email contacts
|
||||
- **Template**: Email templates
|
||||
- **Campaign**: Email campaigns
|
||||
- **Workflow**: Automated sequences
|
||||
- **Email**: Email tracking
|
||||
- **Event**: Custom events
|
||||
|
||||
## Indexes
|
||||
|
||||
Important indexes for performance:
|
||||
|
||||
```sql
|
||||
-- Contact email index (unique per project)
|
||||
CREATE INDEX idx_contact_email ON "Contact" (email, "projectId");
|
||||
|
||||
-- Contact subscription index
|
||||
CREATE INDEX idx_contact_subscribed ON "Contact" (subscribed);
|
||||
|
||||
-- Email tracking indexes
|
||||
CREATE INDEX idx_email_contact ON "Email" ("contactId");
|
||||
CREATE INDEX idx_email_created ON "Email" ("createdAt");
|
||||
|
||||
-- Event indexes
|
||||
CREATE INDEX idx_event_contact ON "Event" ("contactId");
|
||||
CREATE INDEX idx_event_name ON "Event" (event);
|
||||
```
|
||||
|
||||
## Performance Tuning
|
||||
|
||||
### For Large Datasets (1M+ contacts)
|
||||
|
||||
```sql
|
||||
-- Increase shared buffers (25% of RAM)
|
||||
ALTER SYSTEM SET shared_buffers = '2GB';
|
||||
|
||||
-- Increase work memory
|
||||
ALTER SYSTEM SET work_mem = '50MB';
|
||||
|
||||
-- Increase maintenance work memory
|
||||
ALTER SYSTEM SET maintenance_work_mem = '512MB';
|
||||
|
||||
-- Enable parallel queries
|
||||
ALTER SYSTEM SET max_parallel_workers_per_gather = 4;
|
||||
|
||||
-- Reload configuration
|
||||
SELECT pg_reload_conf();
|
||||
```
|
||||
|
||||
### Vacuum and Analyze
|
||||
|
||||
Run regularly for optimal performance:
|
||||
|
||||
```bash
|
||||
# Manual vacuum
|
||||
vacuumdb --analyze --verbose plunk
|
||||
|
||||
# Auto-vacuum (enabled by default)
|
||||
```
|
||||
|
||||
## Backup and Restore
|
||||
|
||||
### Backup
|
||||
|
||||
```bash
|
||||
pg_dump -U plunk -d plunk > backup-$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
### Restore
|
||||
|
||||
```bash
|
||||
psql -U plunk -d plunk < backup.sql
|
||||
```
|
||||
|
||||
### Automated Backups
|
||||
|
||||
Set up cron job:
|
||||
|
||||
```bash
|
||||
0 2 * * * pg_dump -U plunk plunk > /backups/plunk-$(date +\%Y\%m\%d).sql
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Connection Count
|
||||
|
||||
```sql
|
||||
SELECT count(*) FROM pg_stat_activity;
|
||||
```
|
||||
|
||||
### Database Size
|
||||
|
||||
```sql
|
||||
SELECT pg_size_pretty(pg_database_size('plunk'));
|
||||
```
|
||||
|
||||
### Table Sizes
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
schemaname,
|
||||
tablename,
|
||||
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) AS size
|
||||
FROM pg_tables
|
||||
WHERE schemaname = 'public'
|
||||
ORDER BY pg_total_relation_size(schemaname || '.' || tablename) DESC;
|
||||
```
|
||||
|
||||
### Slow Queries
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
query,
|
||||
calls,
|
||||
total_time,
|
||||
mean_time
|
||||
FROM pg_stat_statements
|
||||
ORDER BY mean_time DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection refused
|
||||
|
||||
Check PostgreSQL is running:
|
||||
```bash
|
||||
sudo systemctl status postgresql
|
||||
```
|
||||
|
||||
### Authentication failed
|
||||
|
||||
Verify credentials in connection string.
|
||||
|
||||
### Too many connections
|
||||
|
||||
Increase max_connections:
|
||||
```sql
|
||||
ALTER SYSTEM SET max_connections = 200;
|
||||
SELECT pg_reload_conf();
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configure email delivery](/self-hosting/email-setup)
|
||||
- [Deploy with Docker](/self-hosting/docker)
|
||||
- [Environment variables](/self-hosting/environment-variables)
|
||||
@@ -1,394 +1,82 @@
|
||||
---
|
||||
title: Docker Deployment
|
||||
description: Deploy Plunk with Docker Compose
|
||||
description: Deploy with Docker Compose
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker installed
|
||||
- Docker Compose installed
|
||||
- Git installed
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Clone Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/useplunk/plunk.git
|
||||
cd plunk
|
||||
```
|
||||
|
||||
### 2. Copy Environment File
|
||||
|
||||
```bash
|
||||
cp .env.self-host.example .env
|
||||
```
|
||||
|
||||
### 3. Configure Environment
|
||||
|
||||
Edit `.env` and configure required variables:
|
||||
|
||||
```bash
|
||||
# Database Password (PostgreSQL)
|
||||
DB_PASSWORD="changeme123"
|
||||
|
||||
# JWT Secret (generate with: openssl rand -base64 32)
|
||||
JWT_SECRET="your-secret-here"
|
||||
|
||||
# Domains (for subdomain-based routing)
|
||||
API_DOMAIN="api.localhost"
|
||||
DASHBOARD_DOMAIN="app.localhost"
|
||||
LANDING_DOMAIN="www.localhost"
|
||||
WIKI_DOMAIN="docs.localhost"
|
||||
|
||||
# Set to 'true' for HTTPS in production
|
||||
USE_HTTPS="false"
|
||||
|
||||
# AWS SES (for email sending)
|
||||
AWS_SES_REGION="us-east-1"
|
||||
AWS_SES_ACCESS_KEY_ID="your-access-key"
|
||||
AWS_SES_SECRET_ACCESS_KEY="your-secret-key"
|
||||
SES_CONFIGURATION_SET="plunk-configuration-set"
|
||||
|
||||
# S3-compatible storage (Minio is included by default)
|
||||
# Leave defaults unless using external S3
|
||||
S3_ENDPOINT="http://minio:9000"
|
||||
S3_ACCESS_KEY_ID="plunk"
|
||||
S3_ACCESS_KEY_SECRET="plunkminiopass"
|
||||
S3_BUCKET="uploads"
|
||||
S3_PUBLIC_URL="http://localhost:9000/uploads"
|
||||
S3_FORCE_PATH_STYLE="true"
|
||||
```
|
||||
|
||||
### 4. Start Services
|
||||
|
||||
```bash
|
||||
# Edit .env (see Environment Variables)
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
This starts:
|
||||
- PostgreSQL database
|
||||
- Redis
|
||||
- Minio (S3-compatible storage)
|
||||
- Plunk application (all services in one container with nginx)
|
||||
- API server
|
||||
- Worker process
|
||||
- Web dashboard
|
||||
- Landing page
|
||||
- Documentation
|
||||
See [Environment Variables](/self-hosting/environment-variables) for all configuration options.
|
||||
|
||||
### 5. Access Services
|
||||
## Services
|
||||
|
||||
The services are available at the configured domains:
|
||||
- **Dashboard**: `http://app.localhost` (or your configured domain)
|
||||
- **API**: `http://api.localhost`
|
||||
- **Landing**: `http://www.localhost`
|
||||
- **Docs**: `http://docs.localhost`
|
||||
- **Minio Console**: `http://localhost:9001`
|
||||
| Service | Purpose |
|
||||
|---------|---------|
|
||||
| `plunk` | All apps + nginx (API, Web, Landing, Wiki, SMTP) |
|
||||
| `postgres` | PostgreSQL 16 database |
|
||||
| `redis` | Redis 7 queue |
|
||||
| `minio` | S3-compatible storage |
|
||||
| `ntfy` | Notifications |
|
||||
|
||||
Create your first account and start sending emails!
|
||||
## Ports
|
||||
|
||||
## Docker Compose Configuration
|
||||
| Port | Service |
|
||||
|------|---------|
|
||||
| 80 | Nginx (HTTP) |
|
||||
| 465 | SMTP (implicit TLS) |
|
||||
| 587 | SMTP (STARTTLS) |
|
||||
| 9000 | Minio API |
|
||||
| 9001 | Minio Console |
|
||||
|
||||
The `docker-compose.yml` file uses the pre-built Plunk image from GitHub Container Registry:
|
||||
## Running Individual Services
|
||||
|
||||
Set `SERVICE` environment variable:
|
||||
|
||||
```bash
|
||||
SERVICE=api # API only
|
||||
SERVICE=worker # Worker only
|
||||
SERVICE=web # Dashboard only
|
||||
SERVICE=all # Everything (default)
|
||||
```
|
||||
|
||||
## SMTP TLS Certificates
|
||||
|
||||
For TLS on ports 465/587, provide certificates via one of these methods:
|
||||
|
||||
### Traefik acme.json (Dokploy, Coolify)
|
||||
|
||||
Mount the `acme.json` file and set `SMTP_DOMAIN`:
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: plunk-postgres
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: plunk
|
||||
POSTGRES_USER: plunk
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme123}
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
networks:
|
||||
- plunk
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: plunk-redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly yes
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
networks:
|
||||
- plunk
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
container_name: plunk-minio
|
||||
restart: unless-stopped
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-plunk}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-plunkminiopass}
|
||||
volumes:
|
||||
- minio_data:/data
|
||||
ports:
|
||||
- "9000:9000" # API
|
||||
- "9001:9001" # Console
|
||||
networks:
|
||||
- plunk
|
||||
|
||||
plunk:
|
||||
image: ghcr.io/useplunk/plunk:latest
|
||||
container_name: plunk
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
SERVICE: all # Runs all services (API, Worker, Web, Landing, Wiki)
|
||||
DATABASE_URL: postgresql://plunk:${DB_PASSWORD}@postgres:5432/plunk
|
||||
REDIS_URL: redis://redis:6379
|
||||
JWT_SECRET: ${JWT_SECRET}
|
||||
# Domain configuration for subdomain routing
|
||||
API_DOMAIN: ${API_DOMAIN:-api.localhost}
|
||||
DASHBOARD_DOMAIN: ${DASHBOARD_DOMAIN:-app.localhost}
|
||||
LANDING_DOMAIN: ${LANDING_DOMAIN:-www.localhost}
|
||||
WIKI_DOMAIN: ${WIKI_DOMAIN:-docs.localhost}
|
||||
USE_HTTPS: ${USE_HTTPS:-false}
|
||||
# AWS SES
|
||||
AWS_SES_REGION: ${AWS_SES_REGION}
|
||||
AWS_SES_ACCESS_KEY_ID: ${AWS_SES_ACCESS_KEY_ID}
|
||||
AWS_SES_SECRET_ACCESS_KEY: ${AWS_SES_SECRET_ACCESS_KEY}
|
||||
# S3/Minio storage
|
||||
S3_ENDPOINT: ${S3_ENDPOINT:-http://minio:9000}
|
||||
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:-plunk}
|
||||
S3_ACCESS_KEY_SECRET: ${S3_ACCESS_KEY_SECRET:-plunkminiopass}
|
||||
ports:
|
||||
- "465:465" # SMTP (implicit TLS)
|
||||
- "587:587" # SMTP (STARTTLS)
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- minio
|
||||
networks:
|
||||
- plunk
|
||||
|
||||
environment:
|
||||
SMTP_DOMAIN: "smtp.yourdomain.com"
|
||||
volumes:
|
||||
postgres_data:
|
||||
redis_data:
|
||||
minio_data:
|
||||
plunk_data:
|
||||
|
||||
networks:
|
||||
plunk:
|
||||
driver: bridge
|
||||
- /path/to/acme.json:/certs/acme.json:ro
|
||||
```
|
||||
|
||||
**Note**: The Plunk image contains all applications (API, Worker, Web, Landing, Wiki) and uses nginx for subdomain-based routing.
|
||||
Plunk automatically extracts the certificate for `SMTP_DOMAIN` from acme.json.
|
||||
|
||||
## Production Deployment
|
||||
### PEM Files
|
||||
|
||||
### Using Pre-built Image
|
||||
Mount certificate files directly:
|
||||
|
||||
The easiest way to deploy is using the pre-built image from GitHub Container Registry:
|
||||
|
||||
```bash
|
||||
docker pull ghcr.io/useplunk/plunk:latest
|
||||
docker compose up -d
|
||||
```yaml
|
||||
volumes:
|
||||
- /path/to/privkey.pem:/certs/privkey.pem:ro
|
||||
- /path/to/fullchain.pem:/certs/fullchain.pem:ro
|
||||
```
|
||||
|
||||
### Building Your Own Image
|
||||
If no certificates are mounted, SMTP runs without TLS.
|
||||
|
||||
If you want to build from source:
|
||||
## Building from Source
|
||||
|
||||
```bash
|
||||
docker build -t plunk:custom .
|
||||
```
|
||||
|
||||
Then update `docker-compose.yml` to use your custom image:
|
||||
```yaml
|
||||
plunk:
|
||||
image: plunk:custom
|
||||
# ... rest of configuration
|
||||
```
|
||||
|
||||
### Security Hardening
|
||||
|
||||
1. **Use strong passwords**
|
||||
```bash
|
||||
DB_PASSWORD=$(openssl rand -base64 32)
|
||||
JWT_SECRET=$(openssl rand -base64 32)
|
||||
```
|
||||
|
||||
2. **Use HTTPS**
|
||||
- Set `USE_HTTPS=true` in your `.env`
|
||||
- Set up reverse proxy (Traefik, Caddy, or nginx)
|
||||
- Configure SSL certificates (Let's Encrypt)
|
||||
|
||||
3. **Configure domains**
|
||||
```bash
|
||||
API_DOMAIN=api.yourdomain.com
|
||||
DASHBOARD_DOMAIN=app.yourdomain.com
|
||||
LANDING_DOMAIN=www.yourdomain.com
|
||||
WIKI_DOMAIN=docs.yourdomain.com
|
||||
USE_HTTPS=true
|
||||
```
|
||||
|
||||
4. **Restrict network access**
|
||||
- Don't expose database and Redis ports publicly
|
||||
- Use internal Docker networks
|
||||
- Only expose port 80/443 (via reverse proxy) and SMTP ports
|
||||
|
||||
5. **Regular backups**
|
||||
- Database backups (automated via cron)
|
||||
- Minio data backups
|
||||
|
||||
### Scaling
|
||||
|
||||
The Plunk image runs all services in a single container by default. For higher scale:
|
||||
|
||||
#### Separate Services
|
||||
|
||||
You can run services separately by setting the `SERVICE` environment variable:
|
||||
|
||||
```yaml
|
||||
# API only
|
||||
plunk-api:
|
||||
image: ghcr.io/useplunk/plunk:latest
|
||||
environment:
|
||||
SERVICE: api
|
||||
# ... configuration
|
||||
|
||||
# Worker only
|
||||
plunk-worker:
|
||||
image: ghcr.io/useplunk/plunk:latest
|
||||
environment:
|
||||
SERVICE: worker
|
||||
# ... configuration
|
||||
|
||||
# Web only
|
||||
plunk-web:
|
||||
image: ghcr.io/useplunk/plunk:latest
|
||||
environment:
|
||||
SERVICE: web
|
||||
# ... configuration
|
||||
```
|
||||
|
||||
#### Scale Workers
|
||||
|
||||
For higher email throughput, run multiple worker containers:
|
||||
|
||||
```bash
|
||||
docker compose up -d --scale plunk-worker=3
|
||||
```
|
||||
|
||||
#### External Services
|
||||
|
||||
For production at scale, use managed services:
|
||||
- Managed PostgreSQL (AWS RDS, DigitalOcean, Supabase)
|
||||
- Managed Redis (AWS ElastiCache, Redis Cloud, Upstash)
|
||||
- AWS S3 (instead of Minio)
|
||||
|
||||
## Maintenance
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# All services
|
||||
docker compose logs -f
|
||||
|
||||
# Specific service
|
||||
docker compose logs -f plunk
|
||||
docker compose logs -f postgres
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
docker compose restart plunk
|
||||
```
|
||||
|
||||
### Update Plunk
|
||||
|
||||
Pull the latest image and restart:
|
||||
|
||||
```bash
|
||||
docker compose pull plunk
|
||||
docker compose up -d plunk
|
||||
```
|
||||
|
||||
If you built from source:
|
||||
```bash
|
||||
git pull
|
||||
docker build -t plunk:custom .
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Backup Database
|
||||
|
||||
```bash
|
||||
docker compose exec postgres pg_dump -U plunk plunk > backup-$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
### Restore Database
|
||||
|
||||
```bash
|
||||
docker compose exec -T postgres psql -U plunk plunk < backup.sql
|
||||
```
|
||||
|
||||
### Backup Minio Data
|
||||
|
||||
```bash
|
||||
docker compose exec minio mc alias set local http://localhost:9000 plunk plunkminiopass
|
||||
docker compose exec minio mc mirror local/uploads /backups/minio
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Services won't start
|
||||
|
||||
Check logs:
|
||||
```bash
|
||||
docker compose logs plunk
|
||||
```
|
||||
|
||||
### Database connection errors
|
||||
|
||||
Ensure DATABASE_URL is correct and database is running:
|
||||
```bash
|
||||
docker compose ps postgres
|
||||
docker compose exec postgres psql -U plunk -d plunk -c "SELECT 1;"
|
||||
```
|
||||
|
||||
### Worker not processing jobs
|
||||
|
||||
Check Plunk container logs for worker output:
|
||||
```bash
|
||||
docker compose logs plunk | grep worker
|
||||
```
|
||||
|
||||
Verify Redis connection:
|
||||
```bash
|
||||
docker compose exec redis redis-cli PING
|
||||
```
|
||||
|
||||
### Cannot access services
|
||||
|
||||
Check that your domains resolve correctly:
|
||||
```bash
|
||||
# For local development with *.localhost domains, these should work automatically
|
||||
# For production domains, ensure DNS is configured correctly
|
||||
curl http://api.localhost
|
||||
curl http://app.localhost
|
||||
```
|
||||
|
||||
### Minio not accessible
|
||||
|
||||
Check Minio is running:
|
||||
```bash
|
||||
docker compose ps minio
|
||||
docker compose logs minio
|
||||
```
|
||||
|
||||
Access Minio console at `http://localhost:9001` with credentials from `.env`.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Configure environment variables](/self-hosting/environment-variables)
|
||||
- [Set up email delivery](/self-hosting/email-setup)
|
||||
- [Database setup and migrations](/self-hosting/database-setup)
|
||||
|
||||
@@ -1,218 +1,92 @@
|
||||
---
|
||||
title: Email Setup (AWS SES)
|
||||
description: Configure AWS SES for email delivery
|
||||
title: AWS SES Setup
|
||||
description: Configure email delivery
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
## 1. Create IAM User
|
||||
|
||||
- AWS account
|
||||
- AWS SES access
|
||||
- Domain ownership (for custom domains)
|
||||
1. Go to IAM Console → Users → Create user
|
||||
2. Name: `plunk-ses`
|
||||
3. Attach a custom policy with required permissions (see below)
|
||||
4. Create access keys → Save credentials
|
||||
|
||||
## AWS SES Setup
|
||||
### Required IAM Policy
|
||||
|
||||
### 1. Create AWS Account
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"ses:SetIdentityMailFromDomain",
|
||||
"ses:GetIdentityDkimAttributes",
|
||||
"ses:SendRawEmail",
|
||||
"ses:GetIdentityVerificationAttributes",
|
||||
"ses:VerifyDomainDkim",
|
||||
"ses:ListIdentities",
|
||||
"ses:SetIdentityFeedbackForwardingEnabled"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Sign up at [aws.amazon.com](https://aws.amazon.com)
|
||||
## 2. Request Production Access
|
||||
|
||||
### 2. Request Production Access
|
||||
SES starts in sandbox mode (verified addresses only).
|
||||
|
||||
By default, SES is in sandbox mode (limited to verified addresses).
|
||||
|
||||
1. Go to AWS SES Console
|
||||
1. Go to SES Console
|
||||
2. Click "Request production access"
|
||||
3. Fill out the form
|
||||
4. Wait for approval (usually 24-48 hours)
|
||||
3. Wait for approval (24-48 hours)
|
||||
|
||||
### 3. Create IAM User
|
||||
## 3. Verify Domain
|
||||
|
||||
Create dedicated IAM user for Plunk:
|
||||
1. SES Console → Verified Identities → Create identity
|
||||
2. Choose "Domain" → Enter your domain
|
||||
3. Add DNS records provided by AWS
|
||||
4. Wait for verification
|
||||
|
||||
1. Go to IAM Console
|
||||
2. Create new user: "plunk-ses"
|
||||
3. Attach policy: `AmazonSESFullAccess`
|
||||
4. Create access keys
|
||||
5. Save access key ID and secret key
|
||||
## 4. Enable DKIM (Recommended)
|
||||
|
||||
### 4. Configure Environment Variables
|
||||
1. SES Console → Verified Identities → Your domain
|
||||
2. Enable "Easy DKIM"
|
||||
3. Add the 3 CNAME records to your DNS
|
||||
|
||||
## 5. Create SNS Topic
|
||||
|
||||
1. Go to SNS Console → Topics → Create topic
|
||||
2. Type: Standard
|
||||
3. Name: `plunk-ses-events`
|
||||
4. Create topic
|
||||
5. Create subscription:
|
||||
- Protocol: HTTPS
|
||||
- Endpoint: `https://api.yourdomain.com/webhooks/sns`
|
||||
6. Plunk automatically confirms the subscription. If it fails, check your logs for the confirmation URL.
|
||||
|
||||
## 6. Create Configuration Sets
|
||||
|
||||
### Tracking Configuration Set
|
||||
|
||||
1. SES Console → Configuration sets → Create set
|
||||
2. Name: `plunk-tracking`
|
||||
3. Add event destination:
|
||||
- Name: `sns-events`
|
||||
- Event types: **Sends, Deliveries, Opens, Clicks, Bounces, Complaints**
|
||||
- Destination: SNS → Select `plunk-ses-events` topic
|
||||
|
||||
### No-Tracking Configuration Set
|
||||
|
||||
1. Create another set named `plunk-no-tracking`
|
||||
2. Add event destination with only: **Sends, Deliveries, Bounces, Complaints**
|
||||
|
||||
## 7. Configure Environment
|
||||
|
||||
```bash
|
||||
AWS_SES_REGION="us-east-1"
|
||||
AWS_SES_ACCESS_KEY_ID="your-access-key-id"
|
||||
AWS_SES_SECRET_ACCESS_KEY="your-secret-access-key"
|
||||
```
|
||||
|
||||
## Verify Email Addresses
|
||||
|
||||
### Single Email
|
||||
|
||||
```bash
|
||||
aws ses verify-email-identity --email-address [email protected]
|
||||
```
|
||||
|
||||
Check your inbox and click verification link.
|
||||
|
||||
### Domain Verification
|
||||
|
||||
1. Go to SES Console → Verified Identities
|
||||
2. Click "Create identity"
|
||||
3. Choose "Domain"
|
||||
4. Enter your domain: `yourdomain.com`
|
||||
5. Add DNS records provided by AWS
|
||||
|
||||
DNS records (example):
|
||||
```
|
||||
Type: TXT
|
||||
Name: _amazonses.yourdomain.com
|
||||
Value: provided-by-aws
|
||||
```
|
||||
|
||||
Wait for verification (up to 72 hours).
|
||||
|
||||
## Configuration Sets
|
||||
|
||||
Create configuration sets for tracking:
|
||||
|
||||
### 1. Tracking Configuration Set
|
||||
|
||||
```bash
|
||||
aws ses create-configuration-set \
|
||||
--configuration-set-name plunk-tracking
|
||||
```
|
||||
|
||||
### 2. No-Tracking Configuration Set
|
||||
|
||||
```bash
|
||||
aws ses create-configuration-set \
|
||||
--configuration-set-name plunk-no-tracking
|
||||
```
|
||||
|
||||
### 3. Update Environment
|
||||
|
||||
```bash
|
||||
AWS_SES_ACCESS_KEY_ID="your-access-key"
|
||||
AWS_SES_SECRET_ACCESS_KEY="your-secret-key"
|
||||
SES_CONFIGURATION_SET="plunk-tracking"
|
||||
SES_CONFIGURATION_SET_NO_TRACKING="plunk-no-tracking"
|
||||
```
|
||||
|
||||
## SNS for Email Events
|
||||
|
||||
Set up SNS to receive email events (opens, clicks, bounces):
|
||||
|
||||
### 1. Create SNS Topic
|
||||
|
||||
```bash
|
||||
aws sns create-topic --name plunk-email-events
|
||||
```
|
||||
|
||||
### 2. Subscribe Plunk Webhook
|
||||
|
||||
```bash
|
||||
aws sns subscribe \
|
||||
--topic-arn arn:aws:sns:us-east-1:123456789:plunk-email-events \
|
||||
--protocol https \
|
||||
--notification-endpoint https://api.yourdomain.com/webhooks/sns
|
||||
```
|
||||
|
||||
### 3. Configure SES Event Publishing
|
||||
|
||||
1. Go to SES Console → Configuration Sets
|
||||
2. Select `plunk-tracking`
|
||||
3. Add destination → SNS
|
||||
4. Select your SNS topic
|
||||
5. Enable events: Delivery, Bounce, Complaint, Open, Click
|
||||
|
||||
## DKIM Setup
|
||||
|
||||
Enable DKIM signing for better deliverability:
|
||||
|
||||
1. Go to SES Console → Verified Identities
|
||||
2. Select your domain
|
||||
3. Enable "Easy DKIM"
|
||||
4. Add CNAME records to your DNS
|
||||
|
||||
```
|
||||
Type: CNAME
|
||||
Name: xxx._domainkey.yourdomain.com
|
||||
Value: xxx.dkim.amazonses.com
|
||||
```
|
||||
|
||||
Repeat for all 3 CNAME records provided.
|
||||
|
||||
## Testing Email Delivery
|
||||
|
||||
```bash
|
||||
curl -X POST {{API_URL}}/v1/send \
|
||||
-H "Authorization: Bearer sk_your_secret_key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"to": "[email protected]",
|
||||
"subject": "Test Email",
|
||||
"body": "Hello from Plunk!",
|
||||
"subscribed": true
|
||||
}'
|
||||
```
|
||||
|
||||
Check AWS SES Console → Email sending → Sending statistics.
|
||||
|
||||
## Monitoring
|
||||
|
||||
### SES Dashboard
|
||||
|
||||
View in AWS Console:
|
||||
- Sends
|
||||
- Bounces
|
||||
- Complaints
|
||||
- Reputation
|
||||
|
||||
### CloudWatch Metrics
|
||||
|
||||
Set up alarms for:
|
||||
- Bounce rate > 5%
|
||||
- Complaint rate > 0.1%
|
||||
- Send quota utilization > 80%
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Emails in sandbox mode only
|
||||
|
||||
Request production access via SES Console.
|
||||
|
||||
### Domain not verified
|
||||
|
||||
Check DNS records and wait for propagation (up to 72 hours).
|
||||
|
||||
### High bounce rate
|
||||
|
||||
- Clean your contact list
|
||||
- Use double opt-in
|
||||
- Remove hard bounces immediately
|
||||
|
||||
### Low reputation score
|
||||
|
||||
- Reduce bounce and complaint rates
|
||||
- Send only to engaged users
|
||||
- Implement feedback loops
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Warm up gradually**: Start with low volume, increase slowly
|
||||
2. **Monitor metrics**: Watch bounces and complaints closely
|
||||
3. **Clean lists**: Remove inactive and bounced addresses
|
||||
4. **Use DKIM**: Enable for better deliverability
|
||||
5. **Segment sends**: Don't send same content to everyone
|
||||
|
||||
## Cost Optimization
|
||||
|
||||
- First 62,000 emails/month: **FREE** (from EC2)
|
||||
- Additional: **$0.10 per 1,000 emails**
|
||||
- Data transfer: **$0.12 per GB**
|
||||
|
||||
Example:
|
||||
- 100,000 emails/month: ~$3.80/month
|
||||
- 1,000,000 emails/month: ~$94/month
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Complete environment setup](/self-hosting/environment-variables)
|
||||
- [Deploy with Docker](/self-hosting/docker)
|
||||
- [Send your first email](/getting-started/quick-start)
|
||||
|
||||
@@ -1,182 +1,66 @@
|
||||
---
|
||||
title: Environment Variables
|
||||
description: Complete environment variable reference
|
||||
description: Configuration reference
|
||||
---
|
||||
|
||||
## Required Variables
|
||||
|
||||
### Database
|
||||
## Required
|
||||
|
||||
```bash
|
||||
# PostgreSQL connection string
|
||||
DATABASE_URL="postgresql://user:password@host:5432/plunk"
|
||||
|
||||
# Direct connection (for Prisma migrations)
|
||||
DIRECT_DATABASE_URL="postgresql://user:password@host:5432/plunk"
|
||||
```
|
||||
|
||||
### Redis
|
||||
|
||||
```bash
|
||||
# Redis connection URL
|
||||
REDIS_URL="redis://host:6379"
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
```bash
|
||||
# JWT signing secret (generate with: openssl rand -base64 32)
|
||||
JWT_SECRET="your-secret-here"
|
||||
```
|
||||
|
||||
### AWS SES (Email Delivery)
|
||||
|
||||
```bash
|
||||
AWS_SES_REGION="us-east-1"
|
||||
AWS_SES_ACCESS_KEY_ID="your-access-key"
|
||||
AWS_SES_SECRET_ACCESS_KEY="your-secret-key"
|
||||
|
||||
# SES Configuration Sets
|
||||
SES_CONFIGURATION_SET="plunk-tracking"
|
||||
SES_CONFIGURATION_SET_NO_TRACKING="plunk-no-tracking"
|
||||
```
|
||||
|
||||
### Application URLs
|
||||
|
||||
```bash
|
||||
# Protocol configuration (auto-generates URIs with http:// or https://)
|
||||
USE_HTTPS="false" # Set to "true" for HTTPS in production
|
||||
|
||||
# Application URIs (auto-generated from domains if not set)
|
||||
API_URI="https://api.yourdomain.com"
|
||||
DASHBOARD_URI="https://app.yourdomain.com"
|
||||
LANDING_URI="https://www.yourdomain.com"
|
||||
|
||||
# For Next.js (build time)
|
||||
NEXT_PUBLIC_API_URI="https://api.yourdomain.com"
|
||||
NEXT_PUBLIC_DASHBOARD_URI="https://app.yourdomain.com"
|
||||
NEXT_PUBLIC_LANDING_URI="https://www.yourdomain.com"
|
||||
```
|
||||
|
||||
**Note**: When using domain-based configuration (e.g., `API_DOMAIN=api.yourdomain.com`), the application URIs are automatically generated. Set `USE_HTTPS=true` to use HTTPS protocol, otherwise HTTP will be used by default. You can also manually set the full URIs to override the auto-generation.
|
||||
|
||||
## Optional Variables
|
||||
|
||||
### Plunk API
|
||||
|
||||
If you're using the email package's `sendEmail` function to send emails via the Plunk API:
|
||||
|
||||
```bash
|
||||
# Plunk API Key (obtained from dashboard)
|
||||
PLUNK_API_KEY="sk_your_secret_key"
|
||||
```
|
||||
|
||||
### S3-Compatible Storage (Minio)
|
||||
|
||||
**Note**: When using Docker Compose, Minio is included and these variables are automatically configured with defaults. You typically don't need to set these unless you want to use external S3 storage.
|
||||
|
||||
```bash
|
||||
# Only configure if NOT using the bundled Minio
|
||||
S3_ENDPOINT="http://minio:9000" # Default: uses bundled Minio
|
||||
S3_ACCESS_KEY_ID="plunk" # Default: plunk
|
||||
S3_ACCESS_KEY_SECRET="plunkminiopass" # Default: plunkminiopass
|
||||
S3_BUCKET="uploads" # Default: uploads
|
||||
S3_PUBLIC_URL="http://localhost:9000/uploads" # Default: Minio URL
|
||||
S3_FORCE_PATH_STYLE="true" # Required for Minio
|
||||
```
|
||||
|
||||
### OAuth Providers
|
||||
|
||||
```bash
|
||||
# GitHub OAuth
|
||||
GITHUB_OAUTH_CLIENT="your-client-id"
|
||||
GITHUB_OAUTH_SECRET="your-client-secret"
|
||||
|
||||
# Google OAuth
|
||||
GOOGLE_OAUTH_CLIENT="your-client-id"
|
||||
GOOGLE_OAUTH_SECRET="your-client-secret"
|
||||
```
|
||||
|
||||
### Stripe Billing
|
||||
|
||||
```bash
|
||||
STRIPE_SK="sk_test_..."
|
||||
STRIPE_WEBHOOK_SECRET="whsec_..."
|
||||
|
||||
# Stripe Products
|
||||
STRIPE_PRICE_ONBOARDING="price_..."
|
||||
STRIPE_PRICE_EMAIL_USAGE="price_..."
|
||||
|
||||
# Stripe Metering
|
||||
STRIPE_METER_EVENT_NAME="email_sent"
|
||||
```
|
||||
|
||||
### Internal
|
||||
|
||||
```bash
|
||||
# Node environment
|
||||
NODE_ENV="production"
|
||||
```
|
||||
|
||||
## Example .env File
|
||||
|
||||
```bash
|
||||
# Database
|
||||
DATABASE_URL="postgresql://postgres:password@localhost:5432/plunk"
|
||||
DIRECT_DATABASE_URL="postgresql://postgres:password@localhost:5432/plunk"
|
||||
|
||||
# Redis
|
||||
REDIS_URL="redis://localhost:6379"
|
||||
|
||||
# Security
|
||||
JWT_SECRET="generated-secret-here"
|
||||
JWT_SECRET="your-secret" # openssl rand -base64 32
|
||||
DB_PASSWORD="your-password"
|
||||
|
||||
# Database (auto-configured in Docker)
|
||||
DATABASE_URL="postgresql://plunk:password@postgres:5432/plunk"
|
||||
REDIS_URL="redis://redis:6379"
|
||||
|
||||
# AWS SES
|
||||
AWS_SES_REGION="us-east-1"
|
||||
AWS_SES_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
|
||||
AWS_SES_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
|
||||
AWS_SES_ACCESS_KEY_ID="your-key"
|
||||
AWS_SES_SECRET_ACCESS_KEY="your-secret"
|
||||
SES_CONFIGURATION_SET="plunk-tracking"
|
||||
SES_CONFIGURATION_SET_NO_TRACKING="plunk-no-tracking"
|
||||
|
||||
# Protocol & URLs
|
||||
USE_HTTPS="false"
|
||||
API_URI="http://localhost:3001"
|
||||
DASHBOARD_URI="http://localhost:3000"
|
||||
LANDING_URI="http://localhost:3002"
|
||||
|
||||
# Next.js Public URLs
|
||||
NEXT_PUBLIC_API_URI="http://localhost:3001"
|
||||
NEXT_PUBLIC_DASHBOARD_URI="http://localhost:3000"
|
||||
NEXT_PUBLIC_LANDING_URI="http://localhost:3002"
|
||||
|
||||
# Node Environment
|
||||
NODE_ENV="development"
|
||||
```
|
||||
|
||||
## Generating Secrets
|
||||
|
||||
### JWT Secret
|
||||
## Domains
|
||||
|
||||
```bash
|
||||
openssl rand -base64 32
|
||||
# Subdomains for routing
|
||||
API_DOMAIN="api.yourdomain.com"
|
||||
DASHBOARD_DOMAIN="app.yourdomain.com"
|
||||
LANDING_DOMAIN="www.yourdomain.com"
|
||||
WIKI_DOMAIN="docs.yourdomain.com"
|
||||
SMTP_DOMAIN="smtp.yourdomain.com"
|
||||
|
||||
# Protocol
|
||||
USE_HTTPS="true" # false for local dev
|
||||
```
|
||||
|
||||
### Strong Passwords
|
||||
## Storage (Minio)
|
||||
|
||||
Defaults work with bundled Minio. Only set for external S3:
|
||||
|
||||
```bash
|
||||
openssl rand -base64 24
|
||||
S3_ENDPOINT="http://minio:9000"
|
||||
S3_ACCESS_KEY_ID="plunk"
|
||||
S3_ACCESS_KEY_SECRET="plunkminiopass"
|
||||
S3_BUCKET="uploads"
|
||||
S3_PUBLIC_URL="http://localhost:9000/uploads"
|
||||
S3_FORCE_PATH_STYLE="true"
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
## Optional
|
||||
|
||||
1. **Never commit secrets** to version control
|
||||
2. **Use environment-specific files** (.env.production, .env.development)
|
||||
3. **Rotate secrets regularly**
|
||||
4. **Use secret management** (AWS Secrets Manager, HashiCorp Vault) in production
|
||||
5. **Limit access** to production environment variables
|
||||
```bash
|
||||
# OAuth
|
||||
GITHUB_OAUTH_CLIENT="client-id"
|
||||
GITHUB_OAUTH_SECRET="client-secret"
|
||||
GOOGLE_OAUTH_CLIENT="client-id"
|
||||
GOOGLE_OAUTH_SECRET="client-secret"
|
||||
|
||||
## Next Steps
|
||||
# Stripe
|
||||
STRIPE_SK="sk_..."
|
||||
STRIPE_WEBHOOK_SECRET="whsec_..."
|
||||
|
||||
- [Set up database](/self-hosting/database-setup)
|
||||
- [Configure email delivery](/self-hosting/email-setup)
|
||||
- [Deploy with Docker](/self-hosting/docker)
|
||||
# Notifications
|
||||
NTFY_URL="http://ntfy/plunk-notifications"
|
||||
```
|
||||
|
||||
@@ -1,151 +1,35 @@
|
||||
---
|
||||
title: Self-Hosting Introduction
|
||||
title: Self-Hosting
|
||||
description: Deploy Plunk on your own infrastructure
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Plunk is fully open-source and can be self-hosted on your own infrastructure. This gives you complete control over your data, email delivery, and infrastructure costs.
|
||||
|
||||
## Requirements
|
||||
|
||||
### System Requirements
|
||||
|
||||
- **Node.js**: Version 20 or higher
|
||||
- **PostgreSQL**: Version 14 or higher
|
||||
- **Redis**: Version 6 or higher
|
||||
- **Docker** (recommended): For easy deployment
|
||||
|
||||
### AWS Services
|
||||
|
||||
- **AWS SES** (Required): For email sending
|
||||
- **AWS S3** (Optional): For asset storage (Minio is included by default)
|
||||
|
||||
### Minimum Server Specs
|
||||
|
||||
For small to medium usage (up to 100K contacts):
|
||||
- **CPU**: 1-2 cores
|
||||
- **RAM**: 2GB
|
||||
- **Storage**: 10GB (grows with contact data)
|
||||
|
||||
For larger scale (1M+ contacts):
|
||||
- **CPU**: 2-4 cores
|
||||
- **RAM**: 4GB
|
||||
- **Storage**: 50GB+
|
||||
|
||||
## Architecture Components
|
||||
|
||||
Plunk uses a containerized architecture with the following components:
|
||||
|
||||
### 1. Plunk Application Container
|
||||
Single container running all application services (API, Worker, Web, Landing, Wiki) with nginx reverse proxy for subdomain-based routing.
|
||||
|
||||
**Resources**: 1GB RAM, 1 CPU core (can scale up as needed)
|
||||
|
||||
**Services included**:
|
||||
- **API Server**: Express.js application handling HTTP requests
|
||||
- **Worker Process**: BullMQ worker processing background jobs
|
||||
- **Web Dashboard**: Next.js application for the UI
|
||||
- **Landing Page**: Marketing website
|
||||
- **Documentation**: Wiki/docs site
|
||||
- **SMTP Relay**: Email relay server (ports 465, 587)
|
||||
|
||||
**Note**: Services can be run separately by setting the `SERVICE` environment variable (`api`, `worker`, `web`, `landing`, `wiki`, or `all`).
|
||||
|
||||
### 2. PostgreSQL Database
|
||||
Stores all data (contacts, campaigns, workflows, etc.).
|
||||
|
||||
**Resources**: 512MB-1GB RAM, SSD storage recommended
|
||||
|
||||
### 3. Redis
|
||||
Queue system for background jobs (BullMQ).
|
||||
|
||||
**Resources**: 256MB-512MB RAM
|
||||
|
||||
### 4. Minio (S3-compatible Storage)
|
||||
Object storage for file uploads and assets.
|
||||
|
||||
**Resources**: 256MB-512MB RAM, storage for uploaded files
|
||||
|
||||
## Deployment Options
|
||||
|
||||
### Docker Compose (Recommended)
|
||||
|
||||
Easiest way to get started. Includes all services pre-configured.
|
||||
|
||||
[View Docker Guide](/self-hosting/docker)
|
||||
|
||||
### Kubernetes
|
||||
|
||||
For production deployments at scale.
|
||||
|
||||
### Manual Deployment
|
||||
|
||||
Deploy each component separately on your infrastructure.
|
||||
- Docker and Docker Compose
|
||||
- AWS SES account (for sending emails)
|
||||
- Domain name (for production)
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. Clone the repository
|
||||
2. Copy `.env.self-host.example` to `.env`
|
||||
3. Configure environment variables (see [Environment Variables](/self-hosting/environment-variables))
|
||||
4. Run `docker compose up -d`
|
||||
5. Access dashboard at `http://app.localhost` (or your configured domain)
|
||||
```bash
|
||||
git clone https://github.com/useplunk/plunk.git
|
||||
cd plunk
|
||||
cp .env.self-host.example .env
|
||||
# Edit .env with your settings
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## What's Included
|
||||
## Access
|
||||
|
||||
- ✅ Full API server
|
||||
- ✅ Worker process
|
||||
- ✅ Web dashboard
|
||||
- ✅ PostgreSQL database
|
||||
- ✅ Redis queue
|
||||
- ✅ All features (campaigns, workflows, segments)
|
||||
- ✅ No feature limitations
|
||||
- ✅ No phone-home telemetry
|
||||
|
||||
## What's Not Included
|
||||
|
||||
- ❌ Managed infrastructure
|
||||
- ❌ Automatic updates
|
||||
- ❌ Support (community only)
|
||||
- ❌ SLA guarantees
|
||||
|
||||
## Cost Considerations
|
||||
|
||||
### AWS SES Costs
|
||||
|
||||
- First 62,000 emails/month: **FREE** (when sent from EC2)
|
||||
- Additional emails: **$0.10 per 1,000 emails**
|
||||
|
||||
### Infrastructure Costs
|
||||
|
||||
**All-in-One VPS** (recommended for small to medium usage):
|
||||
- **Single VPS**: $5-12/month (2GB RAM, services like DigitalOcean, Hetzner, Vultr)
|
||||
- Runs all containers (Plunk, PostgreSQL, Redis, Minio)
|
||||
- **AWS SES**: $0-10/month (depends on volume)
|
||||
- **Storage**: Included in VPS
|
||||
|
||||
**Total**: ~$5-20/month for self-hosting
|
||||
|
||||
**Managed Services** (for larger scale or production):
|
||||
- **VPS**: $10-20/month (4GB RAM for Plunk application)
|
||||
- **Managed PostgreSQL**: $10-15/month (512MB-1GB)
|
||||
- **Managed Redis**: $5-10/month (256MB-512MB)
|
||||
- **AWS SES**: $10-50/month (depends on volume)
|
||||
- **AWS S3**: $1-5/month (if not using Minio)
|
||||
|
||||
**Total**: ~$35-100/month for production with managed services
|
||||
|
||||
## Support
|
||||
|
||||
### Community Support
|
||||
|
||||
- GitHub Issues
|
||||
- Community Forum
|
||||
- Documentation
|
||||
| Service | URL |
|
||||
|---------|-----|
|
||||
| Dashboard | http://app.localhost |
|
||||
| API | http://api.localhost |
|
||||
| Docs | http://docs.localhost |
|
||||
| Minio Console | http://localhost:9001 |
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Deploy with Docker](/self-hosting/docker)
|
||||
- [Configure environment variables](/self-hosting/environment-variables)
|
||||
- [Set up database](/self-hosting/database-setup)
|
||||
- [Configure email delivery](/self-hosting/email-setup)
|
||||
- [Docker Deployment](/self-hosting/docker) — Configuration details
|
||||
- [Environment Variables](/self-hosting/environment-variables) — All settings
|
||||
- [AWS SES Setup](/self-hosting/email-setup) — Email configuration
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"title": "Self-Hosting",
|
||||
"pages": ["introduction", "docker", "environment-variables", "database-setup", "email-setup"]
|
||||
"pages": ["introduction", "docker", "environment-variables", "email-setup"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user