add headscale and syncthing
This commit is contained in:
parent
d90ad7fbc5
commit
cfa997a852
9 changed files with 533 additions and 29 deletions
50
flake.lock
generated
50
flake.lock
generated
|
|
@ -8,11 +8,11 @@
|
||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1747575206,
|
"lastModified": 1750173260,
|
||||||
"narHash": "sha256-NwmAFuDUO/PFcgaGGr4j3ozG9Pe5hZ/ogitWhY+D81k=",
|
"narHash": "sha256-9P1FziAwl5+3edkfFcr5HeGtQUtrSdk/MksX39GieoA=",
|
||||||
"owner": "ryantm",
|
"owner": "ryantm",
|
||||||
"repo": "agenix",
|
"repo": "agenix",
|
||||||
"rev": "4835b1dc898959d8547a871ef484930675cb47f1",
|
"rev": "531beac616433bac6f9e2a19feb8e99a22a66baf",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -26,11 +26,11 @@
|
||||||
"nixpkgs": "nixpkgs_2"
|
"nixpkgs": "nixpkgs_2"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1750013871,
|
"lastModified": 1751021896,
|
||||||
"narHash": "sha256-UQx3rC3QDjD/sIen51+5Juk1rqN3y/sTeMY1WinmhqQ=",
|
"narHash": "sha256-L9u68mNPPiuW7+OV5BKbXaj/AENTiiuEx8+QnMBjRlU=",
|
||||||
"owner": "catppuccin",
|
"owner": "catppuccin",
|
||||||
"repo": "nix",
|
"repo": "nix",
|
||||||
"rev": "fe78fa558d6603481c03eb03a946eadb970d1801",
|
"rev": "a6b0e34d083c79f08efabb1fd6ccf12b882daae6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -158,11 +158,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1750127463,
|
"lastModified": 1751384836,
|
||||||
"narHash": "sha256-K2xFtlD3PcKAZriOE3LaBLYmVfGQu+rIF4Jr1RFYR0Q=",
|
"narHash": "sha256-7xRbl/VLXxE5DzJmk1wdKWJmPx8rAfNC/a6mXtqp5cc=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "28eef8722d1af18ca13e687dbf485e1c653a0402",
|
"rev": "479f8889675770881033878a1c114fbfc6de7a4d",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -236,11 +236,11 @@
|
||||||
"spectrum": "spectrum"
|
"spectrum": "spectrum"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1750196518,
|
"lastModified": 1750358184,
|
||||||
"narHash": "sha256-HJYnJg3TvzFZjVgYHZgH3NtwqkqKiGVCJXpZlO4Y4EE=",
|
"narHash": "sha256-17EYMeY5v8KRk9HW6Z4dExY8Wg4y/zM2eM2wbbx+vMs=",
|
||||||
"owner": "astro",
|
"owner": "astro",
|
||||||
"repo": "microvm.nix",
|
"repo": "microvm.nix",
|
||||||
"rev": "094da86a3e68f2f0d93b654e97b5d42398ead67d",
|
"rev": "fd9f5dba1ffee5ad6f29394b2a9e4c66c1ce77dc",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -251,11 +251,11 @@
|
||||||
},
|
},
|
||||||
"nixos-hardware": {
|
"nixos-hardware": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1750083401,
|
"lastModified": 1751393906,
|
||||||
"narHash": "sha256-ynqbgIYrg7P1fAKYqe8I/PMiLABBcNDYG9YaAP/d/C4=",
|
"narHash": "sha256-I1x6K61ZcdFlqc07weRBy3erCAB0lVkX10i0c9eXjDI=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixos-hardware",
|
"repo": "nixos-hardware",
|
||||||
"rev": "61837d2a33ccc1582c5fabb7bf9130d39fee59ad",
|
"rev": "f49bb3b4107a0917ee144337bb02d311033ee1ba",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -299,16 +299,16 @@
|
||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1750005367,
|
"lastModified": 1751271578,
|
||||||
"narHash": "sha256-h/aac1dGLhS3qpaD2aZt25NdKY7b+JT0ZIP2WuGsJMU=",
|
"narHash": "sha256-P/SQmKDu06x8yv7i0s8bvnnuJYkxVGBWLWHaU+tt4YY=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "6c64dabd3aa85e0c02ef1cdcb6e1213de64baee3",
|
"rev": "3016b4b15d13f3089db8a41ef937b13a9e33a8df",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"ref": "nixos-25.05",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
|
|
@ -422,11 +422,11 @@
|
||||||
"nixpkgs": "nixpkgs_4"
|
"nixpkgs": "nixpkgs_4"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1729422940,
|
"lastModified": 1750353031,
|
||||||
"narHash": "sha256-DlvJv33ml5UTKgu4b0HauOfFIoDx6QXtbqUF3vWeRCY=",
|
"narHash": "sha256-Bx7DOPLhkr8Z60U9Qw4l0OidzHoqLDKQH5rDV5ef59A=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "nixos-vscode-server",
|
"repo": "nixos-vscode-server",
|
||||||
"rev": "8b6db451de46ecf9b4ab3d01ef76e59957ff549f",
|
"rev": "4ec4859b12129c0436b0a471ed1ea6dd8a317993",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
@ -443,11 +443,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1750091187,
|
"lastModified": 1751383329,
|
||||||
"narHash": "sha256-mjAol6qR+onnZwLUdYjmuBr/tnyozUBXz75tSePVU00=",
|
"narHash": "sha256-52dUY8jEkuXEIZINYb+AVsrmw6FxMhBAG3K9J/2qiSo=",
|
||||||
"owner": "0xc000022070",
|
"owner": "0xc000022070",
|
||||||
"repo": "zen-browser-flake",
|
"repo": "zen-browser-flake",
|
||||||
"rev": "cfdf98dac59a42e1642c533a5dbfb5bb242903b3",
|
"rev": "f29a4fece3b76c3e4579d67e2cf0cb8037f6a351",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# flake.nix
|
# flake.nix
|
||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05";
|
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||||
nixos-hardware.url = "github:nixos/nixos-hardware/master";
|
nixos-hardware.url = "github:nixos/nixos-hardware/master";
|
||||||
|
|
||||||
lix-module = {
|
lix-module = {
|
||||||
|
|
@ -64,6 +64,8 @@
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ imports = builtins.attrValues nixosModules; }
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -149,6 +149,7 @@ window#waybar {
|
||||||
output = [
|
output = [
|
||||||
"HDMI-A-1"
|
"HDMI-A-1"
|
||||||
"DP-1"
|
"DP-1"
|
||||||
|
"DP-2"
|
||||||
];
|
];
|
||||||
modules-left = [
|
modules-left = [
|
||||||
"sway/workspaces"
|
"sway/workspaces"
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,6 @@
|
||||||
virtualisation.docker = {
|
virtualisation.docker = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableOnBoot = true;
|
enableOnBoot = true;
|
||||||
package = pkgs.docker.override {
|
|
||||||
buildGoModule = pkgs.buildGo123Module;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,12 @@
|
||||||
../../host-secrets.nix
|
../../host-secrets.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
modules.syncthing = {
|
||||||
|
enable = true;
|
||||||
|
openDefaultPorts = true;
|
||||||
|
disableDefaultFolder = true;
|
||||||
|
};
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# SYSTEM CONFIGURATION
|
# SYSTEM CONFIGURATION
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
|
||||||
229
modules/headscale/default.nix
Normal file
229
modules/headscale/default.nix
Normal file
|
|
@ -0,0 +1,229 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.modules.headscale;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
modules = {
|
||||||
|
headscale = {
|
||||||
|
enable = mkEnableOption "Deploy headscale";
|
||||||
|
|
||||||
|
oidcClientSecretPath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "/etc/headscale/oidc_client_secret.key";
|
||||||
|
description = "Path to OIDC client secret file";
|
||||||
|
example = "config.age.secrets.headscale-oidc-key.path";
|
||||||
|
};
|
||||||
|
|
||||||
|
litestream = {
|
||||||
|
enable = mkEnableOption "Enable litestream for headscale database backups";
|
||||||
|
|
||||||
|
replicas = mkOption {
|
||||||
|
type = types.listOf (types.attrsOf types.anything);
|
||||||
|
default = [];
|
||||||
|
description = "List of litestream replica configurations";
|
||||||
|
example = [
|
||||||
|
{
|
||||||
|
url = "s3://your-backup-bucket/headscale/db";
|
||||||
|
access-key-id = "$LITESTREAM_ACCESS_KEY_ID";
|
||||||
|
secret-access-key = "$LITESTREAM_SECRET_ACCESS_KEY";
|
||||||
|
region = "us-east-1";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
backupPath = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Local backup path (alternative to S3)";
|
||||||
|
example = "/backup/headscale";
|
||||||
|
};
|
||||||
|
|
||||||
|
syncInterval = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "1s";
|
||||||
|
description = "How often to sync to replicas";
|
||||||
|
};
|
||||||
|
|
||||||
|
retention = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "72h";
|
||||||
|
description = "How long to retain snapshots";
|
||||||
|
};
|
||||||
|
|
||||||
|
environmentFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Environment file containing S3 credentials (can be agenix secret)";
|
||||||
|
example = "config.age.secrets.litestream-env.path";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
services.headscale = {
|
||||||
|
enable = true;
|
||||||
|
address = "0.0.0.0";
|
||||||
|
port = 8080;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
server_url = "https://headscale.nekomimi.pet";
|
||||||
|
|
||||||
|
# Metrics and gRPC
|
||||||
|
metrics_listen_addr = "127.0.0.1:9090";
|
||||||
|
grpc_listen_addr = "127.0.0.1:50443";
|
||||||
|
grpc_allow_insecure = false;
|
||||||
|
|
||||||
|
# Prefixes
|
||||||
|
prefixes = {
|
||||||
|
v4 = "100.64.0.0/10";
|
||||||
|
v6 = "fd7a:115c:a1e0::/48";
|
||||||
|
allocation = "sequential";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Database
|
||||||
|
database = {
|
||||||
|
type = "sqlite";
|
||||||
|
sqlite = {
|
||||||
|
path = "/var/lib/headscale/db.sqlite";
|
||||||
|
write_ahead_log = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Noise
|
||||||
|
noise = {
|
||||||
|
private_key_path = "/var/lib/headscale/noise_private.key";
|
||||||
|
};
|
||||||
|
|
||||||
|
# DERP
|
||||||
|
derp = {
|
||||||
|
urls = [
|
||||||
|
"https://controlplane.tailscale.com/derpmap/default"
|
||||||
|
];
|
||||||
|
paths = [];
|
||||||
|
auto_update_enabled = true;
|
||||||
|
update_frequency = "24h";
|
||||||
|
server = {
|
||||||
|
enabled = false;
|
||||||
|
region_id = 999;
|
||||||
|
region_code = "headscale";
|
||||||
|
region_name = "Headscale Embedded DERP";
|
||||||
|
stun_listen_addr = "0.0.0.0:3478";
|
||||||
|
private_key_path = "/var/lib/headscale/derp_server_private.key";
|
||||||
|
automatically_add_embedded_derp_region = true;
|
||||||
|
ipv4 = "1.2.3.4";
|
||||||
|
ipv6 = "2001:db8::1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# DNS
|
||||||
|
dns = {
|
||||||
|
magic_dns = true;
|
||||||
|
base_domain = "dns.sharkgirl.pet";
|
||||||
|
nameservers = {
|
||||||
|
global = [
|
||||||
|
"100.64.0.7"
|
||||||
|
"1.1.1.1"
|
||||||
|
"1.0.0.1"
|
||||||
|
"2606:4700:4700::1111"
|
||||||
|
"2606:4700:4700::1001"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
search_domains = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
# OIDC with configurable secret path
|
||||||
|
oidc = {
|
||||||
|
only_start_if_oidc_is_available = true;
|
||||||
|
issuer = "https://pocketid.nekomimi.pet";
|
||||||
|
client_id = "f345acad-3eac-45b7-9d91-57f388987a57";
|
||||||
|
client_secret_path = cfg.oidcClientSecretPath;
|
||||||
|
pkce = {
|
||||||
|
enabled = true;
|
||||||
|
method = "S256";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Policy
|
||||||
|
policy = {
|
||||||
|
mode = "database";
|
||||||
|
};
|
||||||
|
|
||||||
|
# TLS/ACME
|
||||||
|
acme_url = "https://acme-v02.api.letsencrypt.org/directory";
|
||||||
|
acme_email = "";
|
||||||
|
tls_letsencrypt_hostname = "";
|
||||||
|
tls_letsencrypt_cache_dir = "/var/lib/headscale/cache";
|
||||||
|
tls_letsencrypt_challenge_type = "HTTP-01";
|
||||||
|
tls_letsencrypt_listen = ":http";
|
||||||
|
tls_cert_path = "";
|
||||||
|
tls_key_path = "";
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
log = {
|
||||||
|
format = "text";
|
||||||
|
level = "info";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Misc settings
|
||||||
|
disable_check_updates = false;
|
||||||
|
ephemeral_node_inactivity_timeout = "30m";
|
||||||
|
unix_socket = "/var/run/headscale/headscale.sock";
|
||||||
|
unix_socket_permission = "0770";
|
||||||
|
logtail = {
|
||||||
|
enabled = false;
|
||||||
|
};
|
||||||
|
randomize_client_port = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configurable Litestream for SQLite database backups
|
||||||
|
services.litestream = mkIf cfg.litestream.enable {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
dbs = [
|
||||||
|
{
|
||||||
|
path = "/var/lib/headscale/db.sqlite";
|
||||||
|
sync-interval = cfg.litestream.syncInterval;
|
||||||
|
retention = cfg.litestream.retention;
|
||||||
|
replicas =
|
||||||
|
# Use custom replicas if provided
|
||||||
|
if cfg.litestream.replicas != [] then
|
||||||
|
cfg.litestream.replicas
|
||||||
|
# Otherwise use local backup if path is provided
|
||||||
|
else if cfg.litestream.backupPath != null then
|
||||||
|
[{ path = cfg.litestream.backupPath; }]
|
||||||
|
# Default empty (user must configure)
|
||||||
|
else
|
||||||
|
[];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure systemd service to use agenix secrets
|
||||||
|
systemd.services.headscale.serviceConfig = mkMerge [
|
||||||
|
{
|
||||||
|
SupplementaryGroups = [ "headscale-secrets" ];
|
||||||
|
}
|
||||||
|
# Add environment file for litestream if specified
|
||||||
|
(mkIf (cfg.litestream.enable && cfg.litestream.environmentFile != null) {
|
||||||
|
EnvironmentFile = cfg.litestream.environmentFile;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
# Configure litestream service with environment file if specified
|
||||||
|
systemd.services.litestream = mkIf (cfg.litestream.enable && cfg.litestream.environmentFile != null) {
|
||||||
|
serviceConfig = {
|
||||||
|
EnvironmentFile = cfg.litestream.environmentFile;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create a group for accessing secrets
|
||||||
|
users.groups.headscale-secrets = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
257
modules/syncthing/default.nix
Normal file
257
modules/syncthing/default.nix
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
let
|
||||||
|
cfg = config.modules.syncthing;
|
||||||
|
|
||||||
|
# Helper function to create a serviceConfig entry if the condition is met
|
||||||
|
mkServiceConfigOption = name: value: mkIf (value != null) { "${name}" = value; };
|
||||||
|
|
||||||
|
# Construct the settings object for Syncthing
|
||||||
|
syncthingSettings = mkMerge [
|
||||||
|
# GUI configuration
|
||||||
|
(mkIf cfg.gui.enable {
|
||||||
|
gui = mkMerge [
|
||||||
|
(mkIf (cfg.gui.user != null) {
|
||||||
|
user = cfg.gui.user;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
})
|
||||||
|
|
||||||
|
# Devices configuration
|
||||||
|
(mkIf (cfg.devices != {}) {
|
||||||
|
devices = mapAttrs (name: device: {
|
||||||
|
id = device.id;
|
||||||
|
} // optionalAttrs (device.name != null) {
|
||||||
|
name = device.name;
|
||||||
|
} // optionalAttrs (device.addresses != []) {
|
||||||
|
addresses = device.addresses;
|
||||||
|
}) cfg.devices;
|
||||||
|
})
|
||||||
|
|
||||||
|
# Folders configuration
|
||||||
|
(mkIf (cfg.folders != {}) {
|
||||||
|
folders = mapAttrs (name: folder: {
|
||||||
|
path = folder.path;
|
||||||
|
devices = folder.devices;
|
||||||
|
} // optionalAttrs (folder.ignorePerms != null) {
|
||||||
|
ignorePerms = folder.ignorePerms;
|
||||||
|
} // optionalAttrs (folder.type != null) {
|
||||||
|
type = folder.type;
|
||||||
|
} // optionalAttrs (folder.rescanIntervalS != null) {
|
||||||
|
rescanIntervalS = folder.rescanIntervalS;
|
||||||
|
} // optionalAttrs (folder.versioning != null) {
|
||||||
|
versioning = folder.versioning;
|
||||||
|
}) cfg.folders;
|
||||||
|
})
|
||||||
|
|
||||||
|
# Extra options
|
||||||
|
cfg.extraOptions
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
modules.syncthing = {
|
||||||
|
enable = mkEnableOption "Deploy syncthing";
|
||||||
|
|
||||||
|
openDefaultPorts = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Open ports in the firewall for Syncthing";
|
||||||
|
};
|
||||||
|
|
||||||
|
disableDefaultFolder = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Don't create default ~/Sync folder";
|
||||||
|
};
|
||||||
|
|
||||||
|
gui = {
|
||||||
|
enable = mkEnableOption "Enable GUI configuration";
|
||||||
|
|
||||||
|
user = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "GUI username";
|
||||||
|
example = "myuser";
|
||||||
|
};
|
||||||
|
|
||||||
|
passwordFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Path to file containing GUI password";
|
||||||
|
example = "config.age.secrets.syncthing-gui-password.path";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
identity = {
|
||||||
|
keyPath = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Path to Syncthing private key for stable device ID";
|
||||||
|
example = "config.age.secrets.syncthing-key.path";
|
||||||
|
};
|
||||||
|
|
||||||
|
certPath = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = "Path to Syncthing certificate for stable device ID";
|
||||||
|
example = "config.age.secrets.syncthing-cert.path";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
devices = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
id = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Device ID";
|
||||||
|
example = "DMWVMM6-MKEQVB4-I4UZTRH-5A6E24O-XHQTL3K-AAI5R5L-MXNMUGX-QTGRHQ2";
|
||||||
|
};
|
||||||
|
|
||||||
|
name = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = "Device name (optional)";
|
||||||
|
};
|
||||||
|
|
||||||
|
addresses = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "Device addresses";
|
||||||
|
example = [ "tcp://192.168.1.100:22000" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = {};
|
||||||
|
description = "Syncthing devices configuration";
|
||||||
|
example = {
|
||||||
|
"laptop" = {
|
||||||
|
id = "DMWVMM6-MKEQVB4-I4UZTRH-5A6E24O-XHQTL3K-AAI5R5L-MXNMUGX-QTGRHQ2";
|
||||||
|
};
|
||||||
|
"phone" = {
|
||||||
|
id = "ANOTHER-DEVICE-ID-GOES-HERE";
|
||||||
|
addresses = [ "tcp://192.168.1.101:22000" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
folders = mkOption {
|
||||||
|
type = types.attrsOf (types.submodule {
|
||||||
|
options = {
|
||||||
|
path = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Local folder path";
|
||||||
|
example = "/home/myuser/Documents";
|
||||||
|
};
|
||||||
|
|
||||||
|
devices = mkOption {
|
||||||
|
type = types.listOf (types.either types.str (types.submodule {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Device name";
|
||||||
|
};
|
||||||
|
|
||||||
|
encryptionPasswordFile = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = "Path to file containing encryption password";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = [];
|
||||||
|
description = "List of devices that can access this folder";
|
||||||
|
example = [ "laptop" "phone" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
ignorePerms = mkOption {
|
||||||
|
type = types.nullOr types.bool;
|
||||||
|
default = null;
|
||||||
|
description = "Whether to ignore file permissions";
|
||||||
|
};
|
||||||
|
|
||||||
|
type = mkOption {
|
||||||
|
type = types.nullOr (types.enum [ "sendreceive" "sendonly" "receiveonly" ]);
|
||||||
|
default = null;
|
||||||
|
description = "Folder type";
|
||||||
|
};
|
||||||
|
|
||||||
|
rescanIntervalS = mkOption {
|
||||||
|
type = types.nullOr types.int;
|
||||||
|
default = null;
|
||||||
|
description = "Rescan interval in seconds";
|
||||||
|
};
|
||||||
|
|
||||||
|
versioning = mkOption {
|
||||||
|
type = types.nullOr (types.submodule {
|
||||||
|
options = {
|
||||||
|
type = mkOption {
|
||||||
|
type = types.enum [ "external" "simple" "staggered" "trashcan" ];
|
||||||
|
description = "Versioning type";
|
||||||
|
};
|
||||||
|
|
||||||
|
params = mkOption {
|
||||||
|
type = types.attrsOf types.str;
|
||||||
|
default = {};
|
||||||
|
description = "Versioning parameters";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = null;
|
||||||
|
description = "Folder versioning configuration";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = {};
|
||||||
|
description = "Syncthing folders configuration";
|
||||||
|
example = {
|
||||||
|
"Documents" = {
|
||||||
|
path = "/home/myuser/Documents";
|
||||||
|
devices = [ "laptop" "phone" ];
|
||||||
|
ignorePerms = false;
|
||||||
|
};
|
||||||
|
"Sensitive" = {
|
||||||
|
path = "/home/myuser/Sensitive";
|
||||||
|
devices = [
|
||||||
|
"laptop"
|
||||||
|
{
|
||||||
|
name = "phone";
|
||||||
|
encryptionPasswordFile = "/run/secrets/syncthing-sensitive-password";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = mkOption {
|
||||||
|
type = types.attrsOf types.anything;
|
||||||
|
default = {};
|
||||||
|
description = "Additional Syncthing configuration options";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
services.syncthing = {
|
||||||
|
enable = true;
|
||||||
|
openDefaultPorts = cfg.openDefaultPorts;
|
||||||
|
# Set stable identity if provided
|
||||||
|
key = mkIf (cfg.identity.keyPath != null) cfg.identity.keyPath;
|
||||||
|
cert = mkIf (cfg.identity.certPath != null) cfg.identity.certPath;
|
||||||
|
# Combine all settings
|
||||||
|
settings = syncthingSettings;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure systemd service options collectively
|
||||||
|
systemd.services.syncthing = {
|
||||||
|
# Add environment variable to disable default folder creation
|
||||||
|
environment.STNODEFAULTFOLDER = mkIf cfg.disableDefaultFolder "true";
|
||||||
|
|
||||||
|
# Add supplementary groups for secret access
|
||||||
|
serviceConfig.SupplementaryGroups = [ "syncthing-secrets" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create a group for accessing secrets
|
||||||
|
users.groups.syncthing-secrets = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
11
secrets/headscale-oidc-key.path
Normal file
11
secrets/headscale-oidc-key.path
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
age-encryption.org/v1
|
||||||
|
-> ssh-ed25519 i9wBeA DynOTJFDKsSyHKTG9XFAAcZf/T//KKyK8UG4aGgVH2c
|
||||||
|
o+ggJe/HZmPU+Ezw4u4m+l9bQ1furG7G4Oo7xS8PMAs
|
||||||
|
-> ssh-ed25519 UbxDgg b1XiosrWXL9WI1B7YnNSw16l1p4oa3zjDCCgkU/FxiU
|
||||||
|
MY8oubHMth/wDKn9kNOUkaY9ODvrKIn7DeZTuGxj4/g
|
||||||
|
-> ssh-ed25519 YYzA7Q 6ql+gutJfteQM75WL6ywEDA1+fIcYSpLPaTSKhqE1ic
|
||||||
|
tbwXx/feysvpOrxwpDi5B5PveSIbFH0qSsV6/xmo4hk
|
||||||
|
-> ssh-ed25519 3RWqPQ hNVnobsB1OB9woXtn1T1tXJL+1Dbasc9N2tjZdXa0Bw
|
||||||
|
9HlWIX7aroc8kTUW3rPlxvMSTSGJXbMcOEipdoQqnbw
|
||||||
|
--- h8toQGhp/wUgMkJ+RU0bV7E6pHRUM8mKLPcrDmbZ5NQ
|
||||||
|
!Å´·jÖ–n$ÔZªÿŒ$s9fÑö´Ï‰k›.ro—`èCU>Ë»©R‹F;H;—}JÚ(ú0ôáÛ U¦YP
|
||||||
|
|
@ -16,4 +16,5 @@ in
|
||||||
"garage-metrics-token.age".publicKeys = users ++ systems;
|
"garage-metrics-token.age".publicKeys = users ++ systems;
|
||||||
|
|
||||||
"headscale-authkey.age".publicKeys = users ++ systems;
|
"headscale-authkey.age".publicKeys = users ++ systems;
|
||||||
|
"headscale-oidc-key.path".publicKeys = users ++ systems;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue