-
Notifications
You must be signed in to change notification settings - Fork 94
Description
A Docker/self-hosted user cannot deploy Relaticle due to the hardcoded subdomain architecture. Current setup requires app.{domain} subdomain (e.g., app.crm.example.com), which creates issues for:
- SSL certificates — Wildcard certs (
*.example.com) only cover one level, notapp.crm.example.com - Internal networks — Can't use Let's Encrypt for internal DNS; requires manual cert management
- Enterprise environments — Many orgs have DNS policies preventing arbitrary subdomain creation
Current hardcoded implementation in AppPanelProvider.php:
->domain('app.'.parse_url((string) config('app.url'))['host'])Research Objectives
Find the 3 best approaches to allow Relaticle to run on a single domain for self-hosted/Docker deployments while maintaining the current subdomain architecture as default for SaaS.
Proposed Solutions to Research
Solution 1: Path-Based Routing (Single Domain Mode)
Concept: Use ->path('app') instead of ->domain('app.xxx') when env var is set.
Example:
- Current:
https://crm.example.com(landing) +https://app.crm.example.com(CRM) - New:
https://crm.example.com(landing) +https://crm.example.com/app(CRM)
Research needed:
- How does Filament 4 handle
->path()vs->domain()? - Impact on
MacroServiceProvider.phpURL helpers (getAppUrl,getPublicUrl) - Impact on authentication redirects in
routes/web.php - Session/cookie handling across path vs subdomain
- Asset URL generation (
ASSET_URLimplications) - Livewire/Alpine.js routing compatibility
Filament docs reference:
// From Filament docs
->path('app') // Makes panel available at domain.com/app
->path('') // Makes panel available at rootSolution 2: Configurable Domain via Environment Variable
Concept: Allow full override of the app panel domain via env var.
Example .env:
# Option A: Use subdomain (current default)
APP_URL=https://crm.example.com
# Results in: app.crm.example.com
# Option B: Explicit domain override
APP_URL=https://example.com
APP_PANEL_DOMAIN=crm.example.com
# Results in: crm.example.com (no subdomain prefix)Research needed:
- How to conditionally apply
->domain()inAppPanelProvider.php - Landing page routing when app panel is on same domain
- Conflict resolution between public routes and panel routes
- How other Filament multi-panel apps handle this
Implementation sketch:
$appDomain = env('APP_PANEL_DOMAIN');
if ($appDomain) {
$panel->domain($appDomain);
} else {
$panel->domain('app.'.parse_url((string) config('app.url'))['host']);
}Solution 3: Hybrid Mode (Domain OR Path)
Concept: Single env var to switch between subdomain and path-based routing.
Example .env:
# Subdomain mode (default, current behavior)
RELATICLE_ROUTING_MODE=subdomain
# Path mode (single domain)
RELATICLE_ROUTING_MODE=pathResearch needed:
- Full impact analysis on both routing modes
- URL generation throughout the app (
url()->getAppUrl()) - Email links, password resets, team invitations
- OAuth callback URLs
- How to handle the landing page in path mode (same domain conflict)
Implementation sketch:
$routingMode = env('RELATICLE_ROUTING_MODE', 'subdomain');
if ($routingMode === 'path') {
$panel->path('app');
} else {
$panel->domain('app.'.parse_url((string) config('app.url'))['host']);
}Additional Research Items
Trusted Proxies Support
Laravel 12 does NOT natively read TRUSTED_PROXIES from env. Need to implement in bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$proxies = env('TRUSTED_PROXIES');
if ($proxies === '*') {
$middleware->trustProxies(at: '*');
} elseif ($proxies) {
$middleware->trustProxies(at: explode(',', $proxies));
}
})Research: Confirm this works with Laravel 12 + Filament 4. Test with Caddy, Nginx, Traefik reverse proxies.
Files to Modify
app/Providers/Filament/AppPanelProvider.php— Panel domain/path configapp/Providers/MacroServiceProvider.php— URL helper macrosbootstrap/app.php— Trusted proxies middlewareroutes/web.php— Public route redirects.env.example— Document new env varsdocker-compose.prod.yml— Add new env vars- Documentation — Self-hosting guide updates
Test Scenarios
| Scenario | APP_URL | Mode | Expected Landing | Expected App |
|---|---|---|---|---|
| SaaS (current) | https://relaticle.com |
subdomain | relaticle.com |
app.relaticle.com |
| Self-hosted subdomain | https://crm.company.com |
subdomain | crm.company.com |
app.crm.company.com |
| Self-hosted single domain | https://crm.company.com |
path | crm.company.com |
crm.company.com/app |
| Internal network | http://192.168.1.100:8080 |
path | 192.168.1.100:8080 |
192.168.1.100:8080/app |