Compare commits
No commits in common. "5c67309439c82ceee48b92a52442fd2853fbac6f" and "507779e30656c5cbf82639a34e11c10bf7deb5bc" have entirely different histories.
5c67309439
...
507779e306
19 changed files with 252 additions and 357 deletions
|
|
@ -1,28 +0,0 @@
|
|||
# Devil's Advocate Review — Project Conventions
|
||||
|
||||
## Critical rules (must never be violated)
|
||||
|
||||
- **Never update `system.stateVersion`** — it must remain at the original installation version. NixOS upgrades are done by updating the `channel` file, not `stateVersion`.
|
||||
- **Never modify `secrets.yaml` directly** — these are SOPS-encrypted. Changes must be made via `nix-shell -p sops --run 'sops <file>'`.
|
||||
- **No plaintext secrets in Nix files** — passwords, API keys, tokens, and private keys must use `sops.secrets`, never hardcoded strings.
|
||||
|
||||
## Architecture rules
|
||||
|
||||
- **Explicit module imports only** — no wildcard or directory-level imports. Each module must be imported by its explicit path.
|
||||
- **Host structure** — each host in `hosts/<name>/` must have `configuration.nix` and `hardware-configuration.nix`. Symlinks `fleet.nix` and `utils/` point to root level.
|
||||
- **Shared modules** go in `utils/modules/`, not duplicated across hosts.
|
||||
- **Custom packages** in `utils/pkgs/` must include an `update.sh` script for automated version updates.
|
||||
|
||||
## Code style
|
||||
|
||||
- **Two-space indentation** in all Nix files.
|
||||
- **Lower kebab-case** for file and directory naming.
|
||||
- **Conventional Commits** format: `fix:`, `feat:`, `chore:`, with optional scope by host (e.g., `fix(mail):`).
|
||||
- No "Generated with Claude Code" or "Co-Authored-By: Claude" footers in commits.
|
||||
|
||||
## Common review checks
|
||||
|
||||
- New network services must have corresponding `networking.firewall.allowedTCPPorts` or `allowedUDPPorts` entries.
|
||||
- New `sops.secrets.<name>` references must have a corresponding entry in the host's `secrets.yaml` (or the relevant module's `secrets.yaml`).
|
||||
- Changes to `utils/` affect all hosts — verify cross-host compatibility.
|
||||
- Package modifications should be testable with a direct `nix-build`, not just `test-configuration`.
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
# Lint Fixer Instructions
|
||||
|
||||
## Formatter
|
||||
|
||||
This project uses **nixpkgs-fmt** for Nix file formatting.
|
||||
|
||||
## How to run
|
||||
|
||||
1. Find changed `.nix` files:
|
||||
```bash
|
||||
git diff --name-only --diff-filter=d HEAD | grep '\.nix$'
|
||||
```
|
||||
2. Format only those files:
|
||||
```bash
|
||||
nix run nixpkgs#nixpkgs-fmt -- <file1.nix> <file2.nix> ...
|
||||
```
|
||||
3. Stage any formatting changes:
|
||||
```bash
|
||||
git add <formatted files>
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Only format files that were actually modified, not the entire repo.
|
||||
- There is no `.editorconfig` or other formatter config; `nixpkgs-fmt` uses its own defaults.
|
||||
- Non-Nix files do not need formatting.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Secret Scanner Allowlist
|
||||
|
||||
## False positive patterns to ignore
|
||||
|
||||
### SOPS-encrypted secrets files
|
||||
All `secrets.yaml` files in this repo are **SOPS-encrypted** (not plaintext). They contain encrypted ciphertext, not actual secrets. Ignore:
|
||||
- `hosts/*/secrets.yaml`
|
||||
- `hosts/*/modules/*/secrets.yaml`
|
||||
- `utils/modules/*/secrets.yaml`
|
||||
- Any `.yaml` file matching a `path_regex` in `.sops.yaml`
|
||||
|
||||
### Age public keys
|
||||
The file `.sops.yaml` contains **age public keys** (prefix `age1...`). These are public keys used for encryption, not private keys. Ignore:
|
||||
- Age public keys (`age1...`) in `.sops.yaml`
|
||||
- Age public key references (YAML anchors like `&dominik`, `&fw`, etc.) in `.sops.yaml`
|
||||
|
||||
### Nix hashes and store paths
|
||||
Nix derivations contain SHA256/SRI hashes for source integrity verification. These are not secrets. Ignore:
|
||||
- `sha256` / `hash` attributes in `.nix` files (e.g., `sha256 = "sha256-..."` or `hash = "sha256-..."`)
|
||||
- `npmDepsHash`, `vendorHash`, `cargoHash`, and similar dependency hashes
|
||||
- Nix store paths (`/nix/store/...`)
|
||||
- `nix-prefetch-url` output hashes
|
||||
- SRI hashes (`sha256-...`, `sha512-...`)
|
||||
|
||||
### sops-nix module configuration
|
||||
Nix files reference sops secret paths as configuration, not actual secret values. Ignore:
|
||||
- `sops.secrets.<name>` attribute sets
|
||||
- `sopsFile` path references
|
||||
- `key` attributes within `sops.secrets` blocks (these are YAML key paths, not cryptographic keys)
|
||||
- `neededForUsers` attributes
|
||||
|
||||
### Other safe patterns
|
||||
- `flake.lock` — contains Nix flake input hashes (integrity, not secrets)
|
||||
- SSH **public** key strings in NixOS configuration (e.g., `openssh.authorizedKeys.keys`)
|
||||
- Wireguard **public** keys in NixOS configuration
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Test Runner Instructions
|
||||
|
||||
## Determine affected hosts
|
||||
|
||||
Run `git diff --name-only HEAD` (or `git diff --name-only` for unstaged changes) to find changed files.
|
||||
|
||||
### Scope rules
|
||||
|
||||
- If changes are **only** under `hosts/<name>/`, test only that specific host:
|
||||
```bash
|
||||
./scripts/test-configuration <name>
|
||||
```
|
||||
- If changes touch `utils/`, root-level `.nix` files, or any shared configuration, test **all** hosts:
|
||||
```bash
|
||||
for host in amzebs-01 fw mail nas nb web-arm; do
|
||||
./scripts/test-configuration "$host"
|
||||
done
|
||||
```
|
||||
|
||||
### Custom package changes
|
||||
|
||||
If any files under `utils/pkgs/<package-name>/` were modified, also build the package directly:
|
||||
|
||||
```bash
|
||||
nix-build -E 'with import <nixpkgs> { overlays = [ (import ./utils/overlays/packages.nix) ]; config.allowUnfree = true; }; <package-name>'
|
||||
```
|
||||
|
||||
This catches build failures that `test-configuration` (evaluation-only) would miss.
|
||||
|
||||
## Notes
|
||||
|
||||
- Each `test-configuration` run performs a `nix-instantiate` dry-build (evaluation only, no binary builds).
|
||||
- A non-zero exit code from any host means the test failed.
|
||||
- Testable hosts: `amzebs-01`, `fw`, `mail`, `nas`, `nb`, `web-arm`.
|
||||
- `dev` is not independently testable (no `hardware-configuration.nix`); it is deployed as a MicroVM via the `fw` host, so testing `fw` covers `dev`.
|
||||
|
|
@ -89,7 +89,7 @@ nix-build -E 'with import <nixpkgs> { overlays = [ (import ./utils/overlays/pack
|
|||
|
||||
## Workflow
|
||||
|
||||
Run `./scripts/test-configuration <hostname>` to verify NixOS configuration changes build successfully.
|
||||
**IMPORTANT: Always run `./scripts/test-configuration <hostname>` after making any changes** to verify the NixOS configuration builds successfully. This is required before committing.
|
||||
|
||||
## Conventions
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,11 @@
|
|||
networking.domain = "cloonar.com";
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFshMhXwS0FQFPlITipshvNKrV8sA52ZFlnaoHd1thKg"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
programs.ssh = {
|
||||
knownHosts = {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
projectsDir = "projects"; # Relative to /home/dominik
|
||||
projectsDir = "projects"; # Relative to /home/dominik
|
||||
|
||||
repositories = [
|
||||
{ url = "forgejo@git.cloonar.com:Cloonar/wohnservice-wien-typo3.git"; path = "cloonar/wohnservice-wien"; }
|
||||
|
|
@ -46,9 +46,12 @@ in
|
|||
uid = 1000;
|
||||
home = "/home/dominik";
|
||||
extraGroups = [ "wheel" "docker" ];
|
||||
openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix;
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
};
|
||||
users.groups.users = { };
|
||||
users.groups.users = {};
|
||||
|
||||
services.openssh.enable = true;
|
||||
programs.zsh.enable = true;
|
||||
|
|
@ -100,12 +103,12 @@ in
|
|||
Group = "users";
|
||||
};
|
||||
script = ''
|
||||
mkdir -p /home/dominik/.ddev
|
||||
if [ ! -f /home/dominik/.ddev/global_config.yaml ]; then
|
||||
cat > /home/dominik/.ddev/global_config.yaml << 'EOF'
|
||||
router_bind_all_interfaces: true
|
||||
EOF
|
||||
fi
|
||||
mkdir -p /home/dominik/.ddev
|
||||
if [ ! -f /home/dominik/.ddev/global_config.yaml ]; then
|
||||
cat > /home/dominik/.ddev/global_config.yaml << 'EOF'
|
||||
router_bind_all_interfaces: true
|
||||
EOF
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,10 @@
|
|||
zramSwap.enable = true;
|
||||
networking.hostName = "fw";
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
# backups
|
||||
borgbackup.repo = "u149513-sub2@u149513-sub2.your-backup.de:borg";
|
||||
|
|
|
|||
|
|
@ -1,89 +1,87 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
{ config, lib, pkgs, ... }: let
|
||||
# Short names to fit Linux interface name limit (15 chars for vm-fj-runner-1)
|
||||
runners = [ "fj-runner-1" "fj-runner-2" ];
|
||||
runners = ["fj-runner-1" "fj-runner-2"];
|
||||
# Offset by 5 to avoid conflicts with Gitea runners (01-02)
|
||||
runnerOffset = 5;
|
||||
in
|
||||
{
|
||||
microvm.vms = lib.mapAttrs
|
||||
(runner: idx: {
|
||||
config = {
|
||||
microvm = {
|
||||
mem = 8096;
|
||||
shares = [
|
||||
{
|
||||
source = "/nix/store";
|
||||
mountPoint = "/nix/.ro-store";
|
||||
tag = "ro-store";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
{
|
||||
source = "/run/secrets";
|
||||
mountPoint = "/run/secrets";
|
||||
tag = "ro-token";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
];
|
||||
volumes = [
|
||||
{
|
||||
image = "rootfs.img";
|
||||
mountPoint = "/";
|
||||
size = 51200;
|
||||
}
|
||||
];
|
||||
interfaces = [
|
||||
{
|
||||
type = "tap";
|
||||
id = "vm-${runner}";
|
||||
mac = "02:00:00:00:00:0${toString (idx + runnerOffset)}";
|
||||
}
|
||||
];
|
||||
};
|
||||
in {
|
||||
microvm.vms = lib.mapAttrs (runner: idx: {
|
||||
config = {
|
||||
microvm = {
|
||||
mem = 8096;
|
||||
shares = [
|
||||
{
|
||||
source = "/nix/store";
|
||||
mountPoint = "/nix/.ro-store";
|
||||
tag = "ro-store";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
{
|
||||
source = "/run/secrets";
|
||||
mountPoint = "/run/secrets";
|
||||
tag = "ro-token";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
];
|
||||
volumes = [
|
||||
{
|
||||
image = "rootfs.img";
|
||||
mountPoint = "/";
|
||||
size = 51200;
|
||||
}
|
||||
];
|
||||
interfaces = [
|
||||
{
|
||||
type = "tap";
|
||||
id = "vm-${runner}";
|
||||
mac = "02:00:00:00:00:0${toString (idx + runnerOffset)}";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
systemd.network.networks."10-lan" = {
|
||||
matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString (idx + runnerOffset)}";
|
||||
address = [ "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}/24" ];
|
||||
gateway = [ "${config.networkPrefix}.97.1" ];
|
||||
dns = [ "${config.networkPrefix}.97.1" ];
|
||||
};
|
||||
systemd.network.networks."10-lan" = {
|
||||
matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString (idx + runnerOffset)}";
|
||||
address = [ "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}/24" ];
|
||||
gateway = [ "${config.networkPrefix}.97.1" ];
|
||||
dns = [ "${config.networkPrefix}.97.1" ];
|
||||
};
|
||||
|
||||
networking.hostName = runner;
|
||||
networking.hostName = runner;
|
||||
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.podman.enable = true;
|
||||
|
||||
services.gitea-actions-runner.instances.${runner} = {
|
||||
enable = true;
|
||||
url = "https://git.cloonar.com";
|
||||
name = runner;
|
||||
tokenFile = "/run/secrets/forgejo-runner-token";
|
||||
labels = [
|
||||
"ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0"
|
||||
];
|
||||
settings = {
|
||||
container = {
|
||||
network = "podman";
|
||||
};
|
||||
cache = {
|
||||
enabled = true;
|
||||
host = "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}";
|
||||
port = 8088;
|
||||
};
|
||||
services.gitea-actions-runner.instances.${runner} = {
|
||||
enable = true;
|
||||
url = "https://git.cloonar.com";
|
||||
name = runner;
|
||||
tokenFile = "/run/secrets/forgejo-runner-token";
|
||||
labels = [
|
||||
"ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0"
|
||||
];
|
||||
settings = {
|
||||
container = {
|
||||
network = "podman";
|
||||
};
|
||||
cache = {
|
||||
enabled = true;
|
||||
host = "${config.networkPrefix}.97.5${toString (idx + runnerOffset)}";
|
||||
port = 8088;
|
||||
};
|
||||
};
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix;
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ 8088 ];
|
||||
};
|
||||
|
||||
system.stateVersion = "22.05";
|
||||
};
|
||||
})
|
||||
(lib.listToAttrs (lib.lists.imap1 (i: v: { name = v; value = i; }) runners));
|
||||
|
||||
sops.secrets.forgejo-runner-token = { };
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ 8088 ];
|
||||
};
|
||||
|
||||
system.stateVersion = "22.05";
|
||||
};
|
||||
}) (lib.listToAttrs (lib.lists.imap1 (i: v: { name=v; value=i; }) runners));
|
||||
|
||||
sops.secrets.forgejo-runner-token = {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ in
|
|||
privateNetwork = true;
|
||||
hostBridge = "server";
|
||||
hostAddress = "${networkPrefix}.97.1";
|
||||
localAddress = "${networkPrefix}.97.55/24"; # Different from gitea's .50
|
||||
localAddress = "${networkPrefix}.97.55/24"; # Different from gitea's .50
|
||||
bindMounts = {
|
||||
"/var/lib/forgejo" = {
|
||||
hostPath = "/var/lib/forgejo/";
|
||||
|
|
@ -50,7 +50,7 @@ in
|
|||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim # my preferred editor
|
||||
vim # my preferred editor
|
||||
];
|
||||
|
||||
networking = {
|
||||
|
|
@ -96,29 +96,29 @@ in
|
|||
openid = {
|
||||
ENABLE_OPENID_SIGNIN = false;
|
||||
ENABLE_OPENID_SIGNUP = true;
|
||||
WHITELISTED_URIS = "auth.cloonar.com";
|
||||
WHITELISTED_URIS = "auth.cloonar.com";
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = false;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||
SHOW_REGISTRATION_BUTTON = false;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
REQUIRE_SIGNIN_VIEW = false;
|
||||
DISABLE_REGISTRATION = false;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||
SHOW_REGISTRATION_BUTTON = false;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
REQUIRE_SIGNIN_VIEW = false;
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
FROM = "Forgejo Cloonar <gitea@cloonar.com>";
|
||||
PROTOCOL = "smtp+starttls";
|
||||
SMTP_ADDR = "mail.cloonar.com";
|
||||
SMTP_PORT = 587;
|
||||
USER = "gitea@cloonar.com";
|
||||
ENABLED = true;
|
||||
FROM = "Forgejo Cloonar <gitea@cloonar.com>";
|
||||
PROTOCOL = "smtp+starttls";
|
||||
SMTP_ADDR = "mail.cloonar.com";
|
||||
SMTP_PORT = 587;
|
||||
USER = "gitea@cloonar.com";
|
||||
};
|
||||
actions = {
|
||||
ENABLED = true;
|
||||
DEFAULT_ACTIONS_URL = "github"; # Pull actions from GitHub
|
||||
DEFAULT_ACTIONS_URL = "github"; # Pull actions from GitHub
|
||||
};
|
||||
attachment = {
|
||||
MAX_SIZE = 2048; # 2GB in MB for general attachments
|
||||
MAX_SIZE = 2048; # 2GB in MB for general attachments
|
||||
};
|
||||
packages = {
|
||||
ENABLED = true;
|
||||
|
|
@ -130,7 +130,10 @@ in
|
|||
systemd.services.forgejo.serviceConfig.EnvironmentFile = "/run/secrets/forgejo-mailer-password";
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
users.users.forgejo = user;
|
||||
users.groups.forgejo = group;
|
||||
|
|
|
|||
|
|
@ -1,90 +1,88 @@
|
|||
{ config, lib, nixpkgs, pkgs, ... }:
|
||||
let
|
||||
{ config, lib, nixpkgs, pkgs, ... }: let
|
||||
# hostname = "git-02";
|
||||
# json = pkgs.formats.json { };
|
||||
runners = [ "git-runner-1" "git-runner-2" ];
|
||||
indexedRunners = lib.lists.imap1 (i: v: { name = v; value = i; }) runners;
|
||||
in
|
||||
{
|
||||
microvm.vms = lib.mapAttrs
|
||||
(runner: idx: {
|
||||
config = {
|
||||
microvm = {
|
||||
mem = 8096;
|
||||
shares = [
|
||||
{
|
||||
source = "/nix/store";
|
||||
mountPoint = "/nix/.ro-store";
|
||||
tag = "ro-store";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
{
|
||||
source = "/run/secrets";
|
||||
mountPoint = "/run/secrets";
|
||||
tag = "ro-token";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
];
|
||||
volumes = [
|
||||
{
|
||||
image = "rootfs.img";
|
||||
mountPoint = "/";
|
||||
size = 51200;
|
||||
}
|
||||
];
|
||||
interfaces = [
|
||||
{
|
||||
type = "tap";
|
||||
id = "vm-${runner}";
|
||||
mac = "02:00:00:00:00:0${toString idx}";
|
||||
}
|
||||
];
|
||||
};
|
||||
runners = ["git-runner-1" "git-runner-2"];
|
||||
indexedRunners = lib.lists.imap1 (i: v: { name=v; value=i; }) runners;
|
||||
in {
|
||||
microvm.vms = lib.mapAttrs (runner: idx: {
|
||||
config = {
|
||||
microvm = {
|
||||
mem = 8096;
|
||||
shares = [
|
||||
{
|
||||
source = "/nix/store";
|
||||
mountPoint = "/nix/.ro-store";
|
||||
tag = "ro-store";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
{
|
||||
source = "/run/secrets";
|
||||
mountPoint = "/run/secrets";
|
||||
tag = "ro-token";
|
||||
proto = "virtiofs";
|
||||
}
|
||||
];
|
||||
volumes = [
|
||||
{
|
||||
image = "rootfs.img";
|
||||
mountPoint = "/";
|
||||
size = 51200;
|
||||
}
|
||||
];
|
||||
interfaces = [
|
||||
{
|
||||
type = "tap";
|
||||
id = "vm-${runner}";
|
||||
mac = "02:00:00:00:00:0${toString idx}";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
systemd.network.networks."10-lan" = {
|
||||
matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString idx}";
|
||||
address = [ "${config.networkPrefix}.97.5${toString idx}/24" ];
|
||||
gateway = [ "${config.networkPrefix}.97.1" ];
|
||||
dns = [ "${config.networkPrefix}.97.1" ];
|
||||
};
|
||||
systemd.network.networks."10-lan" = {
|
||||
matchConfig.PermanentMACAddress = "02:00:00:00:00:0${toString idx}";
|
||||
address = [ "${config.networkPrefix}.97.5${toString idx}/24" ];
|
||||
gateway = [ "${config.networkPrefix}.97.1" ];
|
||||
dns = [ "${config.networkPrefix}.97.1" ];
|
||||
};
|
||||
|
||||
networking.hostName = runner;
|
||||
networking.hostName = runner;
|
||||
|
||||
virtualisation.podman.enable = true;
|
||||
virtualisation.podman.enable = true;
|
||||
|
||||
services.gitea-actions-runner.instances.${runner} = {
|
||||
enable = true;
|
||||
url = "https://git.cloonar.com";
|
||||
name = runner;
|
||||
tokenFile = "/run/secrets/gitea-runner-token";
|
||||
labels = [
|
||||
# "ubuntu-latest:docker://shivammathur/node:latest"
|
||||
"ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0"
|
||||
];
|
||||
settings = {
|
||||
container = {
|
||||
network = "podman";
|
||||
};
|
||||
cache = {
|
||||
enabled = true;
|
||||
host = "${config.networkPrefix}.97.5${toString idx}"; # LAN IP of the machine running act_runner
|
||||
port = 8088; # any free TCP port
|
||||
};
|
||||
services.gitea-actions-runner.instances.${runner} = {
|
||||
enable = true;
|
||||
url = "https://git.cloonar.com";
|
||||
name = runner;
|
||||
tokenFile = "/run/secrets/gitea-runner-token";
|
||||
labels = [
|
||||
# "ubuntu-latest:docker://shivammathur/node:latest"
|
||||
"ubuntu-latest:docker://git.cloonar.com/infrastructure/gitea-runner:1.0.0"
|
||||
];
|
||||
settings = {
|
||||
container = {
|
||||
network = "podman";
|
||||
};
|
||||
cache = {
|
||||
enabled = true;
|
||||
host = "${config.networkPrefix}.97.5${toString idx}"; # LAN IP of the machine running act_runner
|
||||
port = 8088; # any free TCP port
|
||||
};
|
||||
};
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix;
|
||||
|
||||
networking.firewall = {
|
||||
enable = true; # default, but being explicit is fine
|
||||
allowedTCPPorts = [ 8088 ];
|
||||
};
|
||||
|
||||
system.stateVersion = "22.05";
|
||||
};
|
||||
})
|
||||
(lib.listToAttrs (lib.lists.imap1 (i: v: { name = v; value = i; }) runners));
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
];
|
||||
|
||||
networking.firewall = {
|
||||
enable = true; # default, but being explicit is fine
|
||||
allowedTCPPorts = [ 8088 ];
|
||||
};
|
||||
|
||||
system.stateVersion = "22.05";
|
||||
};
|
||||
}) (lib.listToAttrs (lib.lists.imap1 (i: v: { name=v; value=i; }) runners));
|
||||
|
||||
# microvm.vms = {
|
||||
# gitea = {
|
||||
|
|
@ -242,10 +240,10 @@ in
|
|||
# };
|
||||
# };
|
||||
|
||||
sops.secrets.gitea-runner-token = { };
|
||||
sops.secrets.gitea-runner-token = {};
|
||||
|
||||
environment = {
|
||||
systemPackages = [
|
||||
systemPackages = [
|
||||
pkgs.qemu
|
||||
pkgs.quickemu
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ let
|
|||
cids = import ../modules/staticids.nix;
|
||||
domain = "git.cloonar.com";
|
||||
networkPrefix = config.networkPrefix;
|
||||
|
||||
|
||||
user = {
|
||||
isSystemUser = true;
|
||||
uid = cids.uids.gitea;
|
||||
|
|
@ -50,7 +50,7 @@ in
|
|||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim # my preferred editor
|
||||
vim # my preferred editor
|
||||
];
|
||||
|
||||
networking = {
|
||||
|
|
@ -94,26 +94,26 @@ in
|
|||
openid = {
|
||||
ENABLE_OPENID_SIGNIN = false;
|
||||
ENABLE_OPENID_SIGNUP = true;
|
||||
WHITELISTED_URIS = "auth.cloonar.com";
|
||||
WHITELISTED_URIS = "auth.cloonar.com";
|
||||
};
|
||||
service = {
|
||||
DISABLE_REGISTRATION = false;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||
SHOW_REGISTRATION_BUTTON = false;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
REQUIRE_SIGNIN_VIEW = false;
|
||||
DISABLE_REGISTRATION = false;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||
SHOW_REGISTRATION_BUTTON = false;
|
||||
ENABLE_NOTIFY_MAIL = true;
|
||||
REQUIRE_SIGNIN_VIEW = false;
|
||||
};
|
||||
mailer = {
|
||||
ENABLED = true;
|
||||
FROM = "Gitea Cloonar <gitea@cloonar.com>";
|
||||
PROTOCOL = "smtp+starttls";
|
||||
SMTP_ADDR = "mail.cloonar.com";
|
||||
SMTP_PORT = 587;
|
||||
USER = "gitea@cloonar.com";
|
||||
ENABLED = true;
|
||||
FROM = "Gitea Cloonar <gitea@cloonar.com>";
|
||||
PROTOCOL = "smtp+starttls";
|
||||
SMTP_ADDR = "mail.cloonar.com";
|
||||
SMTP_PORT = 587;
|
||||
USER = "gitea@cloonar.com";
|
||||
};
|
||||
actions.ENABLED = true;
|
||||
actions.ENABLED=true;
|
||||
attachment = {
|
||||
MAX_SIZE = 2048; # 2GB in MB for general attachments
|
||||
MAX_SIZE = 2048; # 2GB in MB for general attachments
|
||||
};
|
||||
packages = {
|
||||
ENABLED = true;
|
||||
|
|
@ -122,7 +122,10 @@ in
|
|||
};
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ../utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
users.users.gitea = user;
|
||||
users.groups.gitea = group;
|
||||
|
|
@ -131,7 +134,7 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
sops.secrets.gitea-runner = { };
|
||||
sops.secrets.gitea-runner = {};
|
||||
sops.secrets.gitea-mailer-password = {
|
||||
owner = "gitea";
|
||||
restartUnits = [ "container@git.service" ];
|
||||
|
|
|
|||
|
|
@ -11,7 +11,10 @@ let
|
|||
gateway = "${config.networkPrefix}.97.1";
|
||||
tapDevice = "vm-openclaw";
|
||||
|
||||
sshAuthorizedKeys = import ../utils/ssh-keys.nix;
|
||||
sshAuthorizedKeys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
gitRepoUrl = "https://git.cloonar.com/openclawd/config.git";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
{ lib, pkgs, config, ... }:
|
||||
let
|
||||
{ lib, pkgs, config, ... }: let
|
||||
hostname = "web-02";
|
||||
json = pkgs.formats.json { };
|
||||
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
|
||||
in
|
||||
{
|
||||
in {
|
||||
microvm.vms = {
|
||||
web = {
|
||||
pkgs = import pkgs.path {
|
||||
|
|
@ -98,7 +96,7 @@ in
|
|||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim # my preferred editor
|
||||
vim # my preferred editor
|
||||
];
|
||||
|
||||
networking.hostName = hostname;
|
||||
|
|
@ -106,18 +104,21 @@ in
|
|||
services.openssh = {
|
||||
enable = true;
|
||||
hostKeys = [
|
||||
{
|
||||
path = "/persist/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}
|
||||
{
|
||||
path = "/persist/etc/ssh/ssh_host_rsa_key";
|
||||
type = "rsa";
|
||||
bits = 4096;
|
||||
}
|
||||
];
|
||||
{
|
||||
path = "/persist/etc/ssh/ssh_host_ed25519_key";
|
||||
type = "ed25519";
|
||||
}
|
||||
{
|
||||
path = "/persist/etc/ssh/ssh_host_rsa_key";
|
||||
type = "rsa";
|
||||
bits = 4096;
|
||||
}
|
||||
];
|
||||
};
|
||||
users.users.root.openssh.authorizedKeys.keys = import ../../utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{ config, pkgs, ... }:
|
||||
{
|
||||
{
|
||||
imports = [
|
||||
./utils/bento.nix
|
||||
./utils/modules/sops.nix
|
||||
|
|
@ -29,7 +29,10 @@
|
|||
environment.systemPackages = with pkgs; [ vim ];
|
||||
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
# backups
|
||||
borgbackup.repo = "u149513-sub7@u149513-sub7.your-backup.de:borg";
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
|
||||
in
|
||||
{
|
||||
in {
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
imports = [
|
||||
|
|
@ -39,7 +38,10 @@ in
|
|||
|
||||
# SSH server
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
# Firewall
|
||||
networking.firewall.enable = true;
|
||||
|
|
|
|||
|
|
@ -81,7 +81,10 @@
|
|||
networking.hostName = "web-arm";
|
||||
networking.domain = "cloonar.com";
|
||||
services.openssh.enable = true;
|
||||
users.users.root.openssh.authorizedKeys.keys = import ./utils/ssh-keys.nix;
|
||||
users.users.root.openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
];
|
||||
|
||||
programs.ssh = {
|
||||
knownHosts = {
|
||||
|
|
|
|||
2
todos.md
2
todos.md
|
|
@ -6,4 +6,4 @@ switch from gitea to forgejo
|
|||
## chache server
|
||||
https://github.com/zhaofengli/attic
|
||||
|
||||
# TODO: set ssh keys that each server should accept somewhere globally in utils and each server should implement it
|
||||
set ssh keys that each server should accept somewhere globally in utils and each server should implement it
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
[
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFshMhXwS0FQFPlITipshvNKrV8sA52ZFlnaoHd1thKg"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue