Migrate localsend to clanServices
This commit is contained in:
@@ -61,6 +61,7 @@ in
|
|||||||
garage = import ./garage nixosTestArgs;
|
garage = import ./garage nixosTestArgs;
|
||||||
heisenbridge = import ./heisenbridge nixosTestArgs;
|
heisenbridge = import ./heisenbridge nixosTestArgs;
|
||||||
mycelium = import ./mycelium nixosTestArgs;
|
mycelium = import ./mycelium nixosTestArgs;
|
||||||
|
localsend = import ./localsend nixosTestArgs;
|
||||||
}
|
}
|
||||||
// lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "aarch64-linux") {
|
// lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "aarch64-linux") {
|
||||||
# for some reason this hangs in an odd place in CI, but it works on my machine ...
|
# for some reason this hangs in an odd place in CI, but it works on my machine ...
|
||||||
|
|||||||
51
checks/localsend/default.nix
Normal file
51
checks/localsend/default.nix
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
nixosLib,
|
||||||
|
clan-core,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
nixosLib.runTest (
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
clan-core.modules.nixosVmTest.clanTest
|
||||||
|
];
|
||||||
|
|
||||||
|
hostPkgs = pkgs;
|
||||||
|
|
||||||
|
name = "localsend";
|
||||||
|
|
||||||
|
clan = {
|
||||||
|
directory = ./.;
|
||||||
|
modules."@clan/localsend" = ../../clanServices/localsend/default.nix;
|
||||||
|
inventory = {
|
||||||
|
machines.server = { };
|
||||||
|
|
||||||
|
instances = {
|
||||||
|
localsend-test = {
|
||||||
|
module.name = "@clan/localsend";
|
||||||
|
roles.default.machines."server".settings = {
|
||||||
|
displayName = "Test Instance";
|
||||||
|
ipv4Addr = "192.168.56.2/24";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes = {
|
||||||
|
server = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
start_all()
|
||||||
|
|
||||||
|
# Check that the localsend wrapper script is available
|
||||||
|
server.succeed("command -v localsend")
|
||||||
|
|
||||||
|
# Verify the 09-zerotier network is configured with the specified IP address
|
||||||
|
server.succeed("grep -q 'Address=192.168.56.2/24' /etc/systemd/network/09-zerotier.network")
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
)
|
||||||
4
checks/localsend/sops/users/admin/key.json
Normal file
4
checks/localsend/sops/users/admin/key.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
|
||||||
|
"type": "age"
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
---
|
---
|
||||||
description = "Securely sharing files and messages over a local network without internet connectivity."
|
description = "Securely sharing files and messages over a local network without internet connectivity."
|
||||||
|
categories = ["Utility"]
|
||||||
|
features = [ "inventory", "deprecated" ]
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
./ergochat/flake-module.nix
|
./ergochat/flake-module.nix
|
||||||
./garage/flake-module.nix
|
./garage/flake-module.nix
|
||||||
./heisenbridge/flake-module.nix
|
./heisenbridge/flake-module.nix
|
||||||
|
./localsend/flake-module.nix
|
||||||
./mycelium/flake-module.nix
|
./mycelium/flake-module.nix
|
||||||
./auto-upgrade/flake-module.nix
|
./auto-upgrade/flake-module.nix
|
||||||
./hello-world/flake-module.nix
|
./hello-world/flake-module.nix
|
||||||
|
|||||||
83
clanServices/localsend/default.nix
Normal file
83
clanServices/localsend/default.nix
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
_class = "clan.service";
|
||||||
|
manifest.name = "clan-core/localsend";
|
||||||
|
manifest.description = "Local network file sharing application";
|
||||||
|
manifest.categories = [ "Utility" ];
|
||||||
|
|
||||||
|
roles.default = {
|
||||||
|
interface =
|
||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
displayName = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = "The name that localsend will use to display your instance.";
|
||||||
|
};
|
||||||
|
|
||||||
|
package = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.package;
|
||||||
|
default = null;
|
||||||
|
defaultText = "pkgs.localsend of the machine";
|
||||||
|
description = "The localsend package to use.";
|
||||||
|
};
|
||||||
|
|
||||||
|
ipv4Addr = lib.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
example = "192.168.56.2/24";
|
||||||
|
description = "Optional IPv4 address for ZeroTier network. Only needed until IPv6 multicasting is supported.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
perInstance =
|
||||||
|
{
|
||||||
|
settings,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
nixosModule =
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
|
||||||
|
config = {
|
||||||
|
|
||||||
|
clan.core.state.localsend.folders = [ "/var/localsend" ];
|
||||||
|
|
||||||
|
environment.systemPackages =
|
||||||
|
let
|
||||||
|
localsend-ensure-config = pkgs.writers.writePython3Bin "localsend-ensure-config" {
|
||||||
|
} ./localsend-ensure-config.py;
|
||||||
|
|
||||||
|
localsend = pkgs.writeShellScriptBin "localsend" ''
|
||||||
|
set -xeu
|
||||||
|
${lib.getExe localsend-ensure-config} ${
|
||||||
|
lib.optionalString (settings.displayName != null) settings.displayName
|
||||||
|
}
|
||||||
|
${if settings.package != null then lib.getExe settings.package else lib.getExe pkgs.localsend}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
[ localsend ];
|
||||||
|
|
||||||
|
networking.firewall.interfaces."zt+".allowedTCPPorts = [ 53317 ];
|
||||||
|
networking.firewall.interfaces."zt+".allowedUDPPorts = [ 53317 ];
|
||||||
|
|
||||||
|
# This is currently needed because there is no ipv6 multicasting support yet
|
||||||
|
systemd.network.networks = lib.mkIf (settings.ipv4Addr != null) {
|
||||||
|
"09-zerotier" = {
|
||||||
|
networkConfig = {
|
||||||
|
Address = settings.ipv4Addr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
6
clanServices/localsend/flake-module.nix
Normal file
6
clanServices/localsend/flake-module.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{ lib, ... }:
|
||||||
|
{
|
||||||
|
clan.modules = {
|
||||||
|
localsend = lib.modules.importApply ./default.nix { };
|
||||||
|
};
|
||||||
|
}
|
||||||
64
clanServices/localsend/localsend-ensure-config.py
Normal file
64
clanServices/localsend/localsend-ensure-config.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def load_json(file_path: Path) -> dict[str, any]:
|
||||||
|
try:
|
||||||
|
with file_path.open("r") as file:
|
||||||
|
return json.load(file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def save_json(file_path: Path, data: dict[str, any]) -> None:
|
||||||
|
with file_path.open("w") as file:
|
||||||
|
json.dump(data, file, indent=4)
|
||||||
|
|
||||||
|
|
||||||
|
def update_json(file_path: Path, updates: dict[str, any]) -> None:
|
||||||
|
data = load_json(file_path)
|
||||||
|
data.update(updates)
|
||||||
|
save_json(file_path, data)
|
||||||
|
|
||||||
|
|
||||||
|
def config_location() -> str:
|
||||||
|
config_file = "shared_preferences.json"
|
||||||
|
config_directory = ".local/share/org.localsend.localsend_app"
|
||||||
|
config_path = Path.home() / Path(config_directory) / Path(config_file)
|
||||||
|
return config_path
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_config_directory() -> None:
|
||||||
|
config_directory = Path(config_location()).parent
|
||||||
|
config_directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def load_config() -> dict[str, any]:
|
||||||
|
return load_json(config_location())
|
||||||
|
|
||||||
|
|
||||||
|
def save_config(data: dict[str, any]) -> None:
|
||||||
|
save_json(config_location(), data)
|
||||||
|
|
||||||
|
|
||||||
|
def update_username(username: str, data: dict[str, any]) -> dict[str, any]:
|
||||||
|
data["flutter.ls_alias"] = username
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def main(argv: list[str]) -> None:
|
||||||
|
try:
|
||||||
|
display_name = argv[1]
|
||||||
|
except IndexError:
|
||||||
|
# This is not an error, just don't update the name
|
||||||
|
print("No display name provided.")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
ensure_config_directory()
|
||||||
|
updated_data = update_username(display_name, load_config())
|
||||||
|
save_config(updated_data)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv[:2])
|
||||||
@@ -89,6 +89,7 @@ nav:
|
|||||||
- reference/clanServices/ergochat.md
|
- reference/clanServices/ergochat.md
|
||||||
- reference/clanServices/garage.md
|
- reference/clanServices/garage.md
|
||||||
- reference/clanServices/heisenbridge.md
|
- reference/clanServices/heisenbridge.md
|
||||||
|
- reference/clanServices/localsend.md
|
||||||
- reference/clanServices/mycelium.md
|
- reference/clanServices/mycelium.md
|
||||||
- reference/clanServices/hello-world.md
|
- reference/clanServices/hello-world.md
|
||||||
- reference/clanServices/wifi.md
|
- reference/clanServices/wifi.md
|
||||||
|
|||||||
Reference in New Issue
Block a user