add headscale and syncthing
This commit is contained in:
parent
d90ad7fbc5
commit
cfa997a852
9 changed files with 533 additions and 29 deletions
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 = {};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue