112 lines
4.7 KiB
PHP
112 lines
4.7 KiB
PHP
<?php
|
|
|
|
return [
|
|
|
|
/*
|
|
| Hostnames the operator console (/admin) may be served on.
|
|
|
|
|
| The Proxmox hosts and the admin console must never be publicly reachable.
|
|
| The primary control belongs in the reverse proxy (only expose the public
|
|
| hostnames); this is defence in depth INSIDE the app, so a proxy
|
|
| misconfiguration cannot silently expose the console on a public domain.
|
|
|
|
|
| Comma-separated in ADMIN_HOSTS. EMPTY = no host restriction (dev default),
|
|
| so nobody gets locked out by simply upgrading.
|
|
|
|
|
| Example (production):
|
|
| ADMIN_HOSTS=admin.clupilot.com
|
|
*/
|
|
// Lowercased: DNS names are case-insensitive and Symfony's getHost() always
|
|
// returns lowercase, so ADMIN_HOSTS=Admin.Example.com must still match.
|
|
'hosts' => array_values(array_filter(array_map(
|
|
fn ($host) => strtolower(trim($host)),
|
|
explode(',', (string) env('ADMIN_HOSTS', ''))
|
|
))),
|
|
|
|
/*
|
|
| Whether the console's hostname serves ONLY the console.
|
|
|
|
|
| Off by default, and deliberately separate from having a hostname at all: a
|
|
| development machine lists its own IP in ADMIN_HOSTS so the console works
|
|
| without DNS, and that same address still has to serve the portal. Switch
|
|
| it on only where the console really has a hostname to itself.
|
|
*/
|
|
'exclusive' => (bool) env('ADMIN_HOST_EXCLUSIVE', false),
|
|
|
|
/*
|
|
| Hostname the public status page lives on, e.g. status.clupilot.com.
|
|
|
|
|
| Empty means it stays on every host, as it does today. Set, it becomes the
|
|
| ONLY place /status answers — everywhere else redirects there, so a link
|
|
| that already exists keeps working instead of hitting the 404 that strict
|
|
| separation would otherwise produce.
|
|
*/
|
|
'status_host' => strtolower(trim((string) env('STATUS_HOST', ''))),
|
|
|
|
/*
|
|
| Key for VPN configs stored at rest (32 bytes, base64). Separate from
|
|
| APP_KEY on purpose — see App\Services\Wireguard\ConfigVault. Empty means
|
|
| storing configs is switched off, and the console says so rather than
|
|
| quietly writing credentials in the clear.
|
|
|
|
|
| Generate with: head -c 32 /dev/urandom | base64
|
|
*/
|
|
'vpn_config_key' => env('VPN_CONFIG_KEY', ''),
|
|
|
|
/*
|
|
| The hostname the console answers on INSIDE the tunnel.
|
|
|
|
|
| Set, the VPN gateway and resolver are started (compose profile `vpn`) and
|
|
| issued client configs point their DNS at the hub. Empty, none of that
|
|
| exists and the VPN is only a management network — which is what an
|
|
| installation without the extra services should be.
|
|
|
|
|
| Deliberately the SAME name the console already uses publicly: the
|
|
| certificate is bound to the name, not to the address serving it, so
|
|
| nothing new has to be issued and nothing about the internal network ends
|
|
| up in a public DNS zone.
|
|
*/
|
|
'vpn_internal_host' => strtolower(trim((string) env('VPN_INTERNAL_HOST', ''))),
|
|
|
|
/*
|
|
| Whether the tunnel-side gateway is actually READY, not merely wanted.
|
|
|
|
|
| The hostname alone is not enough: the deployment refuses to start the
|
|
| gateway until a certificate for it has been found, and a client config
|
|
| that names a resolver nobody started takes the device's whole name
|
|
| resolution down for as long as the tunnel is up. The certificate path is
|
|
| written by the same step that starts the services, so it is the honest
|
|
| signal.
|
|
*/
|
|
'vpn_ready' => strtolower(trim((string) env('VPN_INTERNAL_HOST', ''))) !== ''
|
|
&& filter_var(env('VPN_READY', false), FILTER_VALIDATE_BOOLEAN),
|
|
|
|
/*
|
|
| Key for credentials stored in the console (32 bytes, base64).
|
|
|
|
|
| Separate from APP_KEY on purpose: rotating APP_KEY is ordinary
|
|
| maintenance, and it would otherwise render every stored credential
|
|
| unreadable — discovered when Stripe stops answering. Empty means storing
|
|
| credentials is switched off, and the console says so rather than falling
|
|
| back to a key that gets rotated.
|
|
|
|
|
| Generate with: head -c 32 /dev/urandom | base64
|
|
*/
|
|
'secrets_key' => env('SECRETS_KEY', ''),
|
|
|
|
/*
|
|
| Networks that count as "us" while the public site is hidden
|
|
| (PublicSiteGate). The WireGuard management subnet by default, so anyone on
|
|
| the VPN sees the real site while the outside world sees a placeholder.
|
|
|
|
|
| Note this is compared against the CLIENT address, which is only correct
|
|
| because TrustProxies is configured — behind an untrusted proxy every
|
|
| request would look like it came from the proxy.
|
|
*/
|
|
'trusted_ranges' => array_values(array_filter(array_map(
|
|
'trim',
|
|
explode(',', (string) env('TRUSTED_RANGES', '10.66.0.0/24,127.0.0.1')),
|
|
))),
|
|
|
|
];
|