diff --git a/docker-compose.yml b/docker-compose.yml index cdca568bc..826f7a303 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -60,8 +60,10 @@ services: - 8080:8080/tcp environment: # Web Server - EXTERNAL_URL: http://localhost:8080/ + WEB_EXTERNAL_URL: http://localhost:8080/ + API_EXTERNAL_URL: http://localhost:8081/ PHOENIX_HTTP_WEB_PORT: "8080" + PHOENIX_HTTP_API_PORT: "8081" PHOENIX_SECURE_COOKIES: "false" # Erlang ERLANG_DISTRIBUTION_PORT: 9000 @@ -129,7 +131,9 @@ services: - 8081:8081/tcp environment: # Web Server - EXTERNAL_URL: http://localhost:8081/ + WEB_EXTERNAL_URL: http://localhost:8080/ + API_EXTERNAL_URL: http://localhost:8081/ + PHOENIX_HTTP_WEB_PORT: "8080" PHOENIX_HTTP_API_PORT: "8081" PHOENIX_SECURE_COOKIES: "false" # Erlang @@ -262,7 +266,8 @@ services: hostname: elixir environment: # Web Server - EXTERNAL_URL: http://localhost:8081/ + WEB_EXTERNAL_URL: http://localhost:8080/ + API_EXTERNAL_URL: http://localhost:8081/ # Erlang ERLANG_DISTRIBUTION_PORT: 9000 RELEASE_COOKIE: "NksuBhJFBhjHD1uUa9mDOHV" diff --git a/elixir/apps/domain/lib/domain/config/definitions.ex b/elixir/apps/domain/lib/domain/config/definitions.ex index e914b8330..a4043a33b 100644 --- a/elixir/apps/domain/lib/domain/config/definitions.ex +++ b/elixir/apps/domain/lib/domain/config/definitions.ex @@ -48,7 +48,8 @@ defmodule Domain.Config.Definitions do ]}, {"WebServer", [ - :external_url, + :web_external_url, + :api_external_url, :phoenix_secure_cookies, :phoenix_listen_address, :phoenix_http_web_port, @@ -149,11 +150,26 @@ defmodule Domain.Config.Definitions do ############################################## @doc """ - The external URL the UI/API will be accessible at. + The external URL the UI will be accessible at. If this field is not set or set to `nil`, the server for `api` and `web` apps will not start. """ - defconfig(:external_url, :string, + defconfig(:web_external_url, :string, + default: nil, + changeset: fn changeset, key -> + changeset + |> Domain.Repo.Changeset.validate_uri(key, require_trailing_slash: true) + |> Domain.Repo.Changeset.normalize_url(key) + end + ) + + @doc """ + The external URL the API will be accessible at. + + If this field is not set or set to `nil`, the server for `api` and `web` apps will not start. + """ + + defconfig(:api_external_url, :string, default: nil, changeset: fn changeset, key -> changeset diff --git a/elixir/apps/domain/test/domain/config_test.exs b/elixir/apps/domain/test/domain/config_test.exs index 68d1a7799..61f88c98b 100644 --- a/elixir/apps/domain/test/domain/config_test.exs +++ b/elixir/apps/domain/test/domain/config_test.exs @@ -171,10 +171,10 @@ defmodule Domain.ConfigTest do end test "raises an error when value is invalid", %{account: account} do - put_system_env_override(:external_url, "https://example.com/vpn") + put_system_env_override(:web_external_url, "https://example.com/vpn") message = """ - Invalid configuration for 'external_url' retrieved from environment variable EXTERNAL_URL. + Invalid configuration for 'web_external_url' retrieved from environment variable WEB_EXTERNAL_URL. Errors: @@ -182,7 +182,7 @@ defmodule Domain.ConfigTest do ## Documentation - The external URL the UI/API will be accessible at. + The external URL the UI will be accessible at. If this field is not set or set to `nil`, the server for `api` and `web` apps will not start. @@ -191,7 +191,7 @@ defmodule Domain.ConfigTest do """ assert_raise RuntimeError, message, fn -> - fetch_resolved_configs_with_sources!(account.id, [:external_url]) + fetch_resolved_configs_with_sources!(account.id, [:web_external_url]) end end end diff --git a/elixir/apps/web/lib/web/live/settings/api_clients/beta.ex b/elixir/apps/web/lib/web/live/settings/api_clients/beta.ex index b7a7af6a0..5392fe8cf 100644 --- a/elixir/apps/web/lib/web/live/settings/api_clients/beta.ex +++ b/elixir/apps/web/lib/web/live/settings/api_clients/beta.ex @@ -6,9 +6,12 @@ defmodule Web.Settings.ApiClients.Beta do {:ok, push_navigate(socket, to: ~p"/#{socket.assigns.account}/settings/api_clients")} else socket = - socket - |> assign(:page_title, "API Clients") - |> assign(:requested, false) + assign( + socket, + page_title: "API Clients", + requested: false, + api_url: Domain.Config.get_env(:web, :api_external_url) + ) {:ok, socket} end @@ -25,7 +28,10 @@ defmodule Web.Settings.ApiClients.Beta do <:title><%= @page_title %> <:help> API Clients are used to manage Firezone configuration through a REST API. See our - interactive API docs + <.link navigate={"#{@api_url}/swaggerui"} class={link_style()} target="_blank"> + OpenAPI-powered docs + + for more information. <:content> <.flash kind={:info}> diff --git a/elixir/apps/web/lib/web/live/settings/api_clients/index.ex b/elixir/apps/web/lib/web/live/settings/api_clients/index.ex index c974f476e..54aa8daf3 100644 --- a/elixir/apps/web/lib/web/live/settings/api_clients/index.ex +++ b/elixir/apps/web/lib/web/live/settings/api_clients/index.ex @@ -7,6 +7,7 @@ defmodule Web.Settings.ApiClients.Index do socket = socket |> assign(page_title: "API Clients") + |> assign(api_url: Domain.Config.get_env(:web, :api_external_url)) |> assign_live_table("actors", query_module: Actors.Actor.Query, sortable_fields: [ @@ -56,7 +57,7 @@ defmodule Web.Settings.ApiClients.Index do <:title><%= @page_title %> <:help> API Clients are used to manage Firezone configuration through a REST API. See our - <.link navigate="https://api.firezone.dev/swaggerui" class={link_style()}> + <.link navigate={"#{@api_url}/swaggerui"} class={link_style()} target="_blank"> OpenAPI-powered docs for more information. diff --git a/elixir/config/config.exs b/elixir/config/config.exs index 5ea7d1a31..50c4b8988 100644 --- a/elixir/config/config.exs +++ b/elixir/config/config.exs @@ -128,6 +128,9 @@ config :web, Web.Endpoint, signing_salt: "t01wa0K4lUd7mKa0HAtZdE+jFOPDDejX" ] +config :web, + api_external_url: "http://localhost:13001" + config :web, cookie_secure: false, cookie_signing_salt: "WjllcThpb2Y=", diff --git a/elixir/config/dev.exs b/elixir/config/dev.exs index 1f55052a5..192a20c75 100644 --- a/elixir/config/dev.exs +++ b/elixir/config/dev.exs @@ -50,6 +50,9 @@ config :web, Web.Endpoint, reloadable_apps: [:domain, :web], server: true +config :web, + api_external_url: "http://localhost:13001" + root_path = __ENV__.file |> Path.dirname() diff --git a/elixir/config/runtime.exs b/elixir/config/runtime.exs index c977d7d22..3d2b88e6d 100644 --- a/elixir/config/runtime.exs +++ b/elixir/config/runtime.exs @@ -98,13 +98,13 @@ if config_env() == :prod do config :domain, Domain.Auth.Adapters.Okta.Jobs.SyncDirectory, enabled: compile_config!(:background_jobs_enabled) - if external_url = compile_config!(:external_url) do + if web_external_url = compile_config!(:web_external_url) do %{ - scheme: external_url_scheme, - host: external_url_host, - port: external_url_port, - path: external_url_path - } = URI.parse(external_url) + scheme: web_external_url_scheme, + host: web_external_url_host, + port: web_external_url_port, + path: web_external_url_path + } = URI.parse(web_external_url) ############################### ##### Web ##################### @@ -117,17 +117,17 @@ if config_env() == :prod do protocol_options: compile_config!(:phoenix_http_protocol_options) ], url: [ - scheme: external_url_scheme, - host: external_url_host, - port: external_url_port, - path: external_url_path + scheme: web_external_url_scheme, + host: web_external_url_host, + port: web_external_url_port, + path: web_external_url_path ], secret_key_base: compile_config!(:secret_key_base), check_origin: [ - "#{external_url_scheme}://#{external_url_host}:#{external_url_port}", - "#{external_url_scheme}://*.#{external_url_host}:#{external_url_port}", - "#{external_url_scheme}://#{external_url_host}", - "#{external_url_scheme}://*.#{external_url_host}" + "#{web_external_url_scheme}://#{web_external_url_host}:#{web_external_url_port}", + "#{web_external_url_scheme}://*.#{web_external_url_host}:#{web_external_url_port}", + "#{web_external_url_scheme}://#{web_external_url_host}", + "#{web_external_url_scheme}://*.#{web_external_url_host}" ], live_view: [ signing_salt: compile_config!(:live_view_signing_salt) @@ -143,6 +143,15 @@ if config_env() == :prod do cookie_encryption_salt: compile_config!(:cookie_encryption_salt) config :web, api_url_override: compile_config!(:api_url_override) + end + + if api_external_url = compile_config!(:api_external_url) do + %{ + scheme: api_external_url_scheme, + host: api_external_url_host, + port: api_external_url_port, + path: api_external_url_path + } = URI.parse(api_external_url) ############################### ##### API ##################### @@ -155,10 +164,10 @@ if config_env() == :prod do protocol_options: compile_config!(:phoenix_http_protocol_options) ], url: [ - scheme: external_url_scheme, - host: external_url_host, - port: external_url_port, - path: external_url_path + scheme: api_external_url_scheme, + host: api_external_url_host, + port: api_external_url_port, + path: api_external_url_path ], secret_key_base: compile_config!(:secret_key_base) @@ -170,6 +179,9 @@ if config_env() == :prod do config :api, external_trusted_proxies: compile_config!(:phoenix_external_trusted_proxies), private_clients: compile_config!(:phoenix_private_clients) + + config :web, + api_external_url: api_external_url end ############################### diff --git a/terraform/environments/production/portal.tf b/terraform/environments/production/portal.tf index 23c46fbf6..bd2fcf4c2 100644 --- a/terraform/environments/production/portal.tf +++ b/terraform/environments/production/portal.tf @@ -218,6 +218,23 @@ locals { } shared_application_environment_variables = [ + # Apps + { + name = "WEB_EXTERNAL_URL" + value = "https://app.${local.tld}" + }, + { + name = "API_EXTERNAL_URL" + value = "https://api.${local.tld}" + }, + { + name = "PHOENIX_HTTP_WEB_PORT" + value = "8080" + }, + { + name = "PHOENIX_HTTP_API_PORT" + value = "8080" + }, # Database { name = "DATABASE_HOST" @@ -519,14 +536,6 @@ module "web" { application_environment_variables = concat([ # Web Server - { - name = "EXTERNAL_URL" - value = "https://app.${local.tld}" - }, - { - name = "PHOENIX_HTTP_WEB_PORT" - value = "8080" - }, { name = "BACKGROUND_JOBS_ENABLED" value = "false" @@ -595,14 +604,6 @@ module "api" { application_environment_variables = concat([ # Web Server - { - name = "EXTERNAL_URL" - value = "https://api.${local.tld}" - }, - { - name = "PHOENIX_HTTP_API_PORT" - value = "8080" - }, { name = "BACKGROUND_JOBS_ENABLED" value = "false" diff --git a/terraform/environments/staging/portal.tf b/terraform/environments/staging/portal.tf index 830452af1..cef319c05 100644 --- a/terraform/environments/staging/portal.tf +++ b/terraform/environments/staging/portal.tf @@ -191,6 +191,23 @@ locals { } shared_application_environment_variables = [ + # Apps + { + name = "WEB_EXTERNAL_URL" + value = "https://app.${local.tld}" + }, + { + name = "API_EXTERNAL_URL" + value = "https://api.${local.tld}" + }, + { + name = "PHOENIX_HTTP_WEB_PORT" + value = "8080" + }, + { + name = "PHOENIX_HTTP_API_PORT" + value = "8080" + }, # Database { name = "DATABASE_HOST" @@ -498,14 +515,6 @@ module "web" { application_environment_variables = concat([ # Web Server - { - name = "EXTERNAL_URL" - value = "https://app.${local.tld}" - }, - { - name = "PHOENIX_HTTP_WEB_PORT" - value = "8080" - }, { name = "API_URL_OVERRIDE" value = "wss://api.${local.tld}" @@ -577,14 +586,6 @@ module "api" { application_environment_variables = concat([ # Web Server - { - name = "EXTERNAL_URL" - value = "https://api.${local.tld}" - }, - { - name = "PHOENIX_HTTP_API_PORT" - value = "8080" - }, { name = "BACKGROUND_JOBS_ENABLED" value = "false"