> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/getrupt/sendook/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Hosting

> Learn how to self-host Sendook using Docker, configure environment variables, and run locally

## Overview

Sendook is open source and can be self-hosted for full control over your email infrastructure. The stack includes:

* **API** - Node.js backend with Bun runtime
* **App** - Nuxt 3 dashboard application
* **Landing** - Nuxt 3 marketing website
* **Database** - MongoDB for data persistence
* **Cache** - Redis for session management (optional)

## Quick Start with Docker

The fastest way to get Sendook running is with Docker.

### Prerequisites

* Docker and Docker Compose installed
* MongoDB instance (local or hosted)
* AWS account with SES configured
* Stripe account (for billing)

### Build and Run API

**1. Build the Docker image**

```bash theme={null}
cd api
docker build -t sendook-api .
```

**2. Run the container**

```bash theme={null}
docker run -p 8006:8006 \
  -e MONGO_URI="mongodb://localhost:27017/sendook" \
  -e DEFAULT_EMAIL_DOMAIN="sendook.com" \
  -e AWS_ACCESS_KEY_ID="your_aws_key" \
  -e AWS_SECRET_ACCESS_KEY="your_aws_secret" \
  -e STRIPE_SECRET_KEY="sk_test_..." \
  -e STRIPE_WEBHOOK_SECRET="whsec_..." \
  -e STRIPE_PRICE_ID="price_..." \
  -e STRIPE_PRODUCT_ID="prod_..." \
  -e STRIPE_METER_EVENT="email_sent" \
  sendook-api
```

### Dockerfile Explanation

The API uses Bun's official Docker image:

```dockerfile theme={null}
FROM oven/bun:latest AS base
WORKDIR /usr/src/app

# Install production dependencies
FROM base AS install
RUN mkdir -p /temp/prod
COPY package.json bun.lock /temp/prod/
RUN cd /temp/prod && bun install --frozen-lockfile --production

# Copy dependencies and source code
FROM base AS release
COPY --from=install /temp/prod/node_modules node_modules
COPY . .

ENV NODE_ENV=production

# Run the app
USER bun
EXPOSE 3000/tcp
ENTRYPOINT [ "bun", "run", "index.ts" ]
```

<Note>
  The Dockerfile exposes port 3000 internally, but the API listens on port 8006 by default. Map the ports accordingly.
</Note>

## Environment Variables

### Required Variables

#### MongoDB

```bash theme={null}
MONGO_URI="mongodb://localhost:27017/sendook"
```

Connection string for your MongoDB database.

#### Email Domain

```bash theme={null}
DEFAULT_EMAIL_DOMAIN="sendook.com"
```

Default domain for creating inboxes without custom domains.

#### AWS Credentials

```bash theme={null}
AWS_ACCESS_KEY_ID="AKIA..."
AWS_SECRET_ACCESS_KEY="your_secret_key"
```

AWS credentials with permissions for:

* SES (Simple Email Service) - Send and receive emails
* SES domain verification
* SES configuration sets

#### Stripe Configuration

```bash theme={null}
STRIPE_SECRET_KEY="sk_test_..."  # or sk_live_...
STRIPE_WEBHOOK_SECRET="whsec_..."
STRIPE_PRICE_ID="price_..."
STRIPE_PRODUCT_ID="prod_..."
STRIPE_METER_EVENT="email_sent"
```

* **STRIPE\_SECRET\_KEY** - Your Stripe API secret key
* **STRIPE\_WEBHOOK\_SECRET** - Webhook signing secret for verifying events
* **STRIPE\_PRICE\_ID** - Usage-based price ID from your Stripe product
* **STRIPE\_PRODUCT\_ID** - Product ID from Stripe
* **STRIPE\_METER\_EVENT** - Name of the billing meter event

### Optional Variables

#### Redis

```bash theme={null}
REDIS_HOST="localhost"
```

Redis host for caching (optional but recommended for production).

#### Rupt Integration

```bash theme={null}
RUPT_SECRET_KEY="your_secret_key"
```

Optional secret key for Rupt integration (fake accounts & account takeover features).

#### Port Configuration

```bash theme={null}
PORT="8006"
```

Port for the API server (defaults to 8006).

#### Environment

```bash theme={null}
ENV="production"  # or "development"
```

Environment identifier for logging and debugging.

## Running Locally

### API Server

Sendook uses Bun instead of Node.js for better performance.

**Development Mode**

```bash theme={null}
cd api
bun install
bun dev
```

The API will start on `http://localhost:8006` with hot reload enabled.

**Production Mode**

```bash theme={null}
cd api
bun install
bun start
```

<Info>
  Bun automatically loads `.env` files, so you don't need `dotenv`.
</Info>

### Dashboard App

The dashboard is built with Nuxt 3.

**Development Mode**

```bash theme={null}
cd app
bun install
bun dev
```

**Production Mode**

```bash theme={null}
cd app
bun install
bun build
bun start
```

**Environment Variables**

```bash theme={null}
API_URL="http://localhost:8006"  # Point to your API
```

### Landing Site

The marketing site is also built with Nuxt 3.

```bash theme={null}
cd landing
bun install
bun dev  # Development
bun run build && bun start  # Production
```

No environment variables required for the landing site.

## AWS SES Setup

Sendook uses AWS SES for email sending and receiving.

### Prerequisites

1. **AWS Account** - Sign up at [aws.amazon.com](https://aws.amazon.com)
2. **SES Access** - Enable SES in your AWS region
3. **Move out of sandbox** - Request production access to send to any email

### Configuration Steps

**1. Verify Domain**

In AWS SES Console:

* Go to "Verified identities"
* Click "Create identity"
* Select "Domain"
* Enter your domain
* Follow DNS verification steps

**2. Create IAM User**

Create an IAM user with these permissions:

```json theme={null}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ses:SendEmail",
        "ses:SendRawEmail",
        "ses:VerifyDomainIdentity",
        "ses:GetIdentityVerificationAttributes",
        "ses:VerifyDomainDkim",
        "ses:GetIdentityDkimAttributes"
      ],
      "Resource": "*"
    }
  ]
}
```

Save the access key ID and secret access key.

**3. Configure Receiving**

For receiving emails:

* Create an S3 bucket (optional, for email storage)
* Set up SES receipt rules
* Configure SNS topics or Lambda functions for processing

**4. DNS Records**

Add these DNS records for each domain:

**MX Record** (for receiving):

```
Type: MX
Name: @
Value: inbound-smtp.us-east-1.amazonaws.com
Priority: 10
```

**DKIM Records** (provided by SES):

```
Type: CNAME
Name: [subdomain]._domainkey
Value: [value].dkim.amazonses.com
```

**SPF Record** (optional but recommended):

```
Type: TXT
Name: @
Value: v=spf1 include:amazonses.com ~all
```

**DMARC Record** (optional):

```
Type: TXT
Name: _dmarc
Value: v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
```

## MongoDB Setup

### Local MongoDB

**Using Docker**

```bash theme={null}
docker run -d \
  --name sendook-mongodb \
  -p 27017:27017 \
  -v sendook-data:/data/db \
  mongo:latest
```

**Using MongoDB Community Edition**

Download and install from [mongodb.com](https://www.mongodb.com/try/download/community).

### Hosted MongoDB

Use a managed MongoDB service:

* [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) (recommended)
* [AWS DocumentDB](https://aws.amazon.com/documentdb/)
* [DigitalOcean Managed MongoDB](https://www.digitalocean.com/products/managed-databases-mongodb)

Get your connection string and set it as `MONGO_URI`.

### Database Migrations

Sendook runs migrations automatically on startup:

```typescript theme={null}
startMongo().then(async () => {
  console.log("MongoDB connected, running migrations...");
  await runMigrations();
  // Start server...
});
```

Migrations are located in `api/migrations/`.

## Production Deployment

### Using Docker Compose

Create a `docker-compose.yml`:

```yaml theme={null}
version: '3.8'

services:
  api:
    build: ./api
    ports:
      - "8006:8006"
    environment:
      MONGO_URI: mongodb://mongo:27017/sendook
      DEFAULT_EMAIL_DOMAIN: sendook.com
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
      STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY}
      STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET}
      STRIPE_PRICE_ID: ${STRIPE_PRICE_ID}
      STRIPE_PRODUCT_ID: ${STRIPE_PRODUCT_ID}
      STRIPE_METER_EVENT: email_sent
      REDIS_HOST: redis
    depends_on:
      - mongo
      - redis

  app:
    build: ./app
    ports:
      - "3000:3000"
    environment:
      API_URL: http://api:8006
    depends_on:
      - api

  mongo:
    image: mongo:latest
    volumes:
      - mongo-data:/data/db
    ports:
      - "27017:27017"

  redis:
    image: redis:alpine
    ports:
      - "6379:6379"

volumes:
  mongo-data:
```

Run with:

```bash theme={null}
docker-compose up -d
```

### Deployment Platforms

<CardGroup cols={2}>
  <Card title="Railway" icon="train">
    Deploy with one click using Railway's Docker support. Connect your GitHub repo and set environment variables.
  </Card>

  <Card title="Fly.io" icon="plane">
    Use Fly.io for global edge deployment. Create a `fly.toml` and deploy with `fly deploy`.
  </Card>

  <Card title="AWS ECS" icon="aws">
    Run on AWS ECS with Fargate for serverless containers. Use ECR for Docker images.
  </Card>

  <Card title="DigitalOcean" icon="digital-ocean">
    Deploy to DigitalOcean App Platform or Droplets with Docker.
  </Card>
</CardGroup>

## Repository Structure

Understanding the monorepo layout:

```
sendook/
├── api/                 # Backend API server
│   ├── controllers/     # Business logic
│   ├── db/             # Database schemas
│   ├── models/         # TypeScript interfaces
│   ├── routes/         # API routes
│   ├── migrations/     # Database migrations
│   ├── Dockerfile      # Docker configuration
│   └── index.ts        # Entry point
├── app/                # Dashboard application
│   ├── app/
│   │   ├── components/ # Vue components
│   │   ├── pages/      # Dashboard pages
│   │   └── composables/ # Vue composables
│   └── nuxt.config.ts  # Nuxt configuration
├── landing/            # Marketing website
│   └── nuxt.config.ts
└── node-sdk/           # Official Node.js SDK
    └── src/
```

## Security Considerations

<Warning>
  Always use environment variables for secrets. Never commit credentials to version control.
</Warning>

### Production Checklist

* [ ] Use strong, unique passwords for MongoDB
* [ ] Enable MongoDB authentication
* [ ] Use Stripe live mode keys (not test keys)
* [ ] Configure HTTPS/TLS for all endpoints
* [ ] Set up firewall rules (only allow necessary ports)
* [ ] Enable AWS SES production access (out of sandbox)
* [ ] Rotate AWS and Stripe keys regularly
* [ ] Set up monitoring and logging
* [ ] Configure backup strategy for MongoDB
* [ ] Use Redis for session management
* [ ] Set up rate limiting
* [ ] Enable CORS only for trusted origins

## Monitoring and Logs

### Health Check Endpoint

The API provides a health check:

```bash theme={null}
curl http://localhost:8006/health
```

Response:

```json theme={null}
{
  "healthy": true,
  "environment": "production"
}
```

### Logging

Sendook logs to stdout/stderr. Capture logs with:

**Docker**

```bash theme={null}
docker logs sendook-api
```

**Production**
Use a logging service:

* CloudWatch Logs (AWS)
* Datadog
* Loggly
* Papertrail

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection to MongoDB failed">
    * Verify MONGO\_URI is correct
    * Check MongoDB is running: `docker ps` or `systemctl status mongod`
    * Ensure network connectivity between API and MongoDB
    * Check MongoDB authentication credentials
  </Accordion>

  <Accordion title="Emails not sending">
    * Verify AWS credentials are correct
    * Check SES is enabled in your AWS region
    * Ensure you're out of SES sandbox mode
    * Verify domain is verified in SES
    * Check CloudWatch logs for SES errors
  </Accordion>

  <Accordion title="Stripe errors">
    * Verify all Stripe environment variables are set
    * Check you're using the correct key type (test vs live)
    * Ensure webhook secret matches your Stripe webhook
    * Verify the price ID exists in your Stripe account
  </Accordion>

  <Accordion title="Port already in use">
    * Change PORT environment variable to an available port
    * Check for other processes: `lsof -i :8006`
    * Stop conflicting services
  </Accordion>

  <Accordion title="Docker build fails">
    * Ensure Docker has enough memory allocated
    * Check package.json and bun.lock are present
    * Verify Docker has internet access for dependencies
    * Try `docker system prune` to clear cache
  </Accordion>
</AccordionGroup>

## Performance Optimization

<CardGroup cols={2}>
  <Card title="Use Redis" icon="bolt">
    Configure Redis for session caching and improved performance.
  </Card>

  <Card title="Database Indexing" icon="database">
    MongoDB indexes are created by migrations. Monitor slow queries.
  </Card>

  <Card title="Connection Pooling" icon="network-wired">
    Mongoose handles connection pooling automatically.
  </Card>

  <Card title="Load Balancing" icon="scale-balanced">
    Deploy multiple API instances behind a load balancer for high availability.
  </Card>
</CardGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/guides/authentication">
    Set up API keys and access tokens
  </Card>

  <Card title="Dashboard" icon="gauge" href="/guides/dashboard">
    Learn how to use the dashboard
  </Card>

  <Card title="API Reference" icon="code" href="/api/overview">
    Explore the API endpoints
  </Card>

  <Card title="Billing Setup" icon="credit-card" href="/guides/billing">
    Configure Stripe billing
  </Card>
</CardGroup>
