Merge pull request 'clanServices: add warning if manifest.readme is not set' (#5537) from Qubasa/clan-core:fix_manifest_readmes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5537
This commit is contained in:
@@ -27,6 +27,7 @@
|
||||
modules.new-service = {
|
||||
_class = "clan.service";
|
||||
manifest.name = "new-service";
|
||||
manifest.readme = "Just a sample readme to not trigger the warning.";
|
||||
roles.peer = {
|
||||
description = "A peer that uses the new-service to generate some files.";
|
||||
};
|
||||
|
||||
@@ -34,6 +34,7 @@ nixosLib.runTest (
|
||||
modules.new-service = {
|
||||
_class = "clan.service";
|
||||
manifest.name = "new-service";
|
||||
manifest.readme = "Just a sample readme to not trigger the warning.";
|
||||
roles.peer = {
|
||||
description = "A peer that uses the new-service to generate some files.";
|
||||
};
|
||||
|
||||
25
clanServices/admin/README.md
Normal file
25
clanServices/admin/README.md
Normal file
@@ -0,0 +1,25 @@
|
||||
The admin service aggregates components that allow an administrator to log in to and manage the machine.
|
||||
|
||||
The following configuration:
|
||||
|
||||
1. Enables OpenSSH with root login and adds an SSH public key named`myusersKey` to the machine's authorized_keys via the `allowedKeys` setting.
|
||||
|
||||
2. Automatically generates a password for the root user.
|
||||
|
||||
```nix
|
||||
instances = {
|
||||
admin = {
|
||||
roles.default.tags = {
|
||||
all = { };
|
||||
};
|
||||
roles.default.settings = {
|
||||
allowedKeys = {
|
||||
myusersKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEFDNnynMbFWatSFdANzbJ8iiEKL7+9ZpDaMLrWRQjyH lhebendanz@wintux";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
manifest.name = "clan-core/admin";
|
||||
manifest.description = "Adds a root user with ssh access";
|
||||
manifest.categories = [ "Utility" ];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.default = {
|
||||
description = "Placeholder role to apply the admin service";
|
||||
|
||||
12
clanServices/garage/README.md
Normal file
12
clanServices/garage/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
[Garage](https://garagehq.deuxfleurs.fr/) is an open-source, S3-compatible distributed object storage service for self-hosting.
|
||||
|
||||
This module provisions a single-instance S3 bucket. To customize its behavior, set `services.garage.settings` in your Nix configuration.
|
||||
|
||||
Example configuration:
|
||||
```
|
||||
instances = {
|
||||
garage = {
|
||||
roles.default.machines."server" = {};
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -4,6 +4,7 @@
|
||||
manifest.name = "clan-core/garage";
|
||||
manifest.description = "S3-compatible object store for small self-hosted geo-distributed deployments";
|
||||
manifest.categories = [ "System" ];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.default = {
|
||||
description = "Placeholder role to apply the garage service";
|
||||
|
||||
1
clanServices/hello-world/README.md
Normal file
1
clanServices/hello-world/README.md
Normal file
@@ -0,0 +1 @@
|
||||
This a test README just to appease the eval warnings if we don't have one
|
||||
@@ -9,6 +9,7 @@
|
||||
_class = "clan.service";
|
||||
manifest.name = "clan-core/hello-word";
|
||||
manifest.description = "This is a test";
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
# This service provides two roles: "morning" and "evening". Roles can be
|
||||
# defined in this file directly (e.g. the "morning" role) or split up into a
|
||||
|
||||
19
clanServices/internet/README.md
Normal file
19
clanServices/internet/README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
This module is part of Clan's [networking interface](https://docs.clan.lol/guides/networking/networking/).
|
||||
|
||||
Clan's networking module automatically manages connections across available network transports and falls back intelligently. When you run `clan ssh` or `clan machines update`, Clan attempts each configured network in priority order until a connection succeeds.
|
||||
|
||||
The example below shows how to configure a domain so server1 is reachable over the clearnet. By default, the `internet` module has the highest priority among networks.
|
||||
|
||||
```nix
|
||||
inventory.instances = {
|
||||
# Direct SSH with fallback support
|
||||
internet = {
|
||||
roles.default.machines.server1 = {
|
||||
settings.host = "server1.example.com";
|
||||
};
|
||||
roles.default.machines.server2 = {
|
||||
settings.host = "192.168.1.100";
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -7,6 +7,8 @@
|
||||
"System"
|
||||
"Network"
|
||||
];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.default = {
|
||||
description = "Placeholder role to apply the internet service";
|
||||
interface =
|
||||
|
||||
23
clanServices/matrix-synapse/README.md
Normal file
23
clanServices/matrix-synapse/README.md
Normal file
@@ -0,0 +1,23 @@
|
||||
This NixOS module installs and configures Synapse — a federated Matrix homeserver with end-to-end encryption — and optionally provides the Element web client.
|
||||
|
||||
The example below demonstrates a minimal setup that includes:
|
||||
|
||||
- Element web client.
|
||||
- Synapse backed by PostgreSQL and nginx.
|
||||
- An admin user and an additional regular user.
|
||||
|
||||
Example configuration:
|
||||
|
||||
```nix
|
||||
instances = {
|
||||
matrix-synapse = {
|
||||
roles.default.machines."jon".settings = {
|
||||
acmeEmail = "admins@clan.lol";
|
||||
server_tld = "clan.test";
|
||||
app_domain = "matrix.clan.test";
|
||||
users.admin.admin = true;
|
||||
users.someuser = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -4,6 +4,7 @@
|
||||
manifest.name = "clan-core/matrix-synapese";
|
||||
manifest.description = "A federated messaging server with end-to-end encryption.";
|
||||
manifest.categories = [ "Social" ];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.default = {
|
||||
description = "Placeholder role to apply the matrix-synapse service";
|
||||
|
||||
20
clanServices/mycelium/README.md
Normal file
20
clanServices/mycelium/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
[Mycelium](https://github.com/threefoldtech/mycelium) is an end-to-end encrypted IPv6 overlay network that spans the globe.
|
||||
|
||||
## Features
|
||||
- Locality-aware routing: finds the shortest path between nodes.
|
||||
- All traffic is end-to-end encrypted.
|
||||
- Can route traffic via friend nodes and is location-aware.
|
||||
- Automatic rerouting if a physical link goes down.
|
||||
- IPv6 addresses are derived from private keys.
|
||||
- A simple, reliable message bus is implemented on top of Mycelium.
|
||||
- Supports multiple transports (QUIC, TCP, …). Hole punching for QUIC is in progress to enable true P2P connectivity behind NATs.
|
||||
- Designed for planetary-scale scalability; previous overlay networks reached practical limits, and Mycelium focuses on scaling.
|
||||
- Can run without a TUN device and be used solely as a reliable message bus.
|
||||
|
||||
Example configuration below connects all your machines to the Mycelium network:
|
||||
```nix
|
||||
mycelium = {
|
||||
roles.peer.tags.all = {};
|
||||
};
|
||||
```
|
||||
@@ -7,6 +7,7 @@
|
||||
"System"
|
||||
"Network"
|
||||
];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.peer = {
|
||||
description = "A peer in the mycelium network";
|
||||
|
||||
11
clanServices/packages/README.md
Normal file
11
clanServices/packages/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
This service is meant to be consumed by the UI / API, and exposes a JSON serializable interface to add packages to a machine over the inventory.
|
||||
|
||||
The example below demonstrates installing the "cbonsai" application to a machine named "server.
|
||||
|
||||
```
|
||||
instances.packages = {
|
||||
roles.default.machines."server".settings = {
|
||||
packages = [ "cbonsai" ];
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -6,6 +6,7 @@
|
||||
manifest.categories = [
|
||||
"System"
|
||||
];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.default = {
|
||||
description = "Placeholder role to apply the packages service";
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
## Usage
|
||||
This service configures Syncthing to continuously synchronize a folder peer-to-peer across your machines.
|
||||
|
||||
Example configuration:
|
||||
|
||||
```nix
|
||||
{
|
||||
@@ -6,15 +8,17 @@
|
||||
roles.peer.tags.all = { };
|
||||
roles.peer.settings.folders = {
|
||||
documents = {
|
||||
path = "~/syncthing/documents";
|
||||
path = "/home/youruser/syncthing/documents";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Now the folder `~/syncthing/documents` will be shared and kept in sync with all your machines.
|
||||
Notes:
|
||||
- Each key under `folders` is a folder ID (an arbitrary identifier for Syncthing).
|
||||
- Prefer absolute paths (example shown). `~` may work in some environments but can be ambiguous in service contexts.
|
||||
|
||||
|
||||
## Documentation
|
||||
Extensive documentation is available on the [Syncthing](https://docs.syncthing.net/) website.
|
||||
See the official Syncthing docs: https://docs.syncthing.net/
|
||||
|
||||
14
clanServices/tor/README.md
Normal file
14
clanServices/tor/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
This module is part of Clan's [networking interface](https://docs.clan.lol/guides/networking/networking/).
|
||||
|
||||
Clan's networking module automatically manages connections across available network transports and falls back intelligently. When you run `clan ssh` or `clan machines update`, Clan attempts each configured network in priority order until a connection succeeds.
|
||||
|
||||
The example below configures all your nixos machines to be reachable over the Tor network. By default, the `tor` module has the lowest priority among networks, as it's the slowest.
|
||||
|
||||
```nix
|
||||
inventory.instances = {
|
||||
# Fallback: Secure connections via Tor
|
||||
tor = {
|
||||
roles.server.tags.nixos = { };
|
||||
};
|
||||
};
|
||||
```
|
||||
@@ -7,6 +7,7 @@
|
||||
"System"
|
||||
"Network"
|
||||
];
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.client = {
|
||||
description = ''
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
This module sets up [yggdrasil](https://yggdrasil-network.github.io/) across
|
||||
your clan.
|
||||
This module sets up [yggdrasil](https://yggdrasil-network.github.io/) across your clan.
|
||||
|
||||
Yggdrasil is designed to be a future-proof and decentralised alternative to
|
||||
the structured routing protocols commonly used today on the internet. Inside
|
||||
your clan, it will allow you to reach all of your machines.
|
||||
the structured routing protocols commonly used today on the internet. Inside your clan, it will allow you to reach all of your machines.
|
||||
|
||||
## Example Usage
|
||||
|
||||
While you can specify statically configured peers for each host, yggdrasil does
|
||||
auto-discovery of local peers.
|
||||
While you can specify statically configured peers for each host, yggdrasil does auto-discovery of local peers.
|
||||
|
||||
```nix
|
||||
inventory = {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
_class = "clan.service";
|
||||
manifest.name = "clan-core/yggdrasil";
|
||||
manifest.description = "Yggdrasil encrypted IPv6 routing overlay network";
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
|
||||
roles.default = {
|
||||
description = "Placeholder role to apply the yggdrasil service";
|
||||
|
||||
@@ -979,9 +979,12 @@ in
|
||||
else
|
||||
null
|
||||
) config.roles;
|
||||
manifestWarnings = lib.optionals (config.manifest.readme == null || config.manifest.readme == "") [
|
||||
"Missing manifest.readme for clanService '${formatModule}'"
|
||||
];
|
||||
in
|
||||
{
|
||||
warnings = (lib.filter (v: v != null) warningsWithNull);
|
||||
warnings = (lib.filter (v: v != null) warningsWithNull ++ manifestWarnings);
|
||||
assertions = lib.attrValues failedAssertions;
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import re
|
||||
import tomllib
|
||||
from dataclasses import dataclass, field, fields
|
||||
@@ -16,6 +17,8 @@ from clan_lib.nix_models.clan import (
|
||||
from clan_lib.persist.inventory_store import InventoryStore
|
||||
from clan_lib.persist.path_utils import get_value_by_path, set_value_by_path
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CategoryInfo(TypedDict):
|
||||
color: str
|
||||
@@ -242,6 +245,11 @@ def get_service_readmes(
|
||||
|
||||
readmes = flake.select(query)
|
||||
|
||||
for name, content in readmes.items():
|
||||
if content is None or content.strip() == "":
|
||||
readmes[name] = None
|
||||
log.error(f"Service '{name}' is missing manifest.readme field")
|
||||
|
||||
return ServiceReadmeCollection(input_name=input_name, readmes=readmes)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user