diff --git a/.env.example b/.env.example index f707710..ed29b85 100644 --- a/.env.example +++ b/.env.example @@ -60,6 +60,11 @@ TRAEFIK_ROUTER_RULE='PathPrefix(`/`)' PHX_HOST=localhost PHX_SCHEME=http PHX_URL_PORT=4010 +# Optional comma-separated additional browser origins for Phoenix sockets. +# Keep this empty when the site is reached only through PHX_HOST. For a local +# Compose instance also exposed through an HTTPS tunnel, list both exact +# origins, for example: https://dev.example.com,http://localhost:4010 +PHX_CHECK_ORIGINS= # Android debug builds compile this origin into BuildConfig. The Docker # emulator uses adb reverse to expose the local Compose proxy on loopback. WNH_DEBUG_BASE_URL=http://localhost:4010 diff --git a/compose.yaml b/compose.yaml index fd5ef13..c4f1252 100644 --- a/compose.yaml +++ b/compose.yaml @@ -15,6 +15,7 @@ x-app-environment: &app-environment PHX_HOST: ${PHX_HOST:?Set PHX_HOST in .env} PHX_SCHEME: ${PHX_SCHEME:?Set PHX_SCHEME in .env} PHX_URL_PORT: ${PHX_URL_PORT:?Set PHX_URL_PORT in .env} + PHX_CHECK_ORIGINS: ${PHX_CHECK_ORIGINS:-} PORT: "4000" EMAIL_DELIVERY_PROVIDER: ${EMAIL_DELIVERY_PROVIDER:-smtp} SMTP_RELAY: ${SMTP_RELAY:-mailpit} diff --git a/config/runtime.exs b/config/runtime.exs index f986933..c835665 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -402,6 +402,44 @@ if config_env() == :prod do default_url_port = if scheme == "https", do: "443", else: "80" url_port = String.to_integer(System.get_env("PHX_URL_PORT", default_url_port)) + check_origin = + case System.get_env("PHX_CHECK_ORIGINS") do + value when value in [nil, ""] -> + true + + value -> + origins = + value + |> String.split(",", trim: true) + |> Enum.map(&String.trim/1) + |> Enum.reject(&(&1 == "")) + + if origins == [] do + raise "PHX_CHECK_ORIGINS must contain at least one origin when configured." + end + + Enum.each(origins, fn origin -> + case URI.parse(origin) do + %URI{ + scheme: allowed_scheme, + host: allowed_host, + path: path, + query: nil, + fragment: nil, + userinfo: nil + } + when allowed_scheme in ["http", "https"] and is_binary(allowed_host) and + allowed_host != "" and path in [nil, ""] -> + :ok + + _invalid -> + raise "PHX_CHECK_ORIGINS entries must be comma-separated HTTP(S) origins without paths, query strings, fragments, or credentials; got #{inspect(origin)}." + end + end) + + origins + end + email_delivery_provider = System.get_env("EMAIL_DELIVERY_PROVIDER", "smtp") mailer_config = @@ -527,6 +565,7 @@ if config_env() == :prod do config :who_need_help, WhoNeedHelpWeb.Endpoint, url: [host: host, port: url_port, scheme: scheme], + check_origin: check_origin, http: [ # Enable IPv6 and bind on all interfaces. # Set it to {0, 0, 0, 0, 0, 0, 0, 1} for local network only access.