# DashCaddy

**Self-hosted dashboard for managing Docker apps with automatic SSL, DNS, and reverse proxy configuration.**

![Version](https://img.shields.io/badge/version-1.15.0-blue)
![License](https://img.shields.io/badge/license-Proprietary-red)

## 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
├── dashcaddy-api/         # API backend
│   ├── server.js          # Express server
│   ├── src/docker/app-templates.js   # App template definitions
│   └── package.json       # Dependencies
├── dashcaddy-installer/   # Electron installer (WIP)
└── docs/                  # Documentation
```

### Adding Custom App Templates

Edit `dashcaddy-api/src/docker/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.
