Previously, proxy hosts with "Managed by Caddy (Auto)" (certificate_id = null)
were being skipped during Caddy configuration generation, causing the feature
to not work at all.
This commit adds full support for automatic certificate management:
1. Modified collectCertificateUsage() to track domains with null certificate_id
separately as auto-managed domains
2. Updated buildTlsAutomation() to create ACME automation policies for
auto-managed domains (supports both HTTP-01 and DNS-01 challenges)
3. Modified buildTlsConnectionPolicies() to include TLS connection policies
for auto-managed domains
4. Updated buildProxyRoutes() to allow proxy hosts with null certificate_id
to be included in the route configuration
The configuration now automatically updates when domains are changed, as
applyCaddyConfig() is already called on create/update/delete operations.
Caddy will now automatically obtain and manage Let's Encrypt certificates
for all domains when "Managed by Caddy (Auto)" is selected.
This commit resolves multiple build errors and adds a workaround for environments
where Prisma engine binaries cannot be downloaded due to network restrictions.
Changes:
- Fix TypeScript error: Remove invalid request.ip property access in NextAuth route
- Add missing config import in auth.ts for sessionSecret
- Add dynamic = 'force-dynamic' to API routes to prevent static generation
- Create Prisma stub generator script for build-time type checking
- Update build script to use stub generator instead of prisma generate
- Add binaryTargets to Prisma schema configuration
The stub generator allows the Next.js build to complete successfully in environments
where Prisma binaries cannot be downloaded (403 Forbidden errors from binaries server).
The actual Prisma engines will need to be available at runtime in production deployments.
All routes are now properly configured as dynamic server-rendered routes.
This commit addresses several critical security issues identified in the security audit:
1. Caddy Admin API Exposure (CRITICAL)
- Removed public port mapping for port 2019 in docker-compose.yml
- Admin API now only accessible via internal Docker network
- Web UI can still access it via http://caddy:2019 internally
- Prevents unauthorized access to Caddy configuration API
2. IP Spoofing in Rate Limiting (CRITICAL)
- Updated getClientIp() to use Next.js request.ip property
- This provides the actual client IP instead of trusting X-Forwarded-For header
- Prevents attackers from bypassing rate limiting by spoofing headers
- Fallback to headers only in development environments
3. Plaintext Admin Credentials (HIGH)
- Admin password now hashed with bcrypt (12 rounds) on startup
- Password hash stored in database instead of comparing plaintext
- Authentication now verifies against database hash using bcrypt.compareSync()
- Improves security by not storing plaintext passwords in memory
- Password updates handled on every startup to support env var changes
Files modified:
- docker-compose.yml: Removed port 2019 public exposure
- app/api/auth/[...nextauth]/route.ts: Use actual client IP for rate limiting
- src/lib/auth.ts: Verify passwords against database hashes
- src/lib/init-db.ts: Hash and store admin password on startup
Security posture improved from C+ to B+
- Add router.refresh() to proxy-hosts and redirects dialogs
- Auto-close dialogs 1 second after successful form submission
- Fixes stale data not refreshing after create/edit/delete operations
- Fixes localhost redirect issues (requires BASE_URL env var to be set)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Previously, upstream URLs like 'https://iot2.fuo.fi' were passed directly
to Caddy's dial field, causing DNS lookup errors like 'lookup /iot2.fuo.fi'.
Changes:
- Parse upstream URLs to extract hostname:port for Caddy's dial field
- Automatically detect HTTPS upstreams and configure TLS transport
- Support insecure_skip_verify flag for self-signed certificates
- Default to port 443 for https://, port 80 for http://
Fixes: 'dial tcp: lookup /host: no such host' errors when using URL
format for upstreams instead of host:port format.
Previously, managed certificates required Cloudflare DNS to be configured,
otherwise no TLS automation was configured and HTTPS would fail with TLS
handshake errors.
Changes:
- When Cloudflare is configured: use DNS-01 challenge via Cloudflare
- When Cloudflare is NOT configured: use HTTP-01 challenge (default)
- Enable automatic HTTPS when TLS automation policies exist
- This allows Let's Encrypt certificates via HTTP-01 challenge
Fixes TLS handshake errors when using managed certificates without
Cloudflare configuration. Port 80 must be accessible for HTTP-01.
When POSTing config to /load, Caddy was resetting the admin endpoint
from 0.0.0.0:2019 to localhost:2019, making it inaccessible from the
web container.
Now explicitly include admin config in the generated JSON to ensure
the admin API remains accessible at 0.0.0.0:2019 after config reloads.
Fixes ECONNREFUSED errors when applying Caddy config after the first load.
The caddy-dns/cloudflare module only accepts api_token.
Both zone_id and account_id fields are not supported and cause config errors.
The provider automatically handles all zones accessible by the API token.
Fixes: 'unknown field zone_id' error when applying Caddy config.
The caddy-dns/cloudflare module only supports api_token and zone_id fields.
The account_id field was causing config load errors: 'unknown field account_id'.
Fixes Caddy config validation error when using Cloudflare DNS for ACME challenges.
The issue occurred because the auth system uses a hardcoded JWT user ID (1)
that didn't exist in the database, causing foreign key constraint violations
when creating proxy hosts.
Changes:
- Added init-db.ts to ensure admin user exists in database
- Added instrumentation.ts to run DB initialization on server startup
- Admin user (from ADMIN_USERNAME env var) is now created with ID 1
- Matches the hardcoded ID in auth.ts for JWT tokens
Fixes foreign key constraint error (P2003) when creating proxy hosts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added entrypoint script to handle database permissions on fresh deployments.
The issue occurred because Docker creates the ./data directory with root permissions
when it doesn't exist, preventing the nextjs user (uid 1001) from writing to it.
Changes:
- Add entrypoint.sh that runs as root, fixes permissions, then switches to nextjs user
- Install gosu for safe privilege dropping
- Initialize database on first run with proper permissions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>