Host clan-internal web services with HTTPS, accessible from any machine in your
clan via hostnames like https://music.example.com.
Three services work together to make this possible:
Machines must be able to reach each other via <hostname>.<meta.domain>. How
you achieve this is up to you - for example via yggdrasil, a VPN, or any other networking
setup.
music.example.comThe PKI architecture ensures that adding a new service or endpoint on one machine does not require redeploying other machines:
If you use Caddy or nginx as a reverse proxy, pki automatically configures them with the right certificates.
Data-mesher is required for distributing DNS records across your clan:
inventory.instances = {
data-mesher = {
roles.bootstrap.tags = [ "server" ];
roles.default.tags = [ "all" ];
};
}; Add both services to your inventory, targeting all machines:
inventory.instances = {
# Generates TLS certificates for all internal endpoints
pki = {
module.name = "pki";
roles.default.tags = [ "all" ];
};
# Collects endpoint exports and distributes DNS records via data-mesher
dm-dns = {
module.name = "dm-dns";
roles.push.machines.my-server = { };
roles.default.tags = [ "all" ];
};
}; Any service that exports an endpoints.hosts value will automatically get DNS
records and TLS certificates. For example, a navidrome music server:
inventory.instances = {
navidrome = {
module.name = "@pinpox/navidrome";
roles.default.machines.my-server = {
settings.host = "music.example.com";
};
};
}; After deploying, https://music.example.com will be reachable from any machine
in your clan with a valid, trusted TLS certificate.
If you're authoring a service and want it to participate in this system, export endpoints in your service manifest:
{ ... }:
{
manifest.exports.out = [ "endpoints" ];
roles.default = {
perInstance =
{ mkExports, settings, ... }:
{
exports = mkExports {
endpoints.hosts = [ settings.host ];
};
nixosModule =
{ ... }:
{
# Your service configuration here
};
};
};
} See the exports guide for details on the export system.