# Guide: Adding a New Domain to API Documentation

This guide explains how to connect a new domain to the API Documentation project served from this VPS.

## Architecture Overview

```
Internet → Cloudflare (DNS + CDN) → VPS (Apache) → Static Files / Docker (Swagger)
```

| Component | Role |
|-----------|------|
| **Cloudflare** | DNS, CDN, edge SSL (client ↔ Cloudflare) |
| **Apache** | Virtual hosts, reverse proxy, origin SSL (Cloudflare ↔ VPS) |
| **Let's Encrypt** | Origin SSL certificates on the VPS |
| **Docker (Nginx)** | Swagger UI on port 8081 |
| **Static HTML** | Redoc docs at `/var/www/api-docs/doc/` |

### Key Principle

> **Each domain MUST have its own pair of Apache virtual host files and its own SSL certificate.**
> Never use `ServerAlias` to share a single SSL vhost across domains with different certificates — this causes Cloudflare Error 526.

### Current Domains

| Domain | HTTP Config | SSL Config | Certificate Path |
|--------|-------------|------------|------------------|
| `api.example.com` | `api.example.com.conf` | `api.example.com-le-ssl.conf` | `/etc/letsencrypt/live/api.example.com/` |
| `apidoc.tripfindy.com` | `apidoc.tripfindy.com.conf` | `apidoc.tripfindy.com-le-ssl.conf` | `/etc/letsencrypt/live/apidoc.tripfindy.com/` |

---

## Step-by-Step: Adding a New Domain

Replace `newdomain.example.com` with your actual domain throughout.

### Step 1: Point DNS to this VPS

In your DNS provider (e.g. Cloudflare):

1. Add an **A record**:
   - **Name**: subdomain (e.g. `apidoc`) or `@` for root
   - **Value**: Your VPS IP address
   - **Proxy**: Proxied (orange cloud) for Cloudflare benefits

2. Set **SSL/TLS mode** to **Full (Strict)** in Cloudflare dashboard for the domain.

### Step 2: Create the HTTP Virtual Host (port 80)

Create the file:

```bash
sudo nano /etc/apache2/sites-available/newdomain.example.com.conf
```

Paste this content:

```apache
<VirtualHost *:80>
    ServerName newdomain.example.com

    DocumentRoot /var/www/api-docs

    # =========================
    # Redoc Documentation
    # URL: /doc/ maps naturally via DocumentRoot
    # =========================

    <Directory "/var/www/api-docs">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

    # =========================
    # OpenAPI Static Files
    # =========================
    Alias /openapi /var/www/api-docs/openapi

    <Directory "/var/www/api-docs/openapi">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
        Header set Access-Control-Allow-Origin "*"
    </Directory>

    # =========================
    # Swagger UI (Docker)
    # =========================
    ProxyPreserveHost On
    ProxyPass /swagger http://localhost:8081/
    ProxyPassReverse /swagger http://localhost:8081/

    RewriteEngine on
    RewriteCond %{SERVER_NAME} =newdomain.example.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
```

### Step 3: Enable the HTTP Site

```bash
sudo a2ensite newdomain.example.com.conf
sudo systemctl reload apache2
```

### Step 4: Obtain SSL Certificate with Certbot

> **IMPORTANT**: If the domain is behind Cloudflare proxy, you must **temporarily disable the proxy** 
> (set DNS to "DNS only" / grey cloud) so Certbot can reach port 80 for HTTP-01 validation.

```bash
sudo certbot --apache -d newdomain.example.com
```

Certbot will:
- Obtain a Let's Encrypt certificate
- Automatically create the SSL virtual host file (`newdomain.example.com-le-ssl.conf`)
- Enable it in Apache

**After Certbot completes**, re-enable the Cloudflare proxy (orange cloud).

### Step 5: Verify the SSL Config

Check that Certbot created the SSL config correctly:

```bash
cat /etc/apache2/sites-available/newdomain.example.com-le-ssl.conf
```

Make sure it contains:
- `ServerName newdomain.example.com` (NO other domain's ServerAlias)
- `SSLCertificateFile /etc/letsencrypt/live/newdomain.example.com/fullchain.pem`
- `SSLCertificateKeyFile /etc/letsencrypt/live/newdomain.example.com/privkey.pem`
- `RedirectMatch 301 ^/$ /doc/` (redirect root to Redoc documentation)
- All the Proxy directives from the HTTP config
- **NO** `Alias /docs` line (the `/doc/` path maps naturally via DocumentRoot)

If Certbot didn't add the Proxy/Redirect directives, edit the file and add them (copy from the HTTP config above, plus add the SSL directives, logging, and `RedirectMatch`).

### Step 6: Test and Reload

```bash
# Test config syntax
sudo apachectl configtest

# Reload Apache
sudo systemctl reload apache2
```

### Step 7: Verify Everything Works

```bash
# Check the correct certificate is served
echo | openssl s_client -servername newdomain.example.com -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -subject

# Check HTTP response
curl -sk --resolve newdomain.example.com:443:127.0.0.1 https://newdomain.example.com/ -o /dev/null -w "HTTP %{http_code}\n"
```

Expected output:
```
subject=CN = newdomain.example.com
HTTP 301
```

### 5. Update Branding Configuration

To ensure the documentation displays the correct client name and titles, add an entry for the new domain in `/var/www/api-docs/doc/branding.js`.

1. Open `/var/www/api-docs/doc/branding.js`.
2. Add a new entry under `domains`:
   ```javascript
   "apidoc.newclient.com": {
     clientName: "New Client Name",
     title: "New Client API Documentation",
     subtitle: "Access the technical specifications for New Client services.",
     footer: "© 2026 ITT Platform. All rights reserved. | New Client"
   }
   ```

### 6. Verify and Clear Cache

1. Visit `https://apidoc.newclient.com`.
2. Verify that the title and branding match your configuration.
3. If you still see old branding, clear your browser cache (since we use 301 redirects).

---

## Troubleshooting

### Error 526 — Invalid SSL Certificate

**Cause**: The VPS is serving the wrong SSL certificate for the domain.

**Fix**: Check that the SSL vhost file (`*-le-ssl.conf`) points to the correct certificate:
```bash
grep -E "SSLCertificate|ServerName" /etc/apache2/sites-enabled/newdomain.example.com-le-ssl.conf
```

### Error 522 — Connection Timed Out

**Cause**: Cloudflare can't reach port 443 on your VPS.

**Fix**: Check firewall allows 443:
```bash
sudo ufw status
sudo ufw allow 443
```

### Error 521 — Web Server is Down

**Cause**: Apache is not running.

**Fix**:
```bash
sudo systemctl status apache2
sudo systemctl start apache2
```

### Certbot Fails to Validate

**Cause**: Cloudflare proxy is intercepting the HTTP-01 challenge.

**Fix**: Temporarily set the DNS record to "DNS only" (grey cloud), run Certbot, then re-enable proxy.

---

## Certificate Renewal

Let's Encrypt certificates auto-renew via a cron/systemd timer. Verify it's active:

```bash
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
```

---

## File Reference

| File | Purpose |
|------|---------|
| `/etc/apache2/sites-available/<domain>.conf` | HTTP virtual host (port 80, redirects to HTTPS) |
| `/etc/apache2/sites-available/<domain>-le-ssl.conf` | HTTPS virtual host (port 443, serves the app) |
| `/etc/letsencrypt/live/<domain>/fullchain.pem` | SSL certificate |
| `/etc/letsencrypt/live/<domain>/privkey.pem` | SSL private key |
| `/var/www/api-docs/` | Shared document root for all domains |
| `/var/www/api-docs/swagger/docker-compose.yml` | Swagger UI Docker container config |

## Quick Command Reference

```bash
# Enable a new site
sudo a2ensite <domain>.conf

# Disable a site
sudo a2dissite <domain>.conf

# Test config
sudo apachectl configtest

# Reload (graceful, no downtime)
sudo systemctl reload apache2

# Get new SSL cert
sudo certbot --apache -d <domain>

# Check which cert a domain serves
echo | openssl s_client -servername <domain> -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -subject -dates

# List all enabled sites
ls -la /etc/apache2/sites-enabled/
```
