feat: firezone server coming up correctly

This commit is contained in:
oddlama 2025-01-25 20:23:40 +01:00
parent 7c61ac80fa
commit e7971ccf6c
No known key found for this signature in database
GPG key ID: 14EFE510775FE39A
3 changed files with 470 additions and 303 deletions

View file

@ -13,6 +13,7 @@ let
types
;
cfg = config.services.firezone.server;
apiCfg = config.services.firezone.server.api;
domainCfg = config.services.firezone.server.domain;
webCfg = config.services.firezone.server.web;
@ -58,98 +59,347 @@ let
StateDirectory = "firezone";
WorkingDirectory = "/var/lib/firezone";
};
commonEnv = {
# **EXTERNAL_URL**
# PHOENIX_SECURE_COOKIES
# PHOENIX_HTTP_PORT
# PHOENIX_HTTP_PROTOCOL_OPTIONS
# PHOENIX_EXTERNAL_TRUSTED_PROXIES
# PHOENIX_PRIVATE_CLIENTS
# HTTP_CLIENT_SSL_OPTS
# DATABASE_HOST
# DATABASE_PORT
# DATABASE_NAME
# DATABASE_USER
# DATABASE_PASSWORD
# DATABASE_POOL_SIZE
# DATABASE_SSL_ENABLED
# DATABASE_SSL_OPTS
# RESET_ADMIN_ON_BOOT
# DEFAULT_ADMIN_EMAIL
# DEFAULT_ADMIN_PASSWORD
# **GUARDIAN_SECRET_KEY**
# **DATABASE_ENCRYPTION_KEY**
# **SECRET_KEY_BASE**
# **LIVE_VIEW_SIGNING_SALT**
# **COOKIE_SIGNING_SALT**
# **COOKIE_ENCRYPTION_SALT**
# ALLOW_UNPRIVILEGED_DEVICE_MANAGEMENT
# ALLOW_UNPRIVILEGED_DEVICE_CONFIGURATION
# VPN_SESSION_DURATION
# DEFAULT_CLIENT_PERSISTENT_KEEPALIVE
# DEFAULT_CLIENT_MTU
# DEFAULT_CLIENT_ENDPOINT
# DEFAULT_CLIENT_DNS
# DEFAULT_CLIENT_ALLOWED_IPS
# MAX_DEVICES_PER_USER
# LOCAL_AUTH_ENABLED
# DISABLE_VPN_ON_OIDC_ERROR
# SAML_ENTITY_ID
# SAML_KEYFILE_PATH
# SAML_CERTFILE_PATH
# OPENID_CONNECT_PROVIDERS
# SAML_IDENTITY_PROVIDERS
# WIREGUARD_PORT
# OUTBOUND_EMAIL_FROM
# OUTBOUND_EMAIL_ADAPTER
# OUTBOUND_EMAIL_ADAPTER_OPTS
# CONNECTIVITY_CHECKS_ENABLED
# CONNECTIVITY_CHECKS_INTERVAL
# TELEMETRY_ENABLED
# LOGO
TZDATA_DIR = "/var/lib/firezone/tzdata";
TELEMETRY_ENABLED = "false";
RELEASE_COOKIE = "agfea"; # TODO make option, if null generate automatically on first start
# Database;
DATABASE_SOCKET_DIR = "/run/postgresql";
DATABASE_PORT = "5432";
DATABASE_NAME = "firezone";
DATABASE_USER = "firezone";
DATABASE_POOL_SIZE = "16";
#DATABASE_HOST = "localhost";
#DATABASE_PASSWORD = "";
# Auth;
AUTH_PROVIDER_ADAPTERS = "email,openid_connect,userpass,token";
# Secrets;
TOKENS_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
SECRET_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
TOKENS_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
LIVE_VIEW_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_ENCRYPTION_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
OUTBOUND_EMAIL_ADAPTER = "Elixir.Swoosh.Adapters.Mua";
OUTBOUND_EMAIL_ADAPTER_OPTS = builtins.toJSON {
};
# Feature flags;
FEATURE_FLOW_ACTIVITIES_ENABLED = "true";
FEATURE_POLICY_CONDITIONS_ENABLED = "true";
FEATURE_MULTI_SITE_RESOURCES_ENABLED = "true";
FEATURE_SELF_HOSTED_RELAYS_ENABLED = "true";
FEATURE_IDP_SYNC_ENABLED = "true";
FEATURE_REST_API_ENABLED = "true";
FEATURE_INTERNET_RESOURCE_ENABLED = "true";
FEATURE_TRAFFIC_FILTERS_ENABLED = "true";
FEATURE_SIGN_UP_ENABLED = "true";
};
componentOptions = component: {
enable = mkEnableOption "the Firezone ${component} server";
# TODO: single package plus web and api passthrough.
# package = mkPackageOption pkgs "firezone-server" { };
environment = {
exclude = mkOption {
type = types.attrsOf types.bool;
default = { };
description = ''
Each environment variable specified through either
{option}`services.firezone.server.settings` or
{option}`services.firezone.server.secretSettings`
will only be passed to this component if it is not excluded
by this option.
'';
example = {
PHOENIX_HTTP_PORT = true;
};
};
replaceWithDummy = mkOption {
type = types.attrsOf types.bool;
default = { };
description = ''
Any environment variable specified here will receive a dummy value
instead of the actual value specified through either
{option}`services.firezone.server.settings` or
{option}`services.firezone.server.secretSettings`.
This can be used to hide secret information from components that
require a certain variable to be set while not actually using its
value.
'';
example = {
SECRET_KEY_BASE = true;
};
};
override = mkOption {
description = ''
Any environment variable specified here will receive the associated
value just for this component instead of the actual value specified
through either {option}`services.firezone.server.settings` or
{option}`services.firezone.server.secretSettings`.
'';
default = { };
type = lib.types.submodule {
freeformType = types.attrsOf (
types.oneOf [
types.bool
types.float
types.int
types.str
types.path
types.package
]
);
};
};
};
settings = lib.mkOption {
description = ''
Environment variables for the Firezone server. For a list of available
variables, please refer to the [upstream definitions](https://github.com/firezone/firezone/blob/main/elixir/apps/domain/lib/domain/config/definitions.ex).
Some variables like `OUTBOUND_EMAIL_ADAPTER_OPTS` require json values
for which you can use `VAR = builtins.toJSON { /* ... */ }`.
Configuration variables in Firezone are generally defined across all
components, so certain variables need to be present before any componen
will start up, even if that particular component does not actually
utilize its value.
Each component has an additional `environment` option group which
allows you to exclude, replace or override certain variables passed to
that component. A sensible default filter is provided which you can
modify if necessary.
'';
default = { };
type = lib.types.submodule {
freeformType = types.attrsOf (
types.oneOf [
types.bool
types.float
types.int
types.str
types.path
types.package
]
);
};
};
};
in
{
options.services.firezone.server = {
domain = {
enable = mkEnableOption "the Firezone domain server";
# TODO: single package plus web and api passthrough.
# package = mkPackageOption pkgs "firezone-server" { };
enableLocalDB = mkEnableOption "a local postgresql database for Firezone";
enableLocalDB = mkEnableOption "a local postgresql database for Firezone";
# FIXME: enableNginx = mkEnableOption "a local nginx endpoint";
settings = lib.mkOption {
default = { };
description = ''
TODO
'';
example = {
};
type = lib.types.submodule {
freeformType = types.attrsOf (
types.oneOf [
types.bool
types.float
types.int
types.str
types.path
types.package
]
);
options = {
openClusterFirewall = mkOption {
type = types.bool;
default = false;
description = ''
Opens up the erlang distribution port of all enabled components to
allow reaching the server cluster from the internet. You only need to
set this if you are actually distributing your cluster across multiple
machines.
'';
};
clusterHosts = mkOption {
type = types.listOf types.str;
default = [
"api@localhost.localdomain"
"web@localhost.localdomain"
"domain@localhost.localdomain"
];
description = ''
A list of components and their hosts that are part of this cluster. For
a single-machine setup, the default value will be sufficient. This
value will automatically set `ERLANG_CLUSTER_ADAPTER_CONFIG`.
The format is `<COMPONENT_NAME>@<HOSTNAME>`.
'';
};
secretSettings = mkOption {
default = { };
description = ''
This is a convenience option which allows you to set secret values for
environment variables by specifying a file which will contain the value
at runtime. Before starting the server, the content of each file will
be loaded into the respective environment variable.
Otherwise, this option is equivalent to
{option}`services.firezone.server.settings`. Refer to the settings
option for more information regarding the actual variables and how
filtering rules are applied for each component.
'';
type = lib.types.submodule {
freeformType = types.attrsOf types.path;
options = {
# FIXME: SECRET_KEY_BASE
RELEASE_COOKIE = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
A file containing a unique secret identifier for the Erlang
cluster. All Firezone components in your cluster must use the
same value. If this is `null`, a shared value will automatically
be generated on startup and used for all components on this
machine.
You do not need to set this except when you spread your cluster
over multiple hosts.
'';
};
};
};
};
web = {
enable = mkEnableOption "the Firezone web server";
# TODO: single package plus web and api passthrough.
# package = mkPackageOption pkgs "firezone-server" { };
settings = lib.mkOption {
default = { };
description = ''
TODO
'';
example = {
};
type = lib.types.submodule {
freeformType = types.attrsOf (
types.oneOf [
types.bool
types.float
types.int
types.str
types.path
types.package
]
);
options = {
};
};
settings = lib.mkOption {
description = ''
Environment variables for the Firezone server. For a list of available
variables, please refer to the [upstream definitions](https://github.com/firezone/firezone/blob/main/elixir/apps/domain/lib/domain/config/definitions.ex).
Some variables like `OUTBOUND_EMAIL_ADAPTER_OPTS` require json values
for which you can use `VAR = builtins.toJSON { /* ... */ }`.
Configuration variables in Firezone are generally defined across all
components, so certain variables need to be present before any componen
will start up, even if that particular component does not actually
utilize its value.
Each component has an additional `environment` option group which
allows you to exclude, replace or override certain variables passed to
that component. A sensible default filter is provided which you can
modify if necessary.
'';
default = { };
type = lib.types.submodule {
freeformType = types.attrsOf (
types.oneOf [
types.bool
types.float
types.int
types.str
types.path
types.package
]
);
};
};
api = {
enable = mkEnableOption "the Firezone api server";
# TODO: single package plus web and api passthrough.
# package = mkPackageOption pkgs "firezone-server" { };
settings = lib.mkOption {
default = { };
description = ''
TODO
'';
example = {
};
type = lib.types.submodule {
freeformType = types.attrsOf (
types.oneOf [
types.bool
types.float
types.int
types.str
types.path
types.package
]
);
options = {
};
};
};
domain = componentOptions "domain" // {
};
web = componentOptions "web" // {
};
api = componentOptions "api" // {
};
};
config = {
services.postgresql = mkIf domainCfg.enableLocalDB {
# Specify sensible defaults
services.firezone.server = {
settings = {
LOG_LEVEL = "debug";
RELEASE_HOSTNAME = "localhost.localdomain";
ERLANG_CLUSTER_ADAPTER = "Elixir.Cluster.Strategy.Epmd";
ERLANG_CLUSTER_ADAPTER_CONFIG = builtins.toJSON {
hosts = cfg.clusterHosts;
};
TZDATA_DIR = "/var/lib/firezone/tzdata";
TELEMETRY_ENABLED = false;
WEB_EXTERNAL_URL = "http://localhost:8080/";
API_EXTERNAL_URL = "http://localhost:8081/";
};
domain.settings = {
ERLANG_DISTRIBUTION_PORT = 9000;
HEALTHZ_PORT = 4000;
};
domain.environment.exclude = {
WEB_EXTERNAL_URL = true;
API_EXTERNAL_URL = true;
};
web.settings = {
ERLANG_DISTRIBUTION_PORT = 9001;
HEALTHZ_PORT = 4001;
# Web Server
PHOENIX_HTTP_WEB_PORT = 8080;
PHOENIX_HTTP_API_PORT = 8081;
PHOENIX_SECURE_COOKIES = false;
};
api.settings = {
ERLANG_DISTRIBUTION_PORT = 9002;
HEALTHZ_PORT = 4002;
};
};
# FIXME: mkIf openClusterFirewall {};
services.postgresql = mkIf cfg.enableLocalDB {
enable = true;
ensureUsers = [
{
@ -162,288 +412,97 @@ in
systemd.services.firezone-server-domain = mkIf domainCfg.enable {
description = "Firezone domain server";
after = mkIf domainCfg.enableLocalDB [ "postgresql.service" ];
wants = mkIf domainCfg.enableLocalDB [ "postgresql.service" ];
after = mkIf cfg.enableLocalDB [ "postgresql.service" ];
wants = mkIf cfg.enableLocalDB [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
mkdir -p tzdata
'';
script = ''
${getExe pkgs.firezone-server-domain} eval Domain.Release.migrate
exec ${getExe pkgs.firezone-server-domain} start
'';
serviceConfig = commonServiceConfig // {
ExecStart = "${getExe pkgs.firezone-server-domain} start";
};
environment = {
# **EXTERNAL_URL**
# PHOENIX_SECURE_COOKIES
# PHOENIX_HTTP_PORT
# PHOENIX_HTTP_PROTOCOL_OPTIONS
# PHOENIX_EXTERNAL_TRUSTED_PROXIES
# PHOENIX_PRIVATE_CLIENTS
# HTTP_CLIENT_SSL_OPTS
# DATABASE_HOST
# DATABASE_PORT
# DATABASE_NAME
# DATABASE_USER
# DATABASE_PASSWORD
# DATABASE_POOL_SIZE
# DATABASE_SSL_ENABLED
# DATABASE_SSL_OPTS
# RESET_ADMIN_ON_BOOT
# DEFAULT_ADMIN_EMAIL
# DEFAULT_ADMIN_PASSWORD
# **GUARDIAN_SECRET_KEY**
# **DATABASE_ENCRYPTION_KEY**
# **SECRET_KEY_BASE**
# **LIVE_VIEW_SIGNING_SALT**
# **COOKIE_SIGNING_SALT**
# **COOKIE_ENCRYPTION_SALT**
# ALLOW_UNPRIVILEGED_DEVICE_MANAGEMENT
# ALLOW_UNPRIVILEGED_DEVICE_CONFIGURATION
# VPN_SESSION_DURATION
# DEFAULT_CLIENT_PERSISTENT_KEEPALIVE
# DEFAULT_CLIENT_MTU
# DEFAULT_CLIENT_ENDPOINT
# DEFAULT_CLIENT_DNS
# DEFAULT_CLIENT_ALLOWED_IPS
# MAX_DEVICES_PER_USER
# LOCAL_AUTH_ENABLED
# DISABLE_VPN_ON_OIDC_ERROR
# SAML_ENTITY_ID
# SAML_KEYFILE_PATH
# SAML_CERTFILE_PATH
# OPENID_CONNECT_PROVIDERS
# SAML_IDENTITY_PROVIDERS
# WIREGUARD_PORT
# OUTBOUND_EMAIL_FROM
# OUTBOUND_EMAIL_ADAPTER
# OUTBOUND_EMAIL_ADAPTER_OPTS
# CONNECTIVITY_CHECKS_ENABLED
# CONNECTIVITY_CHECKS_INTERVAL
# TELEMETRY_ENABLED
# LOGO
TZDATA_DIR = "/var/lib/firezone/tzdata";
TELEMETRY_ENABLED = "false";
RELEASE_COOKIE = "agfea"; # TODO make option, if null generate automatically on first start
environment = commonEnv // {
RELEASE_NAME = "domain";
RELEASE_HOSTNAME = "localhost.localdomain";
ERLANG_DISTRIBUTION_PORT = "9000";
HEALTHZ_PORT = "4000";
# Debugging;
LOG_LEVEL = "debug";
# Erlang;
ERLANG_DISTRIBUTION_PORT = "9002";
ERLANG_CLUSTER_ADAPTER = "Elixir.Cluster.Strategy.Epmd";
ERLANG_CLUSTER_ADAPTER_CONFIG = builtins.toJSON {
hosts = [
"api@localhost.localdomain"
"web@localhost.localdomain"
"domain@localhost.localdomain"
];
};
# Database;
DATABASE_SOCKET_DIR = "/run/postgresql";
DATABASE_PORT = "5432";
DATABASE_NAME = "firezone";
DATABASE_USER = "firezone";
#DATABASE_HOST = "localhost";
#DATABASE_PASSWORD = "";
# Auth;
AUTH_PROVIDER_ADAPTERS = "email,openid_connect,userpass,token,google_workspace,microsoft_entra,okta,jumpcloud";
# Secrets;
TOKENS_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
SECRET_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
TOKENS_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
LIVE_VIEW_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_ENCRYPTION_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
# Seeds;
STATIC_SEEDS = "true";
OUTBOUND_EMAIL_FROM = "public-noreply@firez.one";
OUTBOUND_EMAIL_ADAPTER = "Elixir.Swoosh.Adapters.Postmark";
## Warning= The token is for the blackhole Postmark server created in a separate isolated account,;
## that WILL NOT send any actual emails, but you can see and debug them in the Postmark dashboard.;
OUTBOUND_EMAIL_ADAPTER_OPTS = ''{"api_key":"7da7d1cd-111c-44a7-b5ac-4027b9d230e5"}'';
# Feature flags;
FEATURE_FLOW_ACTIVITIES_ENABLED = "true";
FEATURE_POLICY_CONDITIONS_ENABLED = "true";
FEATURE_MULTI_SITE_RESOURCES_ENABLED = "true";
FEATURE_SELF_HOSTED_RELAYS_ENABLED = "true";
FEATURE_IDP_SYNC_ENABLED = "true";
FEATURE_REST_API_ENABLED = "true";
FEATURE_INTERNET_RESOURCE_ENABLED = "true";
RESET_ADMIN_ON_BOOT = "true";
DEFAULT_ADMIN_EMAIL = "admin@example.com";
DEFAULT_ADMIN_PASSWORD = "admin@example.com";
};
};
systemd.services.firezone-server-web = mkIf webCfg.enable {
description = "Firezone web server";
after = mkIf cfg.enableLocalDB [ "postgresql.service" ];
wants = mkIf cfg.enableLocalDB [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
mkdir -p tzdata
'';
script = ''
${getExe pkgs.firezone-server-web} eval Domain.Release.migrate
exec ${getExe pkgs.firezone-server-web} start
'';
serviceConfig = commonServiceConfig // {
ExecStart = "${getExe pkgs.firezone-server-web} start";
};
environment = {
TZDATA_DIR = "/var/lib/firezone/tzdata";
TELEMETRY_ENABLED = "false";
RELEASE_COOKIE = "agfea"; # TODO make option, if null generate automatically on first start
environment = commonEnv // {
RELEASE_NAME = "web";
RELEASE_HOSTNAME = "localhost.localdomain";
ERLANG_DISTRIBUTION_PORT = "9001";
HEALTHZ_PORT = "4001";
# Web Server
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";
HEALTHZ_PORT = "4001";
# Debugging;
LOG_LEVEL = "debug";
# Erlang;
ERLANG_DISTRIBUTION_PORT = "9001";
ERLANG_CLUSTER_ADAPTER = "Elixir.Cluster.Strategy.Epmd";
ERLANG_CLUSTER_ADAPTER_CONFIG = builtins.toJSON {
hosts = [
"api@localhost.localdomain"
"web@localhost.localdomain"
"domain@localhost.localdomain"
];
};
# Database;
DATABASE_SOCKET_DIR = "/run/postgresql";
DATABASE_PORT = "5432";
DATABASE_NAME = "firezone";
DATABASE_USER = "firezone";
#DATABASE_HOST = "localhost";
#DATABASE_PASSWORD = "";
# Auth;
AUTH_PROVIDER_ADAPTERS = "email,openid_connect,userpass,token,google_workspace,microsoft_entra,okta,jumpcloud";
# Secrets;
TOKENS_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
SECRET_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
TOKENS_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
LIVE_VIEW_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_ENCRYPTION_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
# Seeds;
STATIC_SEEDS = "true";
OUTBOUND_EMAIL_FROM = "public-noreply@firez.one";
OUTBOUND_EMAIL_ADAPTER = "Elixir.Swoosh.Adapters.Postmark";
## Warning= The token is for the blackhole Postmark server created in a separate isolated account,;
## that WILL NOT send any actual emails, but you can see and debug them in the Postmark dashboard.;
OUTBOUND_EMAIL_ADAPTER_OPTS = ''{"api_key":"7da7d1cd-111c-44a7-b5ac-4027b9d230e5"}'';
# Feature flags;
FEATURE_FLOW_ACTIVITIES_ENABLED = "true";
FEATURE_POLICY_CONDITIONS_ENABLED = "true";
FEATURE_MULTI_SITE_RESOURCES_ENABLED = "true";
FEATURE_SELF_HOSTED_RELAYS_ENABLED = "true";
FEATURE_IDP_SYNC_ENABLED = "true";
FEATURE_REST_API_ENABLED = "true";
FEATURE_INTERNET_RESOURCE_ENABLED = "true";
};
};
systemd.services.firezone-server-api = mkIf apiCfg.enable {
description = "Firezone api server";
after = mkIf cfg.enableLocalDB [ "postgresql.service" ];
wants = mkIf cfg.enableLocalDB [ "postgresql.service" ];
wantedBy = [ "multi-user.target" ];
preStart = ''
mkdir -p tzdata
'';
script = ''
${getExe pkgs.firezone-server-api} eval Domain.Release.migrate
exec ${getExe pkgs.firezone-server-api} start
'';
serviceConfig = commonServiceConfig // {
ExecStart = "${getExe pkgs.firezone-server-api} start";
};
environment = {
TZDATA_DIR = "/var/lib/firezone/tzdata";
TELEMETRY_ENABLED = "false";
RELEASE_COOKIE = "agfea"; # TODO make option, if null generate automatically on first start
environment = commonEnv // {
RELEASE_NAME = "api";
RELEASE_HOSTNAME = "localhost.localdomain";
ERLANG_DISTRIBUTION_PORT = "9002";
HEALTHZ_PORT = "4002";
# Web Server
WEB_EXTERNAL_URL = "http://localhost:8080/";
API_EXTERNAL_URL = "http://localhost:8081/";
HEALTHZ_PORT = "4002";
# Debugging;
LOG_LEVEL = "debug";
# Erlang;
ERLANG_DISTRIBUTION_PORT = "9000";
ERLANG_CLUSTER_ADAPTER = "Elixir.Cluster.Strategy.Epmd";
ERLANG_CLUSTER_ADAPTER_CONFIG = builtins.toJSON {
hosts = [
"api@localhost.localdomain"
"web@localhost.localdomain"
"domain@localhost.localdomain"
];
};
# Database;
DATABASE_SOCKET_DIR = "/run/postgresql";
DATABASE_PORT = "5432";
DATABASE_NAME = "firezone";
DATABASE_USER = "firezone";
#DATABASE_HOST = "localhost";
#DATABASE_PASSWORD = "";
# Auth;
AUTH_PROVIDER_ADAPTERS = "email,openid_connect,userpass,token,google_workspace,microsoft_entra,okta,jumpcloud";
# Secrets;
TOKENS_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
SECRET_KEY_BASE = "5OVYJ83AcoQcPmdKNksuBhJFBhjHD1uUa9mDOHV/6EIdBQ6pXksIhkVeWIzFk5S2";
TOKENS_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
LIVE_VIEW_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_SIGNING_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
COOKIE_ENCRYPTION_SALT = "t01wa0K4lUd7mKa0HAtZdE+jFOPDDej2";
# Seeds;
STATIC_SEEDS = "true";
OUTBOUND_EMAIL_FROM = "public-noreply@firez.one";
OUTBOUND_EMAIL_ADAPTER = "Elixir.Swoosh.Adapters.Postmark";
## Warning= The token is for the blackhole Postmark server created in a separate isolated account,;
## that WILL NOT send any actual emails, but you can see and debug them in the Postmark dashboard.;
OUTBOUND_EMAIL_ADAPTER_OPTS = ''{"api_key":"7da7d1cd-111c-44a7-b5ac-4027b9d230e5"}'';
# Feature flags;
FEATURE_FLOW_ACTIVITIES_ENABLED = "true";
FEATURE_POLICY_CONDITIONS_ENABLED = "true";
FEATURE_MULTI_SITE_RESOURCES_ENABLED = "true";
FEATURE_SELF_HOSTED_RELAYS_ENABLED = "true";
FEATURE_IDP_SYNC_ENABLED = "true";
FEATURE_REST_API_ENABLED = "true";
FEATURE_INTERNET_RESOURCE_ENABLED = "true";
};
};
};

View file

@ -1,5 +1,5 @@
diff --git a/apps/domain/lib/domain/config/definitions.ex b/apps/domain/lib/domain/config/definitions.ex
index 8cd2e8d0f..f27d67c69 100644
index 8cd2e8d0f..92e18b10b 100644
--- a/apps/domain/lib/domain/config/definitions.ex
+++ b/apps/domain/lib/domain/config/definitions.ex
@@ -61,6 +61,7 @@ defmodule Domain.Config.Definitions do
@ -22,6 +22,14 @@ index 8cd2e8d0f..f27d67c69 100644
@doc """
PostgreSQL port.
"""
@@ -584,6 +590,7 @@ defmodule Domain.Config.Definitions do
Swoosh.Adapters.Mailgun,
Swoosh.Adapters.Mailjet,
Swoosh.Adapters.Mandrill,
+ Swoosh.Adapters.Mua,
Swoosh.Adapters.Postmark,
Swoosh.Adapters.ProtonBridge,
Swoosh.Adapters.SMTP,
diff --git a/apps/domain/lib/domain/telemetry.ex b/apps/domain/lib/domain/telemetry.ex
index af430358d..a544e706e 100644
--- a/apps/domain/lib/domain/telemetry.ex
@ -35,8 +43,29 @@ index af430358d..a544e706e 100644
# Telemetry poller will execute the given period measurements
# every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
diff --git a/apps/web/lib/web/live/sign_up.ex b/apps/web/lib/web/live/sign_up.ex
index c4e06bc58..89533fb81 100644
--- a/apps/web/lib/web/live/sign_up.ex
+++ b/apps/web/lib/web/live/sign_up.ex
@@ -1,5 +1,6 @@
defmodule Web.SignUp do
use Web, {:live_view, layout: {Web.Layouts, :public}}
+ require Logger
alias Domain.{Auth, Accounts, Actors, Config}
alias Web.Registration
@@ -358,7 +359,8 @@ defmodule Web.SignUp do
{:noreply, assign(socket, form: to_form(changeset))}
- {:error, :send_email, _reason, _effects_so_far} ->
+ {:error, :send_email, reason, _effects_so_far} ->
+ Logger.info("aaaaaaaaaaaaaaaaaa", reason: inspect(reason))
changeset =
Ecto.Changeset.add_error(
changeset,
diff --git a/config/runtime.exs b/config/runtime.exs
index 15037e0a3..948f62cc8 100644
index 15037e0a3..475c4ddfb 100644
--- a/config/runtime.exs
+++ b/config/runtime.exs
@@ -8,15 +8,17 @@ if config_env() == :prod do
@ -66,3 +95,54 @@ index 15037e0a3..948f62cc8 100644
config :domain, Domain.Tokens,
key_base: compile_config!(:tokens_key_base),
@@ -226,8 +228,15 @@ if config_env() == :prod do
config :domain,
Domain.Mailer,
[
- adapter: compile_config!(:outbound_email_adapter),
- from_email: compile_config!(:outbound_email_from)
+ adapter: compile_config!(:outbound_email_adapter),
+ from_email: compile_config!(:outbound_email_from),
+ protocol: :ssl,
+ relay: System.get_env("OUTBOUND_EMAIL_RELAY"),
+ port: 465,
+ auth: [
+ username: System.get_env("OUTBOUND_EMAIL_USERNAME"),
+ password: System.get_env("OUTBOUND_EMAIL_PASSWORD")
+ ]
] ++ compile_config!(:outbound_email_adapter_opts)
config :workos, WorkOS.Client,
diff --git a/mix.exs b/mix.exs
index 12782d631..dee1245d2 100644
--- a/mix.exs
+++ b/mix.exs
@@ -47,7 +47,9 @@ defmodule Firezone.MixProject do
# Formatter doesn't track dependencies of children applications
{:phoenix, "~> 1.7.0"},
{:phoenix_live_view, "~> 1.0.0-rc.0"},
- {:floki, "~> 0.37.0"}
+ {:floki, "~> 0.37.0"},
+ {:mua, "~> 0.2.0"},
+ {:mail, "~> 0.3.0"}
]
end
diff --git a/mix.lock b/mix.lock
index 8c4b65959..3d2f9faca 100644
--- a/mix.lock
+++ b/mix.lock
@@ -50,11 +50,13 @@
"junit_formatter": {:hex, :junit_formatter, "3.4.0", "d0e8db6c34dab6d3c4154c3b46b21540db1109ae709d6cf99ba7e7a2ce4b1ac2", [:mix], [], "hexpm", "bb36e2ae83f1ced6ab931c4ce51dd3dbef1ef61bb4932412e173b0cfa259dacd"},
"libcluster": {:hex, :libcluster, "3.3.3", "a4f17721a19004cfc4467268e17cff8b1f951befe428975dd4f6f7b84d927fe0", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "7c0a2275a0bb83c07acd17dab3c3bfb4897b145106750eeccc62d302e3bdfee5"},
"logger_json": {:hex, :logger_json, "6.2.0", "13e2e9f5f7b195865c5c3ef3d296c3ad50e7ecb038d899433702a79e979b91d7", [:mix], [{:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "98366d02bedbb56e41b25a6d248d566d4f4bc224bae2b1e982df00ed04ba9219"},
+ "mail": {:hex, :mail, "0.3.1", "cb0a14e4ed8904e4e5a08214e686ccf6f9099346885db17d8c309381f865cc5c", [:mix], [], "hexpm", "1db701e89865c1d5fa296b2b57b1cd587587cca8d8a1a22892b35ef5a8e352a6"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
"mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"},
"mix_audit": {:hex, :mix_audit, "2.1.4", "0a23d5b07350cdd69001c13882a4f5fb9f90fbd4cbf2ebc190a2ee0d187ea3e9", [:make, :mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.11", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "fd807653cc8c1cada2911129c7eb9e985e3cc76ebf26f4dd628bb25bbcaa7099"},
+ "mua": {:hex, :mua, "0.2.4", "a9172ab0a1ac8732cf2699d739ceac3febcb9b4ffc540260ad2e32c0b6632af9", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "e7e4dacd5ad65f13e3542772e74a159c00bd2d5579e729e9bb72d2c73a266fb7"},
"multipart": {:hex, :multipart, "0.4.0", "634880a2148d4555d050963373d0e3bbb44a55b2badd87fa8623166172e9cda0", [:mix], [{:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm", "3c5604bc2fb17b3137e5d2abdf5dacc2647e60c5cc6634b102cf1aef75a06f0a"},
"nimble_csv": {:hex, :nimble_csv, "1.2.0", "4e26385d260c61eba9d4412c71cea34421f296d5353f914afe3f2e71cce97722", [:mix], [], "hexpm", "d0628117fcc2148178b034044c55359b26966c6eaa8e2ce15777be3bbc91b12a"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},

View file

@ -775,6 +775,19 @@ let
];
};
mail = buildMix rec {
name = "mail";
version = "0.3.1";
src = fetchHex {
pkg = "mail";
version = "${version}";
sha256 = "1db701e89865c1d5fa296b2b57b1cd587587cca8d8a1a22892b35ef5a8e352a6";
};
beamDeps = [ ];
};
metrics = buildRebar3 rec {
name = "metrics";
version = "1.0.1";
@ -846,6 +859,19 @@ let
];
};
mua = buildMix rec {
name = "mua";
version = "0.2.4";
src = fetchHex {
pkg = "mua";
version = "${version}";
sha256 = "e7e4dacd5ad65f13e3542772e74a159c00bd2d5579e729e9bb72d2c73a266fb7";
};
beamDeps = [ castore ];
};
multipart = buildMix rec {
name = "multipart";
version = "0.4.0";
@ -1476,7 +1502,9 @@ let
gen_smtp
hackney
jason
mail
mime
mua
multipart
plug
plug_cowboy