mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
Fixes for local development (#562)
* Fixes for local development A few issues that I ran into getting this up on my local machine. I also made sure it works now properly on Github Codespaces which will hopefully make it easier for devs to get started. - Username/Pass docs updated to correct values - Add runtime.exs and migrate releases.exs over to it as recommended by Elixir 1.11 release notes - Update Endpoint to allow for proxy passed headers if enabled with PROXY_FORWARDED - Add missing .env file section to CONTRIBUTION - Add a sample .env file (.env.sample) to help getting started - Update docs to show how to use Github Codespaces with an external URL. - Remove unused alias from dev (which I think doesn't work anyway due to compile time restrictions, only in runtime or releases.exs) - Ensure pre-commit is in path and available on devcontainer - Simplify some docker commands, remove unneeded ports. * Update runtime.exs with resolved conflicts Co-authored-by: Mark Percival <m@mdp.im>
This commit is contained in:
@@ -16,6 +16,7 @@ RUN echo "APT::Install-Recommends 0;" >> /etc/apt/apt.conf.d/01norecommends \
|
||||
wget \
|
||||
net-tools \
|
||||
wireguard \
|
||||
inotify-tools \
|
||||
ca-certificates \
|
||||
build-essential \
|
||||
python python-pip \
|
||||
@@ -79,9 +80,7 @@ ENV HOME=/home/$USERNAME \
|
||||
ASDF_DATA_DIR="/opt/asdf-data"
|
||||
|
||||
RUN echo '\n. /opt/asdf/asdf.sh' >> ~/.bashrc \
|
||||
&& echo '\n. /opt/asdf/completions/asdf.bash' >> ~/.bashrc \
|
||||
&& echo '\nexport LC_ALL="C.UTF-8"' >> ~/.bashrc \
|
||||
&& echo '\nexport TZ="UTC"' >> ~/.bashrc
|
||||
&& echo '\n. /opt/asdf/completions/asdf.bash' >> ~/.bashrc
|
||||
|
||||
SHELL ["/bin/bash", "-ic"]
|
||||
|
||||
@@ -97,11 +96,15 @@ RUN asdf install erlang
|
||||
# No order to asdf, so elixir error without Erlang
|
||||
RUN asdf install
|
||||
|
||||
RUN mix local.hex --force
|
||||
RUN mix local.rebar --force
|
||||
|
||||
VOLUME ["${ASDF_DATA_DIR}"]
|
||||
|
||||
# Pre-commit install with deps
|
||||
RUN pip install setuptools wheel
|
||||
RUN pip install pre-commit
|
||||
RUN echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
|
||||
|
||||
ENV PATH=${HOME}/.local/bin:/opt/asdf-data/shims:/opt/asdf/bin:${PATH}
|
||||
|
||||
CMD ["/bin/bash"]
|
||||
|
||||
@@ -13,12 +13,13 @@
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"jakebecker.elixir-ls"
|
||||
"jakebecker.elixir-ls",
|
||||
"phoenixframework.phoenix"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// This can be used to network with other containers or with the host.
|
||||
"forwardPorts": [4000, 4001, 4002, 5432],
|
||||
"forwardPorts": [4000, 5432],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "mix deps.get"
|
||||
|
||||
12
.env.sample
Normal file
12
.env.sample
Normal file
@@ -0,0 +1,12 @@
|
||||
MIX_ENV=dev
|
||||
# This is a sample .env file. Update and add variables in here as needed, and
|
||||
# rename to `.env`
|
||||
|
||||
# Set the EXTERNAL_URL if it's not localhost:4000
|
||||
# EXTERNAL_URL=https:///local.dev
|
||||
|
||||
LOCAL_AUTH_ENABLED=true
|
||||
|
||||
# Set PROXY_FORWARDED to true if you're running this behind a proxy or using
|
||||
# GitHub codespaces
|
||||
PROXY_FORWARDED=true
|
||||
@@ -65,6 +65,19 @@ We use [pre-commit](https://pre-commit.com) to catch any static analysis issues
|
||||
before code is committed. Install with Homebrew: `brew install pre-commit` or
|
||||
pip: `pip install pre-commit`.
|
||||
|
||||
### The ENV file
|
||||
|
||||
In order to save local environment variables in your development environment,
|
||||
you can use a `.env` file in the project root directory to store any commonly
|
||||
used settings.
|
||||
|
||||
.env.sample will give you an example of what this file may look like.
|
||||
|
||||
Run the following command to 'source' the environment variables from .env on
|
||||
`mix start`
|
||||
|
||||
`env $(cat .env | grep -v \# | xargs) mix start`
|
||||
|
||||
## Bootstrapping
|
||||
|
||||
Assuming you've completed the steps above, you should be able to get everything
|
||||
@@ -96,8 +109,26 @@ mix start
|
||||
```
|
||||
|
||||
At this point you should be able to sign in to
|
||||
[http://localhost:4000](http://localhost:4000) with email `factory@factory` and
|
||||
password `factory`.
|
||||
[http://localhost:4000](http://localhost:4000) with email `firezone@localhost` and
|
||||
password `firezone1234`.
|
||||
|
||||
## Running this inside a Devcontainer
|
||||
|
||||
You can run this using Github Codespaces or your own devcontainer using Docker.
|
||||
|
||||
On GitHub Codespaces, follow the instructions above but start the server with
|
||||
PROXY_FORWARDED enabled and pass in your Codespace external url:
|
||||
|
||||
`PROXY_FORWARDED=true EXTERNAL_URL=[your_devcontainer_url] MIX_ENV=dev mix start`
|
||||
|
||||
or using the `.env` file
|
||||
|
||||
`env $(cat .env | grep -v \# | xargs) mix start`
|
||||
|
||||
On Github Codespaces you can find your EXTERNAL_URL by issuing the following
|
||||
command in the terminal:
|
||||
|
||||
`echo "https://${CODESPACE_NAME}-4000.githubpreview.dev"`
|
||||
|
||||
# Reporting Bugs
|
||||
We appreciate any and all bug reports.
|
||||
|
||||
@@ -2,6 +2,10 @@ defmodule FzHttpWeb.Endpoint do
|
||||
use Phoenix.Endpoint, otp_app: :fz_http
|
||||
alias FzHttpWeb.Session
|
||||
|
||||
if Application.get_env(:fz_http, FzHttpWeb.Endpoint, :proxy_forwarded) do
|
||||
plug Plug.RewriteOn, [:x_forwarded_host, :x_forwarded_port, :x_forwarded_proto]
|
||||
end
|
||||
|
||||
if Application.get_env(:fz_http, :sql_sandbox) do
|
||||
plug Phoenix.Ecto.SQL.Sandbox
|
||||
end
|
||||
@@ -36,7 +40,15 @@ defmodule FzHttpWeb.Endpoint do
|
||||
# Code reloading can be explicitly enabled under the
|
||||
# :code_reloader configuration of your endpoint.
|
||||
if code_reloading? do
|
||||
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
|
||||
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket,
|
||||
websocket: [
|
||||
connect_info: [
|
||||
session: {Session, :options, []}
|
||||
],
|
||||
# XXX: csrf token should prevent CSWH but double check
|
||||
check_origin: false
|
||||
]
|
||||
|
||||
plug Phoenix.LiveReloader
|
||||
plug Phoenix.CodeReloader
|
||||
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :fz_http
|
||||
|
||||
@@ -104,7 +104,8 @@ external_url = "http://localhost:4000"
|
||||
config :fz_http, FzHttpWeb.Endpoint,
|
||||
url: [host: host, port: port, scheme: scheme, path: path],
|
||||
render_errors: [view: FzHttpWeb.ErrorView, accepts: ~w(html json)],
|
||||
pubsub_server: FzHttp.PubSub
|
||||
pubsub_server: FzHttp.PubSub,
|
||||
proxy_forwarded: false
|
||||
|
||||
# Configures Elixir's Logger
|
||||
config :logger, :console,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import Config
|
||||
|
||||
alias FzCommon.ConfigHelpers
|
||||
|
||||
# Configure your database
|
||||
if url = System.get_env("DATABASE_URL") do
|
||||
config :fz_http, FzHttp.Repo,
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
# In this file, we load production configuration and secrets
|
||||
# from environment variables. You can also hardcode secrets,
|
||||
# although such is generally not recommended and you have to
|
||||
# remember to add this file to your .gitignore.
|
||||
import Config
|
||||
alias FzCommon.{CLI, FzInteger, FzString}
|
||||
|
||||
# For releases, require that all these are set
|
||||
database_name = System.fetch_env!("DATABASE_NAME")
|
||||
database_user = System.fetch_env!("DATABASE_USER")
|
||||
database_host = System.fetch_env!("DATABASE_HOST")
|
||||
database_port = String.to_integer(System.fetch_env!("DATABASE_PORT"))
|
||||
database_pool = String.to_integer(System.fetch_env!("DATABASE_POOL"))
|
||||
database_ssl = FzString.to_boolean(System.fetch_env!("DATABASE_SSL"))
|
||||
database_ssl_opts = Jason.decode!(System.fetch_env!("DATABASE_SSL_OPTS"))
|
||||
database_parameters = Jason.decode!(System.fetch_env!("DATABASE_PARAMETERS"))
|
||||
phoenix_port = String.to_integer(System.fetch_env!("PHOENIX_PORT"))
|
||||
admin_email = System.fetch_env!("ADMIN_EMAIL")
|
||||
default_admin_password = System.fetch_env!("DEFAULT_ADMIN_PASSWORD")
|
||||
wireguard_interface_name = System.fetch_env!("WIREGUARD_INTERFACE_NAME")
|
||||
wireguard_port = String.to_integer(System.fetch_env!("WIREGUARD_PORT"))
|
||||
nft_path = System.fetch_env!("NFT_PATH")
|
||||
wg_path = System.fetch_env!("WG_PATH")
|
||||
egress_interface = System.fetch_env!("EGRESS_INTERFACE")
|
||||
wireguard_public_key = System.fetch_env!("WIREGUARD_PUBLIC_KEY")
|
||||
wireguard_psk_dir = System.fetch_env!("WIREGUARD_PSK_DIR")
|
||||
wireguard_dns = System.fetch_env!("WIREGUARD_DNS")
|
||||
wireguard_allowed_ips = System.fetch_env!("WIREGUARD_ALLOWED_IPS")
|
||||
wireguard_persistent_keepalive = System.fetch_env!("WIREGUARD_PERSISTENT_KEEPALIVE")
|
||||
wireguard_ipv4_enabled = FzString.to_boolean(System.fetch_env!("WIREGUARD_IPV4_ENABLED"))
|
||||
wireguard_ipv4_network = System.fetch_env!("WIREGUARD_IPV4_NETWORK")
|
||||
wireguard_ipv4_address = System.fetch_env!("WIREGUARD_IPV4_ADDRESS")
|
||||
wireguard_ipv6_enabled = FzString.to_boolean(System.fetch_env!("WIREGUARD_IPV6_ENABLED"))
|
||||
wireguard_ipv6_network = System.fetch_env!("WIREGUARD_IPV6_NETWORK")
|
||||
wireguard_ipv6_address = System.fetch_env!("WIREGUARD_IPV6_ADDRESS")
|
||||
wireguard_mtu = System.fetch_env!("WIREGUARD_MTU")
|
||||
wireguard_endpoint = System.fetch_env!("WIREGUARD_ENDPOINT")
|
||||
telemetry_enabled = FzString.to_boolean(System.fetch_env!("TELEMETRY_ENABLED"))
|
||||
telemetry_id = System.fetch_env!("TELEMETRY_ID")
|
||||
guardian_secret_key = System.fetch_env!("GUARDIAN_SECRET_KEY")
|
||||
external_url = System.fetch_env!("EXTERNAL_URL")
|
||||
|
||||
allow_unprivileged_device_management =
|
||||
FzString.to_boolean(System.fetch_env!("ALLOW_UNPRIVILEGED_DEVICE_MANAGEMENT"))
|
||||
|
||||
# Local auth
|
||||
local_auth_enabled = FzString.to_boolean(System.fetch_env!("LOCAL_AUTH_ENABLED"))
|
||||
|
||||
# Okta auth
|
||||
okta_auth_enabled = FzString.to_boolean(System.fetch_env!("OKTA_AUTH_ENABLED"))
|
||||
okta_client_id = System.get_env("OKTA_CLIENT_ID")
|
||||
okta_client_secret = System.get_env("OKTA_CLIENT_SECRET")
|
||||
okta_site = System.get_env("OKTA_SITE")
|
||||
|
||||
# Google auth
|
||||
google_auth_enabled = FzString.to_boolean(System.fetch_env!("GOOGLE_AUTH_ENABLED"))
|
||||
google_client_id = System.get_env("GOOGLE_CLIENT_ID")
|
||||
google_client_secret = System.get_env("GOOGLE_CLIENT_SECRET")
|
||||
google_redirect_uri = System.get_env("GOOGLE_REDIRECT_URI")
|
||||
|
||||
max_devices_per_user =
|
||||
System.fetch_env!("MAX_DEVICES_PER_USER")
|
||||
|> String.to_integer()
|
||||
|> FzInteger.clamp(0, 100)
|
||||
|
||||
telemetry_module =
|
||||
if telemetry_enabled do
|
||||
FzCommon.Telemetry
|
||||
else
|
||||
FzCommon.MockTelemetry
|
||||
end
|
||||
|
||||
connectivity_checks_enabled =
|
||||
FzString.to_boolean(System.fetch_env!("CONNECTIVITY_CHECKS_ENABLED")) &&
|
||||
System.get_env("CI") != "true"
|
||||
|
||||
connectivity_checks_interval =
|
||||
System.fetch_env!("CONNECTIVITY_CHECKS_INTERVAL")
|
||||
|> String.to_integer()
|
||||
|> FzInteger.clamp(60, 86_400)
|
||||
|
||||
# secrets
|
||||
encryption_key = System.fetch_env!("DATABASE_ENCRYPTION_KEY")
|
||||
secret_key_base = System.fetch_env!("SECRET_KEY_BASE")
|
||||
live_view_signing_salt = System.fetch_env!("LIVE_VIEW_SIGNING_SALT")
|
||||
cookie_signing_salt = System.fetch_env!("COOKIE_SIGNING_SALT")
|
||||
|
||||
# Password is not needed if using bundled PostgreSQL, so use nil if it's not set.
|
||||
database_password = System.get_env("DATABASE_PASSWORD")
|
||||
|
||||
# XXX: Using to_atom here because this is trusted input and to_existing_atom
|
||||
# won't work because we won't know the keys ahead of time.
|
||||
ssl_opts = Keyword.new(database_ssl_opts, fn {k, v} -> {String.to_atom(k), v} end)
|
||||
parameters = Keyword.new(database_parameters, fn {k, v} -> {String.to_atom(k), v} end)
|
||||
|
||||
# Database configuration
|
||||
connect_opts = [
|
||||
database: database_name,
|
||||
username: database_user,
|
||||
hostname: database_host,
|
||||
port: database_port,
|
||||
pool_size: database_pool,
|
||||
ssl: database_ssl,
|
||||
ssl_opts: ssl_opts,
|
||||
parameters: parameters,
|
||||
queue_target: 500
|
||||
]
|
||||
|
||||
if database_password do
|
||||
config(:fz_http, FzHttp.Repo, connect_opts ++ [password: database_password])
|
||||
else
|
||||
config(:fz_http, FzHttp.Repo, connect_opts)
|
||||
end
|
||||
|
||||
config :fz_http, FzHttp.Vault,
|
||||
ciphers: [
|
||||
default: {
|
||||
Cloak.Ciphers.AES.GCM,
|
||||
# In AES.GCM, it is important to specify 12-byte IV length for
|
||||
# interoperability with other encryption software. See this GitHub
|
||||
# issue for more details:
|
||||
# https://github.com/danielberkompas/cloak/issues/93
|
||||
#
|
||||
# In Cloak 2.0, this will be the default iv length for AES.GCM.
|
||||
tag: "AES.GCM.V1", key: Base.decode64!(encryption_key), iv_length: 12
|
||||
}
|
||||
]
|
||||
|
||||
%{host: host, path: path, port: port, scheme: scheme} = URI.parse(external_url)
|
||||
|
||||
config :fz_http, FzHttpWeb.Endpoint,
|
||||
http: [ip: {127, 0, 0, 1}, port: phoenix_port],
|
||||
url: [host: host, scheme: scheme, port: port, path: path],
|
||||
check_origin: ["//127.0.0.1", "//localhost", "//#{host}"],
|
||||
server: true,
|
||||
secret_key_base: secret_key_base,
|
||||
live_view: [
|
||||
signing_salt: live_view_signing_salt
|
||||
]
|
||||
|
||||
config :fz_wall,
|
||||
nft_path: nft_path,
|
||||
egress_interface: egress_interface,
|
||||
wireguard_interface_name: wireguard_interface_name,
|
||||
cli: FzWall.CLI.Live
|
||||
|
||||
config :fz_vpn,
|
||||
wireguard_psk_dir: wireguard_psk_dir,
|
||||
wireguard_public_key: wireguard_public_key,
|
||||
wireguard_interface_name: wireguard_interface_name,
|
||||
wireguard_port: wireguard_port,
|
||||
cli: FzVpn.CLI.Live
|
||||
|
||||
# Guardian configuration
|
||||
config :fz_http, FzHttpWeb.Authentication,
|
||||
issuer: "fz_http",
|
||||
secret_key: guardian_secret_key
|
||||
|
||||
config :fz_http,
|
||||
allow_unprivileged_device_management: allow_unprivileged_device_management,
|
||||
max_devices_per_user: max_devices_per_user,
|
||||
local_auth_enabled: local_auth_enabled,
|
||||
okta_auth_enabled: okta_auth_enabled,
|
||||
google_auth_enabled: google_auth_enabled,
|
||||
wireguard_dns: wireguard_dns,
|
||||
wireguard_allowed_ips: wireguard_allowed_ips,
|
||||
wireguard_persistent_keepalive: wireguard_persistent_keepalive,
|
||||
wireguard_ipv4_enabled: wireguard_ipv4_enabled,
|
||||
wireguard_ipv4_network: wireguard_ipv4_network,
|
||||
wireguard_ipv4_address: wireguard_ipv4_address,
|
||||
wireguard_ipv6_enabled: wireguard_ipv6_enabled,
|
||||
wireguard_ipv6_network: wireguard_ipv6_network,
|
||||
wireguard_ipv6_address: wireguard_ipv6_address,
|
||||
wireguard_mtu: wireguard_mtu,
|
||||
wireguard_endpoint: wireguard_endpoint,
|
||||
telemetry_module: telemetry_module,
|
||||
telemetry_id: telemetry_id,
|
||||
connectivity_checks_enabled: connectivity_checks_enabled,
|
||||
connectivity_checks_interval: connectivity_checks_interval,
|
||||
admin_email: admin_email,
|
||||
default_admin_password: default_admin_password
|
||||
|
||||
# Configure strategies
|
||||
identity_strategy =
|
||||
{:identity,
|
||||
{Ueberauth.Strategy.Identity,
|
||||
[
|
||||
callback_methods: ["POST"],
|
||||
callback_url: "#{external_url}/auth/identity/callback",
|
||||
uid_field: :email
|
||||
]}}
|
||||
|
||||
okta_strategy = {:okta, {Ueberauth.Strategy.Okta, []}}
|
||||
google_strategy = {:google, {Ueberauth.Strategy.Google, []}}
|
||||
|
||||
providers =
|
||||
[
|
||||
{local_auth_enabled, identity_strategy},
|
||||
{google_auth_enabled, google_strategy},
|
||||
{okta_auth_enabled, okta_strategy}
|
||||
]
|
||||
|> Enum.filter(fn {key, _val} -> key end)
|
||||
|> Enum.map(fn {_key, val} -> val end)
|
||||
|
||||
config :ueberauth, Ueberauth, providers: providers
|
||||
|
||||
# Configure OAuth portion of enabled strategies
|
||||
if okta_auth_enabled do
|
||||
config :ueberauth, Ueberauth.Strategy.Okta.OAuth,
|
||||
client_id: okta_client_id,
|
||||
client_secret: okta_client_secret,
|
||||
site: okta_site
|
||||
end
|
||||
|
||||
if google_auth_enabled do
|
||||
config :ueberauth, Ueberauth.Strategy.Google.OAuth,
|
||||
client_id: google_client_id,
|
||||
client_secret: google_client_secret,
|
||||
redirect_uri: google_redirect_uri
|
||||
end
|
||||
241
config/runtime.exs
Normal file
241
config/runtime.exs
Normal file
@@ -0,0 +1,241 @@
|
||||
# In this file, we load configuration and secrets
|
||||
# from environment variables. You can also hardcode secrets,
|
||||
# although such is generally not recommended and you have to
|
||||
# remember to add this file to your .gitignore.
|
||||
|
||||
import Config
|
||||
alias FzCommon.{CLI, FzInteger, FzString}
|
||||
|
||||
# Optional config across all envs
|
||||
|
||||
# Defaults to localhost:4000.
|
||||
external_url = System.get_env("EXTERNAL_URL") || "http://localhost:4000"
|
||||
|
||||
if config_env() == :prod do
|
||||
# Errors if not set in production
|
||||
System.fetch_env!("EXTERNAL_URL")
|
||||
end
|
||||
|
||||
# Enable Forwarded headers, e.g 'X-FORWARDED-HOST'
|
||||
proxy_forwarded = FzString.to_boolean(System.get_env("PROXY_FORWARDED") || "false")
|
||||
|
||||
%{host: host, path: path, port: port, scheme: scheme} = URI.parse(external_url)
|
||||
|
||||
config :fz_http, FzHttpWeb.Endpoint,
|
||||
url: [host: host, scheme: scheme, port: port, path: path],
|
||||
check_origin: ["//127.0.0.1", "//localhost", "//#{host}"],
|
||||
proxy_forwarded: proxy_forwarded
|
||||
|
||||
# Formerly releases.exs - Only evaluated in production
|
||||
if config_env() == :prod do
|
||||
# For releases, require that all these are set
|
||||
database_name = System.fetch_env!("DATABASE_NAME")
|
||||
database_user = System.fetch_env!("DATABASE_USER")
|
||||
database_host = System.fetch_env!("DATABASE_HOST")
|
||||
database_port = String.to_integer(System.fetch_env!("DATABASE_PORT"))
|
||||
database_pool = String.to_integer(System.fetch_env!("DATABASE_POOL"))
|
||||
database_ssl = FzString.to_boolean(System.fetch_env!("DATABASE_SSL"))
|
||||
database_ssl_opts = Jason.decode!(System.fetch_env!("DATABASE_SSL_OPTS"))
|
||||
database_parameters = Jason.decode!(System.fetch_env!("DATABASE_PARAMETERS"))
|
||||
phoenix_port = String.to_integer(System.fetch_env!("PHOENIX_PORT"))
|
||||
admin_email = System.fetch_env!("ADMIN_EMAIL")
|
||||
default_admin_password = System.fetch_env!("DEFAULT_ADMIN_PASSWORD")
|
||||
wireguard_interface_name = System.fetch_env!("WIREGUARD_INTERFACE_NAME")
|
||||
wireguard_port = String.to_integer(System.fetch_env!("WIREGUARD_PORT"))
|
||||
nft_path = System.fetch_env!("NFT_PATH")
|
||||
wg_path = System.fetch_env!("WG_PATH")
|
||||
egress_interface = System.fetch_env!("EGRESS_INTERFACE")
|
||||
wireguard_public_key = System.fetch_env!("WIREGUARD_PUBLIC_KEY")
|
||||
wireguard_psk_dir = System.fetch_env!("WIREGUARD_PSK_DIR")
|
||||
wireguard_dns = System.fetch_env!("WIREGUARD_DNS")
|
||||
wireguard_allowed_ips = System.fetch_env!("WIREGUARD_ALLOWED_IPS")
|
||||
wireguard_persistent_keepalive = System.fetch_env!("WIREGUARD_PERSISTENT_KEEPALIVE")
|
||||
wireguard_ipv4_enabled = FzString.to_boolean(System.fetch_env!("WIREGUARD_IPV4_ENABLED"))
|
||||
wireguard_ipv4_network = System.fetch_env!("WIREGUARD_IPV4_NETWORK")
|
||||
wireguard_ipv4_address = System.fetch_env!("WIREGUARD_IPV4_ADDRESS")
|
||||
wireguard_ipv6_enabled = FzString.to_boolean(System.fetch_env!("WIREGUARD_IPV6_ENABLED"))
|
||||
wireguard_ipv6_network = System.fetch_env!("WIREGUARD_IPV6_NETWORK")
|
||||
wireguard_ipv6_address = System.fetch_env!("WIREGUARD_IPV6_ADDRESS")
|
||||
wireguard_mtu = System.fetch_env!("WIREGUARD_MTU")
|
||||
wireguard_endpoint = System.fetch_env!("WIREGUARD_ENDPOINT")
|
||||
telemetry_enabled = FzString.to_boolean(System.fetch_env!("TELEMETRY_ENABLED"))
|
||||
telemetry_id = System.fetch_env!("TELEMETRY_ID")
|
||||
guardian_secret_key = System.fetch_env!("GUARDIAN_SECRET_KEY")
|
||||
|
||||
allow_unprivileged_device_management =
|
||||
FzString.to_boolean(System.fetch_env!("ALLOW_UNPRIVILEGED_DEVICE_MANAGEMENT"))
|
||||
|
||||
# Local auth
|
||||
local_auth_enabled = FzString.to_boolean(System.fetch_env!("LOCAL_AUTH_ENABLED"))
|
||||
|
||||
# Okta auth
|
||||
okta_auth_enabled = FzString.to_boolean(System.fetch_env!("OKTA_AUTH_ENABLED"))
|
||||
okta_client_id = System.get_env("OKTA_CLIENT_ID")
|
||||
okta_client_secret = System.get_env("OKTA_CLIENT_SECRET")
|
||||
okta_site = System.get_env("OKTA_SITE")
|
||||
|
||||
# Google auth
|
||||
google_auth_enabled = FzString.to_boolean(System.fetch_env!("GOOGLE_AUTH_ENABLED"))
|
||||
google_client_id = System.get_env("GOOGLE_CLIENT_ID")
|
||||
google_client_secret = System.get_env("GOOGLE_CLIENT_SECRET")
|
||||
google_redirect_uri = System.get_env("GOOGLE_REDIRECT_URI")
|
||||
|
||||
max_devices_per_user =
|
||||
System.fetch_env!("MAX_DEVICES_PER_USER")
|
||||
|> String.to_integer()
|
||||
|> FzInteger.clamp(0, 100)
|
||||
|
||||
telemetry_module =
|
||||
if telemetry_enabled do
|
||||
FzCommon.Telemetry
|
||||
else
|
||||
FzCommon.MockTelemetry
|
||||
end
|
||||
|
||||
connectivity_checks_enabled =
|
||||
FzString.to_boolean(System.fetch_env!("CONNECTIVITY_CHECKS_ENABLED")) &&
|
||||
System.get_env("CI") != "true"
|
||||
|
||||
connectivity_checks_interval =
|
||||
System.fetch_env!("CONNECTIVITY_CHECKS_INTERVAL")
|
||||
|> String.to_integer()
|
||||
|> FzInteger.clamp(60, 86_400)
|
||||
|
||||
# secrets
|
||||
encryption_key = System.fetch_env!("DATABASE_ENCRYPTION_KEY")
|
||||
secret_key_base = System.fetch_env!("SECRET_KEY_BASE")
|
||||
live_view_signing_salt = System.fetch_env!("LIVE_VIEW_SIGNING_SALT")
|
||||
cookie_signing_salt = System.fetch_env!("COOKIE_SIGNING_SALT")
|
||||
|
||||
# Password is not needed if using bundled PostgreSQL, so use nil if it's not set.
|
||||
database_password = System.get_env("DATABASE_PASSWORD")
|
||||
|
||||
# XXX: Using to_atom here because this is trusted input and to_existing_atom
|
||||
# won't work because we won't know the keys ahead of time.
|
||||
ssl_opts = Keyword.new(database_ssl_opts, fn {k, v} -> {String.to_atom(k), v} end)
|
||||
parameters = Keyword.new(database_parameters, fn {k, v} -> {String.to_atom(k), v} end)
|
||||
|
||||
# Database configuration
|
||||
connect_opts = [
|
||||
database: database_name,
|
||||
username: database_user,
|
||||
hostname: database_host,
|
||||
port: database_port,
|
||||
pool_size: database_pool,
|
||||
ssl: database_ssl,
|
||||
ssl_opts: ssl_opts,
|
||||
parameters: parameters,
|
||||
queue_target: 500
|
||||
]
|
||||
|
||||
if database_password do
|
||||
config(:fz_http, FzHttp.Repo, connect_opts ++ [password: database_password])
|
||||
else
|
||||
config(:fz_http, FzHttp.Repo, connect_opts)
|
||||
end
|
||||
|
||||
config :fz_http, FzHttp.Vault,
|
||||
ciphers: [
|
||||
default: {
|
||||
Cloak.Ciphers.AES.GCM,
|
||||
# In AES.GCM, it is important to specify 12-byte IV length for
|
||||
# interoperability with other encryption software. See this GitHub
|
||||
# issue for more details:
|
||||
# https://github.com/danielberkompas/cloak/issues/93
|
||||
#
|
||||
# In Cloak 2.0, this will be the default iv length for AES.GCM.
|
||||
tag: "AES.GCM.V1", key: Base.decode64!(encryption_key), iv_length: 12
|
||||
}
|
||||
]
|
||||
|
||||
config :fz_http, FzHttpWeb.Endpoint,
|
||||
http: [ip: {127, 0, 0, 1}, port: phoenix_port],
|
||||
server: true,
|
||||
secret_key_base: secret_key_base,
|
||||
live_view: [
|
||||
signing_salt: live_view_signing_salt
|
||||
]
|
||||
|
||||
config :fz_wall,
|
||||
nft_path: nft_path,
|
||||
egress_interface: egress_interface,
|
||||
wireguard_interface_name: wireguard_interface_name,
|
||||
cli: FzWall.CLI.Live
|
||||
|
||||
config :fz_vpn,
|
||||
wireguard_psk_dir: wireguard_psk_dir,
|
||||
wireguard_public_key: wireguard_public_key,
|
||||
wireguard_interface_name: wireguard_interface_name,
|
||||
wireguard_port: wireguard_port,
|
||||
cli: FzVpn.CLI.Live
|
||||
|
||||
# Guardian configuration
|
||||
config :fz_http, FzHttpWeb.Authentication,
|
||||
issuer: "fz_http",
|
||||
secret_key: guardian_secret_key
|
||||
|
||||
config :fz_http,
|
||||
wg_path: wg_path,
|
||||
cookie_signing_salt: cookie_signing_salt,
|
||||
allow_unprivileged_device_management: allow_unprivileged_device_management,
|
||||
max_devices_per_user: max_devices_per_user,
|
||||
local_auth_enabled: local_auth_enabled,
|
||||
okta_auth_enabled: okta_auth_enabled,
|
||||
google_auth_enabled: google_auth_enabled,
|
||||
wireguard_dns: wireguard_dns,
|
||||
wireguard_allowed_ips: wireguard_allowed_ips,
|
||||
wireguard_persistent_keepalive: wireguard_persistent_keepalive,
|
||||
wireguard_ipv4_enabled: wireguard_ipv4_enabled,
|
||||
wireguard_ipv4_network: wireguard_ipv4_network,
|
||||
wireguard_ipv4_address: wireguard_ipv4_address,
|
||||
wireguard_ipv6_enabled: wireguard_ipv6_enabled,
|
||||
wireguard_ipv6_network: wireguard_ipv6_network,
|
||||
wireguard_ipv6_address: wireguard_ipv6_address,
|
||||
wireguard_mtu: wireguard_mtu,
|
||||
wireguard_endpoint: wireguard_endpoint,
|
||||
telemetry_module: telemetry_module,
|
||||
telemetry_id: telemetry_id,
|
||||
connectivity_checks_enabled: connectivity_checks_enabled,
|
||||
connectivity_checks_interval: connectivity_checks_interval,
|
||||
admin_email: admin_email,
|
||||
default_admin_password: default_admin_password
|
||||
|
||||
# Configure strategies
|
||||
identity_strategy =
|
||||
{:identity,
|
||||
{Ueberauth.Strategy.Identity,
|
||||
[
|
||||
callback_methods: ["POST"],
|
||||
callback_url: "#{external_url}/auth/identity/callback",
|
||||
uid_field: :email
|
||||
]}}
|
||||
|
||||
okta_strategy = {:okta, {Ueberauth.Strategy.Okta, []}}
|
||||
google_strategy = {:google, {Ueberauth.Strategy.Google, []}}
|
||||
|
||||
providers =
|
||||
[
|
||||
{local_auth_enabled, identity_strategy},
|
||||
{google_auth_enabled, google_strategy},
|
||||
{okta_auth_enabled, okta_strategy}
|
||||
]
|
||||
|> Enum.filter(fn {key, _val} -> key end)
|
||||
|> Enum.map(fn {_key, val} -> val end)
|
||||
|
||||
config :ueberauth, Ueberauth, providers: providers
|
||||
|
||||
# Configure OAuth portion of enabled strategies
|
||||
if okta_auth_enabled do
|
||||
config :ueberauth, Ueberauth.Strategy.Okta.OAuth,
|
||||
client_id: okta_client_id,
|
||||
client_secret: okta_client_secret,
|
||||
site: okta_site
|
||||
end
|
||||
|
||||
if google_auth_enabled do
|
||||
config :ueberauth, Ueberauth.Strategy.Google.OAuth,
|
||||
client_id: google_client_id,
|
||||
client_secret: google_client_secret,
|
||||
redirect_uri: google_redirect_uri
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user