ByteSend uses a monorepo structure with separate services for the web application and SMTP server. This guide walks you through setting up both services using Docker.
Dockerfile.web: Builds the Next.js web application with all workspace dependenciesDockerfile.smtp: Builds the SMTP server with workspace dependencies- Both respect the pnpm workspace and share package layers
Before you begin, ensure that you have the following installed:
- Docker
- Docker Compose
- Node.js 20.19 or newer (for local development)
To build both images:
./docker/build.shThis builds:
bytesend/bytesend:latest- The ByteSend web applicationbytesend/smtp-proxy:latest- The SMTP server
Start the complete development environment with Docker:
cd docker/dev
docker-compose up -dThis starts:
- PostgreSQL database
- Redis
- ByteSend web application (port 3000)
- ByteSend SMTP server (ports 25, 465, 587, 2465, 2587)
- Local S3 (MinIO) for storage
- Local SES/SNS mock service
-
Download or copy the production compose file:
cd docker/prod -
Create a
.envfile with your configuration:# Database POSTGRES_USER=bytesend POSTGRES_PASSWORD=<secure-password> POSTGRES_DB=bytesend DATABASE_URL=postgresql://bytesend:<password>@postgres:5432/bytesend # Redis REDIS_URL=redis://redis:6379 # NextAuth NEXTAUTH_URL=https://bytesend.cloud NEXTAUTH_SECRET=<secure-secret> # AWS/SES AWS_ACCESS_KEY=<your-key> AWS_SECRET_KEY=<your-secret> AWS_DEFAULT_REGION=us-east-1 # GitHub OAuth GITHUB_ID=<your-github-id> GITHUB_SECRET=<your-github-secret> # SMTP Configuration BYTESEND_BASE_URL=http://web:3000 SMTP_AUTH_USERNAME=bytesend
-
Start the services:
docker-compose --env-file ./.env up -d
This starts a production-ready setup with separate web and SMTP containers.
To run just the web application:
docker pull bytesend/bytesend:latest
docker run -d \
-p 3000:3000 \
-e NEXTAUTH_URL="https://your-domain.com" \
-e NEXTAUTH_SECRET="your-secret" \
-e DATABASE_URL="your-database-url" \
-e REDIS_URL="your-redis-url" \
-e AWS_ACCESS_KEY="your-key" \
-e AWS_SECRET_KEY="your-secret" \
-e AWS_DEFAULT_REGION="us-east-1" \
-e GITHUB_ID="your-github-id" \
-e GITHUB_SECRET="your-github-secret" \
bytesend/bytesend:latestTo run just the SMTP server:
docker pull bytesend/smtp-proxy:latest
docker run -d \
-p 25:25 \
-p 465:465 \
-p 587:587 \
-p 2465:2465 \
-p 2587:2587 \
-e BYTESEND_BASE_URL="http://your-web-server:3000" \
-e SMTP_AUTH_USERNAME="bytesend" \
bytesend/smtp-proxy:latestThe SMTP server exposes the following ports:
| Port | Protocol | Purpose |
|---|---|---|
| 25 | SMTP | Unencrypted email submission |
| 465 | SMTPS | Implicit SSL/TLS |
| 587 | Submission | STARTTLS |
| 2465 | SMTPS | Alternative implicit SSL/TLS |
| 2587 | Submission | Alternative STARTTLS |
Both Dockerfiles respect the pnpm monorepo structure by:
- Using
pnpm turbo pruneto optimize build layers - Installing all workspace dependencies from
packages/* - Building only the necessary app while maintaining symlinks to shared packages
- Sharing a common base image layer for efficiency
SMTP server can't reach the web server:
- Ensure the
BYTESEND_BASE_URLis set to the correct service name or IP - In Docker Compose, use
http://web:3000for service-to-service communication - For external deployments, use the full URL of your web server
Database connection issues:
- Verify
DATABASE_URLis correctly set - Ensure the database container is healthy before starting the web app
- Check the
depends_oncondition in compose files
You have now set up ByteSend with Docker. The web application listens on port 3000 and the SMTP server on ports 25/465/587/2465/2587. For more information, refer to the ByteSend documentation.