enable deno formatter #1717
49
README.md
49
README.md
@ -1,40 +1,64 @@
|
||||
# Clan core repository
|
||||
|
||||
Welcome to the Clan core repository, the heart of the [clan.lol](https://clan.lol/) project! This monorepo is the foundation of Clan, a revolutionary open-source project aimed at restoring fun, freedom, and functionality to computing. Here, you'll find all the essential packages, NixOS modules, CLI tools, and tests needed to contribute to and work with the Clan project. Clan leverages the Nix system to ensure reliability, security, and seamless management of digital environments, putting the power back into the hands of users.
|
||||
Welcome to the Clan core repository, the heart of the
|
||||
[clan.lol](https://clan.lol/) project! This monorepo is the foundation of Clan,
|
||||
a revolutionary open-source project aimed at restoring fun, freedom, and
|
||||
functionality to computing. Here, you'll find all the essential packages, NixOS
|
||||
modules, CLI tools, and tests needed to contribute to and work with the Clan
|
||||
project. Clan leverages the Nix system to ensure reliability, security, and
|
||||
seamless management of digital environments, putting the power back into the
|
||||
hands of users.
|
||||
|
||||
## Why Clan?
|
||||
|
||||
Our mission is simple: to democratize computing by providing tools that empower users, foster innovation, and challenge outdated paradigms. Clan represents our contribution to a future where technology serves humanity, not the other way around. By participating in Clan, you're joining a movement dedicated to creating a secure, user-empowered digital future.
|
||||
Our mission is simple: to democratize computing by providing tools that empower
|
||||
users, foster innovation, and challenge outdated paradigms. Clan represents our
|
||||
contribution to a future where technology serves humanity, not the other way
|
||||
around. By participating in Clan, you're joining a movement dedicated to
|
||||
creating a secure, user-empowered digital future.
|
||||
|
||||
## Features of Clan
|
||||
|
||||
- **Full-Stack System Deployment:** Utilize Clan’s toolkit alongside Nix's reliability to build and manage systems effortlessly.
|
||||
- **Full-Stack System Deployment:** Utilize Clan’s toolkit alongside Nix's
|
||||
reliability to build and manage systems effortlessly.
|
||||
- **Overlay Networks:** Secure, private communication channels between devices.
|
||||
- **Virtual Machine Integration:** Seamless operation of VM applications within the main operating system.
|
||||
- **Virtual Machine Integration:** Seamless operation of VM applications within
|
||||
the main operating system.
|
||||
- **Robust Backup Management:** Long-term, self-hosted data preservation.
|
||||
- **Intuitive Secret Management:** Simplified encryption and password management processes.
|
||||
- **Intuitive Secret Management:** Simplified encryption and password management
|
||||
processes.
|
||||
|
||||
## Getting started with Clan
|
||||
|
||||
If you're new to Clan and eager to dive in, start with our quickstart guide and explore the core functionalities that Clan offers:
|
||||
If you're new to Clan and eager to dive in, start with our quickstart guide and
|
||||
explore the core functionalities that Clan offers:
|
||||
|
||||
- **Quickstart Guide**: Check out [getting started](https://docs.clan.lol/#starting-with-a-new-clan-project)<!-- [docs/site/index.md](docs/site/index.md) --> to get up and running with Clan in no time.
|
||||
- **Quickstart Guide**: Check out
|
||||
[getting started](https://docs.clan.lol/#starting-with-a-new-clan-project)<!-- [docs/site/index.md](docs/site/index.md) -->
|
||||
to get up and running with Clan in no time.
|
||||
|
||||
### Managing secrets
|
||||
|
||||
In the Clan ecosystem, security is paramount. Learn how to handle secrets effectively:
|
||||
In the Clan ecosystem, security is paramount. Learn how to handle secrets
|
||||
effectively:
|
||||
|
||||
- **Secrets Management**: Securely manage secrets by consulting [secrets](https://docs.clan.lol/getting-started/secrets/)<!-- [secrets.md](docs/site/getting-started/secrets.md) -->.
|
||||
- **Secrets Management**: Securely manage secrets by consulting
|
||||
[secrets](https://docs.clan.lol/getting-started/secrets/)<!-- [secrets.md](docs/site/getting-started/secrets.md) -->.
|
||||
|
||||
### Contributing to Clan
|
||||
|
||||
The Clan project thrives on community contributions. We welcome everyone to contribute and collaborate:
|
||||
The Clan project thrives on community contributions. We welcome everyone to
|
||||
contribute and collaborate:
|
||||
|
||||
- **Contribution Guidelines**: Make a meaningful impact by following the steps in [contributing](https://docs.clan.lol/contributing/contributing/)<!-- [contributing.md](docs/CONTRIBUTING.md) -->.
|
||||
- **Contribution Guidelines**: Make a meaningful impact by following the steps
|
||||
in
|
||||
[contributing](https://docs.clan.lol/contributing/contributing/)<!-- [contributing.md](docs/CONTRIBUTING.md) -->.
|
||||
|
||||
## Join the revolution
|
||||
|
||||
Clan is more than a tool; it's a movement towards a better digital future. By contributing to the Clan project, you're part of changing technology for the better, together.
|
||||
Clan is more than a tool; it's a movement towards a better digital future. By
|
||||
contributing to the Clan project, you're part of changing technology for the
|
||||
better, together.
|
||||
|
||||
### Community and support
|
||||
|
||||
@ -42,4 +66,3 @@ Connect with us and the Clan community for support and discussion:
|
||||
|
||||
- [Matrix channel](https://matrix.to/#/#clan:clan.lol) for live discussions.
|
||||
- IRC bridges (coming soon) for real-time chat support.
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
---
|
||||
description = "Statically configure borgbackup with sane defaults."
|
||||
---
|
||||
This module implements the `borgbackup` backend and implements sane defaults
|
||||
for backup management through `borgbackup` for members of the clan.
|
||||
|
||||
This module implements the `borgbackup` backend and implements sane defaults for
|
||||
backup management through `borgbackup` for members of the clan.
|
||||
|
||||
Configure target machines where the backups should be sent to through `targets`.
|
||||
|
||||
Configure machines that should be backuped either through `includeMachines`
|
||||
which will exclusively add the included machines to be backuped, or through
|
||||
`excludeMachines`, which will add every machine except the excluded machine to the backup.
|
||||
`excludeMachines`, which will add every machine except the excluded machine to
|
||||
the backup.
|
||||
|
@ -2,6 +2,7 @@
|
||||
description = "Efficient, deduplicating backup program with optional compression and secure encryption."
|
||||
categories = ["backup"]
|
||||
---
|
||||
|
||||
BorgBackup (short: Borg) gives you:
|
||||
|
||||
- Space efficient storage of backups.
|
||||
@ -10,4 +11,4 @@ BorgBackup (short: Borg) gives you:
|
||||
- Mountable backups with FUSE.
|
||||
- Easy installation on multiple platforms: Linux, macOS, BSD, ...
|
||||
- Free software (BSD license).
|
||||
- Backed by a large and active open source community.
|
||||
- Backed by a large and active open source community.
|
||||
|
@ -4,14 +4,17 @@ description = "Email-based instant messaging for Desktop."
|
||||
|
||||
!!! warning "Under construction"
|
||||
|
||||
!!! info
|
||||
This module will automatically configure an email server on the machine for handling the e-mail messaging seamlessly.
|
||||
!!! info This module will automatically configure an email server on the machine
|
||||
for handling the e-mail messaging seamlessly.
|
||||
|
||||
## Features
|
||||
|
||||
- [x] **Email-based**: Uses any email account as its backend.
|
||||
- [x] **End-to-End Encryption**: Supports Autocrypt to automatically encrypt messages.
|
||||
- [x] **No Phone Number Required**: Uses your email address instead of a phone number.
|
||||
- [x] **End-to-End Encryption**: Supports Autocrypt to automatically encrypt
|
||||
messages.
|
||||
- [x] **No Phone Number Required**: Uses your email address instead of a phone
|
||||
number.
|
||||
- [x] **Cross-Platform**: Available on desktop and mobile platforms.
|
||||
- [x] **Automatic Server Setup**: Includes your own DeltaChat server for enhanced control and privacy.
|
||||
- [x] **Automatic Server Setup**: Includes your own DeltaChat server for
|
||||
enhanced control and privacy.
|
||||
- [ ] **Bake a cake**: This module cannot cake a bake.
|
||||
|
@ -2,11 +2,11 @@
|
||||
description = "Automatically generates and configures a password for the root user."
|
||||
---
|
||||
|
||||
After the system was installed/deployed the following command can be used to display the root-password:
|
||||
After the system was installed/deployed the following command can be used to
|
||||
display the root-password:
|
||||
|
||||
```bash
|
||||
clan secrets get {machine_name}-password
|
||||
```
|
||||
|
||||
|
||||
See also: [Facts / Secrets](../../getting-started/secrets.md)
|
||||
|
@ -2,13 +2,16 @@
|
||||
description = "Configures partitioning of the main disk"
|
||||
categories = ["disk-layout"]
|
||||
---
|
||||
|
||||
# Primary Disk Layout
|
||||
|
||||
A module for the "disk-layout" category MUST be choosen.
|
||||
|
||||
There is exactly one slot for this type of module in the UI, if you don't fill the slot, your machine cannot boot
|
||||
There is exactly one slot for this type of module in the UI, if you don't fill
|
||||
the slot, your machine cannot boot
|
||||
|
||||
This module is a good choice for most machines. In the future clan will offer a broader choice of disk-layouts
|
||||
This module is a good choice for most machines. In the future clan will offer a
|
||||
broader choice of disk-layouts
|
||||
|
||||
The UI will ask for the options of this module:
|
||||
|
||||
@ -17,6 +20,7 @@ The UI will ask for the options of this module:
|
||||
# Usage example
|
||||
|
||||
`inventory.json`
|
||||
|
||||
```json
|
||||
"services": {
|
||||
"single-disk": {
|
||||
@ -39,4 +43,4 @@ The UI will ask for the options of this module:
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
@ -1,33 +1,45 @@
|
||||
---
|
||||
description = "A secure, file synchronization app for devices over networks, offering a private alternative to cloud services."
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
We recommend configuring this module as an sync-service through the provided options. Although it provides a Web GUI through which more usage scenarios are supported.
|
||||
We recommend configuring this module as an sync-service through the provided
|
||||
options. Although it provides a Web GUI through which more usage scenarios are
|
||||
supported.
|
||||
|
||||
## Features
|
||||
|
||||
- **Private and Secure**: Syncthing uses TLS encryption to secure data transfer between devices, ensuring that only the intended devices can read your data.
|
||||
- **Decentralized**: No central server is involved in the data transfer. Each device communicates directly with others.
|
||||
- **Open Source**: The source code is openly available for audit and contribution, fostering trust and continuous improvement.
|
||||
- **Cross-Platform**: Syncthing supports multiple platforms including Windows, macOS, Linux, BSD, and Android.
|
||||
- **Real-time Synchronization**: Changes made to files are synchronized in real-time across all connected devices.
|
||||
- **Web GUI**: It includes a user-friendly web interface for managing devices and configurations. (`127.0.0.1:8384`)
|
||||
- **Private and Secure**: Syncthing uses TLS encryption to secure data transfer
|
||||
between devices, ensuring that only the intended devices can read your data.
|
||||
- **Decentralized**: No central server is involved in the data transfer. Each
|
||||
device communicates directly with others.
|
||||
- **Open Source**: The source code is openly available for audit and
|
||||
contribution, fostering trust and continuous improvement.
|
||||
- **Cross-Platform**: Syncthing supports multiple platforms including Windows,
|
||||
macOS, Linux, BSD, and Android.
|
||||
- **Real-time Synchronization**: Changes made to files are synchronized in
|
||||
real-time across all connected devices.
|
||||
- **Web GUI**: It includes a user-friendly web interface for managing devices
|
||||
and configurations. (`127.0.0.1:8384`)
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Share Folders**: Select folders to share with connected devices and configure permissions and synchronization parameters.
|
||||
- **Share Folders**: Select folders to share with connected devices and
|
||||
configure permissions and synchronization parameters.
|
||||
|
||||
!!! info
|
||||
Clan automatically discovers other devices. Automatic discovery requires one machine to be an [introducer](#clan.syncthing.introducer)
|
||||
!!! info Clan automatically discovers other devices. Automatic discovery
|
||||
requires one machine to be an [introducer](#clan.syncthing.introducer)
|
||||
|
||||
If that is not the case you can add the other device by its Device ID manually.
|
||||
You can find and share Device IDs under the "Add Device" button in the Web GUI. (`127.0.0.1:8384`)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Sync Conflicts**: Resolve synchronization conflicts manually by reviewing file versions and modification times in the Web GUI (`127.0.0.1:8384`).
|
||||
- **Sync Conflicts**: Resolve synchronization conflicts manually by reviewing
|
||||
file versions and modification times in the Web GUI (`127.0.0.1:8384`).
|
||||
|
||||
## Support
|
||||
|
||||
- **Documentation**: Extensive documentation is available on the [Syncthing website](https://docs.syncthing.net/).
|
||||
- **Documentation**: Extensive documentation is available on the
|
||||
[Syncthing website](https://docs.syncthing.net/).
|
||||
|
@ -1,3 +1,3 @@
|
||||
---
|
||||
description = "This module sets the `clan.lol` and `nix-community` cache up as a trusted cache."
|
||||
----
|
||||
|
||||
## description = "This module sets the `clan.lol` and `nix-community` cache up as a trusted cache."
|
||||
|
@ -2,13 +2,14 @@
|
||||
description = "Automatically generates and configures a password for the specified user account."
|
||||
---
|
||||
|
||||
If setting the option prompt to true, the user will be prompted to type in their desired password.
|
||||
If setting the option prompt to true, the user will be prompted to type in their
|
||||
desired password.
|
||||
|
||||
!!! Note
|
||||
This module will set `mutableUsers` to `false`, meaning you can not manage user passwords through `passwd` anymore.
|
||||
!!! Note This module will set `mutableUsers` to `false`, meaning you can not
|
||||
manage user passwords through `passwd` anymore.
|
||||
|
||||
|
||||
After the system was installed/deployed the following command can be used to display the user-password:
|
||||
After the system was installed/deployed the following command can be used to
|
||||
display the user-password:
|
||||
|
||||
```bash
|
||||
clan secrets get {machine_name}-user-password
|
||||
@ -16,4 +17,5 @@ clan secrets get {machine_name}-user-password
|
||||
|
||||
See also: [Facts / Secrets](../../getting-started/secrets.md)
|
||||
|
||||
To regenerate the password, delete the password files in the clan directory and redeploy the machine.
|
||||
To regenerate the password, delete the password files in the clan directory and
|
||||
redeploy the machine.
|
||||
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
description = "Statically configure the `zerotier` peers of a clan network."
|
||||
---
|
||||
|
||||
Statically configure the `zerotier` peers of a clan network.
|
||||
|
||||
Requires a machine, that is the zerotier controller configured in the network.
|
||||
|
@ -1,8 +1,12 @@
|
||||
# Contributing
|
||||
|
||||
**Continuous Integration (CI)**: Each pull request gets automatically tested by gitea. If any errors are detected, it will block pull requests until they're resolved.
|
||||
**Continuous Integration (CI)**: Each pull request gets automatically tested by
|
||||
gitea. If any errors are detected, it will block pull requests until they're
|
||||
resolved.
|
||||
|
||||
**Dependency Management**: We use the [Nix package manager](https://nixos.org/) to manage dependencies and ensure reproducibility, making your development process more robust.
|
||||
**Dependency Management**: We use the [Nix package manager](https://nixos.org/)
|
||||
to manage dependencies and ensure reproducibility, making your development
|
||||
process more robust.
|
||||
|
||||
## Supported Operating Systems
|
||||
|
||||
@ -15,81 +19,84 @@ Let's get your development environment up and running:
|
||||
|
||||
1. **Install Nix Package Manager**:
|
||||
|
||||
- You can install the Nix package manager by either [downloading the Nix installer](https://github.com/DeterminateSystems/nix-installer/releases) or running this command:
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
|
||||
```
|
||||
- You can install the Nix package manager by either
|
||||
[downloading the Nix installer](https://github.com/DeterminateSystems/nix-installer/releases)
|
||||
or running this command:
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
|
||||
```
|
||||
|
||||
2. **Install direnv**:
|
||||
|
||||
- To automatically setup a devshell on entering the directory
|
||||
```bash
|
||||
nix profile install nixpkgs#nix-direnv-flakes
|
||||
```
|
||||
- To automatically setup a devshell on entering the directory
|
||||
```bash
|
||||
nix profile install nixpkgs#nix-direnv-flakes
|
||||
```
|
||||
|
||||
3. **Add direnv to your shell**:
|
||||
|
||||
- Direnv needs to [hook into your shell](https://direnv.net/docs/hook.html) to work.
|
||||
You can do this by executing following command. The example below will setup direnv for `zsh` and `bash`
|
||||
- Direnv needs to [hook into your shell](https://direnv.net/docs/hook.html)
|
||||
to work. You can do this by executing following command. The example below
|
||||
will setup direnv for `zsh` and `bash`
|
||||
|
||||
```bash
|
||||
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc && echo 'eval "$(direnv hook bash)"' >> ~/.bashrc && eval "$SHELL"
|
||||
```
|
||||
```bash
|
||||
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc && echo 'eval "$(direnv hook bash)"' >> ~/.bashrc && eval "$SHELL"
|
||||
```
|
||||
|
||||
4. **Create a Gitea Account**:
|
||||
- Register an account on https://git.clan.lol
|
||||
- Fork the [clan-core](https://git.clan.lol/clan/clan-core) repository
|
||||
- Clone the repository and navigate to it
|
||||
- Add a new remote called upstream:
|
||||
```bash
|
||||
git remote add upstream gitea@git.clan.lol:clan/clan-core.git
|
||||
```
|
||||
- Register an account on https://git.clan.lol
|
||||
- Fork the [clan-core](https://git.clan.lol/clan/clan-core) repository
|
||||
- Clone the repository and navigate to it
|
||||
- Add a new remote called upstream:
|
||||
```bash
|
||||
git remote add upstream gitea@git.clan.lol:clan/clan-core.git
|
||||
```
|
||||
5. **Create an access token**:
|
||||
- Log in to Gitea.
|
||||
- Go to your account settings.
|
||||
- Navigate to the Applications section.
|
||||
- Click Generate New Token.
|
||||
- Name your token and select all available scopes.
|
||||
- Generate the token and copy it for later use.
|
||||
- Your access token is now ready to use with all permissions.
|
||||
- Log in to Gitea.
|
||||
- Go to your account settings.
|
||||
- Navigate to the Applications section.
|
||||
- Click Generate New Token.
|
||||
- Name your token and select all available scopes.
|
||||
- Generate the token and copy it for later use.
|
||||
- Your access token is now ready to use with all permissions.
|
||||
|
||||
5. **Register Your Gitea Account Locally**:
|
||||
6. **Register Your Gitea Account Locally**:
|
||||
|
||||
- Execute the following command to add your Gitea account locally:
|
||||
```bash
|
||||
tea login add
|
||||
```
|
||||
- Fill out the prompt as follows:
|
||||
- URL of Gitea instance: `https://git.clan.lol`
|
||||
- Name of new Login [git.clan.lol]:
|
||||
- Do you have an access token? Yes
|
||||
- Token: <yourtoken>
|
||||
- Set Optional settings: No
|
||||
- Execute the following command to add your Gitea account locally:
|
||||
```bash
|
||||
tea login add
|
||||
```
|
||||
- Fill out the prompt as follows:
|
||||
- URL of Gitea instance: `https://git.clan.lol`
|
||||
- Name of new Login [git.clan.lol]:
|
||||
- Do you have an access token? Yes
|
||||
- Token: <yourtoken>
|
||||
- Set Optional settings: No
|
||||
|
||||
7. **Allow .envrc**:
|
||||
|
||||
6. **Allow .envrc**:
|
||||
- When you enter the directory, you'll receive an error message like this:
|
||||
```bash
|
||||
direnv: error .envrc is blocked. Run `direnv allow` to approve its content
|
||||
```
|
||||
- Execute `direnv allow` to automatically execute the shell script `.envrc`
|
||||
when entering the directory.
|
||||
|
||||
- When you enter the directory, you'll receive an error message like this:
|
||||
```bash
|
||||
direnv: error .envrc is blocked. Run `direnv allow` to approve its content
|
||||
```
|
||||
- Execute `direnv allow` to automatically execute the shell script `.envrc` when entering the directory.
|
||||
8. **(Optional) Install Git Hooks**:
|
||||
- To syntax check your code you can run:
|
||||
```bash
|
||||
nix fmt
|
||||
```
|
||||
- To make this automatic install the git hooks
|
||||
```bash
|
||||
./scripts/pre-commit
|
||||
```
|
||||
|
||||
7. **(Optional) Install Git Hooks**:
|
||||
- To syntax check your code you can run:
|
||||
```bash
|
||||
nix fmt
|
||||
```
|
||||
- To make this automatic install the git hooks
|
||||
```bash
|
||||
./scripts/pre-commit
|
||||
```
|
||||
|
||||
8. **Open a Pull Request**:
|
||||
- To automatically open up a pull request you can use our tool called:
|
||||
```
|
||||
merge-after-ci --reviewers Mic92 Lassulus Qubasa
|
||||
```
|
||||
9. **Open a Pull Request**:
|
||||
- To automatically open up a pull request you can use our tool called:
|
||||
```
|
||||
merge-after-ci --reviewers Mic92 Lassulus Qubasa
|
||||
```
|
||||
|
||||
# Debugging
|
||||
|
||||
@ -103,7 +110,8 @@ To quickly show all possible packages and tests execute:
|
||||
nix flake show --system no-eval
|
||||
```
|
||||
|
||||
Under `checks` you will find all tests that are executed in our CI. Under `packages` you find all our projects.
|
||||
Under `checks` you will find all tests that are executed in our CI. Under
|
||||
`packages` you find all our projects.
|
||||
|
||||
```
|
||||
git+file:///home/lhebendanz/Projects/clan-core
|
||||
@ -138,26 +146,33 @@ git+file:///home/lhebendanz/Projects/clan-core
|
||||
└───new-clan: template: Initialize a new clan flake
|
||||
```
|
||||
|
||||
You can execute every test separately by following the tree path `nix build .#checks.x86_64-linux.clan-pytest` for example.
|
||||
You can execute every test separately by following the tree path
|
||||
`nix build .#checks.x86_64-linux.clan-pytest` for example.
|
||||
|
||||
## Test Locally in Devshell with Breakpoints
|
||||
|
||||
To test the cli locally in a development environment and set breakpoints for debugging, follow these steps:
|
||||
To test the cli locally in a development environment and set breakpoints for
|
||||
debugging, follow these steps:
|
||||
|
||||
1. Run the following command to execute your tests and allow for debugging with breakpoints:
|
||||
1. Run the following command to execute your tests and allow for debugging with
|
||||
breakpoints:
|
||||
```bash
|
||||
cd ./pkgs/clan-cli
|
||||
pytest -n0 -s --maxfail=1 ./tests/test_nameofthetest.py
|
||||
```
|
||||
You can place `breakpoint()` in your Python code where you want to trigger a breakpoint for debugging.
|
||||
You can place `breakpoint()` in your Python code where you want to trigger a
|
||||
breakpoint for debugging.
|
||||
|
||||
## Test Locally in a Nix Sandbox
|
||||
|
||||
To run tests in a Nix sandbox, you have two options depending on whether your test functions have been marked as impure or not:
|
||||
To run tests in a Nix sandbox, you have two options depending on whether your
|
||||
test functions have been marked as impure or not:
|
||||
|
||||
### Running Tests Marked as Impure
|
||||
|
||||
If your test functions need to execute `nix build` and have been marked as impure because you can't execute `nix build` inside a Nix sandbox, use the following command:
|
||||
If your test functions need to execute `nix build` and have been marked as
|
||||
impure because you can't execute `nix build` inside a Nix sandbox, use the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
nix run .#impure-checks
|
||||
@ -167,7 +182,8 @@ This command will run the impure test functions.
|
||||
|
||||
### Running Pure Tests
|
||||
|
||||
For test functions that have not been marked as impure and don't require executing `nix build`, you can use the following command:
|
||||
For test functions that have not been marked as impure and don't require
|
||||
executing `nix build`, you can use the following command:
|
||||
|
||||
```bash
|
||||
nix build .#checks.x86_64-linux.clan-pytest --rebuild
|
||||
@ -179,22 +195,24 @@ This command will run all pure test functions.
|
||||
|
||||
If you need to inspect the Nix sandbox while running tests, follow these steps:
|
||||
|
||||
1. Insert an endless sleep into your test code where you want to pause the execution. For example:
|
||||
1. Insert an endless sleep into your test code where you want to pause the
|
||||
execution. For example:
|
||||
|
||||
```python
|
||||
import time
|
||||
time.sleep(3600) # Sleep for one hour
|
||||
```
|
||||
|
||||
2. Use `cntr` and `psgrep` to attach to the Nix sandbox. This allows you to interactively debug your code while it's paused. For example:
|
||||
2. Use `cntr` and `psgrep` to attach to the Nix sandbox. This allows you to
|
||||
interactively debug your code while it's paused. For example:
|
||||
|
||||
```bash
|
||||
psgrep -a -x your_python_process_name
|
||||
cntr attach <container id, container name or process id>
|
||||
```
|
||||
|
||||
Or you can also use the [nix breakpoint hook](https://nixos.org/manual/nixpkgs/stable/#breakpointhook)
|
||||
|
||||
Or you can also use the
|
||||
[nix breakpoint hook](https://nixos.org/manual/nixpkgs/stable/#breakpointhook)
|
||||
|
||||
# Standards
|
||||
|
||||
|
@ -2,17 +2,27 @@
|
||||
|
||||
## General Description
|
||||
|
||||
Self-hosting refers to the practice of hosting and maintaining servers, networks, storage, services, and other types of infrastructure by oneself rather than relying on a third-party vendor. This could involve running a server from a home or business location, or leasing a dedicated server at a data center.
|
||||
Self-hosting refers to the practice of hosting and maintaining servers,
|
||||
networks, storage, services, and other types of infrastructure by oneself rather
|
||||
than relying on a third-party vendor. This could involve running a server from a
|
||||
home or business location, or leasing a dedicated server at a data center.
|
||||
|
||||
There are several reasons for choosing to self-host. These can include:
|
||||
|
||||
1. Cost savings: Over time, self-hosting can be more cost-effective, especially for businesses with large scale needs.
|
||||
1. Cost savings: Over time, self-hosting can be more cost-effective, especially
|
||||
for businesses with large scale needs.
|
||||
|
||||
1. Control: Self-hosting provides a greater level of control over the infrastructure and services. It allows the owner to customize the system to their specific needs.
|
||||
1. Control: Self-hosting provides a greater level of control over the
|
||||
infrastructure and services. It allows the owner to customize the system to
|
||||
their specific needs.
|
||||
|
||||
1. Privacy and security: Self-hosting can offer improved privacy and security because data remains under the control of the host rather than being stored on third-party servers.
|
||||
1. Privacy and security: Self-hosting can offer improved privacy and security
|
||||
because data remains under the control of the host rather than being stored
|
||||
on third-party servers.
|
||||
|
||||
1. Independent: Being independent of third-party services can ensure that one's websites, applications, or services remain up even if the third-party service goes down.
|
||||
1. Independent: Being independent of third-party services can ensure that one's
|
||||
websites, applications, or services remain up even if the third-party service
|
||||
goes down.
|
||||
|
||||
## Stories
|
||||
|
||||
@ -20,23 +30,32 @@ There are several reasons for choosing to self-host. These can include:
|
||||
|
||||
Alice wants to self-host a mumble server for her family.
|
||||
|
||||
- She visits to the Clan website, and follows the instructions on how to install Clan-OS on her server.
|
||||
- Alice logs into a terminal on her server via SSH (alternatively uses Clan GUI app)
|
||||
- Using the Clan CLI or GUI tool, alice creates a new private network for her family (VPN)
|
||||
- Alice now browses a list of curated Clan modules and finds a module for mumble.
|
||||
- She visits to the Clan website, and follows the instructions on how to install
|
||||
Clan-OS on her server.
|
||||
- Alice logs into a terminal on her server via SSH (alternatively uses Clan GUI
|
||||
app)
|
||||
- Using the Clan CLI or GUI tool, alice creates a new private network for her
|
||||
family (VPN)
|
||||
- Alice now browses a list of curated Clan modules and finds a module for
|
||||
mumble.
|
||||
- She adds this module to her network using the Clan tool.
|
||||
- After that, she uses the clan tool to invite her family members to her network
|
||||
- Other family members join the private network via the invitation.
|
||||
- By accepting the invitation, other members automatically install all required software to interact with the network on their machine.
|
||||
- By accepting the invitation, other members automatically install all required
|
||||
software to interact with the network on their machine.
|
||||
|
||||
### Story 2: Adding a service to an existing network
|
||||
|
||||
Alice wants to add a photos app to her private network
|
||||
|
||||
- She uses the clan CLI or GUI tool to manage her existing private Clan family network
|
||||
- She discovers a module for photoprism, and adds it to her server using the tool
|
||||
- Other members who are already part of her network, will receive a notification that an update is required to their environment
|
||||
- After accepting, all new software and services to interact with the new photoprism service will be installed automatically.
|
||||
- She uses the clan CLI or GUI tool to manage her existing private Clan family
|
||||
network
|
||||
- She discovers a module for photoprism, and adds it to her server using the
|
||||
tool
|
||||
- Other members who are already part of her network, will receive a notification
|
||||
that an update is required to their environment
|
||||
- After accepting, all new software and services to interact with the new
|
||||
photoprism service will be installed automatically.
|
||||
|
||||
## Challenges
|
||||
|
||||
|
@ -2,35 +2,53 @@
|
||||
|
||||
## General Description
|
||||
|
||||
Joining a self-hosted infrastructure involves connecting to a network, server, or system that is privately owned and managed, instead of being hosted by a third-party service provider. This could be a business's internal server, a private cloud setup, or any other private IT infrastructure that is not publicly accessible or controlled by outside entities.
|
||||
Joining a self-hosted infrastructure involves connecting to a network, server,
|
||||
or system that is privately owned and managed, instead of being hosted by a
|
||||
third-party service provider. This could be a business's internal server, a
|
||||
private cloud setup, or any other private IT infrastructure that is not publicly
|
||||
accessible or controlled by outside entities.
|
||||
|
||||
## Stories
|
||||
|
||||
### Story 1: Joining a private network
|
||||
|
||||
Alice' son Bob has never heard of Clan, but receives an invitation URL from Alice who already set up private Clan network for her family.
|
||||
Alice' son Bob has never heard of Clan, but receives an invitation URL from
|
||||
Alice who already set up private Clan network for her family.
|
||||
|
||||
Bob opens the invitation link and lands on the Clan website. He quickly learns about what Clan is and can see that the invitation is for a private network of his family that hosts a number of services, like a private voice chat and a photo sharing platform.
|
||||
Bob opens the invitation link and lands on the Clan website. He quickly learns
|
||||
about what Clan is and can see that the invitation is for a private network of
|
||||
his family that hosts a number of services, like a private voice chat and a
|
||||
photo sharing platform.
|
||||
|
||||
Bob decides to join the network and follows the instructions to install the Clan tool on his computer.
|
||||
Bob decides to join the network and follows the instructions to install the Clan
|
||||
tool on his computer.
|
||||
|
||||
Feeding the invitation link to the Clan tool, bob registers his machine with the network.
|
||||
Feeding the invitation link to the Clan tool, bob registers his machine with the
|
||||
network.
|
||||
|
||||
All programs required to interact with the network will be installed and configured automatically and securely.
|
||||
All programs required to interact with the network will be installed and
|
||||
configured automatically and securely.
|
||||
|
||||
Optionally, bob can customize the configuration of these programs through a simplified configuration interface.
|
||||
Optionally, bob can customize the configuration of these programs through a
|
||||
simplified configuration interface.
|
||||
|
||||
### Story 2: Receiving breaking changes
|
||||
|
||||
The Clan family network which Bob is part of received an update.
|
||||
|
||||
The existing photo sharing service has been removed and replaced with another alternative service. The new photo sharing service requires a different client app to view and upload photos.
|
||||
The existing photo sharing service has been removed and replaced with another
|
||||
alternative service. The new photo sharing service requires a different client
|
||||
app to view and upload photos.
|
||||
|
||||
Bob accepts the update. Now his environment will be updated. The old client software will be removed and the new one installed.
|
||||
Bob accepts the update. Now his environment will be updated. The old client
|
||||
software will be removed and the new one installed.
|
||||
|
||||
Because Bob has customized the previous photo viewing app, he is notified that this customization is no longer valid, as the software has been removed (deprecation message).l
|
||||
Because Bob has customized the previous photo viewing app, he is notified that
|
||||
this customization is no longer valid, as the software has been removed
|
||||
(deprecation message).l
|
||||
|
||||
Optionally, Bob can now customize the new photo viewing software through his Clan configuration app or via a config file.
|
||||
Optionally, Bob can now customize the new photo viewing software through his
|
||||
Clan configuration app or via a config file.
|
||||
|
||||
## Challenges
|
||||
|
||||
|
@ -2,23 +2,30 @@
|
||||
|
||||
## General Description
|
||||
|
||||
Clan modules are pieces of software that can be used by admins to build a private or public infrastructure.
|
||||
Clan modules are pieces of software that can be used by admins to build a
|
||||
private or public infrastructure.
|
||||
|
||||
Clan modules should have the following properties:
|
||||
|
||||
1. Documented: It should be clear what the module does and how to use it.
|
||||
1. Self contained: A module should be usable as is. If it requires any other software or settings, those should be delivered with the module itself.
|
||||
1. Simple to deploy and use: Modules should have opinionated defaults that just work. Any customization should be optional
|
||||
1. Self contained: A module should be usable as is. If it requires any other
|
||||
software or settings, those should be delivered with the module itself.
|
||||
1. Simple to deploy and use: Modules should have opinionated defaults that just
|
||||
work. Any customization should be optional
|
||||
|
||||
## Stories
|
||||
|
||||
### Story 1: Maintaining a shared folder module
|
||||
|
||||
Alice maintains a module for a shared folder service that she uses in her own infra, but also publishes for the community.
|
||||
Alice maintains a module for a shared folder service that she uses in her own
|
||||
infra, but also publishes for the community.
|
||||
|
||||
By following clan module standards (Backups, Interfaces, Output schema, etc), other community members have an easy time re-using the module within their own infra.
|
||||
By following clan module standards (Backups, Interfaces, Output schema, etc),
|
||||
other community members have an easy time re-using the module within their own
|
||||
infra.
|
||||
|
||||
She benefits from publishing the module, because other community members start using it and help to maintain it.
|
||||
She benefits from publishing the module, because other community members start
|
||||
using it and help to maintain it.
|
||||
|
||||
## Challenges
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
# Blog
|
||||
|
||||
|
@ -7,27 +7,34 @@ date: 2024-06-24
|
||||
slug: backups
|
||||
---
|
||||
|
||||
Our goal with [Clan](https://clan.lol/) 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.
|
||||
Our goal with [Clan](https://clan.lol/) 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 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.
|
||||
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](https://wiki.nixos.org/wiki/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](https://docs.clan.lol/blog/2024/05/25/jsonschema-converter/).
|
||||
Our services are built from Clan modules. Clan modules are essentially
|
||||
[NixOS modules](https://wiki.nixos.org/wiki/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](https://docs.clan.lol/blog/2024/05/25/jsonschema-converter/).
|
||||
|
||||
In a simple case, this can be just a bunch of directories, such as what we define for our [ZeroTier](https://www.zerotier.com/) VPN service.
|
||||
In a simple case, this can be just a bunch of directories, such as what we
|
||||
define for our [ZeroTier](https://www.zerotier.com/) VPN service.
|
||||
|
||||
```nix
|
||||
{
|
||||
@ -35,10 +42,12 @@ In a simple case, this can be just a bunch of directories, such as what we defin
|
||||
}
|
||||
```
|
||||
|
||||
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.
|
||||
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:
|
||||
In our PostgreSQL module, for example, we define `preBackupCommand` and
|
||||
`postRestoreCommand` to use `pg_dump` and `pg_restore` to backup and restore
|
||||
individual databases:
|
||||
|
||||
```nix
|
||||
preBackupCommand = ''
|
||||
@ -56,46 +65,54 @@ postRestoreCommand = ''
|
||||
|
||||
## Then the Backup
|
||||
|
||||
Our CLI unifies the different backup providers in one [interface](https://docs.clan.lol/reference/cli/backups/).
|
||||
Our CLI unifies the different backup providers in one
|
||||
[interface](https://docs.clan.lol/reference/cli/backups/).
|
||||
|
||||
As of now, we support backups using [BorgBackup](https://www.borgbackup.org/) and
|
||||
a backup module called "localbackup" based on [rsnapshot](https://rsnapshot.org/), optimized for backup on locally attached storage media.
|
||||
As of now, we support backups using [BorgBackup](https://www.borgbackup.org/)
|
||||
and a backup module called "localbackup" based on
|
||||
[rsnapshot](https://rsnapshot.org/), 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:
|
||||
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:
|
||||
|
||||
```nix
|
||||
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}
|
||||
else
|
||||
tar -cvpf /var/lib/system-back.tar ${builtins.toString uniqueFolders}
|
||||
fi
|
||||
'';
|
||||
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
|
||||
'';
|
||||
};
|
||||
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}
|
||||
else
|
||||
tar -cvpf /var/lib/system-back.tar ${builtins.toString uniqueFolders}
|
||||
fi
|
||||
'';
|
||||
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](https://git.clan.lol/clan/clan-core/src/branch/main/clanModules/borgbackup/default.nix)
|
||||
and [localbackup](https://git.clan.lol/clan/clan-core/src/branch/main/clanModules/localbackup/default.nix).
|
||||
For better real-world implementations, check out the implementations for
|
||||
[BorgBackup](https://git.clan.lol/clan/clan-core/src/branch/main/clanModules/borgbackup/default.nix)
|
||||
and
|
||||
[localbackup](https://git.clan.lol/clan/clan-core/src/branch/main/clanModules/localbackup/default.nix).
|
||||
|
||||
## What It Looks Like to the End User
|
||||
|
||||
After following the guide for configuring a [backup](https://docs.clan.lol/getting-started/backups/),
|
||||
users can use the CLI to create backups, list them, and restore them.
|
||||
After following the guide for configuring a
|
||||
[backup](https://docs.clan.lol/getting-started/backups/), users can use the CLI
|
||||
to create backups, list them, and restore them.
|
||||
|
||||
Backups can be created through the CLI like this:
|
||||
|
||||
@ -113,20 +130,26 @@ clan backups list web01
|
||||
web01::u366395@u366395.your-storagebox.de:/./borgbackup::web01-web01-2024-06-18T01:00:00
|
||||
web03::u366395@u366395.your-storagebox.de:/./borgbackup::web01-web01-2024-06-19T01:00:00
|
||||
```
|
||||
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](https://matrix.org/) chat server; we can just specify it like this:
|
||||
|
||||
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](https://matrix.org/) chat server; we can just specify it like this:
|
||||
|
||||
```
|
||||
clan backups restore --service matrix-synapse web01 borgbackup web03::u366395@u366395.your-storagebox.de:/./borgbackup::web01-web01-2024-06-19T01:00:00
|
||||
```
|
||||
|
||||
In this case, it will first stop the matrix-synapse systemd service, then delete the [PostgreSQL](https://www.postgresql.org/) database, restore the database from the backup, and then start the matrix-synapse service again.
|
||||
In this case, it will first stop the matrix-synapse systemd service, then delete
|
||||
the [PostgreSQL](https://www.postgresql.org/) 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.
|
||||
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.
|
||||
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.
|
||||
|
@ -7,66 +7,113 @@ authors:
|
||||
date: 2024-03-19
|
||||
---
|
||||
|
||||
In a digital age where users are guided increasingly toward submission and
|
||||
dependence, Clan reclaims computing and networking from the ground up.
|
||||
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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:
|
||||
|
||||
- **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).
|
||||
- **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.
|
||||
|
||||
- **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.
|
||||
- **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).
|
||||
|
||||
- **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.
|
||||
- **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.
|
||||
|
||||
- **Reliable:** With Clan, your data and services are preserved for the long haul. We focus on self-hosted backups and integration with the [Fediverse](https://de.wikipedia.org/wiki/Fediverse), a network of interconnected, independent online communities, so your digital life remains uninterrupted and under your control.
|
||||
- **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](https://de.wikipedia.org/wiki/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.
|
||||
- **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.
|
||||
|
||||
{{ video(name="show_join.webm")}}
|
||||
|
||||
- **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.
|
||||
- **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.
|
||||
|
||||
{{ video(name="show_run.webm")}}
|
||||
|
||||
- **Robust Backup Management:** Keep your data safe _forever_ - never worry about cloud services disappearing in 10 years.
|
||||
- **Robust Backup Management:** Keep your data safe _forever_ - never worry
|
||||
about cloud services disappearing in 10 years.
|
||||
|
||||
{{ asciinema(name="backups.cast") }}
|
||||
|
||||
- **Intuitive Secret Management:** Clan simplifies digital security by automating the creation and management of encryption keys and passwords for your services.
|
||||
- **Intuitive Secret Management:** Clan simplifies digital security by
|
||||
automating the creation and management of encryption keys and passwords for
|
||||
your services.
|
||||
|
||||
{{ asciinema(name="secrets.cast") }}
|
||||
|
||||
- **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.
|
||||
- **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.
|
||||
|
||||
{{ asciinema(name="nixos-install.cast") }}
|
||||
|
||||
|
||||
## 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.
|
||||
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.
|
||||
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 clan.lol](https://matrix.to/#/#clan:clan.lol) or through our IRC bridges (coming soon).
|
||||
Connect with us on our
|
||||
[Matrix channel at clan.lol](https://matrix.to/#/#clan:clan.lol) or through our
|
||||
IRC bridges (coming soon).
|
||||
|
||||
Want to see the code? Check it out [on our Gitea](https://git.clan.lol/clan/clan-core) or [on GitHub](https://github.com/clan-lol/clan-core).
|
||||
Want to see the code? Check it out
|
||||
[on our Gitea](https://git.clan.lol/clan/clan-core) or
|
||||
[on GitHub](https://github.com/clan-lol/clan-core).
|
||||
|
||||
Or follow our [RSS feed](https://docs.clan.lol/feed_rss_created.xml)!
|
||||
|
||||
Join us and be part of changing technology for the better, together.
|
||||
|
||||
|
||||
|
@ -9,11 +9,18 @@ slug: jsonschema-converter
|
||||
|
||||
## Overview
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
## Motivation
|
||||
|
||||
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:
|
||||
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
|
||||
@ -21,14 +28,18 @@ In recent months, our team has been exploring various graphical user interfaces
|
||||
- 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:
|
||||
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:
|
||||
|
||||
`configuration.json`:
|
||||
|
||||
```json
|
||||
{ "networking": { "hostName": "my-machine" } }
|
||||
```
|
||||
|
||||
This configuration can be then imported inside a classic NixOS config:
|
||||
|
||||
```nix
|
||||
{config, lib, pkgs, ...}: {
|
||||
imports = [
|
||||
@ -37,14 +48,17 @@ This configuration can be then imported inside a classic NixOS config:
|
||||
}
|
||||
```
|
||||
|
||||
This straightforward approach allows us to build a frontend that generates JSON, enabling the configuration of NixOS machines. But, two critical questions arise:
|
||||
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](https://json-schema.org/), a widely supported standard that defines interfaces in JSON and validates input against them.
|
||||
Introducing [JSON schema](https://json-schema.org/), a widely supported standard
|
||||
that defines interfaces in JSON and validates input against them.
|
||||
|
||||
Example schema for `networking.hostName`:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "object",
|
||||
@ -64,7 +78,9 @@ Example schema for `networking.hostName`:
|
||||
|
||||
## 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`.
|
||||
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:
|
||||
|
||||
@ -93,20 +109,28 @@ On instance['networking']['hostName']:
|
||||
|
||||
## Automatic GUI Generation
|
||||
|
||||
Certain libraries facilitate straightforward GUI generation from JSON schemas. For instance, the [react-jsonschema-form playground](https://rjsf-team.github.io/react-jsonschema-form/) auto-generates a form for any given schema.
|
||||
Certain libraries facilitate straightforward GUI generation from JSON schemas.
|
||||
For instance, the
|
||||
[react-jsonschema-form playground](https://rjsf-team.github.io/react-jsonschema-form/)
|
||||
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.
|
||||
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](https://git.clan.lol/clan/clan-core) flake:
|
||||
Here’s a preview of our library's functions exposed through the
|
||||
[clan-core](https://git.clan.lol/clan/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.
|
||||
- `lib.jsonschema.parseOptions` - Generates a schema from an attrset of NixOS
|
||||
options.
|
||||
|
||||
Example: `module.nix`:
|
||||
|
||||
Example:
|
||||
`module.nix`:
|
||||
```nix
|
||||
{lib, config, pkgs, ...}: {
|
||||
# a simple service with two options
|
||||
@ -121,6 +145,7 @@ Example:
|
||||
```
|
||||
|
||||
Converted, using the `parseModule` function:
|
||||
|
||||
```shell
|
||||
$ cd clan-core
|
||||
$ nix eval --json --impure --expr \
|
||||
@ -142,7 +167,9 @@ 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](https://rjsf-team.github.io/react-jsonschema-form/) can be done quickly:
|
||||
Creating a prototype GUI for the NGINX module using our library and
|
||||
[react-jsonschema-form playground](https://rjsf-team.github.io/react-jsonschema-form/)
|
||||
can be done quickly:
|
||||
|
||||
1. Export all NGINX options into a JSON schema using a Nix expression:
|
||||
|
||||
@ -157,11 +184,14 @@ in
|
||||
```
|
||||
|
||||
2. Write the schema into a file:
|
||||
|
||||
```shell
|
||||
$ nix eval --json -f ./export.nix | jq > nginx.json
|
||||
```
|
||||
|
||||
3. Open the [react-jsonschema-form playground](https://rjsf-team.github.io/react-jsonschema-form/), select `Blank` and paste the `nginx.json` contents.
|
||||
3. Open the
|
||||
[react-jsonschema-form playground](https://rjsf-team.github.io/react-jsonschema-form/),
|
||||
select `Blank` and paste the `nginx.json` contents.
|
||||
|
||||
This provides a quick look at a potential GUI (screenshot is cropped).
|
||||
|
||||
@ -171,19 +201,30 @@ This provides a quick look at a potential GUI (screenshot is cropped).
|
||||
|
||||
### Laziness
|
||||
|
||||
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.
|
||||
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`.
|
||||
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 `type.name` attribute, which is suboptimal. Enhanced introspection capabilities within the NixOS module system would be beneficial.
|
||||
Currently, our converter relies on the `options` attribute of evaluated NixOS
|
||||
modules, extracting information from the `type.name` 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!
|
||||
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!
|
||||
|
||||
## Links
|
||||
|
||||
|
@ -6,8 +6,9 @@ authors:
|
||||
date: 2024-04-16
|
||||
---
|
||||
|
||||
Last week, we added a new documentation hub for clan at [docs.clan.lol](https://docs.clan.lol).
|
||||
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](https://jitsi.lassul.us/clan.lol).
|
||||
Otherwise drop by in our [matrix channel](https://matrix.to/#/#clan:clan.lol).
|
||||
Last week, we added a new documentation hub for clan at
|
||||
[docs.clan.lol](https://docs.clan.lol). 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](https://jitsi.lassul.us/clan.lol). Otherwise
|
||||
drop by in our [matrix channel](https://matrix.to/#/#clan:clan.lol).
|
||||
|
@ -3,7 +3,9 @@
|
||||
## Introduction
|
||||
|
||||
When managing machine configuration this can be done through many possible ways.
|
||||
Ranging from writing `nix` expression in a `flake.nix` file; placing `autoincluded` files into your machine directory; or configuring everything in a simple UI (upcomming).
|
||||
Ranging from writing `nix` expression in a `flake.nix` file; placing
|
||||
`autoincluded` files into your machine directory; or configuring everything in a
|
||||
simple UI (upcomming).
|
||||
|
||||
clan currently offers the following methods to configure machines:
|
||||
|
||||
@ -20,44 +22,43 @@ clan currently offers the following methods to configure machines:
|
||||
- inventory.json
|
||||
- machines/`machine_name`/hardware-configuration.nix (`autoincluded` if it exists)
|
||||
|
||||
|
||||
!!! Warning "Deprecated"
|
||||
|
||||
machines/`machine_name`/settings.json
|
||||
|
||||
## BuildClan
|
||||
|
||||
The core function that produces a clan. It returns a set of consistent configurations for all machines with ready-to-use secrets, backups and other services.
|
||||
The core function that produces a clan. It returns a set of consistent
|
||||
configurations for all machines with ready-to-use secrets, backups and other
|
||||
services.
|
||||
|
||||
### Inputs
|
||||
|
||||
`directory`
|
||||
: The directory containing the machines subdirectory
|
||||
`directory` : The directory containing the machines subdirectory
|
||||
|
||||
`machines`
|
||||
: Allows to include machine-specific modules i.e. machines.${name} = { ... }
|
||||
`machines` : Allows to include machine-specific modules i.e. machines.${name} =
|
||||
{ ... }
|
||||
|
||||
`meta`
|
||||
: An optional set
|
||||
`meta` : An optional set
|
||||
|
||||
: `{ name :: string, icon :: string, description :: string }`
|
||||
|
||||
`inventory`
|
||||
: Service set for easily configuring distributed services, such as backups
|
||||
`inventory` : Service set for easily configuring distributed services, such as
|
||||
backups
|
||||
|
||||
: For more details see [Inventory](#inventory)
|
||||
|
||||
`specialArgs`
|
||||
: Extra arguments to pass to nixosSystem i.e. useful to make self available
|
||||
`specialArgs` : Extra arguments to pass to nixosSystem i.e. useful to make self
|
||||
available
|
||||
|
||||
`pkgsForSystem`
|
||||
: A function that maps from architecture to pkgs, if specified this nixpkgs will be only imported once for each system.
|
||||
This improves performance, but all nipxkgs.* options will be ignored.
|
||||
`(string -> pkgs )`
|
||||
`pkgsForSystem` : A function that maps from architecture to pkgs, if specified
|
||||
this nixpkgs will be only imported once for each system. This improves
|
||||
performance, but all nipxkgs.* options will be ignored. `(string -> pkgs )`
|
||||
|
||||
## Inventory
|
||||
|
||||
`Inventory` is an abstract service layer for consistently configuring distributed services across machine boundaries.
|
||||
`Inventory` is an abstract service layer for consistently configuring
|
||||
distributed services across machine boundaries.
|
||||
|
||||
The following is the specification of the inventory in `cuelang`
|
||||
|
||||
|
@ -5,59 +5,110 @@ authors:
|
||||
- Qubasa
|
||||
date: 2024-05-25
|
||||
---
|
||||
|
||||
## Revolutionizing Server Management
|
||||
|
||||
In the world of server management, countless tools claim to offer seamless deployment of multiple machines. Yet, many fall short, leaving server admins and self-hosting enthusiasts grappling with complexity. Enter the Clan-Core Framework—a groundbreaking all in one solution designed to transform decentralized self-hosting into an effortless and scalable endeavor.
|
||||
In the world of server management, countless tools claim to offer seamless
|
||||
deployment of multiple machines. Yet, many fall short, leaving server admins and
|
||||
self-hosting enthusiasts grappling with complexity. Enter the Clan-Core
|
||||
Framework—a groundbreaking all in one solution designed to transform
|
||||
decentralized self-hosting into an effortless and scalable endeavor.
|
||||
|
||||
### The Power of Clan-Core
|
||||
|
||||
Imagine having the power to manage your servers with unparalleled ease, scaling your IT infrastructure like never before. Clan-Core empowers you to do just that. At its core, Clan-Core leverages a single Git repository to define everything about your machines. This central repository utilizes Nix or JSON files to specify configurations, including disk formatting, ensuring a streamlined and unified approach.
|
||||
Imagine having the power to manage your servers with unparalleled ease, scaling
|
||||
your IT infrastructure like never before. Clan-Core empowers you to do just
|
||||
that. At its core, Clan-Core leverages a single Git repository to define
|
||||
everything about your machines. This central repository utilizes Nix or JSON
|
||||
files to specify configurations, including disk formatting, ensuring a
|
||||
streamlined and unified approach.
|
||||
|
||||
### Simplified Deployment Process
|
||||
|
||||
With Clan-Core, the cumbersome task of bootstrapping a specific ISO is a thing of the past. All you need is SSH access to your Linux server. Clan-Core allows you to overwrite any existing Linux distribution live over SSH, eliminating time-consuming setup processes. This capability means you can deploy updates or new configurations swiftly and efficiently, maximizing uptime and minimizing hassle.
|
||||
With Clan-Core, the cumbersome task of bootstrapping a specific ISO is a thing
|
||||
of the past. All you need is SSH access to your Linux server. Clan-Core allows
|
||||
you to overwrite any existing Linux distribution live over SSH, eliminating
|
||||
time-consuming setup processes. This capability means you can deploy updates or
|
||||
new configurations swiftly and efficiently, maximizing uptime and minimizing
|
||||
hassle.
|
||||
|
||||
### Secure and Efficient Secret Management
|
||||
|
||||
Security is paramount in server management, and Clan-Core takes it seriously. Passwords and other sensitive information are encrypted within the Git repository, automatically decrypted during deployment. This not only ensures the safety of your secrets but also simplifies their management. Clan-Core supports sharing secrets with other admins, fostering collaboration and maintaining reproducibillity and security without sacrificing convenience.
|
||||
Security is paramount in server management, and Clan-Core takes it seriously.
|
||||
Passwords and other sensitive information are encrypted within the Git
|
||||
repository, automatically decrypted during deployment. This not only ensures the
|
||||
safety of your secrets but also simplifies their management. Clan-Core supports
|
||||
sharing secrets with other admins, fostering collaboration and maintaining
|
||||
reproducibillity and security without sacrificing convenience.
|
||||
|
||||
### Services as Apps
|
||||
|
||||
Setting up a service can be quite difficult. Many server adjustments need to be made, from setting up a database to adjusting webserver configurations and generating the correct private keys. However, Clan-Core aims to make setting up a service as easy as installing an application. Through Clan-Core's Module system, everything down to secrets can be automatically set up. This transforms the often daunting task of service setup into a smooth, automated process, making it accessible to all.
|
||||
Setting up a service can be quite difficult. Many server adjustments need to be
|
||||
made, from setting up a database to adjusting webserver configurations and
|
||||
generating the correct private keys. However, Clan-Core aims to make setting up
|
||||
a service as easy as installing an application. Through Clan-Core's Module
|
||||
system, everything down to secrets can be automatically set up. This transforms
|
||||
the often daunting task of service setup into a smooth, automated process,
|
||||
making it accessible to all.
|
||||
|
||||
### Decentralized Mesh VPN
|
||||
|
||||
Building on these features is a self-configuring decentralized mesh VPN that interconnects all your machines into a private darknet. This ensures that sensitive services, which might have too much attack surface to be hosted on the public internet, can still be made available privately without the need to worry about potential system compromise. By creating a secure, private network, Clan-Core offers an additional layer of protection for your most critical services.
|
||||
Building on these features is a self-configuring decentralized mesh VPN that
|
||||
interconnects all your machines into a private darknet. This ensures that
|
||||
sensitive services, which might have too much attack surface to be hosted on the
|
||||
public internet, can still be made available privately without the need to worry
|
||||
about potential system compromise. By creating a secure, private network,
|
||||
Clan-Core offers an additional layer of protection for your most critical
|
||||
services.
|
||||
|
||||
### Decentralized Domain Name System
|
||||
|
||||
Current DNS implementations are distributed but not truly decentralized. For Clan-Core, we implemented our own truly decentralized DNS module. This module uses simple flooding and caching algorithms to discover available domains inside the darknet. This approach ensures that your internal domain name system is robust, reliable, and independent of external control, enhancing the resilience and security of your infrastructure.
|
||||
|
||||
Current DNS implementations are distributed but not truly decentralized. For
|
||||
Clan-Core, we implemented our own truly decentralized DNS module. This module
|
||||
uses simple flooding and caching algorithms to discover available domains inside
|
||||
the darknet. This approach ensures that your internal domain name system is
|
||||
robust, reliable, and independent of external control, enhancing the resilience
|
||||
and security of your infrastructure.
|
||||
|
||||
### A New Era of Decentralized Self-Hosting
|
||||
|
||||
Clan-Core is more than just a tool; it's a paradigm shift in server management. By consolidating machine definitions, secrets and network configuration, into a single, secure repository, it transforms how you manage and scale your infrastructure. Whether you're a seasoned server admin or a self-hosting enthusiast, Clan-Core offers a powerful, user-friendly solution to take your capabilities to the next level.
|
||||
|
||||
Clan-Core is more than just a tool; it's a paradigm shift in server management.
|
||||
By consolidating machine definitions, secrets and network configuration, into a
|
||||
single, secure repository, it transforms how you manage and scale your
|
||||
infrastructure. Whether you're a seasoned server admin or a self-hosting
|
||||
enthusiast, Clan-Core offers a powerful, user-friendly solution to take your
|
||||
capabilities to the next level.
|
||||
|
||||
### Key Features of Clan-Core:
|
||||
|
||||
- **Unified Git Repository**: All machine configurations and secrets stored in a single repository.
|
||||
- **Live Overwrites**: Deploy configurations over existing Linux distributions via SSH.
|
||||
- **Automated Service Setup**: Easily set up services with Clan-Core's Module system.
|
||||
- **Decentralized Mesh VPN**: Securely interconnect all machines into a private darknet.
|
||||
- **Decentralized DNS**: Robust, independent DNS using flooding and caching algorithms.
|
||||
- **Automated Secret Management**: Encrypted secrets that are automatically decrypted during deployment.
|
||||
- **Unified Git Repository**: All machine configurations and secrets stored in a
|
||||
single repository.
|
||||
- **Live Overwrites**: Deploy configurations over existing Linux distributions
|
||||
via SSH.
|
||||
- **Automated Service Setup**: Easily set up services with Clan-Core's Module
|
||||
system.
|
||||
- **Decentralized Mesh VPN**: Securely interconnect all machines into a private
|
||||
darknet.
|
||||
- **Decentralized DNS**: Robust, independent DNS using flooding and caching
|
||||
algorithms.
|
||||
- **Automated Secret Management**: Encrypted secrets that are automatically
|
||||
decrypted during deployment.
|
||||
- **Collaboration Support**: Share secrets securely with other admins.
|
||||
|
||||
|
||||
## Clan-Cores Future
|
||||
|
||||
Our vision for Clan-Core extends far beyond being just another deployment tool. Clan-Core is a framework we've developed to achieve something much greater. We want to put the "personal" back into "personal computing." Our goal is for everyday users to fully customize their phones or laptops and create truly private spaces for friends and family.
|
||||
|
||||
Our first major step is to develop a Graphical User Interface (GUI) that makes configuring all this possible. Initial tests have shown that AI can be leveraged as an alternative to traditional GUIs. This paves the way for a future where people can simply talk to their computers, and they will configure themselves according to the users' wishes.
|
||||
|
||||
By adopting Clan, you're not just embracing a tool—you're joining a movement towards a more efficient, secure, and scalable approach to server management. Join us and revolutionize your IT infrastructure today.
|
||||
|
||||
|
||||
Our vision for Clan-Core extends far beyond being just another deployment tool.
|
||||
Clan-Core is a framework we've developed to achieve something much greater. We
|
||||
want to put the "personal" back into "personal computing." Our goal is for
|
||||
everyday users to fully customize their phones or laptops and create truly
|
||||
private spaces for friends and family.
|
||||
|
||||
Our first major step is to develop a Graphical User Interface (GUI) that makes
|
||||
configuring all this possible. Initial tests have shown that AI can be leveraged
|
||||
as an alternative to traditional GUIs. This paves the way for a future where
|
||||
people can simply talk to their computers, and they will configure themselves
|
||||
according to the users' wishes.
|
||||
|
||||
By adopting Clan, you're not just embracing a tool—you're joining a movement
|
||||
towards a more efficient, secure, and scalable approach to server management.
|
||||
Join us and revolutionize your IT infrastructure today.
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Hardware Installation
|
||||
|
||||
For installations on physical hardware, create a NixOS installer image and transfer it to a bootable USB drive as described below.
|
||||
For installations on physical hardware, create a NixOS installer image and
|
||||
transfer it to a bootable USB drive as described below.
|
||||
|
||||
## Creating a Bootable USB Drive on Linux
|
||||
|
||||
@ -26,40 +27,42 @@ curl -L https://github.com/nix-community/nixos-images/releases/download/nixos-un
|
||||
|
||||
2. Identify your flash drive with `lsblk`.
|
||||
|
||||
```shellSession
|
||||
lsblk
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
|
||||
sdb 8:0 1 117,2G 0 disk
|
||||
└─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO
|
||||
nvme0n1 259:0 0 1,8T 0 disk
|
||||
├─nvme0n1p1 259:1 0 512M 0 part /boot
|
||||
└─nvme0n1p2 259:2 0 1,8T 0 part
|
||||
└─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store
|
||||
```
|
||||
```shellSession
|
||||
lsblk
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
|
||||
sdb 8:0 1 117,2G 0 disk
|
||||
└─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO
|
||||
nvme0n1 259:0 0 1,8T 0 disk
|
||||
├─nvme0n1p1 259:1 0 512M 0 part /boot
|
||||
└─nvme0n1p2 259:2 0 1,8T 0 part
|
||||
└─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store
|
||||
```
|
||||
|
||||
In this case it's `sdb`
|
||||
In this case it's `sdb`
|
||||
|
||||
3. Ensure all partitions on the drive are unmounted. Replace `sdX` in the command below with your device identifier (like `sdb`, etc.):
|
||||
3. Ensure all partitions on the drive are unmounted. Replace `sdX` in the
|
||||
command below with your device identifier (like `sdb`, etc.):
|
||||
|
||||
```shellSession
|
||||
sudo umount /dev/sdb1
|
||||
```
|
||||
```shellSession
|
||||
sudo umount /dev/sdb1
|
||||
```
|
||||
|
||||
### Write the Image to the USB Drive
|
||||
|
||||
Use the `dd` utility to write the NixOS installer image to your USB drive:
|
||||
|
||||
```shellSession
|
||||
sudo dd bs=4M conv=fsync oflag=direct status=progress if=./nixos-installer-x86_64-linux.iso of=/dev/sd<X>
|
||||
```
|
||||
```shellSession
|
||||
sudo dd bs=4M conv=fsync oflag=direct status=progress if=./nixos-installer-x86_64-linux.iso of=/dev/sd<X>
|
||||
```
|
||||
|
||||
In this case, the USB device is `sdb` use `of=/dev/sdb`
|
||||
In this case, the USB device is `sdb` use `of=/dev/sdb`
|
||||
|
||||
### Boot and Connect
|
||||
|
||||
After writing the installer to the USB drive, use it to boot the target machine.
|
||||
|
||||
1. For this secure boot needs to be disabled. Go into your UEFI / Bios settings by pressing one of the keys outlined below while booting:
|
||||
1. For this secure boot needs to be disabled. Go into your UEFI / Bios settings
|
||||
by pressing one of the keys outlined below while booting:
|
||||
|
||||
- **Dell**: F2/Del (BIOS Setup)
|
||||
- **HP**: Esc (Startup Menu)
|
||||
@ -71,9 +74,11 @@ After writing the installer to the USB drive, use it to boot the target machine.
|
||||
- **Samsung**: F2 (BIOS Setup)
|
||||
- **MSI**: Del (BIOS Setup)
|
||||
- **Apple**: Option (Alt) Key (Boot Menu for Mac)
|
||||
- If your hardware was not listed read the manufacturers instructions how to enter the boot Menu/BIOS Setup.
|
||||
- If your hardware was not listed read the manufacturers instructions how to
|
||||
enter the boot Menu/BIOS Setup.
|
||||
|
||||
2. Inside the UEFI/Bios Menu go to `Security->Secure Boot` and disable secure boot
|
||||
2. Inside the UEFI/Bios Menu go to `Security->Secure Boot` and disable secure
|
||||
boot
|
||||
|
||||
3. Save your settings. Put in the USB stick and reboot.
|
||||
|
||||
@ -91,43 +96,46 @@ After writing the installer to the USB drive, use it to boot the target machine.
|
||||
- **Apple**: Option (Alt) Key (Boot Menu for Mac)
|
||||
- If your hardware was not listed read the manufacturers instructions how to enter the boot Menu/BIOS Setup.
|
||||
|
||||
|
||||
5. Select `NixOS` to boot into the clan installer
|
||||
|
||||
6. The installer will display an IP address and a root password, which you can use to connect via SSH.
|
||||
Alternatively you can also use the displayed QR code.
|
||||
6. The installer will display an IP address and a root password, which you can
|
||||
use to connect via SSH.\
|
||||
Alternatively you can also use the displayed QR code.
|
||||
|
||||
7. Set your keyboard language (i.e. `de` for German keyboards, default is English). Important for writing passwords correctly.
|
||||
7. Set your keyboard language (i.e. `de` for German keyboards, default is
|
||||
English). Important for writing passwords correctly.
|
||||
|
||||
```shellSession
|
||||
loadkeys de
|
||||
```
|
||||
```shellSession
|
||||
loadkeys de
|
||||
```
|
||||
|
||||
8. If you only have Wifi available, execute:
|
||||
|
||||
1. Bring up the `iwd` shell
|
||||
1. Bring up the `iwd` shell
|
||||
|
||||
```shellSession
|
||||
iwctl
|
||||
```
|
||||
```shellSession
|
||||
iwctl
|
||||
```
|
||||
|
||||
2. List available networks. Double press tab after station for autocompleting your wlan device. In this case `wlan0`
|
||||
2. List available networks. Double press tab after station for autocompleting
|
||||
your wlan device. In this case `wlan0`
|
||||
|
||||
```shellSession
|
||||
[iwd] station wlan0 get-networks
|
||||
```
|
||||
```shellSession
|
||||
[iwd] station wlan0 get-networks
|
||||
```
|
||||
|
||||
3. Connect to a Wifi network. Replace `SSID` with the wlan network name.
|
||||
3. Connect to a Wifi network. Replace `SSID` with the wlan network name.
|
||||
|
||||
```shellSession
|
||||
[iwd] station wlan0 connect SSID
|
||||
```
|
||||
```shellSession
|
||||
[iwd] station wlan0 connect SSID
|
||||
```
|
||||
|
||||
9. Now that you have internet re-execute the init script by pressing `Ctrl+D` or by executing:
|
||||
9. Now that you have internet re-execute the init script by pressing `Ctrl+D` or
|
||||
by executing:
|
||||
|
||||
```shellSession
|
||||
bash
|
||||
```
|
||||
```shellSession
|
||||
bash
|
||||
```
|
||||
|
||||
10. Connect to the machine over ssh
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
```bash
|
||||
clan secrets set mysecret
|
||||
> Paste your secret:
|
||||
> Paste your secret:
|
||||
```
|
||||
|
||||
!!! note
|
||||
As you type your secret won't be displayed. Press Enter to save the secret.
|
||||
!!! note As you type your secret won't be displayed. Press Enter to save the
|
||||
secret.
|
||||
|
||||
#### List all Secrets (list)
|
||||
|
||||
@ -18,7 +18,8 @@ clan secrets list
|
||||
|
||||
#### Assigning Access (set)
|
||||
|
||||
By default, secrets are encrypted for your key. To specify which users and machines can access a secret:
|
||||
By default, secrets are encrypted for your key. To specify which users and
|
||||
machines can access a secret:
|
||||
|
||||
```bash
|
||||
clan secrets set --machine <machine1> --machine <machine2> --user <user1> --user <user2> <secret_name>
|
||||
@ -54,13 +55,12 @@ Lists all added users
|
||||
clan secrets user list
|
||||
```
|
||||
|
||||
``` {.console, title="Example output", .no-copy}
|
||||
```{.console, title="Example output", .no-copy}
|
||||
jon
|
||||
sara
|
||||
```
|
||||
|
||||
!!! Question "Who can execute this command?"
|
||||
Everyone - completely public.
|
||||
!!! Question "Who can execute this command?" Everyone - completely public.
|
||||
|
||||
#### add user
|
||||
|
||||
@ -70,8 +70,7 @@ add a user
|
||||
clan secrets users add {username} {public-key}
|
||||
```
|
||||
|
||||
!!! Note
|
||||
Changes can be trusted by maintainer review in version control.
|
||||
!!! Note Changes can be trusted by maintainer review in version control.
|
||||
|
||||
#### get user
|
||||
|
||||
@ -81,7 +80,7 @@ get a user public key
|
||||
clan secrets users get {username}
|
||||
```
|
||||
|
||||
``` {.console, title="Example output", .no-copy}
|
||||
```{.console, title="Example output", .no-copy}
|
||||
age1zk8uzrte55wkg9lkqxu5x6twsj2ja4lehegks0cw4mkg6jv37d9qsjpt44
|
||||
```
|
||||
|
||||
@ -93,8 +92,7 @@ remove a user
|
||||
clan secrets users remove {username}
|
||||
```
|
||||
|
||||
!!! Note
|
||||
Changes can be trusted by maintainer review in version control.
|
||||
!!! Note Changes can be trusted by maintainer review in version control.
|
||||
|
||||
#### add-secret user
|
||||
|
||||
@ -104,15 +102,15 @@ Grants the user (`username`) access to the secret (`secret_name`)
|
||||
clan secrets users add-secret {username} {secret_name}
|
||||
```
|
||||
|
||||
!!! Note
|
||||
Requires the executor of the command to have access to the secret (`secret_name`).
|
||||
!!! Note Requires the executor of the command to have access to the secret
|
||||
(`secret_name`).
|
||||
|
||||
#### remove-secret user
|
||||
|
||||
remove the user (`username`) from accessing the secret (`secret_name`)
|
||||
|
||||
!!! Danger "Make sure at least one person has access."
|
||||
It might still be possible for the machine to access the secret. (See [machines](#machines))
|
||||
!!! Danger "Make sure at least one person has access." It might still be
|
||||
possible for the machine to access the secret. (See [machines](#machines))
|
||||
|
||||
We highly recommend to use version control such as `git` which allows you to rollback secrets in case anything gets messed up.
|
||||
|
||||
@ -120,8 +118,8 @@ remove the user (`username`) from accessing the secret (`secret_name`)
|
||||
clan secrets users remove-secret {username} {secret_name}
|
||||
```
|
||||
|
||||
!!! Question "Who can execute this command?"
|
||||
Requires the executor of the command to have access to the secret (`secret_name`).
|
||||
!!! Question "Who can execute this command?" Requires the executor of the
|
||||
command to have access to the secret (`secret_name`).
|
||||
|
||||
### Machines (Reference)
|
||||
|
||||
@ -134,7 +132,8 @@ clan secrets users remove-secret {username} {secret_name}
|
||||
|
||||
#### List machine
|
||||
|
||||
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
|
||||
New machines in Clan come with age keys stored in
|
||||
`./sops/machines/<machine_name>`. To list these machines:
|
||||
|
||||
```bash
|
||||
clan secrets machines list
|
||||
@ -142,13 +141,15 @@ clan secrets machines list
|
||||
|
||||
#### Add machine
|
||||
|
||||
For clan machines the machine key is generated automatically on demand if none exists.
|
||||
For clan machines the machine key is generated automatically on demand if none
|
||||
exists.
|
||||
|
||||
```bash
|
||||
clan secrets machines add <machine_name> <age_key>
|
||||
```
|
||||
|
||||
If you already have a device key and want to add it manually, see: [How to obtain a remote key](#obtain-remote-keys-manually)
|
||||
If you already have a device key and want to add it manually, see:
|
||||
[How to obtain a remote key](#obtain-remote-keys-manually)
|
||||
|
||||
#### get machine
|
||||
|
||||
@ -192,8 +193,7 @@ Assign users to a new group, e.g., `admins`:
|
||||
clan secrets groups add-user admins <username>
|
||||
```
|
||||
|
||||
!!! info
|
||||
The group is created if no such group existed before.
|
||||
!!! info The group is created if no such group existed before.
|
||||
|
||||
The user must exist in beforehand (See: [users](#users-reference))
|
||||
|
||||
@ -234,7 +234,8 @@ TODO
|
||||
|
||||
- [generate]() generate age key
|
||||
- [show]() show age public key
|
||||
- [update]() re-encrypt all secrets with current keys (useful when changing keys)
|
||||
- [update]() re-encrypt all secrets with current keys (useful when changing
|
||||
keys)
|
||||
|
||||
#### generate
|
||||
|
||||
@ -261,7 +262,8 @@ sops/
|
||||
│ └── <your_username>/
|
||||
```
|
||||
|
||||
The content of the secret is stored encrypted inside the `secret` file under `mysecret`.
|
||||
The content of the secret is stored encrypted inside the `secret` file under
|
||||
`mysecret`.
|
||||
|
||||
By default, secrets are encrypted with your key to ensure readability.
|
||||
|
||||
@ -273,8 +275,8 @@ To fetch a **SSH host key** from a preinstalled system:
|
||||
ssh-keyscan <domain_name> | nix shell nixpkgs#ssh-to-age -c ssh-to-age
|
||||
```
|
||||
|
||||
!!! Success
|
||||
This command converts the SSH key into an age key on the fly. Since this is the format used by the clan secrets backend.
|
||||
!!! Success This command converts the SSH key into an age key on the fly. Since
|
||||
this is the format used by the clan secrets backend.
|
||||
|
||||
Once added the **SSH host key** enables seamless integration of existing machines with clan.
|
||||
|
||||
@ -290,8 +292,10 @@ See also: [Machine reference](#machines-reference)
|
||||
|
||||
A NixOS machine will automatically import all secrets that are encrypted for the
|
||||
current machine. At runtime it will use the host key to decrypt all secrets into
|
||||
an in-memory, non-persistent filesystem using [sops-nix](https://github.com/Mic92/sops-nix).
|
||||
In your nixos configuration you can get a path to secrets like this `config.sops.secrets.<name>.path`. For example:
|
||||
an in-memory, non-persistent filesystem using
|
||||
[sops-nix](https://github.com/Mic92/sops-nix). In your nixos configuration you
|
||||
can get a path to secrets like this `config.sops.secrets.<name>.path`. For
|
||||
example:
|
||||
|
||||
```nix
|
||||
{ config, ...}: {
|
||||
@ -309,16 +313,23 @@ examples.
|
||||
|
||||
### Migration: Importing existing sops-based keys / sops-nix
|
||||
|
||||
`clan secrets` stores each secret in a single file, whereas [sops](https://github.com/Mic92/sops-nix) commonly allows to put all secrets in a yaml or json document.
|
||||
`clan secrets` stores each secret in a single file, whereas
|
||||
[sops](https://github.com/Mic92/sops-nix) commonly allows to put all secrets in
|
||||
a yaml or json document.
|
||||
|
||||
If you already happened to use sops-nix, you can migrate by using the `clan secrets import-sops` command by importing these files:
|
||||
If you already happened to use sops-nix, you can migrate by using the
|
||||
`clan secrets import-sops` command by importing these files:
|
||||
|
||||
```bash
|
||||
% clan secrets import-sops --prefix matchbox- --group admins --machine matchbox nixos/matchbox/secrets/secrets.yaml
|
||||
```
|
||||
|
||||
This will create secrets for each secret found in `nixos/matchbox/secrets/secrets.yaml` in a `./sops` folder of your repository.
|
||||
Each member of the group `admins` in this case will be able to decrypt the secrets with their respective key.
|
||||
This will create secrets for each secret found in
|
||||
`nixos/matchbox/secrets/secrets.yaml` in a `./sops` folder of your repository.
|
||||
Each member of the group `admins` in this case will be able to decrypt the
|
||||
secrets with their respective key.
|
||||
|
||||
Since our clan secret module will auto-import secrets that are encrypted for a particular nixos machine,
|
||||
you can now remove `sops.secrets.<secrets> = { };` unless you need to specify more options for the secret like owner/group of the secret file.
|
||||
Since our clan secret module will auto-import secrets that are encrypted for a
|
||||
particular nixos machine, you can now remove `sops.secrets.<secrets> = { };`
|
||||
unless you need to specify more options for the secret like owner/group of the
|
||||
secret file.
|
||||
|
@ -2,23 +2,27 @@
|
||||
|
||||
## Introduction to Backups
|
||||
|
||||
When you're managing your own services, creating regular backups is crucial to ensure your data's safety.
|
||||
This guide introduces you to Clan's built-in backup functionalities.
|
||||
Clan supports backing up your data to both local storage devices (like USB drives) and remote servers, using well-known tools like borgbackup and rsnapshot.
|
||||
We might add more options in the future, but for now, let's dive into how you can secure your data.
|
||||
When you're managing your own services, creating regular backups is crucial to
|
||||
ensure your data's safety. This guide introduces you to Clan's built-in backup
|
||||
functionalities. Clan supports backing up your data to both local storage
|
||||
devices (like USB drives) and remote servers, using well-known tools like
|
||||
borgbackup and rsnapshot. We might add more options in the future, but for now,
|
||||
let's dive into how you can secure your data.
|
||||
|
||||
## Backing Up Locally with Localbackup
|
||||
|
||||
### What is Localbackup?
|
||||
|
||||
Localbackup lets you backup your data onto physical storage devices connected to your computer,
|
||||
such as USB hard drives or network-attached storage. It uses a tool called rsnapshot for this purpose.
|
||||
Localbackup lets you backup your data onto physical storage devices connected to
|
||||
your computer, such as USB hard drives or network-attached storage. It uses a
|
||||
tool called rsnapshot for this purpose.
|
||||
|
||||
### Setting Up Localbackup
|
||||
|
||||
1. **Identify Your Backup Device:**
|
||||
|
||||
First, figure out which device you'll use for backups. You can see all connected devices by running this command in your terminal:
|
||||
First, figure out which device you'll use for backups. You can see all connected
|
||||
devices by running this command in your terminal:
|
||||
|
||||
```bash
|
||||
lsblk --output NAME,PTUUID,FSTYPE,SIZE,MOUNTPOINT
|
||||
@ -29,7 +33,8 @@ Look for the device you intend to use for backups and note its details.
|
||||
2. **Configure Your Backup Device:**
|
||||
|
||||
Once you've identified your device, you'll need to add it to your configuration.
|
||||
Here's an example NixOS configuration for a device located at `/dev/sda2` with an `ext4` filesystem:
|
||||
Here's an example NixOS configuration for a device located at `/dev/sda2` with
|
||||
an `ext4` filesystem:
|
||||
|
||||
```nix
|
||||
{
|
||||
@ -41,9 +46,11 @@ Here's an example NixOS configuration for a device located at `/dev/sda2` with a
|
||||
}
|
||||
```
|
||||
|
||||
Replace `/dev/sda2` with your device and `/mnt/hdd` with your preferred mount point.
|
||||
Replace `/dev/sda2` with your device and `/mnt/hdd` with your preferred mount
|
||||
point.
|
||||
|
||||
3. **Set Backup Targets:** Next, define where on your device you'd like the backups to be stored:
|
||||
3. **Set Backup Targets:** Next, define where on your device you'd like the
|
||||
backups to be stored:
|
||||
|
||||
```nix
|
||||
{
|
||||
@ -66,22 +73,23 @@ Replace `/dev/sda2` with your device and `/mnt/hdd` with your preferred mount po
|
||||
|
||||
5. **Listing Backups:** To see available backups, run:
|
||||
|
||||
```bash
|
||||
clan backups list mymachine
|
||||
```
|
||||
```bash
|
||||
clan backups list mymachine
|
||||
```
|
||||
|
||||
## Remote Backups with Borgbackup
|
||||
|
||||
### Overview of Borgbackup
|
||||
|
||||
Borgbackup splits the backup process into two parts: a backup client that sends data to a backup server.
|
||||
The server stores the backups.
|
||||
Borgbackup splits the backup process into two parts: a backup client that sends
|
||||
data to a backup server. The server stores the backups.
|
||||
|
||||
### Setting Up the Borgbackup Client
|
||||
|
||||
1. **Specify Backup Server:**
|
||||
|
||||
Start by indicating where your backup data should be sent. Replace `hostname` with your server's address:
|
||||
Start by indicating where your backup data should be sent. Replace `hostname`
|
||||
with your server's address:
|
||||
|
||||
```nix
|
||||
{
|
||||
@ -95,7 +103,8 @@ Start by indicating where your backup data should be sent. Replace `hostname` wi
|
||||
|
||||
2. **Select Folders to Backup:**
|
||||
|
||||
Decide which folders you want to back up. For example, to backup your home and root directories:
|
||||
Decide which folders you want to back up. For example, to backup your home and
|
||||
root directories:
|
||||
|
||||
```nix
|
||||
{ clan.core.state.userdata.folders = [ "/home" "/root" ]; }
|
||||
@ -103,13 +112,15 @@ Decide which folders you want to back up. For example, to backup your home and r
|
||||
|
||||
3. **Generate Backup Credentials:**
|
||||
|
||||
Run `clan facts generate <yourmachine>` to prepare your machine for backup, creating necessary SSH keys and credentials.
|
||||
Run `clan facts generate <yourmachine>` to prepare your machine for backup,
|
||||
creating necessary SSH keys and credentials.
|
||||
|
||||
### Setting Up the Borgbackup Server
|
||||
|
||||
1. **Configure Backup Repository:**
|
||||
|
||||
On the server where backups will be stored, enable the SSH daemon and set up a repository for each client:
|
||||
On the server where backups will be stored, enable the SSH daemon and set up a
|
||||
repository for each client:
|
||||
|
||||
```nix
|
||||
{
|
||||
@ -124,13 +135,15 @@ On the server where backups will be stored, enable the SSH daemon and set up a r
|
||||
|
||||
Ensure the path to the public key is correct.
|
||||
|
||||
2. **Update Your Systems:** Apply your changes by running `clan machines update` to both the server and your client
|
||||
2. **Update Your Systems:** Apply your changes by running `clan machines update`
|
||||
to both the server and your client
|
||||
|
||||
### Managing Backups
|
||||
|
||||
- **Scheduled Backups:**
|
||||
|
||||
Backups are automatically performed nightly. To check the next scheduled backup, use:
|
||||
Backups are automatically performed nightly. To check the next scheduled
|
||||
backup, use:
|
||||
|
||||
```bash
|
||||
systemctl list-timers | grep -E 'NEXT|borg'
|
||||
|
@ -50,30 +50,31 @@ Adding or configuring a new machine requires two simple steps:
|
||||
|
||||
1. Find the remote disk id by executing:
|
||||
|
||||
```bash title="setup computer"
|
||||
ssh root@flash-installer.local lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT
|
||||
```
|
||||
```bash title="setup computer"
|
||||
ssh root@flash-installer.local lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT
|
||||
```
|
||||
|
||||
!!! Note
|
||||
Replace `flash-installer.local` with the IP address of the machine if you don't have the avahi service running which resolves mDNS local domains.
|
||||
!!! Note Replace `flash-installer.local` with the IP address of the machine
|
||||
if you don't have the avahi service running which resolves mDNS local
|
||||
domains.
|
||||
|
||||
Which should show something like:
|
||||
Which should show something like:
|
||||
|
||||
```{.shellSession hl_lines="6" .no-copy}
|
||||
NAME ID-LINK FSTYPE SIZE MOUNTPOINT
|
||||
sda usb-ST_16GB_AA6271026J1000000509-0:0 14.9G
|
||||
├─sda1 usb-ST_16GB_AA6271026J1000000509-0:0-part1 1M
|
||||
├─sda2 usb-ST_16GB_AA6271026J1000000509-0:0-part2 vfat 100M /boot
|
||||
└─sda3 usb-ST_16GB_AA6271026J1000000509-0:0-part3 ext4 2.9G /
|
||||
nvme0n1 nvme-eui.e8238fa6bf530001001b448b4aec2929 476.9G
|
||||
├─nvme0n1p1 nvme-eui.e8238fa6bf530001001b448b4aec2929-part1 vfat 512M
|
||||
├─nvme0n1p2 nvme-eui.e8238fa6bf530001001b448b4aec2929-part2 ext4 459.6G
|
||||
└─nvme0n1p3 nvme-eui.e8238fa6bf530001001b448b4aec2929-part3 swap 16.8G
|
||||
```
|
||||
```{.shellSession hl_lines="6" .no-copy}
|
||||
NAME ID-LINK FSTYPE SIZE MOUNTPOINT
|
||||
sda usb-ST_16GB_AA6271026J1000000509-0:0 14.9G
|
||||
├─sda1 usb-ST_16GB_AA6271026J1000000509-0:0-part1 1M
|
||||
├─sda2 usb-ST_16GB_AA6271026J1000000509-0:0-part2 vfat 100M /boot
|
||||
└─sda3 usb-ST_16GB_AA6271026J1000000509-0:0-part3 ext4 2.9G /
|
||||
nvme0n1 nvme-eui.e8238fa6bf530001001b448b4aec2929 476.9G
|
||||
├─nvme0n1p1 nvme-eui.e8238fa6bf530001001b448b4aec2929-part1 vfat 512M
|
||||
├─nvme0n1p2 nvme-eui.e8238fa6bf530001001b448b4aec2929-part2 ext4 459.6G
|
||||
└─nvme0n1p3 nvme-eui.e8238fa6bf530001001b448b4aec2929-part3 swap 16.8G
|
||||
```
|
||||
|
||||
1. Edit the following fields inside the `flake.nix`
|
||||
|
||||
=== "**buildClan**"
|
||||
=== "**buildClan**"
|
||||
|
||||
```nix title="clan-core.lib.buildClan" hl_lines="18 23"
|
||||
buildClan {
|
||||
@ -106,7 +107,7 @@ Adding or configuring a new machine requires two simple steps:
|
||||
}
|
||||
```
|
||||
|
||||
=== "**flakeParts**"
|
||||
=== "**flakeParts**"
|
||||
|
||||
```nix title="clan-core.flakeModules.default" hl_lines="18 23"
|
||||
clan = {
|
||||
@ -139,36 +140,40 @@ Adding or configuring a new machine requires two simple steps:
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
!!! Info "Replace `__CHANGE_ME__` with the appropriate identifier, such as `nvme-eui.e8238fa6bf530001001b448b4aec2929`"
|
||||
!!! Info "Replace `__YOUR_SSH_KEY__` with your personal key, like `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILoMI0NC5eT9pHlQExrvR5ASV3iW9+BXwhfchq0smXUJ jon@jon-desktop`"
|
||||
!!! Info "Replace `__CHANGE_ME__` with the appropriate identifier, such as
|
||||
`nvme-eui.e8238fa6bf530001001b448b4aec2929`" !!! Info "Replace
|
||||
`__YOUR_SSH_KEY__` with your personal key, like
|
||||
`ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILoMI0NC5eT9pHlQExrvR5ASV3iW9+BXwhfchq0smXUJ jon@jon-desktop`"
|
||||
|
||||
These steps will allow you to update your machine later.
|
||||
|
||||
### Step 2: Detect Drivers
|
||||
|
||||
Generate the `hardware-configuration.nix` file for your machine by executing the following command:
|
||||
Generate the `hardware-configuration.nix` file for your machine by executing the
|
||||
following command:
|
||||
|
||||
```bash
|
||||
clan machines hw-generate [MACHINE_NAME] [HOSTNAME]
|
||||
```
|
||||
|
||||
replace `[MACHINE_NAME]` with the name of the machine i.e. `jon` and `[HOSTNAME]` with the `ip_adress` or `hostname` of the machine within the network. i.e. `flash-installer.local`
|
||||
replace `[MACHINE_NAME]` with the name of the machine i.e. `jon` and
|
||||
`[HOSTNAME]` with the `ip_adress` or `hostname` of the machine within the
|
||||
network. i.e. `flash-installer.local`
|
||||
|
||||
!!! Example
|
||||
```bash
|
||||
clan machines hw-generate jon flash-installer.local
|
||||
```
|
||||
!!! Example `bash clan machines hw-generate jon flash-installer.local`
|
||||
|
||||
This command connects to `flash-installer.local` as `root`, runs `nixos-generate-config` to detect hardware configurations (excluding filesystems), and writes them to `machines/jon/hardware-configuration.nix`.
|
||||
|
||||
### Step 3: Custom Disk Formatting
|
||||
|
||||
In `./modules/disko.nix`, a simple `ext4` disk partitioning scheme is defined for the Disko module. For more complex disk partitioning setups, refer to the [Disko examples](https://github.com/nix-community/disko/tree/master/example).
|
||||
In `./modules/disko.nix`, a simple `ext4` disk partitioning scheme is defined
|
||||
for the Disko module. For more complex disk partitioning setups, refer to the
|
||||
[Disko examples](https://github.com/nix-community/disko/tree/master/example).
|
||||
|
||||
### Step 4: Custom Configuration
|
||||
|
||||
Modify `./machines/jon/configuration.nix` to personalize the system settings according to your requirements.
|
||||
Modify `./machines/jon/configuration.nix` to personalize the system settings
|
||||
according to your requirements.
|
||||
|
||||
### Step 5: Check Configuration
|
||||
|
||||
@ -178,13 +183,13 @@ Validate your configuration by running:
|
||||
nix flake check
|
||||
```
|
||||
|
||||
This command helps ensure that your system configuration is correct and free from errors.
|
||||
This command helps ensure that your system configuration is correct and free
|
||||
from errors.
|
||||
|
||||
!!! Note
|
||||
|
||||
Integrate this step into your [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration) workflow to ensure that only valid Nix configurations are merged into your codebase. This practice helps maintain system stability and reduces integration issues.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Whats next?
|
||||
|
@ -1,14 +1,19 @@
|
||||
# Deploy Machine
|
||||
|
||||
Integrating a new machine into your Clan environment is an easy yet flexible process, allowing for a straight forward management of multiple NixOS configurations.
|
||||
Integrating a new machine into your Clan environment is an easy yet flexible
|
||||
process, allowing for a straight forward management of multiple NixOS
|
||||
configurations.
|
||||
|
||||
We'll walk you through adding a new computer to your Clan.
|
||||
|
||||
## Installing a New Machine
|
||||
|
||||
Clan CLI, in conjunction with [nixos-anywhere](https://github.com/nix-community/nixos-anywhere), provides a seamless method for installing NixOS on various machines.
|
||||
Clan CLI, in conjunction with
|
||||
[nixos-anywhere](https://github.com/nix-community/nixos-anywhere), provides a
|
||||
seamless method for installing NixOS on various machines.
|
||||
|
||||
This process involves preparing a suitable hardware and disk partitioning configuration and ensuring the target machine is accessible via SSH.
|
||||
This process involves preparing a suitable hardware and disk partitioning
|
||||
configuration and ensuring the target machine is accessible via SSH.
|
||||
|
||||
### Step 0. Prerequisites
|
||||
|
||||
@ -35,11 +40,10 @@ This process involves preparing a suitable hardware and disk partitioning config
|
||||
|
||||
- Any cloud machine if it is reachable via SSH and supports `kexec`.
|
||||
|
||||
|
||||
### Step 1. Deploy the machine
|
||||
|
||||
**Finally deployment time!** Use the following command to build and deploy the image via SSH onto your machine.
|
||||
|
||||
**Finally deployment time!** Use the following command to build and deploy the
|
||||
image via SSH onto your machine.
|
||||
|
||||
=== "**Image Installer**"
|
||||
|
||||
@ -136,21 +140,20 @@ This process involves preparing a suitable hardware and disk partitioning config
|
||||
clan machines install [MACHINE] <target_host>
|
||||
```
|
||||
|
||||
|
||||
If you are using our template `[MACHINE]` would be `jon`
|
||||
|
||||
|
||||
!!! success
|
||||
Your machine is all set up. 🎉 🚀
|
||||
|
||||
!!! success Your machine is all set up. 🎉 🚀
|
||||
|
||||
## Update Your Machines
|
||||
|
||||
Clan CLI enables you to remotely update your machines over SSH. This requires setting up a target address for each target machine.
|
||||
Clan CLI enables you to remotely update your machines over SSH. This requires
|
||||
setting up a target address for each target machine.
|
||||
|
||||
### Setting the Target Host
|
||||
|
||||
Replace `root@jon` with the actual hostname or IP address of your target machine:
|
||||
Replace `root@jon` with the actual hostname or IP address of your target
|
||||
machine:
|
||||
|
||||
```{.nix hl_lines="9" .no-copy}
|
||||
buildClan {
|
||||
# ...
|
||||
@ -166,10 +169,8 @@ buildClan {
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
!!! warning
|
||||
The use of `root@` in the target address implies SSH access as the `root` user.
|
||||
Ensure that the root login is secured and only used when necessary.
|
||||
!!! warning The use of `root@` in the target address implies SSH access as the
|
||||
`root` user. Ensure that the root login is secured and only used when necessary.
|
||||
|
||||
### Updating Machine Configurations
|
||||
|
||||
@ -179,7 +180,8 @@ Execute the following command to update the specified machine:
|
||||
clan machines update jon
|
||||
```
|
||||
|
||||
You can also update all configured machines simultaneously by omitting the machine name:
|
||||
You can also update all configured machines simultaneously by omitting the
|
||||
machine name:
|
||||
|
||||
```bash
|
||||
clan machines update
|
||||
@ -187,10 +189,9 @@ clan machines update
|
||||
|
||||
### Setting a Build Host
|
||||
|
||||
If the machine does not have enough resources to run the NixOS evaluation or build itself,
|
||||
it is also possible to specify a build host instead.
|
||||
During an update, the cli will ssh into the build host and run `nixos-rebuild` from there.
|
||||
|
||||
If the machine does not have enough resources to run the NixOS evaluation or
|
||||
build itself, it is also possible to specify a build host instead. During an
|
||||
update, the cli will ssh into the build host and run `nixos-rebuild` from there.
|
||||
|
||||
```{.nix hl_lines="5" .no-copy}
|
||||
buildClan {
|
||||
@ -205,8 +206,9 @@ buildClan {
|
||||
|
||||
### Excluding a machine from `clan machine update`
|
||||
|
||||
To exclude machines from being updated when running `clan machines update` without any machines specified,
|
||||
one can set the `clan.deployment.requireExplicitUpdate` option to true:
|
||||
To exclude machines from being updated when running `clan machines update`
|
||||
without any machines specified, one can set the
|
||||
`clan.deployment.requireExplicitUpdate` option to true:
|
||||
|
||||
```{.nix hl_lines="5" .no-copy}
|
||||
buildClan {
|
||||
@ -219,7 +221,8 @@ buildClan {
|
||||
};
|
||||
```
|
||||
|
||||
This is useful for machines that are not always online or are not part of the regular update cycle.
|
||||
This is useful for machines that are not always online or are not part of the
|
||||
regular update cycle.
|
||||
|
||||
---
|
||||
|
||||
@ -228,4 +231,3 @@ This is useful for machines that are not always online or are not part of the re
|
||||
- [**Mesh VPN**](./mesh-vpn.md): Configuring a secure mesh network.
|
||||
|
||||
---
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
# Clan with `flake-parts`
|
||||
|
||||
Clan supports integration with [flake.parts](https://flake.parts/) a tool which allows composing nixos modules in a modular way.
|
||||
Clan supports integration with [flake.parts](https://flake.parts/) a tool which
|
||||
allows composing nixos modules in a modular way.
|
||||
|
||||
Here's how to set up Clan using `nix flakes` and `flake-parts`.
|
||||
|
||||
## 1. Update Your Flake Inputs
|
||||
|
||||
To begin, you'll need to add `flake-parts` as a new dependency in your flake's inputs. This is alongside the already existing dependencies, such as `clan-core` and `nixpkgs`. Here's how you can update your `flake.nix` file:
|
||||
To begin, you'll need to add `flake-parts` as a new dependency in your flake's
|
||||
inputs. This is alongside the already existing dependencies, such as `clan-core`
|
||||
and `nixpkgs`. Here's how you can update your `flake.nix` file:
|
||||
|
||||
```nix
|
||||
# flake.nix
|
||||
@ -28,19 +31,22 @@ inputs = {
|
||||
|
||||
## 2. Import Clan-Core Flake Module
|
||||
|
||||
After updating your flake inputs, the next step is to import the `clan-core` flake module. This will make the [clan options](https://git.clan.lol/clan/clan-core/src/branch/main/flakeModules/clan.nix) available within `mkFlake`.
|
||||
After updating your flake inputs, the next step is to import the `clan-core`
|
||||
flake module. This will make the
|
||||
[clan options](https://git.clan.lol/clan/clan-core/src/branch/main/flakeModules/clan.nix)
|
||||
available within `mkFlake`.
|
||||
|
||||
```nix
|
||||
outputs =
|
||||
inputs@{ flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } (
|
||||
{
|
||||
#
|
||||
imports = [
|
||||
inputs.clan-core.flakeModules.default
|
||||
];
|
||||
}
|
||||
);
|
||||
outputs =
|
||||
inputs@{ flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } (
|
||||
{
|
||||
#
|
||||
imports = [
|
||||
inputs.clan-core.flakeModules.default
|
||||
];
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### 3. Configure Clan Settings and Define Machines
|
||||
@ -91,7 +97,8 @@ Below is a guide on how to structure this in your flake.nix:
|
||||
});
|
||||
```
|
||||
|
||||
For detailed information about configuring `flake-parts` and the available options within Clan,
|
||||
refer to the Clan module documentation located [here](https://git.clan.lol/clan/clan-core/src/branch/main/flakeModules/clan.nix).
|
||||
For detailed information about configuring `flake-parts` and the available
|
||||
options within Clan, refer to the Clan module documentation located
|
||||
[here](https://git.clan.lol/clan/clan-core/src/branch/main/flakeModules/clan.nix).
|
||||
|
||||
---
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
Our installer image simplifies the process of performing remote installations.
|
||||
|
||||
Follow our step-by-step guide to create and transfer this image onto a bootable USB drive.
|
||||
Follow our step-by-step guide to create and transfer this image onto a bootable
|
||||
USB drive.
|
||||
|
||||
!!! info
|
||||
If you already have a NixOS machine you can ssh into (in the cloud for example) you can skip this chapter and go directly to [Configure Machines](configure.md).
|
||||
!!! info If you already have a NixOS machine you can ssh into (in the cloud for
|
||||
example) you can skip this chapter and go directly to
|
||||
[Configure Machines](configure.md).
|
||||
|
||||
### Step 0. Prerequisites
|
||||
|
||||
@ -18,29 +20,30 @@ Follow our step-by-step guide to create and transfer this image onto a bootable
|
||||
|
||||
2. Identify your flash drive with `lsblk`:
|
||||
|
||||
```shellSession
|
||||
lsblk
|
||||
```
|
||||
```shellSession
|
||||
lsblk
|
||||
```
|
||||
|
||||
```{.shellSession hl_lines="2" .no-copy}
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
|
||||
sdb 8:0 1 117,2G 0 disk
|
||||
└─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO
|
||||
nvme0n1 259:0 0 1,8T 0 disk
|
||||
├─nvme0n1p1 259:1 0 512M 0 part /boot
|
||||
└─nvme0n1p2 259:2 0 1,8T 0 part
|
||||
└─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store
|
||||
```
|
||||
```{.shellSession hl_lines="2" .no-copy}
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
|
||||
sdb 8:0 1 117,2G 0 disk
|
||||
└─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO
|
||||
nvme0n1 259:0 0 1,8T 0 disk
|
||||
├─nvme0n1p1 259:1 0 512M 0 part /boot
|
||||
└─nvme0n1p2 259:2 0 1,8T 0 part
|
||||
└─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store
|
||||
```
|
||||
|
||||
!!! Info "In this case the USB device is `sdb`"
|
||||
!!! Info "In this case the USB device is `sdb`"
|
||||
|
||||
3. Ensure all partitions on the drive are unmounted. Replace `sdb1` in the command below with your device identifier (like `sdc1`, etc.):
|
||||
3. Ensure all partitions on the drive are unmounted. Replace `sdb1` in the
|
||||
command below with your device identifier (like `sdc1`, etc.):
|
||||
|
||||
```shellSession
|
||||
sudo umount /dev/sdb1
|
||||
```
|
||||
=== "**Linux OS**"
|
||||
### Step 2. Flash Custom Installer
|
||||
|
||||
=== "**Linux OS**" ### Step 2. Flash Custom Installer
|
||||
|
||||
Using clan flash enables the inclusion of ssh public keys.
|
||||
It also allows to set language and keymap currently in the installer image.
|
||||
@ -62,10 +65,7 @@ sudo umount /dev/sdb1
|
||||
|
||||
The `clan flash` utility will erase the disk. Make sure to specify the correct device
|
||||
|
||||
|
||||
|
||||
=== "**Other OS**"
|
||||
### Step 2. Download Generic Installer
|
||||
=== "**Other OS**" ### Step 2. Download Generic Installer
|
||||
|
||||
```shellSession
|
||||
wget https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-x86_64-linux.iso
|
||||
@ -91,21 +91,19 @@ sudo umount /dev/sdb1
|
||||
|
||||
After writing the installer to the USB drive, use it to boot the target machine.
|
||||
|
||||
!!! info
|
||||
Plug it into the target machine and select the USB drive as a temporary boot device.
|
||||
!!! info Plug it into the target machine and select the USB drive as a temporary
|
||||
boot device.
|
||||
|
||||
??? tip "Here you can find the key combinations for selection used by most vendors."
|
||||
- **Dell**: F12 (Boot Menu), F2/Del (BIOS Setup)
|
||||
- **HP**: F9 (Boot Menu), Esc (Startup Menu)
|
||||
- **Lenovo**: F12 (ThinkPad Boot Menu), F2/Fn+F2/Novo Button (IdeaPad Boot Menu/BIOS Setup)
|
||||
- **Acer**: F12 (Boot Menu), F2/Del (BIOS Setup)
|
||||
- **Asus**: F8/Esc (Boot Menu), F2/Del (BIOS Setup)
|
||||
- **Toshiba**: F12/F2 (Boot Menu), Esc then F12 (Alternate Method)
|
||||
- **Sony**: F11/Assist Button (Boot Menu/Recovery Options)
|
||||
- **Samsung**: F2/F12/Esc (Boot Menu), F2 (BIOS Setup)
|
||||
- **MSI**: F11 (Boot Menu), Del (BIOS Setup)
|
||||
- **Apple**: Option (Alt) Key (Boot Menu for Mac)
|
||||
- If your hardware was not listed read the manufacturers instructions how to enter the boot Menu/BIOS Setup.
|
||||
??? tip "Here you can find the key combinations for selection used by most
|
||||
vendors." - **Dell**: F12 (Boot Menu), F2/Del (BIOS Setup) - **HP**: F9 (Boot
|
||||
Menu), Esc (Startup Menu) - **Lenovo**: F12 (ThinkPad Boot Menu), F2/Fn+F2/Novo
|
||||
Button (IdeaPad Boot Menu/BIOS Setup) - **Acer**: F12 (Boot Menu), F2/Del (BIOS
|
||||
Setup) - **Asus**: F8/Esc (Boot Menu), F2/Del (BIOS Setup) - **Toshiba**: F12/F2
|
||||
(Boot Menu), Esc then F12 (Alternate Method) - **Sony**: F11/Assist Button (Boot
|
||||
Menu/Recovery Options) - **Samsung**: F2/F12/Esc (Boot Menu), F2 (BIOS Setup) -
|
||||
**MSI**: F11 (Boot Menu), Del (BIOS Setup) - **Apple**: Option (Alt) Key (Boot
|
||||
Menu for Mac) - If your hardware was not listed read the manufacturers
|
||||
instructions how to enter the boot Menu/BIOS Setup.
|
||||
|
||||
**During Boot**
|
||||
|
||||
@ -113,12 +111,13 @@ Select `NixOS` to boot into the clan installer.
|
||||
|
||||
**After Booting**
|
||||
|
||||
For deploying your configuration the machine needs to be connected via LAN (recommended).
|
||||
|
||||
For deploying your configuration the machine needs to be connected via LAN
|
||||
(recommended).
|
||||
|
||||
## (Optional) Connect to Wifi
|
||||
|
||||
If you don't have access via LAN the Installer offers support for connecting via Wifi.
|
||||
If you don't have access via LAN the Installer offers support for connecting via
|
||||
Wifi.
|
||||
|
||||
```shellSession
|
||||
iwctl
|
||||
@ -159,8 +158,8 @@ IPv4 address 192.168.188.50 (Your new local ip)
|
||||
|
||||
Press ++ctrl+d++ to exit `IWD`.
|
||||
|
||||
!!! Important
|
||||
Press ++ctrl+d++ **again** to update the displayed QR code and connection information.
|
||||
!!! Important Press ++ctrl+d++ **again** to update the displayed QR code and
|
||||
connection information.
|
||||
|
||||
You're all set up
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
# Mesh VPN
|
||||
|
||||
This guide provides detailed instructions for configuring
|
||||
[ZeroTier VPN](https://zerotier.com) within Clan. Follow the
|
||||
outlined steps to set up a machine as a VPN controller (`<CONTROLLER>`) and to
|
||||
include a new machine into the VPN.
|
||||
[ZeroTier VPN](https://zerotier.com) within Clan. Follow the outlined steps to
|
||||
set up a machine as a VPN controller (`<CONTROLLER>`) and to include a new
|
||||
machine into the VPN.
|
||||
|
||||
## Concept
|
||||
|
||||
By default all machines within one clan are connected via a chosen network technology.
|
||||
By default all machines within one clan are connected via a chosen network
|
||||
technology.
|
||||
|
||||
```{.no-copy}
|
||||
Clan
|
||||
@ -16,13 +17,15 @@ Clan
|
||||
Node B
|
||||
```
|
||||
|
||||
If you select multiple network technologies at the same time. e.g. (zerotier + yggdrassil)
|
||||
You must choose one of them as primary network and the machines are always connected via the primary network.
|
||||
If you select multiple network technologies at the same time. e.g. (zerotier +
|
||||
yggdrassil) You must choose one of them as primary network and the machines are
|
||||
always connected via the primary network.
|
||||
|
||||
## 1. Set-Up the VPN Controller
|
||||
|
||||
The VPN controller is initially essential for providing configuration to new
|
||||
peers. Once addresses are allocated, the controller's continuous operation is not essential.
|
||||
peers. Once addresses are allocated, the controller's continuous operation is
|
||||
not essential.
|
||||
|
||||
1. **Designate a Machine**: Label a machine as the VPN controller in the clan,
|
||||
referred to as `<CONTROLLER>` henceforth in this guide.
|
||||
@ -44,8 +47,9 @@ peers. Once addresses are allocated, the controller's continuous operation is no
|
||||
|
||||
To introduce a new machine to the VPN, adhere to the following steps:
|
||||
|
||||
1. **Update Configuration**: On the new machine, incorporate the following to its
|
||||
configuration, substituting `<CONTROLLER>` with the controller machine name:
|
||||
1. **Update Configuration**: On the new machine, incorporate the following to
|
||||
its configuration, substituting `<CONTROLLER>` with the controller machine
|
||||
name:
|
||||
```nix
|
||||
{ config, ... }: {
|
||||
clan.networking.zerotier.networkId = builtins.readFile (config.clan.core.clanDir + "/machines/<CONTROLLER>/facts/zerotier-network-id");
|
||||
@ -57,24 +61,15 @@ To introduce a new machine to the VPN, adhere to the following steps:
|
||||
```
|
||||
Replace `<NEW_MACHINE>` with the designated new machine name.
|
||||
|
||||
!!! Note "For Private Networks"
|
||||
1. **Retrieve the ZeroTier ID**: On the `new_machine`, execute:
|
||||
```bash
|
||||
$ sudo zerotier-cli info
|
||||
```
|
||||
Example Output:
|
||||
```{.console, .no-copy}
|
||||
200 info d2c71971db 1.12.1 OFFLINE
|
||||
```
|
||||
, where `d2c71971db` is the ZeroTier ID.
|
||||
2. **Authorize the New Machine on the Controller**: On the controller machine,
|
||||
execute:
|
||||
```bash
|
||||
$ sudo zerotier-members allow <ID>
|
||||
```
|
||||
Substitute `<ID>` with the ZeroTier ID obtained previously.
|
||||
!!! Note "For Private Networks" 1. **Retrieve the ZeroTier ID**: On the
|
||||
`new_machine`, execute: `bash $ sudo zerotier-cli info` Example Output:
|
||||
`{.console, .no-copy} 200 info d2c71971db 1.12.1 OFFLINE` , where
|
||||
`d2c71971db` is the ZeroTier ID. 2. **Authorize the New Machine on the
|
||||
Controller**: On the controller machine, execute:
|
||||
`bash $ sudo zerotier-members allow <ID>` Substitute `<ID>` with the ZeroTier
|
||||
ID obtained previously.
|
||||
|
||||
2. **Verify Connection**: On the `new_machine`, re-execute:
|
||||
1. **Verify Connection**: On the `new_machine`, re-execute:
|
||||
```bash
|
||||
$ sudo zerotier-cli info
|
||||
```
|
||||
@ -83,15 +78,17 @@ To introduce a new machine to the VPN, adhere to the following steps:
|
||||
200 info d2c71971db 1.12.1 ONLINE
|
||||
```
|
||||
|
||||
!!! success "Congratulations!"
|
||||
The new machine is now part of the VPN, and the ZeroTier
|
||||
configuration on NixOS within the Clan project is complete.
|
||||
!!! success "Congratulations!" The new machine is now part of the VPN, and the
|
||||
ZeroTier configuration on NixOS within the Clan project is complete.
|
||||
|
||||
## Further
|
||||
|
||||
Currently you can only use **Zerotier** as networking technology because this is the first network stack we aim to support.
|
||||
In the future we plan to add additional network technologies like tinc, head/tailscale, yggdrassil and mycelium.
|
||||
Currently you can only use **Zerotier** as networking technology because this is
|
||||
the first network stack we aim to support. In the future we plan to add
|
||||
additional network technologies like tinc, head/tailscale, yggdrassil and
|
||||
mycelium.
|
||||
|
||||
We chose zerotier because in our tests it was a straight forwards solution to bootstrap.
|
||||
It allows you to selfhost a controller and the controller doesn't need to be globally reachable.
|
||||
Which made it a good fit for starting the project.
|
||||
We chose zerotier because in our tests it was a straight forwards solution to
|
||||
bootstrap. It allows you to selfhost a controller and the controller doesn't
|
||||
need to be globally reachable. Which made it a good fit for starting the
|
||||
project.
|
||||
|
@ -1,21 +1,26 @@
|
||||
# Secrets / Facts
|
||||
|
||||
Clan enables encryption of secrets (such as passwords & keys) ensuring security and ease-of-use among users.
|
||||
Clan enables encryption of secrets (such as passwords & keys) ensuring security
|
||||
and ease-of-use among users.
|
||||
|
||||
Clan utilizes the [sops](https://github.com/getsops/sops) format and integrates with [sops-nix](https://github.com/Mic92/sops-nix) on NixOS machines.
|
||||
Clan utilizes the [sops](https://github.com/getsops/sops) format and integrates
|
||||
with [sops-nix](https://github.com/Mic92/sops-nix) on NixOS machines.
|
||||
|
||||
This guide will walk you through:
|
||||
|
||||
- **Creating a Keypair for Your User**: Learn how to generate a keypair for $USER to securely control all secrets.
|
||||
- **Creating Your First Secret**: Step-by-step instructions on creating your initial secret.
|
||||
- **Assigning Machine Access to the Secret**: Understand how to grant a machine access to the newly created secret.
|
||||
- **Creating a Keypair for Your User**: Learn how to generate a keypair for
|
||||
$USER to securely control all secrets.
|
||||
- **Creating Your First Secret**: Step-by-step instructions on creating your
|
||||
initial secret.
|
||||
- **Assigning Machine Access to the Secret**: Understand how to grant a machine
|
||||
access to the newly created secret.
|
||||
|
||||
## Create Your Admin Keypair
|
||||
|
||||
To get started, you'll need to create **Your admin keypair**.
|
||||
|
||||
!!! info
|
||||
Don't worry — if you've already made one before, this step won't change or overwrite it.
|
||||
!!! info Don't worry — if you've already made one before, this step won't change
|
||||
or overwrite it.
|
||||
|
||||
```bash
|
||||
clan secrets key generate
|
||||
@ -30,12 +35,12 @@ Generated age private key at '/home/joerg/.config/sops/age/keys.txt' for your us
|
||||
Also add your age public key to the repository with 'clan secrets users add YOUR_USER age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7' (replace YOUR_USER with your actual username)
|
||||
```
|
||||
|
||||
!!! warning
|
||||
Make sure to keep a safe backup of the private key you've just created.
|
||||
If it's lost, you won't be able to get to your secrets anymore because they all need the admin key to be unlocked.
|
||||
!!! warning Make sure to keep a safe backup of the private key you've just
|
||||
created. If it's lost, you won't be able to get to your secrets anymore because
|
||||
they all need the admin key to be unlocked.
|
||||
|
||||
!!! note
|
||||
It's safe to add any secrets created by the clan CLI and placed in your repository to version control systems like `git`.
|
||||
!!! note It's safe to add any secrets created by the clan CLI and placed in your
|
||||
repository to version control systems like `git`.
|
||||
|
||||
### Add Your Public Key
|
||||
|
||||
@ -43,7 +48,8 @@ Also add your age public key to the repository with 'clan secrets users add YOUR
|
||||
clan secrets users add $USER <your_public_key>
|
||||
```
|
||||
|
||||
It's best to choose the same username as on your Setup/Admin Machine that you use to control the deployment with.
|
||||
It's best to choose the same username as on your Setup/Admin Machine that you
|
||||
use to control the deployment with.
|
||||
|
||||
Once run this will create the following files:
|
||||
|
||||
@ -53,7 +59,9 @@ sops/
|
||||
└── <your_username>/
|
||||
└── key.json
|
||||
```
|
||||
If you followed the quickstart tutorial all necessary secrets are initialized at this point.
|
||||
|
||||
If you followed the quickstart tutorial all necessary secrets are initialized at
|
||||
this point.
|
||||
|
||||
---
|
||||
|
||||
@ -65,7 +73,8 @@ If you followed the quickstart tutorial all necessary secrets are initialized at
|
||||
|
||||
## More on Secrets
|
||||
|
||||
If you want to know more about how to save and share passwords in your clan read further!
|
||||
If you want to know more about how to save and share passwords in your clan read
|
||||
further!
|
||||
|
||||
### Adding a Secret
|
||||
|
||||
@ -90,8 +99,10 @@ clan secrets list
|
||||
|
||||
A NixOS machine will automatically import all secrets that are encrypted for the
|
||||
current machine. At runtime it will use the host key to decrypt all secrets into
|
||||
an in-memory, non-persistent filesystem using [sops-nix](https://github.com/Mic92/sops-nix).
|
||||
In your nixos configuration you can get a path to secrets like this `config.sops.secrets.<name>.path`. For example:
|
||||
an in-memory, non-persistent filesystem using
|
||||
[sops-nix](https://github.com/Mic92/sops-nix). In your nixos configuration you
|
||||
can get a path to secrets like this `config.sops.secrets.<name>.path`. For
|
||||
example:
|
||||
|
||||
```nix
|
||||
{ config, ...}: {
|
||||
@ -106,12 +117,13 @@ In your nixos configuration you can get a path to secrets like this `config.sops
|
||||
|
||||
### Assigning Access
|
||||
|
||||
When using `clan secrets set <secret>` without arguments, secrets are encrypted for the key of the user named like your current $USER.
|
||||
When using `clan secrets set <secret>` without arguments, secrets are encrypted
|
||||
for the key of the user named like your current $USER.
|
||||
|
||||
To add machines/users to an existing secret use:
|
||||
|
||||
```bash
|
||||
clan secrets machines add-secret <machine_name> <secret_name>
|
||||
clan secrets machines add-secret <machine_name> <secret_name>
|
||||
```
|
||||
|
||||
Alternatively specify users and machines while creating a secret:
|
||||
@ -156,44 +168,50 @@ Here's how to get started:
|
||||
|
||||
### Adding Machine Keys
|
||||
|
||||
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
|
||||
New machines in Clan come with age keys stored in
|
||||
`./sops/machines/<machine_name>`. To list these machines:
|
||||
|
||||
```bash
|
||||
clan secrets machines list
|
||||
clan secrets machines list
|
||||
```
|
||||
|
||||
For existing machines, add their keys:
|
||||
|
||||
```bash
|
||||
clan secrets machines add <machine_name> <age_key>
|
||||
clan secrets machines add <machine_name> <age_key>
|
||||
```
|
||||
|
||||
To fetch an age key from an SSH host key:
|
||||
|
||||
```bash
|
||||
ssh-keyscan <domain_name> | nix shell nixpkgs#ssh-to-age -c ssh-to-age
|
||||
ssh-keyscan <domain_name> | nix shell nixpkgs#ssh-to-age -c ssh-to-age
|
||||
```
|
||||
|
||||
### Migration: Importing existing sops-based keys / sops-nix
|
||||
|
||||
`clan secrets` stores each secret in a single file, whereas [sops](https://github.com/Mic92/sops-nix) commonly allows to put all secrets in a yaml or json document.
|
||||
`clan secrets` stores each secret in a single file, whereas
|
||||
[sops](https://github.com/Mic92/sops-nix) commonly allows to put all secrets in
|
||||
a yaml or json document.
|
||||
|
||||
If you already happened to use sops-nix, you can migrate by using the `clan secrets import-sops` command by importing these files:
|
||||
If you already happened to use sops-nix, you can migrate by using the
|
||||
`clan secrets import-sops` command by importing these files:
|
||||
|
||||
```bash
|
||||
% clan secrets import-sops --prefix matchbox- --group admins --machine matchbox nixos/matchbox/secrets/secrets.yaml
|
||||
```
|
||||
|
||||
This will create secrets for each secret found in `nixos/matchbox/secrets/secrets.yaml` in a `./sops` folder of your repository.
|
||||
Each member of the group `admins` in this case will be able to decrypt the secrets with their respective key.
|
||||
|
||||
Since our clan secret module will auto-import secrets that are encrypted for a particular nixos machine,
|
||||
you can now remove `sops.secrets.<secrets> = { };` unless you need to specify more options for the secret like owner/group of the secret file.
|
||||
This will create secrets for each secret found in
|
||||
`nixos/matchbox/secrets/secrets.yaml` in a `./sops` folder of your repository.
|
||||
Each member of the group `admins` in this case will be able to decrypt the
|
||||
secrets with their respective key.
|
||||
|
||||
Since our clan secret module will auto-import secrets that are encrypted for a
|
||||
particular nixos machine, you can now remove `sops.secrets.<secrets> = { };`
|
||||
unless you need to specify more options for the secret like owner/group of the
|
||||
secret file.
|
||||
|
||||
## Indepth Explanation
|
||||
|
||||
|
||||
The secrets system conceptually knows two different entities:
|
||||
|
||||
- **Machine**: consumes secrets
|
||||
@ -201,37 +219,48 @@ The secrets system conceptually knows two different entities:
|
||||
|
||||
**A Users** Can add or revoke machines' access to secrets.
|
||||
|
||||
**A machine** Can decrypt secrets that where encrypted specifically for that machine.
|
||||
**A machine** Can decrypt secrets that where encrypted specifically for that
|
||||
machine.
|
||||
|
||||
!!! Danger
|
||||
**Always make sure at least one _User_ has access to a secret**. Otherwise you could lock yourself out from accessing the secret.
|
||||
!!! Danger **Always make sure at least one _User_ has access to a secret**.
|
||||
Otherwise you could lock yourself out from accessing the secret.
|
||||
|
||||
### Inherited implications
|
||||
|
||||
By default clan uses [sops](https://github.com/getsops/sops) through [sops-nix](https://github.com/Mic92/sops-nix) for managing its secrets which inherits some implications that are important to understand:
|
||||
By default clan uses [sops](https://github.com/getsops/sops) through
|
||||
[sops-nix](https://github.com/Mic92/sops-nix) for managing its secrets which
|
||||
inherits some implications that are important to understand:
|
||||
|
||||
- **Public/Private keys**: Entities are identified via their public keys. Each Entity can use their respective private key to decrypt a secret.
|
||||
- **Public/Private keys**: Entities are identified via their public keys. Each
|
||||
Entity can use their respective private key to decrypt a secret.
|
||||
- **Public keys are stored**: All Public keys are stored inside the repository
|
||||
- **Secrets are stored Encrypted**: secrets are stored inside the repository encrypted with the respective public keys
|
||||
- **Secrets are deployed encrypted**: Fully encrypted secrets are deployed to machines at deployment time.
|
||||
- **Secrets are decrypted by sops on-demand**: Each machine decrypts its secrets at runtime and stores them at an ephemeral location.
|
||||
- **Machine key-pairs are auto-generated**: When a machine is created **no user-interaction is required** to setup public/private key-pairs.
|
||||
- **secrets are re-encrypted**: In case machines, users or groups are modified secrets get re-encrypted on demand.
|
||||
- **Secrets are stored Encrypted**: secrets are stored inside the repository
|
||||
encrypted with the respective public keys
|
||||
- **Secrets are deployed encrypted**: Fully encrypted secrets are deployed to
|
||||
machines at deployment time.
|
||||
- **Secrets are decrypted by sops on-demand**: Each machine decrypts its secrets
|
||||
at runtime and stores them at an ephemeral location.
|
||||
- **Machine key-pairs are auto-generated**: When a machine is created **no
|
||||
user-interaction is required** to setup public/private key-pairs.
|
||||
- **secrets are re-encrypted**: In case machines, users or groups are modified
|
||||
secrets get re-encrypted on demand.
|
||||
|
||||
!!! Important
|
||||
After revoking access to a secret you should also change the underlying secret. i.e. change the API key, or the password.
|
||||
!!! Important After revoking access to a secret you should also change the
|
||||
underlying secret. i.e. change the API key, or the password.
|
||||
|
||||
---
|
||||
|
||||
### Machine and user keys
|
||||
|
||||
The following diagrams illustrates how a user can provide a secret (i.e. a Password).
|
||||
The following diagrams illustrates how a user can provide a secret (i.e. a
|
||||
Password).
|
||||
|
||||
- By using the **Clan CLI** a user encrypts the password with both the **User public-key** and the **machine's public-key**
|
||||
- By using the **Clan CLI** a user encrypts the password with both the **User
|
||||
public-key** and the **machine's public-key**
|
||||
|
||||
- The *Machine* can decrypt the password with its private-key on demand.
|
||||
- The _Machine_ can decrypt the password with its private-key on demand.
|
||||
|
||||
- The *User* is able to decrypt the password to make changes to it.
|
||||
- The _User_ is able to decrypt the password to make changes to it.
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
@ -248,14 +277,14 @@ Rel_R(secret, machine, "Decrypt", "", "machine privkey" )
|
||||
@enduml
|
||||
```
|
||||
|
||||
|
||||
#### User groups
|
||||
|
||||
Here we illustrate how machine groups work.
|
||||
|
||||
Common use cases:
|
||||
|
||||
- **Shared Management**: Access among multiple users. I.e. a subset of secrets/machines that have two admins
|
||||
- **Shared Management**: Access among multiple users. I.e. a subset of
|
||||
secrets/machines that have two admins
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
@ -309,12 +338,9 @@ Rel(secret, c1, "Decrypt", "", "Both machine A or B can decrypt using their priv
|
||||
|
||||
<!-- TODO: See also [Groups Reference](#groups-reference) -->
|
||||
|
||||
|
||||
|
||||
See the [readme](https://github.com/Mic92/sops-nix) of sops-nix for more
|
||||
examples.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Whats next?
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Setup
|
||||
|
||||
Create your own clan with these initial steps and manage a fleet of machines with one single testable git repository!
|
||||
Create your own clan with these initial steps and manage a fleet of machines
|
||||
with one single testable git repository!
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@ -35,9 +36,11 @@ Add the Clan CLI into your development workflow:
|
||||
nix shell git+https://git.clan.lol/clan/clan-core#clan-cli
|
||||
```
|
||||
|
||||
You can find reference documentation for the `clan` cli program [here](./reference/cli/index.md).
|
||||
You can find reference documentation for the `clan` cli program
|
||||
[here](./reference/cli/index.md).
|
||||
|
||||
Alternatively you can check out the help pages directly:
|
||||
|
||||
```terminalSession
|
||||
clan --help
|
||||
```
|
||||
@ -51,7 +54,8 @@ clan flakes create my-clan
|
||||
```
|
||||
|
||||
This command creates the `flake.nix` and `.clan-flake` files for your project.
|
||||
It will also generate files from a default template, to help show general clan usage patterns.
|
||||
It will also generate files from a default template, to help show general clan
|
||||
usage patterns.
|
||||
|
||||
### Step 3: Verify the Project Structure
|
||||
|
||||
@ -64,7 +68,7 @@ tree
|
||||
|
||||
This should yield the following:
|
||||
|
||||
``` { .console .no-copy }
|
||||
```{ .console .no-copy }
|
||||
.
|
||||
├── flake.nix
|
||||
├── machines
|
||||
@ -84,7 +88,7 @@ This should yield the following:
|
||||
clan machines list
|
||||
```
|
||||
|
||||
``` { .console .no-copy }
|
||||
```{ .console .no-copy }
|
||||
jon
|
||||
sara
|
||||
```
|
||||
@ -97,6 +101,7 @@ sara
|
||||
|
||||
### What's Next?
|
||||
|
||||
- [**Installer**](getting-started/installer.md): Setting up new computers remotely is easy with an USB stick.
|
||||
- [**Installer**](getting-started/installer.md): Setting up new computers
|
||||
remotely is easy with an USB stick.
|
||||
|
||||
---
|
||||
|
@ -11,6 +11,7 @@
|
||||
treefmt.programs.nixfmt.enable = true;
|
||||
treefmt.programs.nixfmt.package = pkgs.nixfmt-rfc-style;
|
||||
treefmt.programs.deadnix.enable = true;
|
||||
treefmt.programs.deno.enable = true;
|
||||
|
||||
treefmt.programs.mypy.directories = {
|
||||
"pkgs/clan-cli".extraPythonPackages = self'.packages.clan-cli.testDependencies;
|
||||
@ -20,6 +21,7 @@
|
||||
};
|
||||
treefmt.programs.ruff.check = true;
|
||||
treefmt.programs.ruff.format = true;
|
||||
treefmt.settings.global.excludes = [ "*/sops/*" ];
|
||||
|
||||
# FIXME: currently broken in CI
|
||||
#treefmt.settings.formatter.vale =
|
||||
|
@ -1,11 +1,15 @@
|
||||
# Inventory
|
||||
|
||||
The inventory is our concept for distributed services. Users can configure multiple machines with minimal effort.
|
||||
The inventory is our concept for distributed services. Users can configure
|
||||
multiple machines with minimal effort.
|
||||
|
||||
- The inventory acts as a declarative source of truth for all machine configurations.
|
||||
- The inventory acts as a declarative source of truth for all machine
|
||||
configurations.
|
||||
- Users can easily add or remove machines to/from services.
|
||||
- Ensures that all machines and services are configured consistently, across multiple nixosConfigs.
|
||||
- Defaults and predefined roles in our modules minimizes the need for manual configuration.
|
||||
- Ensures that all machines and services are configured consistently, across
|
||||
multiple nixosConfigs.
|
||||
- Defaults and predefined roles in our modules minimizes the need for manual
|
||||
configuration.
|
||||
|
||||
Open questions:
|
||||
|
||||
@ -13,13 +17,13 @@ Open questions:
|
||||
- It must be accessible from Python.
|
||||
- It must set the value in the module system.
|
||||
|
||||
- [ ] Inventory might use assertions. Should each machine inherit the inventory assertions ?
|
||||
- [ ] Inventory might use assertions. Should each machine inherit the inventory
|
||||
assertions ?
|
||||
|
||||
- [ ] Is the service config interface the same as the module config interface ?
|
||||
|
||||
- [ ] As a user do I want to see borgbackup as the high level category?
|
||||
|
||||
|
||||
Architecture
|
||||
|
||||
```
|
||||
@ -61,7 +65,8 @@ Comments are rendered as descriptions in the json schema.
|
||||
name: string
|
||||
```
|
||||
|
||||
Cue open sets. In the following `foo = {...}` means that the key `foo` can contain any arbitrary json object.
|
||||
Cue open sets. In the following `foo = {...}` means that the key `foo` can
|
||||
contain any arbitrary json object.
|
||||
|
||||
```cue
|
||||
foo: { ... }
|
||||
@ -79,12 +84,12 @@ This is the schema of
|
||||
|
||||
```json
|
||||
{
|
||||
"a": {
|
||||
"attr": "foo"
|
||||
},
|
||||
"b": {
|
||||
"attr": "bar"
|
||||
}
|
||||
// ... Indefinitely more dynamic keys of type "string"
|
||||
"a": {
|
||||
"attr": "foo"
|
||||
},
|
||||
"b": {
|
||||
"attr": "bar"
|
||||
}
|
||||
// ... Indefinitely more dynamic keys of type "string"
|
||||
}
|
||||
```
|
||||
|
@ -1,6 +1,7 @@
|
||||
# clan app
|
||||
|
||||
Provides users with the simple functionality to manage their locally registered clans.
|
||||
Provides users with the simple functionality to manage their locally registered
|
||||
clans.
|
||||
|
||||
![app-preview](screenshots/image.png)
|
||||
|
||||
@ -52,8 +53,9 @@ PERF=1 ./bin/clan-app
|
||||
|
||||
> Note:
|
||||
>
|
||||
> we recognized bugs when starting some cli-commands through the integrated vs-code terminal.
|
||||
> If encountering issues make sure to run commands in a regular os-shell.
|
||||
> we recognized bugs when starting some cli-commands through the integrated
|
||||
> vs-code terminal. If encountering issues make sure to run commands in a
|
||||
> regular os-shell.
|
||||
|
||||
lib-Adw has a demo application showing all widgets. You can run it by executing
|
||||
|
||||
@ -77,18 +79,34 @@ gtk4-icon-browser
|
||||
|
||||
Here are some important documentation links related to the Clan App:
|
||||
|
||||
- [Adw PyGobject Reference](http://lazka.github.io/pgi-docs/index.html#Adw-1): This link provides the PyGObject reference documentation for the Adw library, which is used in the Clan App. It contains detailed information about the Adw widgets and their usage.
|
||||
- [Adw PyGobject Reference](http://lazka.github.io/pgi-docs/index.html#Adw-1):
|
||||
This link provides the PyGObject reference documentation for the Adw library,
|
||||
which is used in the Clan App. It contains detailed information about the Adw
|
||||
widgets and their usage.
|
||||
|
||||
- [GTK4 PyGobject Reference](http://lazka.github.io/pgi-docs/index.html#Gtk-4.0): This link provides the PyGObject reference documentation for GTK4, the toolkit used for building the user interface of the clan app. It includes information about GTK4 widgets, signals, and other features.
|
||||
- [GTK4 PyGobject Reference](http://lazka.github.io/pgi-docs/index.html#Gtk-4.0):
|
||||
This link provides the PyGObject reference documentation for GTK4, the toolkit
|
||||
used for building the user interface of the clan app. It includes information
|
||||
about GTK4 widgets, signals, and other features.
|
||||
|
||||
- [Adw Widget Gallery](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/widget-gallery.html): This link showcases a widget gallery for Adw, allowing you to see the available widgets and their visual appearance. It can be helpful for designing the user interface of the clan app.
|
||||
- [Adw Widget Gallery](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/widget-gallery.html):
|
||||
This link showcases a widget gallery for Adw, allowing you to see the
|
||||
available widgets and their visual appearance. It can be helpful for designing
|
||||
the user interface of the clan app.
|
||||
|
||||
- [Python + GTK3 Tutorial](https://python-gtk-3-tutorial.readthedocs.io/en/latest/textview.html): Although the clan app uses GTK4, this tutorial for GTK3 can still be useful as it covers the basics of building GTK-based applications with Python. It includes examples and explanations for various GTK widgets, including text views.
|
||||
- [Python + GTK3 Tutorial](https://python-gtk-3-tutorial.readthedocs.io/en/latest/textview.html):
|
||||
Although the clan app uses GTK4, this tutorial for GTK3 can still be useful as
|
||||
it covers the basics of building GTK-based applications with Python. It
|
||||
includes examples and explanations for various GTK widgets, including text
|
||||
views.
|
||||
|
||||
- [GNOME Human Interface Guidelines](https://developer.gnome.org/hig/): This link provides the GNOME Human Interface Guidelines, which offer design and usability recommendations for creating GNOME applications. It covers topics such as layout, navigation, and interaction patterns.
|
||||
- [GNOME Human Interface Guidelines](https://developer.gnome.org/hig/): This
|
||||
link provides the GNOME Human Interface Guidelines, which offer design and
|
||||
usability recommendations for creating GNOME applications. It covers topics
|
||||
such as layout, navigation, and interaction patterns.
|
||||
|
||||
## Error handling
|
||||
|
||||
> Error dialogs should be avoided where possible, since they are disruptive.
|
||||
>
|
||||
> For simple non-critical errors, toasts can be a good alternative.
|
||||
> For simple non-critical errors, toasts can be a good alternative.
|
||||
|
@ -1,7 +1,10 @@
|
||||
# Webkit GTK doesn't interop flawless with Solid.js build result
|
||||
|
||||
1. Webkit expects script tag to be in `body` only solid.js puts the in the head.
|
||||
2. script and css files are loaded with type="module" and crossorigin tags beeing set. WebKit silently fails to load then.
|
||||
3. Paths to resiources are not allowed to start with "/" because webkit interprets them relative to the system and not the base url.
|
||||
4. webkit doesn't support native features such as directly handling external urls (i.e opening them in the default browser)
|
||||
6. Other problems to be found?
|
||||
2. script and css files are loaded with type="module" and crossorigin tags
|
||||
beeing set. WebKit silently fails to load then.
|
||||
3. Paths to resiources are not allowed to start with "/" because webkit
|
||||
interprets them relative to the system and not the base url.
|
||||
4. webkit doesn't support native features such as directly handling external
|
||||
urls (i.e opening them in the default browser)
|
||||
5. Other problems to be found?
|
||||
|
48
pkgs/clan-cli/.vscode/launch.json
vendored
48
pkgs/clan-cli/.vscode/launch.json
vendored
@ -1,26 +1,24 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Clan Webui",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "clan_cli.webui",
|
||||
"justMyCode": false,
|
||||
"args": [ "--reload", "--no-open", "--log-level", "debug" ],
|
||||
|
||||
},
|
||||
{
|
||||
"name": "Clan Cli VMs",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "clan_cli",
|
||||
"justMyCode": false,
|
||||
"args": [ "vms" ],
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Clan Webui",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "clan_cli.webui",
|
||||
"justMyCode": false,
|
||||
"args": ["--reload", "--no-open", "--log-level", "debug"]
|
||||
},
|
||||
{
|
||||
"name": "Clan Cli VMs",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"module": "clan_cli",
|
||||
"justMyCode": false,
|
||||
"args": ["vms"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
42
pkgs/clan-cli/.vscode/settings.json
vendored
42
pkgs/clan-cli/.vscode/settings.json
vendored
@ -1,22 +1,22 @@
|
||||
{
|
||||
"python.testing.pytestArgs": [
|
||||
// Coverage is not supported by vscode:
|
||||
// https://github.com/Microsoft/vscode-python/issues/693
|
||||
// Note that this will make pytest fail if pytest-cov is not installed,
|
||||
// if that's the case, then this option needs to be be removed (overrides
|
||||
// can be set at a workspace level, it's up to you to decide what's the
|
||||
// best approach). You might also prefer to only set this option
|
||||
// per-workspace (wherever coverage is used).
|
||||
"--no-cov",
|
||||
"tests"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"search.exclude": {
|
||||
"**/.direnv": true
|
||||
},
|
||||
"python.linting.mypyPath": "mypy",
|
||||
"python.linting.mypyEnabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.defaultInterpreterPath": "python"
|
||||
}
|
||||
"python.testing.pytestArgs": [
|
||||
// Coverage is not supported by vscode:
|
||||
// https://github.com/Microsoft/vscode-python/issues/693
|
||||
// Note that this will make pytest fail if pytest-cov is not installed,
|
||||
// if that's the case, then this option needs to be be removed (overrides
|
||||
// can be set at a workspace level, it's up to you to decide what's the
|
||||
// best approach). You might also prefer to only set this option
|
||||
// per-workspace (wherever coverage is used).
|
||||
"--no-cov",
|
||||
"tests"
|
||||
],
|
||||
"python.testing.unittestEnabled": false,
|
||||
"python.testing.pytestEnabled": true,
|
||||
"search.exclude": {
|
||||
"**/.direnv": true
|
||||
},
|
||||
"python.linting.mypyPath": "mypy",
|
||||
"python.linting.mypyEnabled": true,
|
||||
"python.linting.enabled": true,
|
||||
"python.defaultInterpreterPath": "python"
|
||||
}
|
||||
|
@ -4,8 +4,9 @@ The clan-cli contains the command line interface
|
||||
|
||||
## Hacking on the cli
|
||||
|
||||
We recommend setting up [direnv](https://direnv.net/) to load the developement with nix.
|
||||
If you do not have it set up you can also use `nix develop` directly like this:
|
||||
We recommend setting up [direnv](https://direnv.net/) to load the developement
|
||||
with nix. If you do not have it set up you can also use `nix develop` directly
|
||||
like this:
|
||||
|
||||
```
|
||||
use flake .#clan-cli --builders ''
|
||||
@ -19,8 +20,8 @@ After you can use the local bin wrapper to test things in the cli:
|
||||
|
||||
## Run locally single-threaded for debugging
|
||||
|
||||
By default tests run in parallel using pytest-parallel.
|
||||
pytest-parallel however breaks `breakpoint()`. To disable it, use this:
|
||||
By default tests run in parallel using pytest-parallel. pytest-parallel however
|
||||
breaks `breakpoint()`. To disable it, use this:
|
||||
|
||||
```bash
|
||||
pytest -n0 -s
|
||||
|
8
pkgs/webview-ui/.vscode/settings.json
vendored
8
pkgs/webview-ui/.vscode/settings.json
vendored
@ -1,5 +1,7 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"tailwindCSS.experimental.classRegex": [["cx\\(([^)]*)\\)", "[\"'`]([^\"'`]*)[\"'`]"]],
|
||||
"editor.wordWrap": "on"
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["cx\\(([^)]*)\\)", "[\"'`]([^\"'`]*)[\"'`]"]
|
||||
],
|
||||
"editor.wordWrap": "on"
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
## Usage
|
||||
|
||||
Those templates dependencies are maintained via [pnpm](https://pnpm.io) via `pnpm up -Lri`.
|
||||
Those templates dependencies are maintained via [pnpm](https://pnpm.io) via
|
||||
`pnpm up -Lri`.
|
||||
|
||||
This is the reason you see a `pnpm-lock.yaml`. That being said, any package manager will work. This file can be safely be removed once you clone a template.
|
||||
This is the reason you see a `pnpm-lock.yaml`. That being said, any package
|
||||
manager will work. This file can be safely be removed once you clone a template.
|
||||
|
||||
```bash
|
||||
$ npm install # or pnpm install or yarn install
|
||||
@ -16,19 +18,20 @@ In the project directory, you can run:
|
||||
|
||||
### `npm run dev` or `npm start`
|
||||
|
||||
Runs the app in the development mode.<br>
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
Runs the app in the development mode.<br> Open
|
||||
[http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.<br>
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `dist` folder.<br>
|
||||
It correctly bundles Solid in production mode and optimizes the build for the best performance.
|
||||
Builds the app for production to the `dist` folder.<br> It correctly bundles
|
||||
Solid in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.<br>
|
||||
Your app is ready to be deployed!
|
||||
The build is minified and the filenames include the hashes.<br> Your app is
|
||||
ready to be deployed!
|
||||
|
||||
## Deployment
|
||||
|
||||
You can deploy the `dist` folder to any static host provider (netlify, surge, now, etc.)
|
||||
You can deploy the `dist` folder to any static host provider (netlify, surge,
|
||||
now, etc.)
|
||||
|
@ -43,7 +43,7 @@ fs.readFile(manifestPath, { encoding: "utf8" }, (err, data) => {
|
||||
console.log(`Rewriting CSS url(): ${asset.url} to ${res}`);
|
||||
return res;
|
||||
},
|
||||
})
|
||||
}),
|
||||
)
|
||||
.process(css, {
|
||||
from: `dist/${cssEntry}`,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createSignal, type Component } from "solid-js";
|
||||
import { type Component, createSignal } from "solid-js";
|
||||
import { MachineProvider } from "./Config";
|
||||
import { Layout } from "./layout/layout";
|
||||
import { Route, Router } from "./Routes";
|
||||
@ -8,7 +8,7 @@ import { Toaster } from "solid-toast";
|
||||
const [route, setRoute] = createSignal<Route>("machines");
|
||||
|
||||
const [currClanURI, setCurrClanURI] = createSignal<string>(
|
||||
"/home/johannes/git/testing/xd"
|
||||
"/home/johannes/git/testing/xd",
|
||||
);
|
||||
|
||||
export { currClanURI, setCurrClanURI };
|
||||
|
@ -1,16 +1,17 @@
|
||||
import {
|
||||
createSignal,
|
||||
createContext,
|
||||
useContext,
|
||||
JSXElement,
|
||||
createEffect,
|
||||
createSignal,
|
||||
JSXElement,
|
||||
useContext,
|
||||
} from "solid-js";
|
||||
import { OperationResponse, pyApi } from "./api";
|
||||
import { currClanURI } from "./App";
|
||||
|
||||
export const makeMachineContext = () => {
|
||||
const [machines, setMachines] =
|
||||
createSignal<OperationResponse<"list_machines">>();
|
||||
const [machines, setMachines] = createSignal<
|
||||
OperationResponse<"list_machines">
|
||||
>();
|
||||
const [loading, setLoading] = createSignal(false);
|
||||
|
||||
pyApi.list_machines.receive((machines) => {
|
||||
|
@ -48,18 +48,17 @@ const obs: ObserverRegistry = operationNames.reduce(
|
||||
...acc,
|
||||
[opName]: [],
|
||||
}),
|
||||
{} as ObserverRegistry
|
||||
{} as ObserverRegistry,
|
||||
);
|
||||
|
||||
interface ReceiveOptions {
|
||||
/**
|
||||
* Calls only the registered function that has the same key as used with dispatch
|
||||
*
|
||||
*/
|
||||
fnKey: string;
|
||||
}
|
||||
function createFunctions<K extends OperationNames>(
|
||||
operationName: K
|
||||
operationName: K,
|
||||
): {
|
||||
dispatch: (args: OperationArgs<K>) => void;
|
||||
receive: (fn: (response: OperationResponse<K>) => void) => void;
|
||||
@ -76,7 +75,7 @@ function createFunctions<K extends OperationNames>(
|
||||
});
|
||||
},
|
||||
receive: (
|
||||
fn: (response: OperationResponse<K>) => void
|
||||
fn: (response: OperationResponse<K>) => void,
|
||||
// options?: ReceiveOptions
|
||||
) => {
|
||||
obs[operationName].push(fn);
|
||||
@ -94,16 +93,14 @@ type PyApi = {
|
||||
};
|
||||
};
|
||||
|
||||
const deserialize =
|
||||
<T>(fn: (response: T) => void) =>
|
||||
(str: string) => {
|
||||
try {
|
||||
fn(JSON.parse(str) as T);
|
||||
} catch (e) {
|
||||
console.error(str);
|
||||
alert(`Error parsing JSON: ${e}`);
|
||||
}
|
||||
};
|
||||
const deserialize = <T>(fn: (response: T) => void) => (str: string) => {
|
||||
try {
|
||||
fn(JSON.parse(str) as T);
|
||||
} catch (e) {
|
||||
console.error(str);
|
||||
alert(`Error parsing JSON: ${e}`);
|
||||
}
|
||||
};
|
||||
|
||||
// Create the API object
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Match, Show, Switch, createSignal } from "solid-js";
|
||||
import { ErrorData, SuccessData, pyApi } from "../api";
|
||||
import { createSignal, Match, Show, Switch } from "solid-js";
|
||||
import { ErrorData, pyApi, SuccessData } from "../api";
|
||||
import { currClanURI } from "../App";
|
||||
|
||||
type MachineDetails = SuccessData<"list_machines">["data"][string];
|
||||
|
@ -10,7 +10,7 @@ window.clan = window.clan || {};
|
||||
|
||||
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
||||
throw new Error(
|
||||
"Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?"
|
||||
"Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,8 @@ export const Layout: Component<LayoutProps> = (props) => {
|
||||
for="toplevel-drawer"
|
||||
aria-label="close sidebar"
|
||||
class="drawer-overlay"
|
||||
></label>
|
||||
>
|
||||
</label>
|
||||
<Sidebar route={route} setRoute={setRoute} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { route } from "@/src/App";
|
||||
import { OperationResponse, pyApi } from "@/src/api";
|
||||
import { Component, For, Show, createEffect, createSignal } from "solid-js";
|
||||
import { Component, createEffect, createSignal, For, Show } from "solid-js";
|
||||
|
||||
type DevicesModel = Extract<
|
||||
OperationResponse<"show_block_devices">,
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { OperationResponse, pyApi } from "@/src/api";
|
||||
import {
|
||||
createEffect,
|
||||
createSignal,
|
||||
For,
|
||||
JSX,
|
||||
Match,
|
||||
Show,
|
||||
Switch,
|
||||
createEffect,
|
||||
createSignal,
|
||||
} from "solid-js";
|
||||
import {
|
||||
SubmitHandler,
|
||||
createForm,
|
||||
email,
|
||||
required,
|
||||
SubmitHandler,
|
||||
} from "@modular-forms/solid";
|
||||
|
||||
interface ClanDetailsProps {
|
||||
@ -172,9 +172,9 @@ export const ClanDetails = (props: ClanDetailsProps) => {
|
||||
const [loading, setLoading] = createSignal(false);
|
||||
const [errors, setErrors] = createSignal<
|
||||
| Extract<
|
||||
OperationResponse<"show_clan_meta">,
|
||||
{ status: "error" }
|
||||
>["errors"]
|
||||
OperationResponse<"show_clan_meta">,
|
||||
{ status: "error" }
|
||||
>["errors"]
|
||||
| null
|
||||
>(null);
|
||||
const [data, setData] = createSignal<ClanMeta>();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { pyApi } from "@/src/api";
|
||||
import { Match, Switch, createEffect, createSignal } from "solid-js";
|
||||
import { createEffect, createSignal, Match, Switch } from "solid-js";
|
||||
import toast from "solid-toast";
|
||||
import { ClanDetails, ClanForm } from "./clanDetails";
|
||||
|
||||
@ -56,9 +56,7 @@ export const clan = () => {
|
||||
<ClanForm
|
||||
actions={
|
||||
<div class="card-actions justify-end">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
// onClick={() => {
|
||||
<button class="btn btn-primary" // onClick={() => {
|
||||
// pyApi.open_file.dispatch({
|
||||
// file_request: { mode: "save" },
|
||||
// });
|
||||
|
@ -1,9 +1,9 @@
|
||||
import {
|
||||
For,
|
||||
Show,
|
||||
type Component,
|
||||
createEffect,
|
||||
createSignal,
|
||||
type Component,
|
||||
For,
|
||||
Show,
|
||||
} from "solid-js";
|
||||
import { route } from "@/src/App";
|
||||
import { OperationResponse, pyApi } from "@/src/api";
|
||||
|
@ -1,11 +1,11 @@
|
||||
import {
|
||||
type Component,
|
||||
createEffect,
|
||||
createSignal,
|
||||
For,
|
||||
Match,
|
||||
Show,
|
||||
Switch,
|
||||
createEffect,
|
||||
createSignal,
|
||||
type Component,
|
||||
} from "solid-js";
|
||||
import { useMachineContext } from "../../Config";
|
||||
import { route } from "@/src/App";
|
||||
@ -69,7 +69,7 @@ export const MachineListView: Component = () => {
|
||||
toast.error("Error loading machines");
|
||||
response.errors.forEach((error) =>
|
||||
toast.error(
|
||||
`${error.message}: ${error.description} From ${error.location}`
|
||||
`${error.message}: ${error.description} From ${error.location}`,
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -86,8 +86,7 @@ export const MachineListView: Component = () => {
|
||||
title: "Open Clan",
|
||||
mode: "select_folder",
|
||||
},
|
||||
})
|
||||
}
|
||||
})}
|
||||
>
|
||||
<span class="material-icons ">folder_open</span>
|
||||
</button>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { describe, it, expectTypeOf } from "vitest";
|
||||
import { describe, expectTypeOf, it } from "vitest";
|
||||
|
||||
import { OperationNames, pyApi } from "@/src/api";
|
||||
|
||||
@ -44,13 +44,13 @@ describe.concurrent("API types work properly", () => {
|
||||
.parameter(0)
|
||||
.toMatchTypeOf<
|
||||
| {
|
||||
status: "success";
|
||||
data: {
|
||||
machine_name: string;
|
||||
machine_icon?: string | null;
|
||||
machine_description?: string | null;
|
||||
};
|
||||
}
|
||||
status: "success";
|
||||
data: {
|
||||
machine_name: string;
|
||||
machine_icon?: string | null;
|
||||
machine_description?: string | null;
|
||||
};
|
||||
}
|
||||
| { status: "error"; errors: any }
|
||||
>();
|
||||
});
|
||||
|
@ -14,6 +14,7 @@
|
||||
"allowJs": true,
|
||||
"isolatedModules": true,
|
||||
"paths": {
|
||||
"@/*": ["./*"]}
|
||||
},
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user