From 39e37b6175f4c50a595486a7395c4a45cf53dfe4 Mon Sep 17 00:00:00 2001 From: Badlop Date: Fri, 29 Nov 2024 11:07:26 +0100 Subject: [PATCH] Add support to define macros as environment variables Define and macro by setting as environment variable: EJABBERD_MACRO_ + macro name For example, if you configure in ejabberd.yml: define_macro: LOGLEVEL: 4 loglevel: LOGLEVEL You can define (and overwrite) that macro definition when starting ejabberd: EJABBERD_MACRO_LOGLEVEL=5 make relive --- CONTAINER.md | 38 ++++++++++++++++++++++++++++++++++++-- mix.exs | 2 +- mix.lock | 2 +- rebar.config | 2 +- rebar.lock | 11 ++++++----- src/ejabberd_config.erl | 17 ++++++++++++++++- 6 files changed, 61 insertions(+), 11 deletions(-) diff --git a/CONTAINER.md b/CONTAINER.md index c62e597d7..38b37768f 100644 --- a/CONTAINER.md +++ b/CONTAINER.md @@ -234,6 +234,30 @@ Example usage (or check the [full example](#customized-example)): ``` +### Macros in environment + +ejabberd reads `EJABBERD_MACRO_*` environment variables +and uses them to define the `*` +[macros](https://docs.ejabberd.im/admin/configuration/file-format/#macros-in-configuration-file), +overwriting the corresponding macro definition if it was set in the configuration file. + +For example, if you configure this in `ejabberd.yml`: + +```yaml +acl: + admin: + user: ADMINJID +``` + +now you can define the admin account JID using an environment variable: +```yaml + environment: + - EJABBERD_MACRO_ADMINJID=admin@localhost +``` + +Check the [full example](#customized-example) for other example. + + ### Clustering When setting several containers to form a @@ -371,6 +395,7 @@ docker-compose up This example shows the usage of several customizations: it uses a local configuration file, +defines a configuration macro using an environment variable, stores the mnesia database in a local path, registers an account when it's created, and checks the number of registered accounts every time it's started. @@ -381,6 +406,14 @@ wget https://raw.githubusercontent.com/processone/ejabberd/master/ejabberd.yml.e mv ejabberd.yml.example ejabberd.yml ``` +Use a macro in `ejabberd.yml` to set the served vhost, with `localhost` as default value: +```bash +define_macro: + XMPPHOST: localhost +hosts: + - XMPPHOST +``` + Create the database directory and allow the container access to it: ```bash mkdir database @@ -397,8 +430,9 @@ services: image: ghcr.io/processone/ejabberd container_name: ejabberd environment: - - CTL_ON_CREATE=register admin localhost asd - - CTL_ON_START=registered_users localhost ; + - EJABBERD_MACRO_XMPPHOST=example.com + - CTL_ON_CREATE=register admin example.com asd + - CTL_ON_START=registered_users example.com ; status ports: - "5222:5222" diff --git a/mix.exs b/mix.exs index 494d0c7d1..256ae12d8 100644 --- a/mix.exs +++ b/mix.exs @@ -145,7 +145,7 @@ defmodule Ejabberd.MixProject do {:pkix, "~> 1.0"}, {:stringprep, ">= 1.0.26"}, {:xmpp, "~> 1.9"}, - {:yconf, "~> 1.0"}] + {:yconf, git: "https://github.com/processone/yconf.git", ref: "9898754f16cbd4585a1c2061d72fa441ecb2e938", override: true}] ++ cond_deps() end diff --git a/mix.lock b/mix.lock index 55b187837..b514cdd00 100644 --- a/mix.lock +++ b/mix.lock @@ -35,5 +35,5 @@ "stun": {:hex, :stun, "1.2.15", "eec510af6509201ff97f1f2c87b7977c833bf29c04e985383370ec21f04e4ccf", [:rebar3], [{:fast_tls, "1.1.22", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:p1_utils, "1.0.26", [hex: :p1_utils, repo: "hexpm", optional: false]}], "hexpm", "f6d8a541a29fd13f2ce658b676c0cc661262b96e045b52def1644b75ebc0edef"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "xmpp": {:hex, :xmpp, "1.9.0", "d92446bf51d36adda02db63b963fe6d4a1ede33e59b38a43d9b90afd20c25b74", [:rebar3], [{:ezlib, "~> 1.0.12", [hex: :ezlib, repo: "hexpm", optional: false]}, {:fast_tls, "~> 1.1.19", [hex: :fast_tls, repo: "hexpm", optional: false]}, {:fast_xml, "~> 1.1.51", [hex: :fast_xml, repo: "hexpm", optional: false]}, {:idna, "~> 6.0", [hex: :idna, repo: "hexpm", optional: false]}, {:p1_utils, "~> 1.0.25", [hex: :p1_utils, repo: "hexpm", optional: false]}, {:stringprep, "~> 1.0.29", [hex: :stringprep, repo: "hexpm", optional: false]}], "hexpm", "c1b91be74a9a9503afa6766f756477516920ffbfeea0c260c2fa171355f53c27"}, - "yconf": {:hex, :yconf, "1.0.16", "d59521d66ff89f219411b6e9277cd6feec7cc6fce11554e67de02a8d0a470479", [:rebar3], [{:fast_yaml, "1.0.37", [hex: :fast_yaml, repo: "hexpm", optional: false]}], "hexpm", "e947813273f38711c7b2e5a8e4acc9a51c7bbe854f744a345f60300b38586c89"}, + "yconf": {:git, "https://github.com/processone/yconf.git", "9898754f16cbd4585a1c2061d72fa441ecb2e938", [ref: "9898754f16cbd4585a1c2061d72fa441ecb2e938"]}, } diff --git a/rebar.config b/rebar.config index e6f59bebd..68d9af275 100644 --- a/rebar.config +++ b/rebar.config @@ -70,7 +70,7 @@ {if_var_true, stun, {stun, "~> 1.2.12", {git, "https://github.com/processone/stun", {tag, "1.2.15"}}}}, {xmpp, "~> 1.9.0", {git, "https://github.com/processone/xmpp", {tag, "1.9.0"}}}, - {yconf, "~> 1.0.15", {git, "https://github.com/processone/yconf", {tag, "1.0.16"}}} + {yconf, ".*", {git, "https://github.com/processone/yconf", "9898754f16cbd4585a1c2061d72fa441ecb2e938"}} ]}. {gitonly_deps, [ejabberd_po]}. diff --git a/rebar.lock b/rebar.lock index cdfae8f58..68d5f7061 100644 --- a/rebar.lock +++ b/rebar.lock @@ -25,7 +25,10 @@ {<<"stun">>,{pkg,<<"stun">>,<<"1.2.15">>},0}, {<<"unicode_util_compat">>,{pkg,<<"unicode_util_compat">>,<<"0.7.0">>},1}, {<<"xmpp">>,{pkg,<<"xmpp">>,<<"1.9.0">>},0}, - {<<"yconf">>,{pkg,<<"yconf">>,<<"1.0.16">>},0}]}. + {<<"yconf">>, + {git,"https://github.com/processone/yconf", + {ref,"9898754f16cbd4585a1c2061d72fa441ecb2e938"}}, + 0}]}. [ {pkg_hash,[ {<<"base64url">>, <<"F8C7F2DA04CA9A5D0F5F50258F055E1D699F0E8BF4CFDB30B750865368403CF6">>}, @@ -53,8 +56,7 @@ {<<"stringprep">>, <<"46CF0FF631B3E7328F61F20B454D59428D87738F25D709798B5DCBB9B83C23F1">>}, {<<"stun">>, <<"EEC510AF6509201FF97F1F2C87B7977C833BF29C04E985383370EC21F04E4CCF">>}, {<<"unicode_util_compat">>, <<"BC84380C9AB48177092F43AC89E4DFA2C6D62B40B8BD132B1059ECC7232F9A78">>}, - {<<"xmpp">>, <<"D92446BF51D36ADDA02DB63B963FE6D4A1EDE33E59B38A43D9B90AFD20C25B74">>}, - {<<"yconf">>, <<"D59521D66FF89F219411B6E9277CD6FEEC7CC6FCE11554E67DE02A8D0A470479">>}]}, + {<<"xmpp">>, <<"D92446BF51D36ADDA02DB63B963FE6D4A1EDE33E59B38A43D9B90AFD20C25B74">>}]}, {pkg_hash_ext,[ {<<"base64url">>, <<"F9B3ADD4731A02A9B0410398B475B33E7566A695365237A6BDEE1BB447719F5C">>}, {<<"cache_tab">>, <<"8582B60A4A09B247EF86355BA9E07FCE9E11EDC0345A775C9171F971C72B6351">>}, @@ -81,6 +83,5 @@ {<<"stringprep">>, <<"F6FC9B3384A03877830F89B2F38580CAF3F4A27448A4A333D6A8C3975C220B9A">>}, {<<"stun">>, <<"F6D8A541A29FD13F2CE658B676C0CC661262B96E045B52DEF1644B75EBC0EDEF">>}, {<<"unicode_util_compat">>, <<"25EEE6D67DF61960CF6A794239566599B09E17E668D3700247BC498638152521">>}, - {<<"xmpp">>, <<"C1B91BE74A9A9503AFA6766F756477516920FFBFEEA0C260C2FA171355F53C27">>}, - {<<"yconf">>, <<"E947813273F38711C7B2E5A8E4ACC9A51C7BBE854F744A345F60300B38586C89">>}]} + {<<"xmpp">>, <<"C1B91BE74A9A9503AFA6766F756477516920FFBFEEA0C260C2FA171355F53C27">>}]} ]. diff --git a/src/ejabberd_config.erl b/src/ejabberd_config.erl index 3a77c2720..8b63cc7bb 100644 --- a/src/ejabberd_config.erl +++ b/src/ejabberd_config.erl @@ -516,8 +516,23 @@ read_file(File, Opts) -> Err end. +get_additional_macros() -> + MacroStrings = lists:foldl(fun([$E, $J, $A, $B, $B, $E, $R, $D, $_, $M, $A, $C, $R, $O, $_ | MacroString], Acc) -> + [parse_macro_string(MacroString) | Acc]; + (_, Acc) -> + Acc + end, + [], + os:getenv()), + {additional_macros, MacroStrings}. + +parse_macro_string(MacroString) -> + [NameString, ValueString] = string:split(MacroString, "="), + {ok, [ValueDecoded]} = fast_yaml:decode(ValueString, [plain_as_atom]), + {list_to_atom(NameString), ValueDecoded}. + read_yaml_files(Files, Opts) -> - ParseOpts = [plain_as_atom | lists:flatten(Opts)], + ParseOpts = [plain_as_atom, get_additional_macros() | lists:flatten(Opts)], lists:foldl( fun(File, {ok, Y1}) -> case econf:parse(File, #{'_' => econf:any()}, ParseOpts) of