DC-095 masks emails at every live log sink; the rotated archive was the remaining belt-and-braces gap — any future sink that forgets masking would persist raw PII in error.log.1 for a full rotation cycle. appendErrorLog now scrubs the freshly rotated archive with the SAME canonical mask (sa****@example.com) via atomic rewrite (sibling .redact-<pid> temp, wx open preserving mode else 0600, fsync, rename). Scrub failure is caught and logged; the new error line is still appended. Stale crash-leftover .redact-<pid> temps are swept best-effort on every rotation. Also documents scripts/redact-log-pii.js usage in README (queue item e). Judge: GLM-5.3 cold read (deleg_e7cd7f8c), round-1 grade B ship — both nits addressed in-commit: stale-temp sweep (new 5th test pins it), quoted-local-part mask edge deferred as pre-existing DC-095 primitive. Tests: 122 suites / 2790 green (+5 DC-108 pins; was 2785 post-DC-107).
434 lines
12 KiB
Markdown
434 lines
12 KiB
Markdown
# DashCaddy
|
|
|
|
**Self-hosted dashboard for managing Docker apps with automatic SSL, DNS, and reverse proxy configuration.**
|
|
|
|

|
|

|
|
|
|
## What is DashCaddy?
|
|
|
|
DashCaddy is an all-in-one solution for self-hosting Docker applications. It combines:
|
|
- 🎨 **Beautiful Dashboard** - Monitor all your services in one place
|
|
- 🐳 **Docker Management** - Deploy 50+ pre-configured apps with one click
|
|
- 🔒 **Automatic SSL** - Internal CA with automatic certificate generation
|
|
- 🌐 **DNS Integration** - Automatic DNS record creation (Technitium DNS)
|
|
- 🔄 **Reverse Proxy** - Caddy configuration managed automatically
|
|
- 🔐 **Tailscale Support** - Secure remote access built-in
|
|
|
|
## Features
|
|
|
|
### Authentication & Security
|
|
- Built-in TOTP two-factor authentication
|
|
- Fine-grained access control per service
|
|
- Secure session management
|
|
- Group-based permissions
|
|
|
|
### Dashboard
|
|
- Real-time service health monitoring
|
|
- Response time tracking
|
|
- Status indicators with visual feedback
|
|
- Weather widget
|
|
- Multiple themes (dark/light/blue)
|
|
- Import/export configuration
|
|
|
|
### App Deployment
|
|
- 50+ pre-configured app templates
|
|
- One-click deployment
|
|
- Automatic DNS + SSL + reverse proxy setup
|
|
- Container health checking
|
|
- Deployment status tracking
|
|
- SSL certificate generation monitoring
|
|
|
|
### Service Management
|
|
- Add/edit/delete services
|
|
- Restart containers
|
|
- View logs
|
|
- Update configurations
|
|
- Silent deletions (no annoying popups)
|
|
|
|
### Developer Tools
|
|
- Error log viewer
|
|
- API endpoints for automation
|
|
- Import/export for testing
|
|
- Comprehensive error logging
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
- Docker & Docker Compose
|
|
- Caddy web server
|
|
- Technitium DNS (optional, for automatic DNS)
|
|
- Node.js 18+ (for API server)
|
|
|
|
### Installation
|
|
|
|
1. **Clone the repository**
|
|
```bash
|
|
git clone https://github.com/yourusername/dashcaddy.git
|
|
cd dashcaddy
|
|
```
|
|
|
|
2. **Install dependencies**
|
|
```bash
|
|
cd caddy-api
|
|
npm install
|
|
```
|
|
|
|
3. **Configure environment**
|
|
```bash
|
|
cp .env.example .env
|
|
# Edit .env with your settings
|
|
```
|
|
|
|
4. **Start the API server**
|
|
```bash
|
|
npm start
|
|
```
|
|
|
|
5. **Configure Caddy**
|
|
Add to your Caddyfile:
|
|
```
|
|
status.yourdomain.com {
|
|
root * /path/to/dashcaddy/status
|
|
file_server
|
|
reverse_proxy /api/* localhost:3001
|
|
}
|
|
```
|
|
|
|
6. **Access the dashboard**
|
|
Open `https://status.yourdomain.com` in your browser
|
|
|
|
## Health Probes
|
|
|
|
DashCaddy exposes Kubernetes/Docker-standard health endpoints for container orchestration. **No auth required** — these are designed for orchestration tooling to poll.
|
|
|
|
| Path | Purpose | Returns |
|
|
|------|---------|---------|
|
|
| `/healthz` or `/health/live` | **Liveness** — is the Node.js process alive? | 200 with `{status: "alive", uptime: <seconds>}` |
|
|
| `/readyz` or `/health/ready` | **Readiness** — are critical deps reachable? (config file, services file, Docker daemon, Caddy admin API) | 200 if all OK, 503 if any dep fails (with details in the `checks` object) |
|
|
| `/health` | Backwards-compat alias for `/healthz` | Same as `/healthz` |
|
|
|
|
**When to use which:**
|
|
- Use `/healthz` / `/health/live` in a `livenessProbe` — should the container be **restarted**?
|
|
- Use `/readyz` / `/health/ready` in a `readinessProbe` — should traffic be **routed** to this instance?
|
|
|
|
### Docker Compose healthcheck
|
|
|
|
Copy-paste this into your DashCaddy `docker-compose.yml`:
|
|
|
|
```yaml
|
|
services:
|
|
dashcaddy-api:
|
|
image: ghcr.io/samiahmed7777/dashcaddy-api:latest
|
|
# ... your existing config ...
|
|
healthcheck:
|
|
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3001/readyz', r => process.exit(r.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
```
|
|
|
|
### Kubernetes probes
|
|
|
|
```yaml
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /healthz
|
|
port: 3001
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /readyz
|
|
port: 3001
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
```
|
|
|
|
Both endpoints return JSON. Liveness is cheap (no I/O, no deps). Readiness touches the Docker daemon and Caddy admin API with a 3-second timeout each, so it's safe to poll every 10s without load concerns.
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
Create a `.env` file in the `caddy-api` directory:
|
|
|
|
```env
|
|
# Caddy Configuration
|
|
CADDYFILE_PATH=/path/to/Caddyfile
|
|
CADDY_ADMIN_URL=http://localhost:2019
|
|
|
|
# DNS Configuration (optional)
|
|
DNS_SERVER=192.168.1.1
|
|
DNS_TOKEN=your-dns-token
|
|
|
|
# File Paths
|
|
SERVICES_FILE=/path/to/services.json
|
|
ERROR_LOG_FILE=/path/to/dashcaddy-errors.log
|
|
```
|
|
|
|
### DNS Integration
|
|
|
|
DashCaddy works with Technitium DNS for automatic DNS record creation:
|
|
|
|
1. Install Technitium DNS
|
|
2. Create an API token with DNS management permissions
|
|
3. Configure DNS credentials in dashboard (🔑 Tokens button)
|
|
|
|
### Tailscale Integration
|
|
|
|
For secure remote access:
|
|
|
|
1. Install Tailscale on your server
|
|
2. Services can be restricted to Tailscale-only access
|
|
3. Configure in deployment settings
|
|
|
|
## Usage
|
|
|
|
### Deploying an App
|
|
|
|
1. Click **"App Selector"** button
|
|
2. Choose an app from the template library
|
|
3. Configure:
|
|
- Subdomain (e.g., `jellyfin` → `jellyfin.yourdomain.com`)
|
|
- Port (auto-suggested)
|
|
- IP address (defaults to localhost)
|
|
- Tailscale-only access (optional)
|
|
4. Click **"Deploy"**
|
|
5. Wait for SSL certificate generation (30-60 seconds)
|
|
6. Access your app!
|
|
|
|
### Managing Services
|
|
|
|
- **View Status**: Cards show real-time health and response times
|
|
- **Open Service**: Click "Open" button
|
|
- **Restart**: Click restart button (for Docker containers)
|
|
- **Delete**: Click delete button (removes everything: container, DNS, Caddy config)
|
|
- **Edit**: Click settings button to modify configuration
|
|
|
|
### Viewing Error Logs
|
|
|
|
1. Click **"📋 Logs"** button in toolbar
|
|
2. View all errors with timestamps and context
|
|
3. Refresh to see latest errors
|
|
4. Clear logs when resolved
|
|
|
|
### Log PII Redaction
|
|
|
|
Every log sink (console JSON, `error.log`, audit details) masks email addresses with a canonical form (`sa****@example.com`) — raw addresses never reach disk or stdout. When `error.log` crosses 5 MB it rotates to `error.log.1`, and the archive is scrubbed with the same canonical mask on rotation.
|
|
|
|
For **pre-existing** log files written before this defense existed:
|
|
|
|
```bash
|
|
node scripts/redact-log-pii.js --dry-run <file-or-dir> # see what would change
|
|
node scripts/redact-log-pii.js <file-or-dir> # atomic in-place rewrite
|
|
```
|
|
|
|
The script is idempotent, never touches byte-identical files (mtime preserved), reuses the same masking code the live logger uses (no regex drift), and post-verifies that no raw address remains (exit code 2 if any does). See `dashcaddy-api/scripts/redact-log-pii.js` header for flags including `--keep-raw` (explicitly preserves the raw copy — avoid unless required).
|
|
|
|
### Backup & Restore
|
|
|
|
**Export Configuration:**
|
|
1. Click **"📤 Export"** button
|
|
2. JSON file downloads with all your services
|
|
3. Save safely
|
|
|
|
**Import Configuration:**
|
|
1. Click **"📥 Import"** button
|
|
2. Select your backup JSON file
|
|
3. Confirm import
|
|
4. Dashboard reloads with restored configuration
|
|
|
|
**Note**: API tokens are not exported for security. Reconfigure after import.
|
|
|
|
## App Templates
|
|
|
|
DashCaddy includes 50+ pre-configured templates:
|
|
|
|
### Media & Entertainment
|
|
- Plex, Jellyfin, Emby
|
|
- Navidrome, Airsonic
|
|
- Tautulli, Overseerr
|
|
|
|
### Downloads
|
|
- Sonarr, Radarr, Lidarr, Readarr
|
|
- Prowlarr, Bazarr
|
|
- qBittorrent, Transmission
|
|
- SABnzbd, NZBGet
|
|
|
|
### Productivity
|
|
- Nextcloud
|
|
- Paperless-ngx
|
|
- BookStack, Outline
|
|
- Standard Notes
|
|
|
|
### Management
|
|
- Portainer
|
|
- Homepage, Homarr
|
|
- Uptime Kuma
|
|
- Grafana
|
|
|
|
### Security & Authentication
|
|
- Vaultwarden (Password Manager)
|
|
|
|
### Development
|
|
- Gitea
|
|
- VS Code Server
|
|
- Jenkins, Drone CI
|
|
|
|
### And many more!
|
|
|
|
## API Endpoints
|
|
|
|
### Services
|
|
- `GET /api/services` - List all services
|
|
- `POST /api/services` - Add service
|
|
- `PUT /api/services` - Bulk import services
|
|
- `DELETE /api/services/:id` - Remove service
|
|
|
|
### App Deployment
|
|
- `GET /api/apps/templates` - List app templates
|
|
- `POST /api/apps/deploy` - Deploy new app
|
|
- `DELETE /api/apps/:id` - Remove deployed app
|
|
|
|
### Error Logs
|
|
- `GET /api/error-logs` - Get error logs
|
|
- `DELETE /api/error-logs` - Clear error logs
|
|
|
|
### DNS Management
|
|
- `POST /api/dns/record` - Create DNS record
|
|
- `DELETE /api/dns/record` - Delete DNS record
|
|
|
|
### Caddy Management
|
|
- `GET /api/caddy/config` - Get Caddyfile content
|
|
- `POST /api/caddy/reload` - Reload Caddy configuration
|
|
|
|
## Troubleshooting
|
|
|
|
### SSL Certificate Errors
|
|
|
|
**Problem**: "Secure Connection Failed" when accessing new service
|
|
|
|
**Solution**:
|
|
- Wait 30-60 seconds for certificate generation
|
|
- Check dashboard notification for SSL status
|
|
- Manually reload Caddy: `caddy reload --config /path/to/Caddyfile`
|
|
- Check error logs in dashboard
|
|
|
|
### DNS Not Resolving
|
|
|
|
**Problem**: Service URL doesn't resolve
|
|
|
|
**Solution**:
|
|
- Verify DNS server is running
|
|
- Check DNS credentials in 🔑 Tokens menu
|
|
- Manually add DNS record in Technitium DNS
|
|
- Flush DNS cache: `ipconfig /flushdns` (Windows) or `sudo systemd-resolve --flush-caches` (Linux)
|
|
|
|
### Container Won't Start
|
|
|
|
**Problem**: Deployment succeeds but service is offline
|
|
|
|
**Solution**:
|
|
- Check Docker logs: `docker logs [container-id]`
|
|
- Verify port isn't already in use
|
|
- Check container resource limits
|
|
- View error logs in dashboard
|
|
|
|
### Import/Export Issues
|
|
|
|
**Problem**: Import fails or data is incomplete
|
|
|
|
**Solution**:
|
|
- Validate JSON format
|
|
- Check file has `version` and `services` fields
|
|
- Reconfigure API tokens after import
|
|
- Check error logs for details
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
dashcaddy/
|
|
├── status/ # Dashboard frontend
|
|
│ ├── index.html # Main dashboard
|
|
│ └── assets/ # Logos, icons, fonts
|
|
├── caddy-api/ # API backend
|
|
│ ├── server.js # Express server
|
|
│ ├── app-templates.js # App template definitions
|
|
│ └── package.json # Dependencies
|
|
├── dashcaddy-installer/ # Electron installer (WIP)
|
|
└── docs/ # Documentation
|
|
```
|
|
|
|
### Adding Custom App Templates
|
|
|
|
Edit `caddy-api/app-templates.js`:
|
|
|
|
```javascript
|
|
"myapp": {
|
|
name: "My App",
|
|
description: "Description of my app",
|
|
icon: "🚀",
|
|
logo: "https://cdn.example.com/logo.png",
|
|
category: "Productivity",
|
|
docker: {
|
|
image: "myapp/myapp:latest",
|
|
ports: ["{{PORT}}:8080"],
|
|
volumes: ["/opt/myapp:/data"],
|
|
environment: {
|
|
"APP_ENV": "production"
|
|
}
|
|
},
|
|
subdomain: "myapp",
|
|
defaultPort: 8080,
|
|
healthCheck: "/health"
|
|
}
|
|
```
|
|
|
|
### Contributing
|
|
|
|
Contributions are welcome! Please:
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Make your changes
|
|
4. Test thoroughly
|
|
5. Submit a pull request
|
|
|
|
## Roadmap
|
|
|
|
- [ ] Service groups/categories
|
|
- [ ] Container log viewer
|
|
- [ ] DNS management UI
|
|
- [ ] Backup automation
|
|
- [ ] Multi-user support
|
|
- [ ] Mobile app
|
|
- [ ] Analytics dashboard
|
|
- [ ] Template marketplace
|
|
|
|
## License
|
|
|
|
Proprietary software. All rights reserved. See [LICENSE](LICENSE) for the End-User License Agreement (EULA).
|
|
|
|
## Credits
|
|
|
|
- **Dashboard Icons**: [walkxcode/dashboard-icons](https://github.com/walkxcode/dashboard-icons) (MIT License)
|
|
- **Caddy**: [caddyserver.com](https://caddyserver.com/)
|
|
- **Technitium DNS**: [technitium.com/dns](https://technitium.com/dns/)
|
|
|
|
## Support
|
|
|
|
- **Issues**: [GitHub Issues](https://github.com/yourusername/dashcaddy/issues)
|
|
- **Discussions**: [GitHub Discussions](https://github.com/yourusername/dashcaddy/discussions)
|
|
- **Documentation**: [Wiki](https://github.com/yourusername/dashcaddy/wiki)
|
|
|
|
## Acknowledgments
|
|
|
|
Built with ❤️ for the self-hosting community.
|
|
|
|
---
|
|
|
|
**DashCaddy** - Making self-hosting beautiful and effortless.
|