Merge pull request #1 from genichin/copilot/add-deployment-docs-using-caddy
docs: add Caddy HTTPS deployment guide
This commit is contained in:
@@ -57,6 +57,26 @@ uvicorn app.main:app --reload
|
||||
pytest
|
||||
```
|
||||
|
||||
## Production Deployment (HTTPS with Caddy)
|
||||
|
||||
For production, it is recommended to run PortfolioHub behind [Caddy](https://caddyserver.com/), which handles TLS certificate provisioning automatically.
|
||||
|
||||
A minimal `Caddyfile`:
|
||||
|
||||
```
|
||||
your-domain.com {
|
||||
reverse_proxy localhost:8000
|
||||
}
|
||||
```
|
||||
|
||||
See **[docs/deployment.md](docs/deployment.md)** for a full guide covering:
|
||||
|
||||
- Caddy installation on Linux/Ubuntu
|
||||
- CORS configuration (`PORTFOLIOHUB_ALLOWED_ORIGINS`)
|
||||
- Running `uvicorn` as a systemd service
|
||||
- Docker Compose setup with a Caddy sidecar container
|
||||
- Firewall port configuration (80, 443)
|
||||
|
||||
## CLI
|
||||
|
||||
The repository now includes a `portfoliohub` CLI that mirrors the main portfolio flows from `jsbot-kis`.
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
# Production Deployment: HTTPS with Caddy
|
||||
|
||||
This guide describes how to deploy PortfolioHub behind [Caddy](https://caddyserver.com/), a reverse proxy that automatically provisions and renews TLS certificates from Let's Encrypt or ZeroSSL.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A Linux/Ubuntu server with a public IP address
|
||||
- A domain name (e.g., `api.example.com`) with a DNS `A` record pointing to that IP
|
||||
- Ports **80** and **443** open on your firewall (see [Firewall Setup](#firewall-setup))
|
||||
|
||||
---
|
||||
|
||||
## 1. Install Caddy (Ubuntu/Debian)
|
||||
|
||||
```bash
|
||||
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
|
||||
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
|
||||
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
|
||||
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
|
||||
sudo apt update
|
||||
sudo apt install caddy
|
||||
```
|
||||
|
||||
Verify the installation:
|
||||
|
||||
```bash
|
||||
caddy version
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Configure the Caddyfile
|
||||
|
||||
Create or edit `/etc/caddy/Caddyfile`:
|
||||
|
||||
```
|
||||
your-domain.com {
|
||||
reverse_proxy localhost:8000
|
||||
}
|
||||
```
|
||||
|
||||
Replace `your-domain.com` with your actual domain. Caddy automatically:
|
||||
|
||||
- Obtains and renews TLS certificates from Let's Encrypt/ZeroSSL
|
||||
- Redirects plain HTTP (port 80) to HTTPS (port 443)
|
||||
- Forwards all requests to the PortfolioHub `uvicorn` process on port 8000
|
||||
|
||||
Reload Caddy after editing the Caddyfile:
|
||||
|
||||
```bash
|
||||
sudo systemctl reload caddy
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. CORS Configuration
|
||||
|
||||
When PortfolioHub is accessed from a browser-based frontend over HTTPS, the `PORTFOLIOHUB_ALLOWED_ORIGINS` environment variable must list the exact HTTPS origin(s) of your frontend.
|
||||
|
||||
Set the variable in your environment or `.env` file:
|
||||
|
||||
```bash
|
||||
PORTFOLIOHUB_ALLOWED_ORIGINS=https://app.example.com,https://www.example.com
|
||||
```
|
||||
|
||||
Multiple origins are comma-separated. For the CORS policy details see section 12 of `docs/portfoliohub-spec.md`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Start PortfolioHub for Production
|
||||
|
||||
Run `uvicorn` without `--reload` and bind only to `localhost` so that external traffic is always routed through Caddy:
|
||||
|
||||
```bash
|
||||
uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2
|
||||
```
|
||||
|
||||
For a systemd service, create `/etc/systemd/system/portfoliohub.service`:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=PortfolioHub API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=www-data
|
||||
WorkingDirectory=/opt/portfoliohub
|
||||
EnvironmentFile=/opt/portfoliohub/.env
|
||||
ExecStart=/opt/portfoliohub/.venv/bin/uvicorn app.main:app \
|
||||
--host 127.0.0.1 --port 8000 --workers 2
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Enable and start the service:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable portfoliohub
|
||||
sudo systemctl start portfoliohub
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Docker Compose Setup (Optional)
|
||||
|
||||
If you run PortfolioHub in Docker, you can add Caddy as a sidecar container.
|
||||
|
||||
`docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
expose:
|
||||
- "8000"
|
||||
environment:
|
||||
- PORTFOLIOHUB_ALLOWED_ORIGINS=https://your-domain.com
|
||||
# add other env vars or reference an env_file
|
||||
restart: unless-stopped
|
||||
|
||||
caddy:
|
||||
image: caddy:2-alpine
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||
- caddy_data:/data
|
||||
- caddy_config:/config
|
||||
depends_on:
|
||||
- app
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
```
|
||||
|
||||
`Caddyfile` (placed next to `docker-compose.yml`):
|
||||
|
||||
```
|
||||
your-domain.com {
|
||||
reverse_proxy app:8000
|
||||
}
|
||||
```
|
||||
|
||||
Note: inside a Docker Compose network, Caddy reaches the app container via its service name (`app`) instead of `localhost`.
|
||||
|
||||
Start everything:
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Firewall Setup
|
||||
|
||||
Open ports 80 (HTTP, needed for ACME certificate challenge) and 443 (HTTPS):
|
||||
|
||||
```bash
|
||||
# UFW (Ubuntu)
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
sudo ufw reload
|
||||
```
|
||||
|
||||
```bash
|
||||
# firewalld (RHEL/CentOS/Fedora)
|
||||
sudo firewall-cmd --permanent --add-service=http
|
||||
sudo firewall-cmd --permanent --add-service=https
|
||||
sudo firewall-cmd --reload
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Verify the Deployment
|
||||
|
||||
```bash
|
||||
# Health check over HTTPS
|
||||
curl https://your-domain.com/health
|
||||
# Expected: {"status":"ok"}
|
||||
```
|
||||
|
||||
Check Caddy's status and certificate renewal:
|
||||
|
||||
```bash
|
||||
sudo systemctl status caddy
|
||||
sudo journalctl -u caddy -f
|
||||
```
|
||||
Reference in New Issue
Block a user