Added user tab and oauth2, streamlined readme

This commit is contained in:
fuomag9
2025-12-28 15:14:56 +01:00
parent f8a673cc03
commit be21f46ad5
28 changed files with 3213 additions and 245 deletions

191
README.md
View File

@@ -17,69 +17,39 @@ This project provides a web UI for Caddy Server, eliminating the need to manuall
**Key features:**
- Reverse proxy configuration with upstream pools and custom headers
- HTTP basic auth access lists
- OAuth2/OIDC authentication support
- Automatic HTTPS via Caddy's ACME (Let's Encrypt) with Cloudflare DNS-01 support
- Custom certificate import (internal CA, wildcards, etc.)
- Audit logging of all configuration changes
- Login rate limiting and session management
- Built with Next.js 16, React 19, Drizzle ORM, and TypeScript
---
## Installation
### Docker Compose
```bash
git clone https://github.com/fuomag9/caddy-proxy-manager.git
cd caddy-proxy-manager
cp .env.example .env
# Edit .env with your credentials (see Configuration section below)
# Edit .env with your credentials
docker compose up -d
```
The stack includes:
- `web` - Next.js app with SQLite database
- `caddy` - Custom Caddy build (includes Cloudflare DNS and Layer4 modules)
Access at `http://localhost:3000/login`
Data is persisted in:
- `./data` - Application database and certificates
- `./caddy-data` - ACME certificates
- `./caddy-config` - Caddy runtime config
### Local Development
```bash
npm install
cp .env.example .env
# Edit .env with your credentials
npm run dev
```
Access the interface at `http://localhost:3000/login`.
Login attempts are rate-limited (5 attempts per 5 minutes, 15 minute lockout after repeated failures).
Data persists in `./data`, `./caddy-data`, and `./caddy-config`.
---
## Features
| Module | Description |
|--------|-------------|
| **Proxy Hosts** | HTTP/HTTPS reverse proxies with upstream pools, custom headers, Authentik forward auth |
| **Redirects** | 301/302 redirects with optional query string preservation |
| **Dead Hosts** | Maintenance pages with custom status codes |
| **Access Lists** | HTTP basic auth user management for proxy hosts |
| **Certificates** | Custom SSL/TLS certificate import (Caddy auto-manages Let's Encrypt) |
| **Settings** | ACME email and Cloudflare API configuration |
| **Audit Log** | Chronological log of all configuration changes |
**Technical Stack:**
- Next.js 16 App Router with React 19
- Material UI (dark theme)
- Drizzle ORM with SQLite
- Direct integration with Caddy Admin API
- Cloudflare DNS-01 challenge support
- bcrypt for access list password hashing
- **Proxy Hosts** - Reverse proxies with custom headers and upstream pools
- **Redirects** - 301/302 redirects
- **Dead Hosts** - Maintenance pages
- **Access Lists** - HTTP basic auth
- **Certificates** - Custom SSL/TLS import (automatic Let's Encrypt via Caddy)
- **Settings** - ACME email and Cloudflare DNS-01 configuration
- **Audit Log** - Configuration change tracking
---
@@ -99,153 +69,68 @@ Login attempts are rate-limited (5 attempts per 5 minutes, 15 minute lockout aft
| `LOGIN_MAX_ATTEMPTS` | Max login attempts before rate limit | `5` | No |
| `LOGIN_WINDOW_MS` | Rate limit window in milliseconds | `300000` (5 min) | No |
| `LOGIN_BLOCK_MS` | Rate limit block duration in milliseconds | `900000` (15 min) | No |
| `OAUTH_ENABLED` | Enable OAuth2/OIDC authentication | `false` | No |
| `OAUTH_PROVIDER_NAME` | Display name for OAuth provider | `OAuth2` | No |
| `OAUTH_CLIENT_ID` | OAuth2 client ID | None | No |
| `OAUTH_CLIENT_SECRET` | OAuth2 client secret | None | No |
| `OAUTH_ISSUER` | OAuth2 OIDC issuer URL | None | No |
**Production Security Requirements (Strictly Enforced):**
**Production Requirements:**
- `SESSION_SECRET`: 32+ characters (`openssl rand -base64 32`)
- `ADMIN_PASSWORD`: 12+ chars with uppercase, lowercase, numbers, and special characters
The application will **fail to start** in production if these requirements are not met:
- **`SESSION_SECRET`**:
- Must be at least 32 characters long
- Cannot be a known placeholder value
- Generate with: `openssl rand -base64 32`
- **`ADMIN_USERNAME`**:
- Must be set (any value is acceptable, including `admin`)
- **`ADMIN_PASSWORD`**:
- Minimum 12 characters
- Must include uppercase letters (A-Z)
- Must include lowercase letters (a-z)
- Must include numbers (0-9)
- Must include special characters (!@#$%^&* etc.)
- Cannot be `admin` in production
**Development Mode:**
- Default credentials (`admin`/`admin`) are allowed in development
- Set `NODE_ENV=development` to use relaxed validation
Development mode (`NODE_ENV=development`) allows default `admin`/`admin` credentials.
---
## Architecture
```
caddy-proxy-manager/
├── app/ # Next.js App Router
│ ├── (auth)/ # Authentication pages
│ ├── (dashboard)/ # Dashboard and feature modules
│ ├── api/ # API routes
│ └── providers.tsx # Theme providers
├── src/lib/ # Core business logic
│ ├── models/ # Database models
│ ├── caddy/ # Caddy config generation
│ └── auth/ # Authentication
├── drizzle/ # Database migrations
├── docker/
│ ├── web/ # Next.js Dockerfile
│ └── caddy/ # Custom Caddy build
├── docker-compose.yml # Deployment stack
└── data/ # SQLite + certificates
```
---
## Security
**Authentication:**
- Production mode enforces strong credentials (12+ chars, mixed case, numbers, special characters)
- Application refuses to start with weak passwords in production
- Production enforces strong passwords (12+ chars, mixed case, numbers, special characters)
- 32+ character session secrets required
- Login rate limiting: 5 attempts per 5 minutes, 15 minute lockout
- Single admin user model
**Data Protection:**
- Imported certificates stored with `0600` permissions
- Session encryption with validated secrets
- API tokens redacted after initial entry
- Login rate limiting: 5 attempts per 5 minutes
- Audit trail for all configuration changes
- HSTS headers applied to managed hosts
- Supports OAuth2/OIDC for SSO
**Production Setup:**
```bash
export SESSION_SECRET=$(openssl rand -base64 32)
export ADMIN_USERNAME="admin"
export ADMIN_PASSWORD="YourStr0ng-P@ssw0rd123!"
echo "SESSION_SECRET=$SESSION_SECRET" > .env
echo "ADMIN_USERNAME=$ADMIN_USERNAME" >> .env
echo "ADMIN_PASSWORD=$ADMIN_PASSWORD" >> .env
chmod 600 .env
```
**Development Mode:**
```bash
export NODE_ENV=development
npm run dev
# Login with admin/admin
docker compose up -d
```
**Limitations:**
- Certificate private keys stored unencrypted in SQLite
- In-memory rate limiting (not suitable for multi-instance deployments)
- No 2FA support
---
## Certificate Management
**Automatic HTTPS (Default):**
Caddy automatically obtains Let's Encrypt certificates for all proxy hosts.
Caddy automatically obtains and renews Let's Encrypt certificates for all proxy hosts. Just add a domain and certificates are handled automatically.
**Cloudflare DNS-01** (optional): Configure in Settings with a Cloudflare API token (`Zone.DNS:Edit` permissions).
For automatic certificates, configure Cloudflare DNS-01 in Settings (see below).
**Custom Certificates (Optional):**
Import your own certificates for:
- Internal CA certificates
- Certificates from other providers
- Compliance requirements
To import:
1. Go to Certificates page
2. Click Import Custom Certificate
3. Enter certificate name and domains
4. Paste certificate PEM (full chain recommended)
5. Paste private key PEM
6. Assign to proxy hosts as needed
Note: Private keys are stored in SQLite without encryption.
**Custom Certificates** (optional): Import your own certificates via the Certificates page. Private keys are stored unencrypted in SQLite.
---
## Cloudflare DNS-01 Setup
## OAuth Authentication
For automatic certificates via DNS-01 challenge:
Supports any OIDC-compliant provider (Authentik, Keycloak, Auth0, etc.).
1. Go to Settings
2. Create a Cloudflare API token with `Zone.DNS:Edit` permissions
3. Enter token (not displayed again after saving)
4. Optionally add Zone ID / Account ID
5. Set ACME email for certificate notifications
```bash
OAUTH_ENABLED=true
OAUTH_PROVIDER_NAME="Authentik" # Display name
OAUTH_CLIENT_ID=your-client-id
OAUTH_CLIENT_SECRET=your-client-secret
OAUTH_ISSUER=https://auth.example.com/application/o/app/
```
To revoke: Select "Remove existing token" in Settings.
**Redirect URI**: `{BASE_URL}/api/auth/callback/oauth2`
---
## Development
| Command | Description |
|---------|-------------|
| `npm run dev` | Development server with hot reload |
| `npm run build` | Production build |
| `npm start` | Run production server |
| `npm run typecheck` | TypeScript type checking |
| `npm run db:migrate` | Apply database migrations |
**Notes:**
- Drizzle migrations are in `/drizzle`
- Caddy config regenerated on each mutation and pushed via Admin API
- Rate limiting is in-memory (not suitable for multi-instance deployments)
- Single admin user architecture
OAuth login appears on the login page alongside credentials. Users can link OAuth to existing accounts from the Profile page.
---