Complete configuration guide for Postiz covering environment variables, OAuth credentials, social media integrations, operational procedures, and best practices for production deployments.
Create or edit your .env file in the Postiz application directory:
# Application Settings
APP_ENV=production
NODE_ENV=production
APP_URL=https://postiz.example.com
PORT=3000
# Database Configuration
DATABASE_URL=postgresql://postiz:YOUR_PASSWORD@localhost:5432/postiz
# Redis Configuration
REDIS_URL=redis://:YOUR_REDIS_PASSWORD@localhost:6379
# Security
JWT_SECRET=your-random-secret-minimum-32-characters
SESSION_SECRET=your-session-secret-minimum-32-chars
# Email Notifications (Optional)
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxx
FROM_EMAIL=noreply@example.com
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=notifications@example.com
SMTP_PASSWORD=your-smtp-password
# Storage (Optional - for R2/S3)
R2_ENDPOINT=https://xxx.r2.cloudflarestorage.com
R2_ACCESS_KEY=your-access-key
R2_SECRET_KEY=your-secret-key
R2_BUCKET=postiz-uploads
R2_REGION=auto
# OIDC Authentication (Optional)
OIDC_ENABLED=false
OIDC_ISSUER=https://auth.example.com
OIDC_CLIENT_ID=postiz
OIDC_CLIENT_SECRET=your-oidc-secret
OIDC_SCOPE=openid,email,profile
OIDC_LOGIN_ENABLED=false
# Logging
LOG_LEVEL=info
DEBUG=false
# Rate Limiting
RATE_LIMIT_TTL=60
RATE_LIMIT_MAX=100
| Variable | Required | Default | Description |
|---|---|---|---|
APP_ENV |
Yes | production |
Application environment (development/staging/production) |
NODE_ENV |
Yes | production |
Node.js environment |
APP_URL |
Yes | - | Public URL of your Postiz instance |
PORT |
No | 3000 |
Application port |
DATABASE_URL |
Yes | - | PostgreSQL connection string |
REDIS_URL |
Yes | - | Redis connection string |
JWT_SECRET |
Yes | - | Secret for JWT token signing (min 32 chars) |
SESSION_SECRET |
No | - | Secret for session encryption |
RESEND_API_KEY |
No | - | Resend API key for email notifications |
FROM_EMAIL |
No | - | Sender email address |
SMTP_HOST |
No | - | SMTP server hostname |
SMTP_PORT |
No | 587 |
SMTP server port |
SMTP_USER |
No | - | SMTP authentication username |
SMTP_PASSWORD |
No | - | SMTP authentication password |
R2_ENDPOINT |
No | - | Cloudflare R2 or S3-compatible endpoint |
R2_ACCESS_KEY |
No | - | R2/S3 access key |
R2_SECRET_KEY |
No | - | R2/S3 secret key |
R2_BUCKET |
No | - | Bucket name for media storage |
R2_REGION |
No | auto |
R2/S3 region |
OIDC_ENABLED |
No | false |
Enable OIDC authentication |
OIDC_ISSUER |
No | - | OIDC provider URL |
OIDC_CLIENT_ID |
No | - | OIDC client ID |
OIDC_CLIENT_SECRET |
No | - | OIDC client secret |
OIDC_SCOPE |
No | openid,email,profile |
OIDC scopes |
OIDC_LOGIN_ENABLED |
No | false |
Enable OIDC login button |
LOG_LEVEL |
No | info |
Logging verbosity (debug/info/warn/error) |
DEBUG |
No | false |
Enable debug mode |
RATE_LIMIT_TTL |
No | 60 |
Rate limit time window (seconds) |
RATE_LIMIT_MAX |
No | 100 |
Maximum requests per window |
Generate JWT Secret:
openssl rand -base64 48
Generate Database Password:
openssl rand -base64 32
Generate Redis Password:
openssl rand -base64 32
Use Separate Apps Per Environment
Document Callback URLs
Rotate Credentials Regularly
Restrict Admin Access
Required: Twitter Developer Account
https://postiz.example.com/auth/twitter/callbackConfiguration in Postiz:
Required: Facebook Developer Account, Facebook App
https://postiz.example.com/auth/facebook/callbackFor Instagram:
Required: LinkedIn Developer Account
https://postiz.example.com/auth/linkedin/callbackRequired: Google Cloud Project
https://postiz.example.com/auth/youtube/callbackRequired: TikTok Developer Account
https://postiz.example.com/auth/tiktok/callbackRequired: Discord Developer Account
https://postiz.example.com/auth/discord/callbackRequired: Telegram Account
Required: Reddit Account
https://postiz.example.com/auth/reddit/callbackRequired: Pinterest Developer Account
https://postiz.example.com/auth/pinterest/callbackSelf-hosted instances:
| Platform | Daily Limit | Recommended Frequency | Best Times |
|---|---|---|---|
| X (Twitter) | 2400 posts | 3-15/day | 9 AM, 12 PM, 5 PM |
| 50 posts | 1-3/day | 1-4 PM | |
| 25 posts | 1-2/day | 11 AM-1 PM | |
| 100 posts | 1/day | 8-10 AM, 5-6 PM | |
| YouTube | 100 videos | 2-3/week | 2-4 PM |
| TikTok | 50 videos | 1-3/day | 6-10 PM |
| 500 pins | 5-10/day | 8-11 PM | |
| 10 posts | Varies by subreddit | Varies |
| Platform | Text | Images | Video | Stories | Reels | Carousels |
|---|---|---|---|---|---|---|
| X | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | |
| ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | |
| YouTube | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| TikTok | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
| ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | |
| Threads | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
Enable auto-actions:
AUTO_POST_ENABLED=true
AUTO_LIKE_ENABLED=true
AUTO_COMMENT_ENABLED=true
AUTO_SHARE_ENABLED=true
Configure engagement thresholds:
AUTO_LIKE_THRESHOLD=10
AUTO_COMMENT_THRESHOLD=50
AUTO_SHARE_THRESHOLD=100
RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxxx
FROM_EMAIL=noreply@yourdomain.com
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_NAME=Postiz
SMTP_FROM_EMAIL=noreply@yourdomain.com
Gmail SMTP:
smtp.gmail.com587 (TLS) or 465 (SSL)Outlook SMTP:
smtp.office365.com587 (STARTTLS)Configure notification preferences in Postiz UI:
Media stored in Docker volume or host path:
volumes:
- app-uploads:/app/uploads
R2_ENDPOINT=https://YOUR_ACCOUNT_ID.r2.cloudflarestorage.com
R2_ACCESS_KEY=YOUR_ACCESS_KEY
R2_SECRET_KEY=YOUR_SECRET_KEY
R2_BUCKET=postiz-uploads
R2_REGION=auto
R2_ENDPOINT=https://s3.amazonaws.com
R2_ACCESS_KEY=YOUR_AWS_ACCESS_KEY
R2_SECRET_KEY=YOUR_AWS_SECRET_KEY
R2_BUCKET=postiz-uploads
R2_REGION=us-east-1
| Storage Type | Recommended Limit | Notes |
|---|---|---|
| Local | 50 GB | Depends on server storage |
| R2 | Unlimited | $0.015/GB/month |
| S3 | Unlimited | $0.023/GB/month |
Environment variables:
WORKER_CONCURRENCY=5
WORKER_TIMEOUT=30000
WORKER_MAX_ATTEMPTS=3
Docker Compose worker settings:
worker:
deploy:
resources:
limits:
cpus: '1.0'
memory: 1G
reservations:
cpus: '0.25'
memory: 256M
Job queue settings:
QUEUE_PROCESS_INTERVAL=5000
QUEUE_MAX_JOBS_PER_RUN=50
QUEUE_RETRY_DELAY=60000
Scheduled posting:
SCHEDULER_TIMEZONE=UTC
SCHEDULER_MAX_POSTS_PER_HOUR=100
SCHEDULER_BATCH_SIZE=10
Check queue status:
docker compose exec redis redis-cli -a YOUR_REDIS_PASSWORD
> KEYS bull:*
> LLEN bull:jobs:wait
Clear stuck jobs:
docker compose restart worker
Connection string format:
postgresql://USER:PASSWORD@HOST:PORT/DATABASE
Example:
DATABASE_URL=postgresql://postiz:secretpassword@postgres:5432/postiz
postgresql.conf optimizations:
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 64MB
work_mem = 4MB
wal_buffers = 4MB
random_page_cost = 1.1
effective_io_concurrency = 200
Manual backup:
docker compose exec postgres pg_dump -U postiz postiz > backup.sql
Restore:
docker compose exec -T postgres psql -U postiz postiz < backup.sql
REDIS_URL=redis://:YOUR_PASSWORD@redis:6379
redis.conf optimizations:
maxmemory 256mb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
Check memory usage:
docker compose exec redis redis-cli -a YOUR_PASSWORD INFO memory
Check connected clients:
docker compose exec redis redis-cli -a YOUR_PASSWORD CLIENT LIST
See Docker Setup for complete Nginx configuration.
Key settings:
client_max_body_size 50M; # For media uploads
proxy_read_timeout 86400; # For long-running requests
proxy_send_timeout 86400;
Docker labels:
labels:
- "traefik.http.routers.postiz.rule=Host(`postiz.example.com`)"
- "traefik.http.routers.postiz.entrypoints=websecure"
- "traefik.http.routers.postiz.tls.certresolver=letsencrypt"
- "traefik.http.middlewares.postiz-headers.headers.stsSeconds=31536000"
Caddyfile:
postiz.example.com {
reverse_proxy localhost:3000
tls admin@example.com
}
Create /opt/postiz/backup.sh:
#!/bin/bash
set -e
BACKUP_DIR="/opt/postiz/backups"
DATE=$(date +%Y%m%d_%H%M%S)
POSTGRES_CONTAINER="postiz-postgres"
POSTGRES_USER="postiz"
POSTGRES_DB="postiz"
# Create backup directory
mkdir -p $BACKUP_DIR/{postgres,uploads,config}
# Backup PostgreSQL
docker exec $POSTGRES_CONTAINER pg_dump -U $POSTGRES_USER $POSTGRES_DB | gzip > $BACKUP_DIR/postgres/postiz_$DATE.sql.gz
# Backup uploads
tar -czf $BACKUP_DIR/uploads/uploads_$DATE.tar.gz -C /var/lib/docker/volumes/postiz_app-uploads/_data .
# Backup environment
cp /opt/postiz/.env $BACKUP_DIR/config/env_$DATE.backup
# Remove old backups (keep 30 days)
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE"
Make executable:
chmod +x /opt/postiz/backup.sh
Add to crontab:
0 2 * * * /opt/postiz/backup.sh >> /var/log/postiz-backup.log 2>&1
1. Stop services:
docker compose down
2. Restore database:
gunzip < postgres/postiz_20260216_020000.sql.gz | docker exec -i postiz-postgres psql -U postiz -d postiz
3. Restore uploads:
tar -xzf uploads/uploads_20260216_020000.tar.gz -C /var/lib/docker/volumes/postiz_app-uploads/_data
4. Restore environment:
cp config/env_20260216_020000.backup .env
5. Restart services:
docker compose up -d
https://postiz.example.com/healthhealthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
Docker logging:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Container status:
docker compose ps
Resource usage:
docker stats postiz-app postiz-worker postgres redis
View logs:
docker compose logs -f app
docker compose logs -f worker
Database queries:
docker compose exec postgres psql -U postiz -c "SELECT count(*) FROM posts;"
Application won’t start:
docker compose logs app
docker compose restart app
Database connection timeout:
docker compose exec postgres pg_isready
docker compose logs postgres
Worker not processing jobs:
docker compose logs worker
docker compose restart worker
OAuth callback errors:
Media upload failures:
Email not sending:
Enable debug logging:
LOG_LEVEL=debug
DEBUG=true
Restart with debug:
docker compose down
docker compose up -d
docker compose logs -f
High memory usage:
docker update --memory=2g postiz-app
Slow database queries:
EXPLAIN ANALYZE SELECT * FROM posts WHERE created_at > NOW() - INTERVAL '7 days';
Queue backlog:
docker compose exec redis redis-cli -a PASSWORD LLEN bull:jobs:wait
docker compose scale worker=2
Any questions?
Feel free to contact us. Find all contact information on our contact page.