Skip to content


Dev Report: Declarative Backups and Restore

Our goal with Clan is to give users control over their data. However, with great power comes great responsibility, and owning your data means you also need to take care of backups yourself.

In our experience, setting up automatic backups is often a tedious process as it requires custom integration of the backup software and the services that produce the state. More important than the backup is the restore. Restores are often not well tested or documented, and if not working correctly, they can render the backup useless.

In Clan, we want to make backup and restore a first-class citizen. Every service should describe what state it produces and how it can be backed up and restored.

In this article, we will discuss how our backup interface in Clan works. The interface allows different backup software to be used interchangeably and allows module authors to define custom backup and restore logic for their services.

First Comes the State

Our services are built from Clan modules. Clan modules are essentially NixOS modules, the basic configuration components of NixOS. However, we have enhanced them with additional features provided by Clan and restricted certain option types to enable configuration through a graphical interface.

In a simple case, this can be just a bunch of directories, such as what we define for our ZeroTier VPN service.

  clan.core.state.zerotier.folders =  [ "/var/lib/zerotier-one" ];

For other systems, we need more complex backup and restore logic. For each state, we can provide custom command hooks for backing up and restoring.

In our PostgreSQL module, for example, we define preBackupCommand and postRestoreCommand to use pg_dump and pg_restore to backup and restore individual databases:

preBackupCommand = ''
  # ...
  runuser -u postgres -- pg_dump ${compression} --dbname=${} -Fc -c > "${current}.tmp"
  # ...
postRestoreCommand = ''
  # ...
  runuser -u postgres -- dropdb "${}"
  runuser -u postgres -- pg_restore -C -d postgres "${current}"
  # ...

Then the Backup

Our CLI unifies the different backup providers in one interface.

As of now, we support backups using BorgBackup and a backup module called "localbackup" based on rsnapshot, optimized for backup on locally attached storage media.

To use different backup software, a module needs to set the options provided by our backup interface. The following Nix code is a toy example that uses the tar program to perform backup and restore to illustrate how the backup interface works:

  clan.core.backups.providers.tar = {
    list = ''
      echo /var/lib/system-back.tar
    create = let
      uniqueFolders = lib.unique (
        lib.flatten (lib.mapAttrsToList (_name: state: state.folders) config.clan.core.state)
    in ''
      # FIXME: a proper implementation should also run `state.preBackupCommand` of each state
      if [ -f /var/lib/system-back.tar ]; then
        tar -uvpf /var/lib/system-back.tar ${builtins.toString uniqueFolders}
        tar -cvpf /var/lib/system-back.tar ${builtins.toString uniqueFolders}
    restore = ''
      IFS=':' read -ra FOLDER <<< "''$FOLDERS"
      echo "${FOLDER[@]}" > /run/folders-to-restore.txt
      tar -xvpf /var/lib/system-back.tar -C / -T /run/folders-to-restore.txt

For better real-world implementations, check out the implementations for BorgBackup and localbackup.

What It Looks Like to the End User

After following the guide for configuring a backup, users can use the CLI to create backups, list them, and restore them.

Backups can be created through the CLI like this:

clan backups create web01

BorgBackup will also create backups itself every day by default.

Completed backups can be listed like this:

clan backups list web01
One cool feature of our backup system is that it is aware of individual services/applications. Let's say we want to restore the state of our Matrix chat server; we can just specify it like this:

clan backups restore --service matrix-synapse web01 borgbackup

In this case, it will first stop the matrix-synapse systemd service, then delete the PostgreSQL database, restore the database from the backup, and then start the matrix-synapse service again.

Future work

As of now we implemented our backup and restore for a handful of services and we expect to refine the interface as we test the interface for more applications.

Currently, our backup implementation backs up filesystem state from running services. This can lead to inconsistencies if applications change the state while the backup is running. In the future, we hope to make backups more atomic by backing up a filesystem snapshot instead of normal directories. This, however, requires the use of modern filesystems that support these features.

Dev Report: Introducing the NixOS to JSON Schema Converter


We’ve developed a new library designed to extract interfaces from NixOS modules and convert them into JSON schemas, paving the way for effortless GUI generation. This blog post outlines the motivations behind this development, demonstrates the capabilities of the library, and guides you through leveraging it to create GUIs seamlessly.


In recent months, our team has been exploring various graphical user interfaces (GUIs) to streamline NixOS machine configuration. While our opinionated Clan modules simplify NixOS configurations, there's a need to configure these modules from diverse frontends, such as:

  • Command-line interfaces (CLIs)
  • Web-based UIs
  • Desktop applications
  • Mobile applications
  • Large Language Models (LLMs)

Given this need, a universal format like JSON is a natural choice. It is already possible as of now, to import json based NixOS configurations, as illustrated below:


{ "networking": { "hostName": "my-machine" } }

This configuration can be then imported inside a classic NixOS config:

{config, lib, pkgs, ...}: {
  imports = [
    (lib.importJSON ./configuration.json)

This straightforward approach allows us to build a frontend that generates JSON, enabling the configuration of NixOS machines. But, two critical questions arise:

  1. How does the frontend learn about existing configuration options?
  2. How can it verify user input without running Nix?

Introducing JSON schema, a widely supported standard that defines interfaces in JSON and validates input against them.

Example schema for networking.hostName:

  "type": "object",
  "properties": {
    "networking": {
      "type": "object",
      "properties": {
        "hostName": {
          "type": "string",
          "pattern": "^$|^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$"

Client-Side Input Validation

Validating input against JSON schemas is both efficient and well-supported across numerous programming languages. Using JSON schema validators, you can accurately check configurations like our configuration.json.

Validation example:

$ nix-shell -p check-jsonschema
$ jsonschema -o pretty ./schema.json -i ./configuration.json

In case of invalid input, schema validators provide explicit error messages:

$ echo '{ "networking": { "hostName": "my/machine" } }' > configuration.json
$ jsonschema -o pretty ./schema.json -i ./configuration.json

'my/machine' does not match '^$|^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$'

Failed validating 'pattern' in schema['properties']['networking']['properties']['hostName']:
    {'pattern': '^$|^[a-z0-9]([a-z0-9_-]{0,61}[a-z0-9])?$',
     'type': 'string'}

On instance['networking']['hostName']:

Automatic GUI Generation

Certain libraries facilitate straightforward GUI generation from JSON schemas. For instance, the react-jsonschema-form playground auto-generates a form for any given schema.

NixOS Module to JSON Schema Converter

To enable the development of responsive frontends, our library allows the extraction of interfaces from NixOS modules to JSON schemas. Open-sourced for community collaboration, this library supports building sophisticated user interfaces for NixOS.

Here’s a preview of our library's functions exposed through the clan-core flake:

  • lib.jsonschema.parseModule - Generates a schema for a NixOS module.
  • lib.jsonschema.parseOption - Generates a schema for a single NixOS option.
  • lib.jsonschema.parseOptions - Generates a schema from an attrset of NixOS options.

Example: module.nix:

{lib, config, pkgs, ...}: {
  # a simple service with two options = {
    enable = lib.mkEnableOption "Example web service";
    port = lib.mkOption {
      type =;
      description = "Port used to serve the content";

Converted, using the parseModule function:

$ cd clan-core
$ nix eval --json --impure --expr \
  '(import ./lib/jsonschema {}).parseModule ./module.nix' | jq | head
  "properties": {
    "services": {
      "properties": {
        "example-web-service": {
          "properties": {
            "enable": {
              "default": false,
              "description": "Whether to enable Example web service.",
              "examples": [

This utility can also generate interfaces for existing NixOS modules or options.

GUI for NGINX in Under a Minute

Creating a prototype GUI for the NGINX module using our library and react-jsonschema-form playground can be done quickly:

  1. Export all NGINX options into a JSON schema using a Nix expression:
# export.nix
  pkgs = import <nixpkgs> {};
  clan-core = builtins.getFlake "git+";
  options = (pkgs.nixos {});
  clan-core.lib.jsonschema.parseOption options
  1. Write the schema into a file:

    $ nix eval --json -f ./export.nix | jq > nginx.json

  2. Open the react-jsonschema-form playground, select Blank and paste the nginx.json contents.

This provides a quick look at a potential GUI (screenshot is cropped).

Image title



JSON schema mandates the declaration of all required fields upfront, which might be configured implicitly or remain unused. For instance, services.nginx.virtualHosts.<name>.sslCertificate must be specified even if SSL isn’t enabled.

Limited Types

Certain NixOS module types, like types.functionTo and types.package, do not map straightforwardly to JSON. For full compatibility, adjustments to NixOS modules might be necessary, such as substituting listOf package with listOf str.

Parsing NixOS Modules

Currently, our converter relies on the options attribute of evaluated NixOS modules, extracting information from the attribute, which is suboptimal. Enhanced introspection capabilities within the NixOS module system would be beneficial.

Future Prospects

We hope these experiments inspire the community, encourage contributions and further development in this space. Share your ideas and contributions through our issue tracker or matrix channel!

New documentation site and weekly new meetup

Last week, we added a new documentation hub for clan at We are still working on improving the installation procedures, so stay tuned. We now have weekly office hours where people are invited to hangout and ask questions. They are every Wednesday 15:30 UTC (17:30 CEST) in our jitsi. Otherwise drop by in our matrix channel.

Introducing Clan: Full-Stack Computing Redefined

In a digital age where users are guided increasingly toward submission and dependence, Clan reclaims computing and networking from the ground up.

Clan enables users to build any system from a git repository, automate secret handling, and join devices in a secure darknet. This control extends beyond applications to communication protocols and the operating system itself, putting you fully in charge of your own digital environment.

Why We're Building Clan

Our mission is simple: to restore fun, freedom, and functionality to computing as an open source project. We believe in building tools that empower users, foster innovation, and challenge the limitations imposed by outdated paradigms. Clan, in its essence, is an open source endeavor; it's our contribution to a future where technology serves humanity, not the other way around.

How Clan Changes the Game

Clan embodies a new philosophy in system, application, and network design. It enables seamless, secure communication across devices, simplifies software distribution and updates, and offers both public and private network configurations. Here are some of the ways it accomplishes this:

  • Nix as a Foundation: Imagine a safety net for your computer's operating system, one that lets you make changes or updates without the fear of causing a crash or losing data. Nix simplifies the complexities of system design, ensuring that updates are safe and systems are more reliable.

  • Simplified System Deployment: Building and managing a computer system, from the operating system to the software you use, often feels like putting together a complex puzzle. With Clan, the puzzle pieces are replaced by a set of building blocks. Leveraging the power of Nix and Clan's innovative toolkit, anyone from tech-savvy administrators to everyday users can create and maintain what we call "full-stack systems" (everything your computer needs to run smoothly).

  • A Leap in Connectivity: Imagine if you could create private, secure pathways between your devices, bypassing the noisy and often insecure internet. Clan makes this possible through something called "overlay networks." These networks are like private tunnels, allowing your devices to talk to each other securely and directly. With Clan's built-in overlay networks and automatically configured services, connecting your devices becomes seamless, secure, and hassle-free.

  • Security Through Separation: Clan employs sandboxing and virtual machines, a technology that runs code in isolated environments - so even if you explore new Clans, your system remains protected from potential threats.

  • Reliable: With Clan, your data and services are preserved for the long haul. We focus on self-hosted backups and integration with the Fediverse, a network of interconnected, independent online communities, so your digital life remains uninterrupted and under your control.

A Glimpse at Clan's Features

  • Social Scaling: Choose between creating a private sanctuary for your closest contacts, a dynamic space for a self-contained community, or embracing the open web with public Clans anyone can join.
  • Seamless VM Integration: Applications running in virtual machines can appear and behave as if they're part of your main operating system — a blend of power and simplicity.
  • Robust Backup Management: Keep your data safe forever - never worry about cloud services disappearing in 10 years.
  • Intuitive Secret Management: Clan simplifies digital security by automating the creation and management of encryption keys and passwords for your services.
  • Remote Install: Set up and manage Clan systems anywhere in the world with just a QR scan or SSH access, making remote installations as easy as snapping a photo or sharing a link.

Who Stands to Benefit?

Clan is for anyone and everyone who believes in the power of open source technology to connect, empower, and protect. From system administrators to less tech-savvy individuals, small business owners to privacy-conscious users, Clan offers something for everyone — a way to reclaim control and redefine how we interact with technology.

Join the Revolution

Ready to control your digital world? Clan is more than a tool—it's a movement. Secure your data, manage your systems easily, or connect with others how you like. Start with Clan for a better digital future.

Connect with us on our Matrix channel at or through our IRC bridges (coming soon).

Want to see the code? Check it out on our Gitea or on GitHub.

Or follow our RSS feed!

Join us and be part of changing technology for the better, together.