Configuration guide
Configure your self-hosted Screenshothis instance with the right environment variables and settings for your deployment. This guide covers everything from basic setup to advanced production configurations.
Always check the source : Refer to the Screenshothis repository .env.example
files for the most up-to-date configuration options. This guide is based on the actual environment variables used in the codebase.
Quick configuration
Start with this minimal setup and expand as needed:
Set up database connection
Configure PostgreSQL connection details in your apps/server/.env
file.
Configure storage
Set up S3-compatible storage credentials for screenshot storage.
Add authentication secrets
Generate secure secrets for user authentication and API keys.
Customize performance settings
Adjust rate limits, timeouts, and screenshot quality settings.
Database configuration
Configure your PostgreSQL database connection:
Complete PostgreSQL connection string. This is the primary database configuration. # Format: postgresql://username:password@host:port/database
DATABASE_URL = postgresql://screenshothis:password@localhost:5432/screenshothis
Database server hostname or IP address. DATABASE_HOST = localhost # Development
DATABASE_HOST = prod-db.example.com # Production
Name of the Screenshothis database. DATABASE_NAME = screenshothis
Database username for connections.
Database password for the specified user.
DATABASE_URL = postgresql://screenshothis:password@localhost:5432/screenshothis
DATABASE_HOST = localhost
DATABASE_PORT = 5432
DATABASE_NAME = screenshothis
DATABASE_USER = screenshothis
DATABASE_PASSWORD = password
Redis configuration
Configure Redis for caching and session management:
Complete Redis connection string. This is the primary Redis configuration. # Development
REDIS_URL = redis://localhost:6379
# Production with authentication
REDIS_URL = redis://user:password@prod-redis.example.com:6379
REDIS_HOST
string
default: "localhost"
Redis server hostname (optional if using REDIS_URL).
Redis server port (optional if using REDIS_URL).
Redis password if authentication is required.
S3-compatible storage
Configure storage for screenshots using any S3-compatible service:
Access key ID for your S3-compatible storage service.
Secret access key for your S3-compatible storage service.
Storage region. Use auto
for Cloudflare R2, or the appropriate region for your service.
Name of the bucket where screenshots will be stored.
Complete endpoint URL for your S3-compatible service.
S3 endpoint URL (usually same as AWS_URL).
AWS_USE_PATH_STYLE_ENDPOINT
Use path-style URLs instead of virtual-hosted style. Set to true
for MinIO and some other services.
Storage provider examples
AWS S3 DigitalOcean Spaces Cloudflare R2 MinIO (Local) AWS_ACCESS_KEY_ID = AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
AWS_REGION = us-east-1
AWS_BUCKET = my-screenshothis-bucket
AWS_URL = https://s3.us-east-1.amazonaws.com
AWS_USE_PATH_STYLE_ENDPOINT = false
For production, we recommend AWS S3 for reliability, or DigitalOcean Spaces for cost-effectiveness. Cloudflare R2 offers excellent performance and free egress.
Application settings
Configure basic application behavior:
Port number for the server to listen on.
Environment mode. Use development
for local work, production
for live deployments. NODE_ENV = development # Development
NODE_ENV = production # Production
Authentication and security
Configure authentication and API key generation:
Secret key for Better Auth authentication system. Must be a strong, random string. Generate a secure secret:
Prefix for generated API keys. Use different prefixes for different environments. DEFAULT_API_KEY_PREFIX = ss_test # Development
DEFAULT_API_KEY_PREFIX = ss_live # Production
Production security : Always use a strong, unique BETTER_AUTH_SECRET
for production. Never reuse secrets across environments or share them in version control.
Frontend configuration
Configure the web interface in apps/web/.env
:
URL of your backend API server. VITE_SERVER_URL = http://localhost:3000 # Development
VITE_SERVER_URL = https://api.yourdomain.com # Production
Google OAuth client ID for Google authentication (optional).
Polar access token for billing integration (optional).
Polar environment. Use sandbox
for testing, production
for live billing.
Google OAuth and Polar configurations are optional. You only need them if you want to offer Google sign-in or integrate with Polar for billing.
Configure rate limiting and screenshot performance:
Rate limit window duration in milliseconds. Default is 1 minute (60000ms).
Maximum requests allowed per rate limit window.
MAX_CONCURRENT_SCREENSHOTS
Maximum number of screenshots that can be processed simultaneously.
Screenshot generation timeout in milliseconds. Default is 30 seconds.
Screenshot settings
Configure screenshot generation limits and defaults:
Maximum allowed screenshot width in pixels.
Maximum allowed screenshot height in pixels.
Default viewport width when not specified in requests.
Default viewport height when not specified in requests.
Maximum time to wait for page loading in milliseconds.
Built-in security features
Screenshothis includes several built-in security measures that you should be aware of:
Automatically enforced limits:
Header size limit: 8 KB (8192 characters) per request
Cookie size limit: 4 KB (4096 characters) per request
URL length limit: Standard browser limits (2048 characters)
These limits prevent abuse and ensure consistent performance across all deployments.
Built-in rate limiting:
Per-user rate limiting via internal requestLimits
system
Configurable via RATE_LIMIT_*
environment variables
Automatic abuse protection
The system tracks usage per API key and enforces limits automatically.
Security auditing:
Every use of bypass_csp=true
is logged server-side
Helps identify potential security issues
Enables compliance and security reviews
Monitor these logs regularly in production environments.
Complete configuration examples
Minimal production setup
Backend configuration (apps/server/.env
):
# Database
DATABASE_URL = postgresql://user:secure_pass@db.example.com:5432/screenshothis
# Redis
REDIS_URL = redis://user:password@redis.example.com:6379
# Storage (AWS S3)
AWS_ACCESS_KEY_ID = your_access_key
AWS_SECRET_ACCESS_KEY = your_secret_key
AWS_REGION = us-east-1
AWS_BUCKET = your-production-bucket
AWS_URL = https://s3.us-east-1.amazonaws.com
# Authentication
BETTER_AUTH_SECRET = your_strong_random_secret_here
DEFAULT_API_KEY_PREFIX = ss_live
# Application
NODE_ENV = production
PORT = 3000
Frontend configuration (apps/web/.env
):
VITE_SERVER_URL = https://api.yourdomain.com
NODE_ENV = production
For high-traffic deployments, use these optimized settings:
# ... base configuration above ...
# Performance optimization
MAX_CONCURRENT_SCREENSHOTS = 20
SCREENSHOT_TIMEOUT = 15000
RATE_LIMIT_MAX_REQUESTS = 1000
RATE_LIMIT_WINDOW_MS = 60000
# Optimized screenshot settings
MAX_SCREENSHOT_WIDTH = 1920
MAX_SCREENSHOT_HEIGHT = 1080
DEFAULT_VIEWPORT_WIDTH = 1280
DEFAULT_VIEWPORT_HEIGHT = 720
MAX_PAGE_LOAD_TIMEOUT = 20000
Development with external services
For development using cloud services instead of local Docker:
# Database (managed PostgreSQL)
DATABASE_URL = postgresql://dev_user:dev_pass@dev-db.provider.com:5432/screenshothis_dev
# Redis (managed Redis)
REDIS_URL = redis://dev_user:dev_pass@dev-redis.provider.com:6379
# Storage (DigitalOcean Spaces for cost-effective development)
AWS_ACCESS_KEY_ID = your_dev_spaces_key
AWS_SECRET_ACCESS_KEY = your_dev_spaces_secret
AWS_REGION = nyc3
AWS_BUCKET = screenshothis-dev
AWS_URL = https://nyc3.digitaloceanspaces.com
# Development authentication
BETTER_AUTH_SECRET = dev_secret_change_for_production
DEFAULT_API_KEY_PREFIX = ss_test
# Application
NODE_ENV = development
PORT = 3000
Docker deployment configuration
Using environment files
Organize your configuration using environment files:
# docker-compose.yml
version : '3.8'
services :
screenshothis-server :
image : screenshothis/server
env_file :
- .env.production
ports :
- "3000:3000"
restart : unless-stopped
screenshothis-web :
image : screenshothis/web
env_file :
- .env.web.production
ports :
- "3001:3000"
restart : unless-stopped
Using Docker secrets
For enhanced security in production:
# docker-compose.yml
version : '3.8'
services :
screenshothis-server :
image : screenshothis/server
secrets :
- better_auth_secret
- aws_secret_key
- database_password
environment :
DATABASE_URL : postgresql://user:password@postgres:5432/screenshothis
BETTER_AUTH_SECRET_FILE : /run/secrets/better_auth_secret
AWS_SECRET_ACCESS_KEY_FILE : /run/secrets/aws_secret_key
DATABASE_PASSWORD_FILE : /run/secrets/database_password
ports :
- "3000:3000"
secrets :
better_auth_secret :
file : ./secrets/better_auth_secret.txt
aws_secret_key :
file : ./secrets/aws_secret_key.txt
database_password :
file : ./secrets/database_password.txt
Configuration validation
Validate your configuration before deployment:
Check required variables
Ensure all required environment variables are set: # Test configuration by starting the application
pnpm run dev
# Check for missing variables in the startup logs
Test database connection
Verify your database connection: # Test database connectivity
pnpm run db:studio
# Should open Drizzle Studio if connection is successful
Validate storage configuration
Test your S3-compatible storage: # For MinIO (local development)
curl http://localhost:9000/minio/health/live
# For production, test with a simple API call
curl "https://your-api.com/v1/screenshots/take?api_key=test&url=https://example.com"
Verify rate limits
Test rate limiting behavior with multiple requests to ensure limits are working correctly.
Troubleshooting configuration
Common causes:
Missing required environment variables
Invalid database connection string
Incorrect Redis URL format
S3 credentials or bucket access issues
Solution: Check the startup logs for specific error messages about missing or invalid configuration.
Database connection errors
Common causes:
Incorrect DATABASE_URL format
Database server not accessible
Wrong credentials
Database doesn’t exist
Solution: Test connection manually: psql "postgresql://user:pass@host:port/db"
Common causes:
Invalid credentials
Bucket doesn’t exist
Wrong region configuration
Incorrect endpoint URL
Solution: Verify bucket exists and credentials have proper permissions (read/write access).
Next steps