diff --git a/guides/advanced/advanced-configuration.md b/guides/advanced/advanced-configuration.md index 39daeb7c..6a0daa8d 100644 --- a/guides/advanced/advanced-configuration.md +++ b/guides/advanced/advanced-configuration.md @@ -465,3 +465,25 @@ You can modify the kernel parameters for your application or custom Nerves system by copying the default `sysctl.conf` file to your `rootfs_overlay/etc` directory and making the desired changes. Use `System.cmd/3` to run `sysctl` to change settings after initialization. + +## Post-processing or signing the root filesystem + +When generating a Nerves firmware there is stage where `mix firmware` takes +your application code, makes a release and adds that release into the root +filesystem. After this the root filesystem is complete. This is the point where +you could generate signatures, hashes and such for a tool like dm-verity. To +allow this Nerves provides an entrypoint for a script that you can add to your +Nerves firmware config, such as `config/target.exs` or for the specific target. + +``` +config :nerves, + firmware: [ + post_processing_script: Path.expand("./scripts/sign.sh") + ] +``` + +Create your desired `sign.sh` in a `scripts` directory in your Nerves project +or put it wherever you prefer. The configuration file is not running with the +Nerves environment variables. The script will have access to them however. The +script will receive the filepath of the filesystem as the first argument and +this allows you to sign it or otherwise amend it. diff --git a/lib/mix/tasks/firmware.ex b/lib/mix/tasks/firmware.ex index 108f27c8..ccbb19a5 100644 --- a/lib/mix/tasks/firmware.ex +++ b/lib/mix/tasks/firmware.ex @@ -109,18 +109,7 @@ defmodule Mix.Tasks.Firmware do write_erlinit_config(build_rootfs_overlay) - project_rootfs_overlay = - case firmware_config[:rootfs_overlay] || firmware_config[:rootfs_additions] do - nil -> - [] - - overlays when is_list(overlays) -> - overlays - - overlay -> - [Path.expand(overlay)] - end - + project_rootfs_overlay = config_arg(:rootfs_overlay, firmware_config) prevent_overlay_overwrites!(project_rootfs_overlay) rootfs_overlays = @@ -128,16 +117,19 @@ defmodule Mix.Tasks.Firmware do |> Enum.map(&["-a", &1]) |> List.flatten() - fwup_conf = - case firmware_config[:fwup_conf] do - nil -> [] - fwup_conf -> ["-c", Path.join(File.cwd!(), fwup_conf)] - end + fwup_conf = config_arg(:fwup_conf, firmware_config) + + post_processing_script = config_arg(:post_processing_script, firmware_config) fw = ["-f", fw_out] release_path = Path.join(Mix.Project.build_path(), "rel/#{otp_app}") output = [release_path] - args = args ++ fwup_conf ++ rootfs_overlays ++ fw ++ rootfs_priorities ++ output + + args = + args ++ + fwup_conf ++ + rootfs_overlays ++ fw ++ rootfs_priorities ++ post_processing_script ++ output + env = [{"MIX_BUILD_PATH", Mix.Project.build_path()} | standard_fwup_variables(config)] set_provisioning(firmware_config[:provisioning]) @@ -296,4 +288,31 @@ defmodule Mix.Tasks.Firmware do """) end end + + defp config_arg(:rootfs_overlay, firmware_config) do + case firmware_config[:rootfs_overlay] || firmware_config[:rootfs_additions] do + nil -> + [] + + overlays when is_list(overlays) -> + overlays + + overlay -> + [Path.expand(overlay)] + end + end + + defp config_arg(:fwup_conf, firmware_config) do + case firmware_config[:fwup_conf] do + nil -> [] + fwup_conf -> ["-c", Path.join(File.cwd!(), fwup_conf)] + end + end + + defp config_arg(:post_processing_script, firmware_config) do + case firmware_config[:post_processing_script] do + nil -> [] + script when is_binary(script) -> ["-s", script] + end + end end