fixes and docs
This commit is contained in:
116
README.md
116
README.md
@@ -113,6 +113,122 @@ sudo nixos-rebuild switch --flake .#hostname
|
||||
home-manager switch --flake .#username@hostname
|
||||
```
|
||||
|
||||
## Secrets Management
|
||||
|
||||
Secrets are managed with [sops-nix](https://github.com/Mic92/sops-nix). Each secret file is encrypted with [age](https://age-encryption.org/), using the SSH host key (`/etc/ssh/ssh_host_ed25519_key`) of each machine as a recipient, so that machine can decrypt its own secrets at boot without any passphrase.
|
||||
|
||||
### How age keys work
|
||||
|
||||
sops-nix derives an age key from the machine's ed25519 SSH host key automatically. The corresponding age **public key** must be added to `.sops.yaml` before you can encrypt secrets for that machine.
|
||||
|
||||
To get the age public key for a machine:
|
||||
|
||||
```bash
|
||||
# On the target machine (or from its host key file):
|
||||
nix-shell -p ssh-to-age --run \
|
||||
'ssh-keyscan localhost 2>/dev/null | ssh-to-age'
|
||||
|
||||
# Or directly from the key file:
|
||||
nix-shell -p ssh-to-age --run \
|
||||
'ssh-to-age < /etc/ssh/ssh_host_ed25519_key.pub'
|
||||
```
|
||||
|
||||
### Adding a new machine
|
||||
|
||||
1. **Get the age public key** for the new machine using the command above.
|
||||
|
||||
2. **Add it to `.sops.yaml`**:
|
||||
```yaml
|
||||
keys:
|
||||
- &new-machine age1<public-key-here>
|
||||
creation_rules:
|
||||
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
|
||||
key_groups:
|
||||
- age:
|
||||
- *new-machine
|
||||
# ... existing recipients
|
||||
```
|
||||
|
||||
3. **Re-encrypt all secret files** so the new machine becomes a recipient:
|
||||
```bash
|
||||
find secrets/ -name '*.yaml' -exec sops updatekeys {} \;
|
||||
```
|
||||
|
||||
### Adding a new secret
|
||||
|
||||
To add a secret to an existing file:
|
||||
|
||||
```bash
|
||||
# Edit the file interactively (sops decrypts, opens $EDITOR, re-encrypts on save)
|
||||
sops secrets/nas-secrets.yaml
|
||||
```
|
||||
|
||||
To create a new secrets file:
|
||||
|
||||
```bash
|
||||
sops secrets/mymachine-secrets.yaml
|
||||
```
|
||||
|
||||
The `.sops.yaml` `creation_rules` determine which keys encrypt the file based on its path.
|
||||
|
||||
### Generating Nebula VPN certificates
|
||||
|
||||
The Nebula module (`mjallen.services.nebula`) expects three secrets per host under a configurable prefix:
|
||||
- `<prefix>/ca-cert` — the CA certificate (shared across all nodes)
|
||||
- `<prefix>/host-cert` — this node's signed certificate
|
||||
- `<prefix>/host-key` — this node's private key
|
||||
|
||||
**Step 1 — Create the CA** (once per network, on a trusted machine):
|
||||
|
||||
```bash
|
||||
nebula-cert ca -name "jallen-nebula"
|
||||
# Produces: ca.crt, ca.key
|
||||
```
|
||||
|
||||
**Step 2 — Sign a certificate for each node**:
|
||||
|
||||
```bash
|
||||
# Lighthouse (assign an overlay IP, e.g. 10.1.1.1)
|
||||
nebula-cert sign -name "pi5" -ip "10.1.1.1/24" \
|
||||
-ca-crt ca.crt -ca-key ca.key \
|
||||
-out-crt lighthouse.crt -out-key lighthouse.key
|
||||
|
||||
# Regular node (assign a unique overlay IP, e.g. 10.1.1.2)
|
||||
nebula-cert sign -name "nas" -ip "10.1.1.2/24" \
|
||||
-ca-crt ca.crt -ca-key ca.key \
|
||||
-out-crt nas.crt -out-key nas.key
|
||||
```
|
||||
|
||||
**Step 3 — Add the secrets to SOPS**:
|
||||
|
||||
```bash
|
||||
# Edit the target host's secrets file
|
||||
sops secrets/pi5-secrets.yaml
|
||||
```
|
||||
|
||||
Add the certificate contents under the configured prefix (e.g. `pi5/nebula`):
|
||||
|
||||
```yaml
|
||||
pi5:
|
||||
nebula:
|
||||
ca-cert: |
|
||||
<contents of ca.crt>
|
||||
lighthouse-cert: |
|
||||
<contents of lighthouse.crt>
|
||||
lighthouse-key: |
|
||||
<contents of lighthouse.key>
|
||||
```
|
||||
|
||||
The key name for the cert/key pair matches the `hostSecretName` option (e.g. `hostSecretName = "lighthouse"` → looks for `lighthouse-cert` / `lighthouse-key`).
|
||||
|
||||
**Step 4 — Shred the plaintext key files** once they are in SOPS:
|
||||
|
||||
```bash
|
||||
shred -u ca.key lighthouse.key nas.key
|
||||
```
|
||||
|
||||
> Keep `ca.crt` accessible if you need to sign more nodes later, but store `ca.key` only in SOPS.
|
||||
|
||||
## Documentation
|
||||
|
||||
Comprehensive documentation is available in the [docs](./docs) directory:
|
||||
|
||||
72
packages/cockpit-benchmark/default.nix
Normal file
72
packages/cockpit-benchmark/default.nix
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
fio,
|
||||
jq,
|
||||
lib,
|
||||
namespace,
|
||||
nodejs,
|
||||
npmHooks,
|
||||
fetchNpmDeps,
|
||||
stdenv,
|
||||
}:
|
||||
let
|
||||
inherit (lib.trivial) importJSON;
|
||||
inherit (lib.${namespace}) mkAllSources selectVariant;
|
||||
|
||||
versionSpec = importJSON ./version.json;
|
||||
selected = selectVariant versionSpec null null;
|
||||
sources = mkAllSources selected;
|
||||
inherit (selected.variables) version;
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "cockpit-benchmark";
|
||||
inherit version;
|
||||
|
||||
src = sources.src;
|
||||
|
||||
npmDeps = fetchNpmDeps {
|
||||
src = "${finalAttrs.src}/benchmark";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
jq
|
||||
nodejs
|
||||
npmHooks.npmConfigHook
|
||||
npmHooks.npmBuildHook
|
||||
npmHooks.npmInstallHook
|
||||
];
|
||||
|
||||
# fio is the runtime benchmark tool invoked by the plugin's backend script.
|
||||
passthru.cockpitPath = [ fio ];
|
||||
|
||||
# npmConfigHook expects to run in the directory with package.json
|
||||
preConfigure = ''
|
||||
cd benchmark
|
||||
'';
|
||||
|
||||
# Write version.js before vite build (mirrors what the Makefile does)
|
||||
preBuild = ''
|
||||
pluginVersion="$(jq -r '.version' ../manifest.json)-$(jq -r '.build_number' ../manifest.json)"
|
||||
echo "export const pluginVersion = \"''${pluginVersion}\";" > src/version.js
|
||||
'';
|
||||
|
||||
npmBuildScript = "build";
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share/cockpit/benchmark
|
||||
cp -r dist/* $out/share/cockpit/benchmark/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Cockpit storage benchmark utility using fio";
|
||||
homepage = "https://github.com/45Drives/cockpit-benchmark";
|
||||
changelog = "https://github.com/45Drives/cockpit-benchmark/releases/tag/v${version}";
|
||||
license = lib.licenses.gpl3Plus;
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = [ ];
|
||||
};
|
||||
})
|
||||
15
packages/cockpit-benchmark/version.json
Normal file
15
packages/cockpit-benchmark/version.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"variables": {
|
||||
"version": "2.1.2"
|
||||
},
|
||||
"sources": {
|
||||
"src": {
|
||||
"fetcher": "github",
|
||||
"owner": "45Drives",
|
||||
"repo": "cockpit-benchmark",
|
||||
"tag": "v${version}",
|
||||
"hash": "sha256-YmOCdqAdYPnNcXqCccvI0nVhR/EdYXdkeenmy4DdGK0="
|
||||
}
|
||||
}
|
||||
}
|
||||
82
packages/cockpit-machines/default.nix
Normal file
82
packages/cockpit-machines/default.nix
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
lib,
|
||||
namespace,
|
||||
nodejs,
|
||||
stdenv,
|
||||
}:
|
||||
let
|
||||
inherit (lib.trivial) importJSON;
|
||||
inherit (lib.${namespace}) mkAllSources selectVariant;
|
||||
|
||||
versionSpec = importJSON ./version.json;
|
||||
selected = selectVariant versionSpec null null;
|
||||
sources = mkAllSources selected;
|
||||
inherit (selected.variables) version;
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "cockpit-machines";
|
||||
inherit version;
|
||||
|
||||
src = sources.src;
|
||||
|
||||
# Pre-vendored node_modules from cockpit-project/node-cache, pinned via the
|
||||
# node_modules submodule reference in the source tree.
|
||||
inherit (sources) nodeModules;
|
||||
|
||||
# pkg/lib checked out from the main cockpit repo at the commit pinned in
|
||||
# the Makefile (COCKPIT_REPO_COMMIT).
|
||||
inherit (sources) cockpitLib;
|
||||
|
||||
nativeBuildInputs = [ nodejs ];
|
||||
|
||||
# passthru.cockpitPath is used by the NixOS cockpit module to add runtime
|
||||
# dependencies to the cockpit service's PATH.
|
||||
passthru.cockpitPath = [ ];
|
||||
|
||||
configurePhase = ''
|
||||
runHook preConfigure
|
||||
|
||||
# Replace the empty git submodule placeholder with the real vendored modules.
|
||||
# Use dotglob so hidden entries (.bin, .package-lock.json, etc.) are included.
|
||||
rm -rf node_modules
|
||||
mkdir node_modules
|
||||
(shopt -s dotglob; cp -r $nodeModules/* node_modules/)
|
||||
chmod -R u+w node_modules
|
||||
|
||||
# Node needs package-lock.json at the project root to resolve modules.
|
||||
cp node_modules/.package-lock.json package-lock.json
|
||||
|
||||
# Wire up pkg/lib from the pinned cockpit repo.
|
||||
mkdir -p pkg
|
||||
cp -r $cockpitLib/pkg/lib pkg/lib
|
||||
chmod -R u+w pkg
|
||||
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
NODE_ENV=production node build.js
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share/cockpit/machines
|
||||
cp -r dist/* $out/share/cockpit/machines/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Cockpit UI for virtual machines (libvirt/KVM)";
|
||||
homepage = "https://github.com/cockpit-project/cockpit-machines";
|
||||
changelog = "https://github.com/cockpit-project/cockpit-machines/releases/tag/${version}";
|
||||
license = lib.licenses.lgpl21Plus;
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = [ ];
|
||||
};
|
||||
}
|
||||
31
packages/cockpit-machines/version.json
Normal file
31
packages/cockpit-machines/version.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"variables": {
|
||||
"version": "350",
|
||||
"cockpitRepoCommit": "5fb84eaefbc5ff4433a21bc452270af8d09e1ab7",
|
||||
"nodeCacheRev": "d1c928e67c7891bb05238dde9caa6486bba15625"
|
||||
},
|
||||
"sources": {
|
||||
"src": {
|
||||
"fetcher": "github",
|
||||
"owner": "cockpit-project",
|
||||
"repo": "cockpit-machines",
|
||||
"tag": "${version}",
|
||||
"hash": "sha256-jP/ffo0kwju0xxKMHhDwOsNKO7HjOaJZ/uXYijsElNg="
|
||||
},
|
||||
"nodeModules": {
|
||||
"fetcher": "github",
|
||||
"owner": "cockpit-project",
|
||||
"repo": "node-cache",
|
||||
"rev": "${nodeCacheRev}",
|
||||
"hash": "sha256-yonEQ7hRskbFDnW/Pc3aOeV7bgu1LCYpi1Ok5/aHeC8="
|
||||
},
|
||||
"cockpitLib": {
|
||||
"fetcher": "github",
|
||||
"owner": "cockpit-project",
|
||||
"repo": "cockpit",
|
||||
"rev": "${cockpitRepoCommit}",
|
||||
"hash": "sha256-H9eeTprI0rBKv//1TvGWTtgb5N09/8Audtu5dE1y86o="
|
||||
}
|
||||
}
|
||||
}
|
||||
83
packages/cockpit-podman/default.nix
Normal file
83
packages/cockpit-podman/default.nix
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
fetchFromGitHub,
|
||||
lib,
|
||||
nodejs,
|
||||
stdenv,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "cockpit-podman";
|
||||
version = "123";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "cockpit-project";
|
||||
repo = "cockpit-podman";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-N5nhJU9XUsxLWq3mk3bSyorHEM4zSLHt9I+zkdgU2Vk=";
|
||||
};
|
||||
|
||||
# Pre-vendored node_modules from cockpit-project/node-cache, pinned via the
|
||||
# node_modules submodule reference in the source tree.
|
||||
nodeModules = fetchFromGitHub {
|
||||
owner = "cockpit-project";
|
||||
repo = "node-cache";
|
||||
rev = "e39ef3621b5aefa5bf1c2de7e66a5918fcef620c";
|
||||
hash = "sha256-+yhHsGEN1IqIxPY7vQysp1ZczcHzXRoNIVN3DyVgwB8=";
|
||||
};
|
||||
|
||||
# pkg/lib is checked out from the main cockpit repo at the pinned commit
|
||||
# referenced in the Makefile (COCKPIT_REPO_COMMIT).
|
||||
cockpitLib = fetchFromGitHub {
|
||||
owner = "cockpit-project";
|
||||
repo = "cockpit";
|
||||
rev = "5fb84eaefbc5ff4433a21bc452270af8d09e1ab7";
|
||||
hash = "sha256-FR6TIKQ+3GuDMOMEivDxEx6E/SVIAXh9Cg36JJ694Wc=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [ nodejs ];
|
||||
|
||||
# cockpit-podman uses passthru.cockpitPath for the NixOS cockpit module to
|
||||
# add runtime dependencies to the cockpit service's PATH.
|
||||
passthru.cockpitPath = [ ];
|
||||
|
||||
configurePhase = ''
|
||||
runHook preConfigure
|
||||
|
||||
# Wire up the vendored node_modules
|
||||
cp -r ${finalAttrs.nodeModules} node_modules
|
||||
chmod -R u+w node_modules
|
||||
|
||||
# Wire up pkg/lib from the pinned cockpit repo
|
||||
mkdir -p pkg
|
||||
cp -r ${finalAttrs.cockpitLib}/pkg/lib pkg/lib
|
||||
chmod -R u+w pkg
|
||||
|
||||
runHook postConfigure
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
NODE_ENV=production node build.js
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out/share/cockpit/podman
|
||||
cp -r dist/* $out/share/cockpit/podman/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
description = "Cockpit UI for Podman containers";
|
||||
homepage = "https://github.com/cockpit-project/cockpit-podman";
|
||||
changelog = "https://github.com/cockpit-project/cockpit-podman/releases/tag/${finalAttrs.version}";
|
||||
license = lib.licenses.lgpl21Plus;
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = [ ];
|
||||
};
|
||||
})
|
||||
31
packages/cockpit-podman/version.json
Normal file
31
packages/cockpit-podman/version.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"variables": {
|
||||
"version": "123",
|
||||
"cockpitRepoCommit": "5fb84eaefbc5ff4433a21bc452270af8d09e1ab7",
|
||||
"nodeCacheRev": "e39ef3621b5aefa5bf1c2de7e66a5918fcef620c"
|
||||
},
|
||||
"sources": {
|
||||
"src": {
|
||||
"fetcher": "github",
|
||||
"owner": "cockpit-project",
|
||||
"repo": "cockpit-podman",
|
||||
"tag": "${version}",
|
||||
"hash": "sha256-SkZb8NcN8iSocVpdg4Y8KWNKfyBKn6HhYSO7kIcjxHw="
|
||||
},
|
||||
"nodeModules": {
|
||||
"fetcher": "github",
|
||||
"owner": "cockpit-project",
|
||||
"repo": "node-cache",
|
||||
"rev": "${nodeCacheRev}",
|
||||
"hash": "sha256-v+0y2MWvx3NSxEwnuC9GYY0wyRYOV/YnG0a2QbsP/kA="
|
||||
},
|
||||
"cockpitLib": {
|
||||
"fetcher": "github",
|
||||
"owner": "cockpit-project",
|
||||
"repo": "cockpit",
|
||||
"rev": "${cockpitRepoCommit}",
|
||||
"hash": "sha256-H9eeTprI0rBKv//1TvGWTtgb5N09/8Audtu5dE1y86o="
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user