docs(custom-service): Document the use of a custom service definition (#243)

Resolves https://github.com/juspay/services-flake/issues/242

Preview:
```sh
nix run "github:juspay/services-flake/custom-service?dir=doc"
```
This commit is contained in:
Shivaraj B H 2024-06-21 00:23:01 +05:30 committed by GitHub
parent 647bff2c44
commit d16e7950ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 167 additions and 0 deletions

166
doc/custom-service.md Normal file
View File

@ -0,0 +1,166 @@
# Custom service
When using `services-flake` you are not just limited to the [[services|builtin services]]. You can also define your own service.
By default, `services-flake` supports multiple instances for each service, allowing you to run several instances of the same service simultaneously. However, you also have the option to create custom single-instance services. In the following sections, well explore how to define custom services of both types.
{#single-instance}
## Single instance service
We will create a `hello` service that will return a greeting message:
```nix
{ config, lib, pkgs, ... }:
{
options = {
services.hello = {
enable = lib.mkEnableOption "Enable hello service";
package = lib.mkPackageOption pkgs "hello" { };
message = lib.mkOption {
type = lib.types.str;
default = "Hello, world!";
description = "The message to be displayed";
};
};
};
config =
let
cfg = config.services.hello;
in
lib.mkIf cfg.enable {
settings.processes.hello = {
command = "${lib.getExe cfg.package} --greeting='${cfg.message}'";
};
};
}
```
Let's call this file `hello.nix`.
Now, we can import this service in our flake. In this example, we will configure an existing service, [[ollama]], and our custom service from above:
```nix
{
description = "A demo of importing a single instance custom service";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
systems.url = "github:nix-systems/default";
process-compose-flake.url = "github:Platonic-Systems/process-compose-flake";
services-flake.url = "github:juspay/services-flake";
};
outputs = inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = import inputs.systems;
imports = [
inputs.process-compose-flake.flakeModule
];
perSystem = { self', pkgs, lib, ... }: {
process-compose."default" = { config, ... }: {
imports = [
inputs.services-flake.processComposeModules.default
./hello.nix
];
services.ollama."ollama1".enable = true;
services.hello.enable = true;
};
};
};
}
```
Finally, `nix run`:
![[single-instance-hello.png]]
{#multi-instance}
## Multi-instance service
For this purpose, `services-flake` exports a [multiService](https://github.com/juspay/services-flake/blob/647bff2c44b42529461f60a7fe07851ff93fb600/nix/lib.nix#L1-L34) library function. It aims to provide an interface wherein the user just writes the configuration like they would for a single instance service, and the library takes care of creating multiple instances of the service.
Let's write the same `hello` service as above, in `hello.nix`, but this time as a multi-instance service:
```nix
{ config, lib, name, pkgs, ... }:
{
options = {
enable = lib.mkEnableOption "Enable ${name} service";
package = lib.mkPackageOption pkgs "hello" { };
message = lib.mkOption {
type = lib.types.str;
default = "Hello, world!";
description = "The message to be displayed";
};
outputs.settings = lib.mkOption {
type = lib.types.deferredModule;
internal = true;
readOnly = true;
default = {
processes.${name} = {
command = "${lib.getExe config.package} --greeting='${config.message}'";
};
};
};
};
}
```
The primary differences from the single instance service are:
- The module now takes an additional argument `name`, which is the name of the instance of the service.
- We no longer have to write the `config` block, as it is now handled by the library by importing the `outputs.settings` option.
- And we don't have to write `options.services."${name}"`, as that is abstracted away by the library.
Now that we have defined the multi-instance service, we can import it in our flake:
```nix
{
description = "A demo of importing a multi-instance custom service";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
systems.url = "github:nix-systems/default";
process-compose-flake.url = "github:Platonic-Systems/process-compose-flake";
services-flake.url = "github:juspay/services-flake";
};
outputs = inputs:
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
systems = import inputs.systems;
imports = [
inputs.process-compose-flake.flakeModule
];
perSystem = { self', pkgs, lib, ... }: {
process-compose."default" =
let
inherit (inputs.services-flake.lib) multiService;
in
{
imports = [
inputs.services-flake.processComposeModules.default
(multiService ./hello.nix)
];
services.ollama."ollama1".enable = true;
services.hello = {
hello1 = {
enable = true;
message = "Hello, world!";
};
hello2 = {
enable = true;
message = "Hello, Nix!";
};
};
};
};
};
}
```
And finally, `nix run`:
![[multi-instance-hello.png]]
## See also
- [Postgres with replica](https://github.com/nammayatri/nammayatri/blob/main/Backend/nix/services/postgres-with-replica.nix)
- [Passetto (A custom encryption service)](https://github.com/nammayatri/passetto/blob/nixify/process-compose.nix), is [imported](https://github.com/nammayatri/nammayatri/blob/e8032f1fac3581b9062e2469dfc778d2913d3665/Backend/nix/services/nammayatri.nix#L32) and [configured in the Nammayatri flake](https://github.com/nammayatri/nammayatri/blob/e8032f1fac3581b9062e2469dfc778d2913d3665/Backend/nix/services/nammayatri.nix#L285-L297).

View File

@ -20,6 +20,7 @@ See:
- [[services]]#
- [[contributing]]#
- [[guide]]#
- [[custom-service]]#
## Demo

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB