# Self-Signed HTTPS via Caddy — Complete Walkthrough

## Problem
n8n sets `secure` cookie flag → Safari blocks login via HTTP. Caddy's Let's Encrypt cannot issue certs for raw IP addresses. Solution: self-signed certificate.

## Environment
- Linux (Ubuntu 22.04), Docker 29.1.3
- Caddy in bridge mode, connected to `n8n-net`
- n8n-v2 running on port 5679 in same network
- Other device: same LAN, Chrome or Safari

## Step-by-Step

### 1. Generate cert
```bash
mkdir -p ~/.caddy/certs
openssl req -x509 -newkey rsa:4096 \
  -keyout ~/.caddy/certs/key.pem \
  -out ~/.caddy/certs/cert.pem \
  -days 365 -nodes -subj "/CN=192.168.1.142"
```

### 2. Copy cert into Caddy container
```bash
docker cp ~/.caddy/certs/cert.pem caddy:/etc/caddy/cert.pem
docker cp ~/.caddy/certs/key.pem caddy:/etc/caddy/key.pem
```

**Critical:** Caddyfile cannot reference host paths (`/home/kuhnn/.caddy/...`) when Caddy is in bridge mode — the container filesystem has no access to host paths except via volume mounts. Copying files in is the reliable approach.

### 3. Update Caddyfile
```
:443 {
    tls /etc/caddy/cert.pem /etc/caddy/key.pem
    reverse_proxy n8n-v2:5678
}
```

### 4. Reload Caddy
```bash
docker exec caddy caddy reload --config /etc/caddy/Caddyfile
```

### 5. Verify
```bash
curl -k https://localhost
# HTTP/2 200 ✓
```

### 6. Install cert on other devices
Copy cert file: `~/.caddy/certs/cert.pem` → download to target device

| Platform | Install path |
|----------|-------------|
| iOS | Settings → General → VPN & Device Management → Install |
| Android | Security → Install from storage |
| Mac | Keychain Access → File → Import |
| Windows | Double-click .crt → Install to "Trusted Root CA" |

After import, browsers will trust the cert. Safari on iOS/macOS requires the cert to be explicitly trusted.

## Why not volume mount certs directly?
Tried: `-v ~/.caddy/certs:/container/path` → Caddyfile `/container/path/cert.pem` → fails because Caddy's Caddyfile adapter resolves paths at config load time from container's perspective, not host's. Copy-in approach is more reliable.

## Why not localhost in reverse_proxy?
When Caddy is in bridge mode, `localhost` refers to the Caddy container itself, not the host or other containers. Must use container name (e.g., `n8n-v2`) which requires both containers on the same Docker network (`n8n-net`).