Commit Graph

47 Commits

Author SHA1 Message Date
6c3848102b refactor: Phase 1 code cleanup - constants, logging, and repository organization 2026-03-28 18:54:39 -07:00
f1b0ac43d0 fix: Taxi theme accent color now distinct from text
Accent was #0e0e00 (same as --fg), making buttons and interactive
elements invisible. Changed to #7a4a00/#5c3800 dark amber.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:19:00 -07:00
4ab9a770be chore: bump version to 1.1.5
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:40:18 -07:00
c49d86b0b8 fix: preserve service ID on subdomain change, accept localhost as IP
- serviceUrl() now checks service.url before falling back to buildServiceUrl(id)
- Service update no longer overwrites ID with the new subdomain
- Accept "localhost" as valid IP in service update validation
- Find services by ID or URL match when updating

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 17:38:41 -07:00
e5cd8678b0 fix: add pylon relay fallback to dashboard status endpoint
The dashboard uses /api/v1/services/status (not /api/health/services)
for live status cards. This endpoint was missing pylon relay fallback,
so services unreachable from the Docker container showed as OFF even
when the pylon was running. Also adds Windows VBS startup wrapper for
pylon persistence across reboots.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:50:24 -07:00
fc6275a96b feat: add Pylon health relay for remote service health checks
DashCaddy Pylon is a lightweight probe agent that runs on remote
networks to relay health checks for services the main DashCaddy
instance can't reach directly (e.g., .sami domains, LAN IPs).

- Standalone zero-dependency Node.js script (pylon/dashcaddy-pylon.js)
- Optional API key auth, HEAD→GET fallback, batch probe support
- Health routes now try direct check first, fall back to pylon relay
- New endpoints: /health/probe (act as pylon), /health/pylon (status)
- Config: add "pylon": { "url": "...", "key": "..." } to config.json

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 15:52:43 -07:00
d332084206 feat: add host-side auto-updater for zero-touch API container rebuilds
When the in-container self-updater downloads a new version, it writes
trigger.json. The new systemd path unit watches for this file and runs
dashcaddy-update.sh, which backs up current API files, copies the new
ones, rebuilds the container, verifies health, and writes result.json.
Automatic rollback on build or health check failure.

Also fixes undefined `isWindows` variable in self-updater.js and adds
DASHCADDY_HOST_UPDATES_DIR env var to the installer's docker-compose
template for correct container-to-host path translation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:25:22 -07:00
abd54d4b99 fix: prevent encryption key conflicts and add license backup
- Remove eager key generation from crypto-utils module load (was baking
  keys into Docker images that conflicted with mounted production keys)
- Add license backup to config.json (survives credential store failures)
- LicenseManager.load() falls back to config.json backup if credential
  store decryption fails (e.g. after container rebuild with new key)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 14:17:25 -07:00
64b3534c7d Merge branch 'main' of http://100.98.123.59:3000/sami7777/dashcaddy
# Conflicts:
#	dashcaddy-api/.license-counter
#	dashcaddy-api/__tests__/docker-security.test.js
2026-03-23 13:42:22 -07:00
b4022288dc fix: service edit, CSRF token stability, and license restore (v1.1.1)
- Fix service edit double-write bug (was creating duplicate entries)
- Add editable display name field to service edit modal
- Backend update endpoint now accepts name, logo, and recalculates url
- Fix CSRF token regeneration breaking all POST requests (nonce was
  being regenerated on every request, invalidating cached tokens)
- CSRF nonce now persists across requests, rotated only on TOTP login
- Frontend secureFetch auto-retries on CSRF failure with fresh token
- Restore lifetime license activation on DNS2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 13:39:05 -07:00
Krystie
d76644d948 Sync DNS2 production changes - removed obsolete test suite and refactored structure 2026-03-23 10:47:15 +01:00
Krystie
1ac50918ab Add package-lock and deployment script updates 2026-03-23 10:35:29 +01:00
Krystie
024be9c929 Build frontend bundles with CSRF token support 2026-03-23 10:34:57 +01:00
263b090769 test: add comprehensive docker-security test suite (41 tests) 2026-03-22 11:46:30 -07:00
Krystie
883cce27df Phase 3 (WIP): Refactor license, credentials, backups routes
- All use explicit deps instead of ctx
- Pattern consistent across all refactored routes
2026-03-22 11:09:55 +01:00
Krystie
81f778df72 Phase 3 (WIP): Refactor containers & monitoring routes
- routes/containers.js: Explicit deps (docker, asyncHandler, log)
- routes/monitoring.js: Explicit deps (docker, resourceMonitor)
- Pattern established: factory function with destructured deps
2026-03-22 11:09:16 +01:00
Krystie
3efa5dc3f4 Phase 2 (WIP): Extract context modules (caddy, dns)
- src/context/caddy.js: Caddyfile manipulation, reload, config generation
- src/context/dns.js: DNS API wrapper with token management
- All context modules use factory pattern with explicit dependencies
2026-03-22 11:08:05 +01:00
Krystie
efa9c7ba6b Phase 2 (WIP): Add caddy context module
- src/context/caddy.js: Caddyfile manipulation, reload, config generation
- Uses dependency injection (init() pattern) for siteConfig, log, fetchT
- Atomic mutex-based modifications with rollback on failure
- All Caddy operations now in one module
2026-03-22 11:07:03 +01:00
Krystie
6771e4775e Phase 2 (WIP): Add logger and docker context modules
- src/utils/logger.js: Structured JSON logging
- src/context/docker.js: Docker API wrapper (pull, findContainer, getUsedPorts)
- All modules can now be imported directly instead of via ctx
2026-03-22 11:05:50 +01:00
Krystie
d5a6789366 Phase 2 (WIP): Extract config and utils modules
- Created src/config/ (env.js, site-config.js)
- Created src/utils/ (async-handler.js, responses.js, safe-error.js)
- server.js not yet modified (backward-compatible extraction)
2026-03-22 11:04:04 +01:00
Krystie
039d3d07e2 Phase 1: Add dependency analysis documentation 2026-03-22 11:01:40 +01:00
Krystie
e2c67a8fe8 Phase 1: Add ESLint/Prettier config + baseline auto-fixes 2026-03-22 11:00:25 +01:00
41a0cdee7e test: expand credential-manager edge case coverage 2026-03-22 02:37:32 -07:00
6775dc154b test: add comprehensive docker-security test suite (39 tests) 2026-03-20 22:45:55 -07:00
43b06c519f test: add comprehensive docker-security test suite (39 tests, Phase 3) 2026-03-20 22:45:11 -07:00
d15c160185 test: add comprehensive auth-manager test suite (Phase 3 WIP) 2026-03-20 22:19:45 -07:00
Krystie
3c5376c7b9 security: implement Phase 1-2 fixes (logger sanitization + tests)
- Add logger-utils.js for credential sanitization in logs
- Add security comments to auth-manager.js
- Create .env.example template
- Add .env to .gitignore
- Implement comprehensive logger-utils tests (16 cases)

Desloppify score: 15.4 → ~25-30 (estimated)
Security: 62.5% → ~80%
Test coverage: 0% → ~5%

Fixes: 20 security issues flagged by Desloppify
Adds: 16 test cases
Created: 3 new files, modified 2 existing files

See SECURITY-IMPROVEMENTS.md for full details.
2026-03-21 03:43:03 +01:00
06fc5f1d95 Add uptime bars to DNS cards
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 21:33:00 -07:00
75e2d7853e Unify backup/restore into single v2.0 file with full state capture
Server export now includes encryption key, themes, and all config files.
Client export bundles all DashCaddy localStorage keys (19 named + dynamic
widget keys) as browserState. Restore handles both server and browser
state in one operation. Legacy v1.0 import format still supported.
Removed redundant Export/Import toolbar buttons — Backup modal is now
the single entry point.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 21:06:56 -07:00
6d098fd96f Exempt DNS logs from rate limiting and hide Tokens button when no DNS configured
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 19:31:12 -07:00
f2f33b4b40 Make DNS servers fully dynamic from config.json
DNS server IDs (dns1, dns2, dns3) were hardcoded throughout the frontend
and backend. Now config.json's dnsServers object is the single source of
truth — adding or removing a DNS server in config automatically updates
the dashboard cards, credential modal, health checks, and probes.

- credentials.js: rebuild modal sections dynamically from SITE.dnsServers
- globals.js: add getPrimaryDnsId() helper for primary DNS lookups
- service-create.js, service-infrastructure.js: use dynamic DNS ID
- startup-validator.js: dynamic topCardServices from config
- middleware.js: add license endpoints to public routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 16:55:07 -07:00
2815233e86 Unify URL resolution, add health checker sync, and make modules optional
- Add url-resolver.js with single resolveServiceUrl() used by all 5 consumers
  (probes, health routes, health checker auto-config)
- Health checker now does full sync (add/update/remove) instead of add-only,
  and re-syncs automatically after every services.json mutation
- docker-maintenance and log-digest are now optional imports with try/catch,
  preventing container crashes when these files are absent
- Add null guards in routes/logs.js for graceful 503 responses

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 23:01:20 -07:00
70b818c2bd Fix Tailscale route prefix mismatch and increase health check timeout
Mount Tailscale router at /tailscale prefix so all 10 routes resolve
to /api/tailscale/* as expected by middleware, audit logger, and
frontend. Previously 5 routes (status, config, check-connection,
devices, protect-service) resolved to /api/* instead, with config
colliding with the settings route. Strip redundant /tailscale/ prefix
from OAuth routes that were compensating for the missing mount prefix.

Increase default health check timeout from 10s to 20s to reduce false
positives on slower services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-14 18:44:20 -07:00
Krystie
df0daaad46 Add full cross-platform path support
- Added automatic volume path translation in deployment (deploy.js)
- Updated FileBrowser template to use /opt/ instead of hard-coded E:/
- Migrated self-updater.js to use centralized platformPaths module
- Updated UI placeholders to use platform-neutral paths (/media/)
- All paths now automatically adapt to Windows or Linux at runtime via process.platform detection
2026-03-14 06:52:18 +01:00
e615f24627 Add Docker hygiene, deployment manifests, and daily log digest
Prevents Docker disk bloat by adding log rotation (10MB max, 3 files)
to all container creation and update paths, auto-pruning dangling
images after deploy/remove/update, and a daily maintenance module
that cleans build cache and warns on disk thresholds.

Saves a deployment manifest in services.json at deploy time so users
can restore all their apps after a Docker purge. Adds restore-all
and restore-single endpoints that recreate containers, Caddy config,
and DNS records from the saved manifests.

Adds an hourly log collector and daily digest generator that
summarizes errors, warnings, and events across all services into
a single human-readable report with guidance on where to investigate.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 21:41:40 -07:00
root
4131c3c6f6 Fix CSRF cookie Secure flag for localhost development
- Changed hardcoded secure:true to req.secure || req.protocol === 'https'
- Allows CSRF cookies to work over HTTP on localhost
- Still enforces secure flag for HTTPS connections
- Enables OpenClaw programmatic API access
2026-03-13 05:30:09 +01:00
0f4bd419e1 Add batched status endpoint and optimize frontend performance
Server-side batched /api/v1/services/status endpoint replaces N
individual browser probes with a single API call (HEAD-first with
GET fallback, concurrency-limited, CA-aware HTTPS agent).

Frontend: clock reuses DOM instead of rebuilding innerHTML every
second with drift-correcting timer that pauses on hidden tabs.
Card animations use CSS transitionDelay + requestAnimationFrame.
Internet dot blink moved from JS intervals to CSS keyframes with
prefers-reduced-motion support. Service worker rewritten with
network-first navigation, stale-while-revalidate assets, and
navigation preload. Font faces drop TTF fallbacks, use font-display
swap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 22:39:29 -07:00
063bf948b1 Make onboarding tour install-wide instead of per-browser
Persist onboardingCompleted flag server-side via /api/v1/config so the
tour only auto-starts once per DashCaddy installation, not on every
new browser that connects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 21:58:10 -07:00
2d1944fd55 Fix auto-update pipeline bugs discovered in e2e testing
- Fix container-to-host path mapping in trigger.json (stagingDir
  was using container path /app/updates/ instead of host path
  /opt/dashcaddy/updates/)
- Fix download race condition: primary download's async unlink
  could delete mirror download's file — use unlinkSync before retry
- Fix DASHCADDY_COMMIT build arg not passed to docker compose build
  (was set as env var, now uses --build-arg)
- Remove MakeDirectory=yes from systemd path unit (was creating
  trigger.json as directory instead of file)
- Remove unused 'tar' npm module import
- Add mirror fallback for tarball downloads (not just version checks)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:32:08 -08:00
ffa6966fd3 Add auto-update system for DashCaddy instances
- self-updater.js: polls for new versions, downloads/verifies tarballs,
  triggers host-side rebuild via systemd path unit
- dashcaddy-update.sh + systemd units: host-side container rebuild with
  automatic rollback on health check failure
- 7 new /api/v1/system/* endpoints for version info, update check/apply,
  rollback, and update history
- Frontend: DashCaddy tab in Updates modal with version display,
  changelog, update button, rollback, and notification dot
- install.sh: updater service installation, volume mounts, env vars
- build-release.sh + webhook-handler.js: release server pipeline
  (Gitea webhook → build tarball → deploy to get.dashcaddy.net)
- Dockerfile: DASHCADDY_COMMIT build arg → VERSION file
- Version bump to 1.1.0

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 03:11:35 -08:00
9a0abc02d1 Fix remaining frontend security issues (3 medium, 2 low)
- Escape user-input port number in app-selector innerHTML
- Replace inline onclick with addEventListener in backup history (HTML entity decode bypass)
- Add Content-Security-Policy meta tag with script hash
- Replace document.write with textContent for footer year
- Filter __proto__/constructor/prototype in Object.assign calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 02:06:55 -08:00
52577b11ed Fix 7 frontend security vulnerabilities (4 critical, 3 high)
- Escape all innerHTML assignments with user/external data across 12 JS files
- Upgrade credential encryption: per-value IV, key moved to sessionStorage
- Fix open redirect in TOTP auth via proper URL hostname validation
- Remove sensitive DNS topology data from localStorage cache
- Add security regression test suite (51 tests)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:29:04 -08:00
59b6d7d360 Fix 16 HIGH/MEDIUM security bugs across API
HIGH fixes:
- TOTP disable now requires valid code verification
- TOTP secret removed from plaintext file storage
- Container ID validated before update/check-update/logs operations
- DNS server parameter restricted to configured servers (SSRF prevention)
- Backup export no longer includes encryption key
- Backup restore of sensitive files requires TOTP re-authentication

MEDIUM fixes:
- Session cookie Secure flag added
- Caddy reload errors no longer leaked to client
- saveConfig uses atomic locked updates via configStateManager
- Log file path traversal prevented via symlink resolution
- Credential cache entries now expire after 5 minutes
- _httpFetch enforces 10MB response size limit
- External URL path injection into Caddyfile blocked
- Custom volume host paths validated against allowed roots
- Error logs endpoint no longer returns stack traces
- Logo delete path traversal prevented via path.basename()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 00:15:28 -08:00
6979302fb7 Fix 7 critical security bugs and 1 high-severity data loss bug
- CSRF: HMAC-signed double-submit cookie (server-bound, not raw compare)
- Keychain: execFileSync with arg arrays to prevent command injection
- Caddy config: always use structured generation, never accept raw config
- Templates: replace {{GENERATED_SECRET}} with crypto.randomBytes
- Caddyfile removal: move regex inside ctx.caddy.modify() to fix TOCTOU race
- Credentials: proper-lockfile for all file operations, fix key rotation
  to decrypt with old key before generating new key
- Service removal: filter by ID only, not AND with appTemplate

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:08:30 -08:00
3a6d2ce93d Fix input validation and error handling across API endpoints
- Deploy endpoint: validate appId, config, and subdomain before use (prevents 500 crash on empty body)
- Container ops: return 404 instead of 500 for non-existent containers
- Update-subdomain: require oldSubdomain/newSubdomain fields (prevents false 200 with undefined values)
- Global error handler: catch-all that never leaks stack traces or internal paths
- API 404 catch-all: return JSON instead of HTML for unmatched /api/* routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 20:21:21 -08:00
77030931b7 Add subdirectory routing mode for public domain deployments
Apps can now be served at domain.com/appname/ instead of requiring
subdomain DNS records (appname.domain.com). Supports three subpath
modes per template: native (URL base env var), strip (handle_path),
and none (incompatible warning). Tested on Linux with deploy/removal
lifecycle verified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 03:03:17 -08:00
f61e85d9a7 Initial commit: DashCaddy v1.0
Full codebase including API server (32 modules + routes), dashboard frontend,
DashCA certificate distribution, installer script, and deployment skills.
2026-03-05 02:26:12 -08:00