Creating a binary-only Erlang release - erlang

I have created a release of my program with rebar. Navigating around in the output directory I see my Erlang source files. Is there any way to create binary only releases of Erlang programs, so that they can be distributed (as closed source) to customers?

Yes, in rebar.config file. {include_src, false} in prod section
{profiles, [
{dev1, [{relx, [{dev_mode, false},
{include_erts, false},
{sys_config, "./config/dev1/sys.config"},
{vm_args, "./config/dev1/vm.args"}]}
]
},
{prod, [{relx, [{dev_mode, false},
{include_erts, true},
{include_src, false},
{sys_config, "./config/prod/sys.config"},
{vm_args, "./config/prod/vm.args"}]}]

Related

Including start_sasl.boot when creating a release with rebar3

When I create a release with rebar3 (rebar3 release or rebar3 tar) and that I include ERTS, the start_sasl.boot script is missing and prevents me from starting my application.
# ./erts-8.2.1/bin/erl -boot start_sasl [...]
{"init terminating in do_boot",{'cannot get bootfile','start_sasl.boot'}}
init terminating in do_boot ()
My current rebar.config section for releases:
{relx, [
{release, {my_app, "1.0.0"}, [my_app]},
{dev_mode, false},
{include_erts, true},
{extended_start_script, false},
{generate_start_script, false},
{overlay, [
{copy, "priv/scripts/nodetool", "bin"},
{copy, "priv/scripts/run", "bin"}
]}
]}.
Is there a setting that I'm missing that to include start_sasl.boot in the release directory?

How to configure httpc profiles with rebar3?

How can I set configuration options for httpc's profiles when using rebar3?
Here is the only example being via erl -config inets.config that looks like this:
[{inets,
[{services,[{httpc,[{profile, server1}]},
{httpc, [{profile, server2}]}]}]
}].
I tried adopting it to my rebar3 project structure.
Code
Project was created with rebar3, with standard OTP layout:
rebar3 new release myapp
Here is my myapp/config/sys.config:
[
{ myapp, []},
{inets, [{services, [{httpc, [{profile, myapp}]}]}]}
].
rebar.config:
{erl_opts, [debug_info]}.
{deps, []}.
{relx, [{release, { myapp, "0.1.0" },
[myapp,
sasl]},
{sys_config, "./config/sys.config"},
{vm_args, "./config/vm.args"},
{dev_mode, true},
{include_erts, false},
{extended_start_script, true}]
}.
{profiles, [{prod, [{relx, [{dev_mode, false},
{include_erts, true}]}]
}]
}.
Here is my myapp.app.src file for completeness:
{application, myapp,
[{description, "An OTP application"},
{vsn, "0.1.0"},
{registered, []},
{mod, { myapp_app, []}},
{applications,
[kernel,
stdlib
]},
{env,[]},
{modules, []},
{maintainers, []},
{licenses, []},
{links, []}
]}.
Requests
Here is a request I'm trying to make from rebar`s shell:
$ ./rebar3 shell
1> ===> Booted myapp
1> ===> Booted sasl
...
1> httpc:request( "http://reddit.com", myapp).
** exception exit: {noproc,
{gen_server,call,
[httpc_myapp,
{request,
{request,undefined,<0.88.0>,0,http,
{"reddit.com",80},
"/",[],get,
{http_request_h,undefined,"keep-alive",undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,...},
{[],[]},
{http_options,"HTTP/1.1",infinity,true,
{essl,[]},
undefined,false,infinity,...},
"http://reddit.com",[],none,[],1478280329839,
undefined,undefined,false}},
infinity]}}
in function gen_server:call/3 (gen_server.erl, line 212)
in call from httpc:handle_request/9 (httpc.erl, line 574)
Here is the request without a profile, to check that inets actually works:
2> httpc:request( "http://reddit.com").
=PROGRESS REPORT==== 4-Nov-2016::13:25:51 ===
supervisor: {local,inet_gethost_native_sup}
started: [{pid,<0.107.0>},{mfa,{inet_gethost_native,init,[[]]}}]
=PROGRESS REPORT==== 4-Nov-2016::13:25:51 ===
supervisor: {local,kernel_safe_sup}
started: [{pid,<0.106.0>},
{id,inet_gethost_native_sup},
{mfargs,{inet_gethost_native,start_link,[]}},
{restart_type,temporary},
{shutdown,1000},
{child_type,worker}]
{ok,{{"HTTP/1.1",200,"OK"},...
rebar3 itself use inets http clients so when It starts your application in shell, inets is already started and configured. One workaround would be stop inets before your application starts, as It's suggested by rebar3 developer (copied below). Another one would be boot your release in console mode:
./_build/default/rel/myapp/bin/myapp console
Beside that there is another problem with your project. You have not told you want inets being started for you. You should have this line in myapp.src:
{applications, [kernel, stdlib, inets]}
Or you can list inets in rebar.config release section, to tell relx this app should be included in release and started on boot.
{relx, [{release, { myapp, "0.1.0" }, [inets, myapp, sasl]} ]}
Stop Inets from Loading on rebar3 shell startup
Here is the copy of the full answer by Fred Hebert from the rebar3 mailing list:
We do need inets for package fetching and will likely not turn it off
automatically for all use cases as this could compromise general usage
of the rebar3 agent in case where the user application does not use
inets, but still asks to fetch packages in a subsequent run. The
workaround I would suggest would be to use a hook script for it. Hook
scripts run before we boot user applications and are regular escripts:
#!/usr/bin/env escript
main(_) -> application:stop(inets).
You can then hook the script in with:
{shell, [{script_file, "path/to/file"}]}
in rebar3.config, or with
rebar3 shell --script_file test/check_env.escript
I can't find anything in the documentation to suggest that rebar.config can contain the application configuration you want.
Instead, application configuration is often kept in a configuration directory in your application, and like the example you gave says, you must use the -config flag when launching erl to point to the configuration file.
If you use rebar3 for making release and start your service by script made with relx (from _build/default/rel/<release_name>/bin/<release_name> by default) the application configuration file is passed to erl for you. If config file exist in your application directory, by default in config/sys.config, It will be regarded as application configuration, otherwise an empty configuration will be made. You can customize Its path by relax' release option sys_config.
For our software, we typically had a single config/sys.config file. The structure is the same as the config sample you have provided. Note that the configuration file can contain settings for many different services. For example, mixing inets with one of ours:
[{inets, [
{services,[{httpc,[{profile, server1}]},
{httpc, [{profile, server2}]}]}
]},
{my_app, [
{my_setting, "my value"}
]}
].
We launch with erl -config config/sys.config.
This way if we need to set service configuration we can simply update our configuration file, which also houses the configuration specific to this application.
As far as I'm aware, this is the correct method to use. I have not been able to find documentation supporting any other way of doing this.

Erlang cuttlefish schema for nested list of configuration items

I am trying to generate cuttlefish schema ( github cuttlefish) for the following proplist configuration structure.
I have several machine entries and under each machine entry there
are several ip entries.
[{machines,
[{machine1, [
{mach_id, "BeeHive"},
{ram, "2G"},
{ips, [
{ip1, [
{ip, "IP1"},
{sessions, 10}
]},
----,
---- ]}
]},
{machine2, [
{mach_id, "BeeHive2"},
{ram, "2G"},
{ips, [
{ip1, [
{ip, "IP1"},
{sessions, 11}
]},
----,
---- ]}
]}
]
}].
In cuttlefish mapping configuration, this requires multiple $ variables and for nested listing like several ip entries inside machine entry .
Please provide any pointers towards making a schema for the
above listed proplist structure.

erlang lager_syslog driver failure

I'm trying to use lager_syslog in my project but it seems like a driver is missing.
This is in my rebar.conf:
{deps, [
...
{lager_syslog, {git, "https://github.com/basho/lager_syslog.git", {branch, master}}}
]}.
My test handler:
{lager_syslog_backend, ["test", local1, info]},
The error:
19:29:09.981 [error] Lager failed to install handler {lager_syslog_backend,{"test",local1}} into lager_event, retrying later : {error,
{{shutdown,
{failed_to_start_child,
syslog,
"could not load driver syslog_drv: \"cannot open shared object file: No such file or directory\""}},
{syslog_app,
start,
[normal,
[]]}}}
Any suggestion?
thanks to Kenneth Lakin who answered my question in mailing list
IIRC, rebar3 moved the port compiler out to a rebar3 plugin, rather than
packing it in with the core project. From what I've seen, rebar2
projects that relied on it will fail to load their port drivers.
Add
{overrides,
[{override, syslog, [
{plugins, [pc]},
{artifacts, ["priv/syslog_drv.so"]},
{provider_hooks, [
{post,
[
{compile, {pc, compile}},
{clean, {pc, clean}}
]
}]
}
]}
]}.
to a rebar.conf in your project, clean, and rebuild. (The syslog project
is where lager_syslog's port driver lives.)
See also: https://github.com/blt/port_compiler#use-with-existing-dependency

Chicagoboss - How to update lager_file_backend config?

I have updated ChicagoBoss to my latest version. When I'm compiling it, I'm getting a notice as
Deprecated lager_file_backend config detected, please consider updating it
I'm compiling it using following command:
./rebar get-deps clean compile
So, the questions are:
What is lager_file_backend config?
Why it is deprecated?
How to update it.?
lager_file_backend config simply refers to the 'lager_file_backend' section of your configuration file (boss.config)
I don't know why it is being deprecated, sorry.
I had trouble finding release notes detailing the differences. I figured out how to update by looking at the example here: https://github.com/basho/lager
Here's what the old style looks like:
{lager, [
{handlers, [
{lager_console_backend, info},
{lager_file_backend, [
{"/var/log/foo/boss_error.log", error, 10485760, "$D0", 5},
{"/var/log/foo/boss_console.log", info, 10485760, "$D0", 5}
]}
]}
]},
Here's what the new style looks like:
{lager, [
{handlers, [
{lager_console_backend, info},
{lager_file_backend, [{file, "/var/log/foo/boss_error.log"}, {level, error}]},
{lager_file_backend, [{file, "/var/log/foo/boss_console.log"}, {level, info}]}
]}
]},

Resources