Skip to content

Commit d28c9c9

Browse files
committed
Document Xamal-style unit generation
1 parent 2b7273b commit d28c9c9

5 files changed

Lines changed: 55 additions & 6 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The package depends on [`rebus`](https://hex.pm/packages/rebus) for the D-Bus wi
3636

3737
APIs return idiomatic `{:ok, value}` / `{:error, %Systemd.Error{}}` tuples. Permission and polkit failures are classified with `category: :permission` and can be checked with `Systemd.Error.permission?/1`.
3838

39-
See `examples/` for service, timer, and user-bus snippets.
39+
See `examples/` for service, timer, and user-bus snippets, and `guides/xamal-style-deployment.md` for a deployment-oriented template unit example.
4040

4141
## Permissions
4242

guides/xamal-style-deployment.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Xamal-style deployment units
2+
3+
`systemdkit` can build and validate template service units like the ones used by
4+
Xamal-style blue/green deployments. The port is the instance identifier, so
5+
`my_app@4000.service` and `my_app@4001.service` can be started independently.
6+
7+
```elixir
8+
unit_file =
9+
Systemd.UnitFile.service(
10+
unit: [
11+
description: "my_app (%i)",
12+
after: "network.target"
13+
],
14+
service: [
15+
type: :exec,
16+
user: "deploy",
17+
working_directory: "/opt/xamal/my-app/current",
18+
environment_file: "-/opt/xamal/my-app/env/app.env",
19+
environment: ["PORT=%i", "RELEASE_NODE=my_app_%i"],
20+
exec_start: "/opt/xamal/my-app/current/bin/my_app start",
21+
restart: "on-failure",
22+
restart_sec: 5,
23+
timeout_stop_sec: 30,
24+
limit_nofile: 1_048_576
25+
],
26+
install: [wanted_by: "multi-user.target"]
27+
)
28+
29+
:ok = Systemd.UnitFile.validate(unit_file, :service)
30+
Systemd.UnitFile.to_string(unit_file)
31+
```
32+
33+
For local systemd managers, D-Bus operations can be used directly:
34+
35+
```elixir
36+
:ok = Systemd.reload()
37+
:ok = Systemd.start_unit("my_app@4000.service")
38+
{:ok, state} = Systemd.unit_state("my_app@4000.service")
39+
```
40+
41+
For remote deployment tools, generate and validate unit files locally, then use
42+
the tool's remote execution layer to install the rendered unit on the host.

lib/systemd/unit_file/builder.ex

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ defmodule Systemd.UnitFile.Builder do
77

88
@type directives :: keyword() | %{optional(atom() | String.t()) => term()}
99

10+
@directive_names %{
11+
limit_nofile: "LimitNOFILE"
12+
}
13+
1014
@doc """
1115
Builds a unit file from common `Unit`, `Service`, and `Install` sections.
1216
"""
@@ -46,9 +50,11 @@ defmodule Systemd.UnitFile.Builder do
4650
end
4751

4852
defp normalize_name(name) when is_atom(name) do
49-
name
50-
|> Atom.to_string()
51-
|> Macro.camelize()
53+
Map.get_lazy(@directive_names, name, fn ->
54+
name
55+
|> Atom.to_string()
56+
|> Macro.camelize()
57+
end)
5258
end
5359

5460
defp normalize_name(name) when is_binary(name), do: name

mix.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ defmodule Systemd.MixProject do
6262
main: "readme",
6363
source_url: @source_url,
6464
source_ref: "v#{@version}",
65-
extras: ["README.md", "CHANGELOG.md", "LICENSE"]
65+
extras: ["README.md", "CHANGELOG.md", "LICENSE", "guides/xamal-style-deployment.md"],
66+
groups_for_extras: [Guides: ~r/guides\//]
6667
]
6768
end
6869

test/systemd/unit_file_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ defmodule Systemd.UnitFileTest do
8484
unit_file =
8585
UnitFile.service(
8686
unit: [description: "My app", after: ["network.target", "postgresql.service"]],
87-
service: [exec_start: "/opt/app/bin/app start", restart: :always, LimitNOFILE: 1_048_576],
87+
service: [exec_start: "/opt/app/bin/app start", restart: :always, limit_nofile: 1_048_576],
8888
install: [wanted_by: "multi-user.target"]
8989
)
9090

0 commit comments

Comments
 (0)