Fosi Fossil Service
Small teams. Open source. Built on Fossil.

CaaS / Lamina

Unified Management for Fossil Repositories

Public | Owner: CaaS | Default branch: trunk | Last update: 2026-10-25 00:41

Artifact 4bfbb0edd03c6e458b953980f2fb19919a4eb75a6981db0c9e6ca26408716303:


Running several Nova applications

Nova can serve more than one Nova application from the same node. An application can be mounted into another one's listener at startup, or started and stopped on its own listener at runtime.

Including another application at startup

Add the application as a dependency in rebar.config, then list it under the nova_apps key in your own application's configuration. nova_apps takes application names, or {Name, Options} two-tuples when you want to configure how it is mounted.

Included applications are resolved depth-first, so an application that declares nova_apps of its own has those registered too.

Options

Key Value Description
prefix string() Mount the application's routes under this path
secure false | fun/1 Security callback for the application's routes
override_secure false | fun/1 Replace the security callback the application declares for itself
plugin_strategy see the routing guide How the application's route-local plugins combine with the global ones

Example

rebar.config:

{deps, [
        {another_nova_app, "1.0.0"}
       ]}.

sys.config:

{my_nova_app, [
   {nova_apps, [{another_nova_app, #{prefix => "/another"}}]}
  ]}.

another_nova_app now shares the listener, and the routing table, of my_nova_app. Its routes answer under /another.

Starting an application at runtime

nova_sup:add_application/2 starts a Nova application while the node is running. The second argument takes the same shape as the cowboy_configuration environment key.

{ok, App, Host, Port} = nova_sup:add_application(my_other_app, #{port => 8081}).

What happens depends on whether the host and port are already bound:

Starting an application that is already running returns {error, {already_started, App}}.

Because each listener has its own routing table, two applications on two ports do not serve each other's routes. That is the point of binding a second port: an admin interface on 8081 is not reachable on the public 8080 just because both are running in the same node.

Stopping an application

ok = nova_sup:remove_application(my_other_app).

The application's routes are removed from the listener serving it. If that leaves the listener with no applications, the listener is stopped and its routing table discarded, releasing the port. Other applications on the same listener are unaffected.

Removing an application that was never started returns {error, not_found}.

Inspecting what is running

nova_sup:get_started_applications().
%% [#{app => my_app, host => {0,0,0,0}, port => 8080, listener => nova_listener},
%%  #{app => my_other_app, host => {0,0,0,0}, port => 8081,
%%    listener => {nova_listener, my_other_app, 8081}}]

nova_router:compiled_apps/0 lists the applications compiled into the default listener's routing table, and nova_router:compiled_apps/1 does the same for any other.

Graceful shutdown

Every listener Nova has started is suspended, drained and stopped on shutdown, including ones added at runtime. See the graceful shutdown guide.

Clone

You can clone this repository with the following command:

fossil clone https://fosi.dev/CaaS/Lamina

Contribute

The best way to contribute is through e-mail. See the project documentation for more details.