adds headscale/planescale support (for one user -> me)

This commit is contained in:
eyjhb 2025-06-05 17:45:41 +02:00
parent 96f4272724
commit 038865ba84
Signed by: eyjhb
GPG key ID: 609F508E3239F920
10 changed files with 267 additions and 3 deletions

View file

@ -32,6 +32,8 @@
./gerd/services/drtvrss.nix ./gerd/services/drtvrss.nix
./gerd/services/vikunja.nix ./gerd/services/vikunja.nix
./gerd/services/headscale
./gerd/services/monitoring ./gerd/services/monitoring
]; ];

View file

@ -0,0 +1,26 @@
{ config, pkgs, ... }:
let
svc_domain = "headscale.${config.mine.shared.settings.domain}";
in {
imports = [
./headscale.nix
./headplane.nix
];
mine.shared.meta.headscale = {
name = "";
description = "";
package = let
pkg = pkgs.headscale;
in {
name = pkg.pname;
version = pkg.version;
meta = pkg.meta;
};
};
mine.shared.settings.headscale.domain = svc_domain;
}

View file

@ -0,0 +1,126 @@
{ config, pkgs, ... }:
let
svc_domain = config.mine.shared.settings.headscale.domain;
sources = import ./../../../../shared/sources;
flake-compat = sources.flake-compat;
newpkgs = (import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/c2a03962b8e24e669fb37b7df10e7c79531ff1a4.tar.gz";
}) {});
headplanesrc = let
tmppkgs = (import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/ab7b6889ae9d484eed2876868209e33eb262511d.tar.gz";
}) {});
src = builtins.fetchTarball {
url = "https://github.com/tale/headplane/archive/2f316176c8c37ad63946d7075c727478f81303b2.tar.gz";
};
in tmppkgs.applyPatches {
src = src;
name = "headplane-patched";
patches = [
(tmppkgs.writeText "headplane-package-pnpm-hash.patch" ''
diff --git a/nix/package.nix b/nix/package.nix
index bb430d7..11349c4 100644
--- a/nix/package.nix
+++ b/nix/package.nix
@@ -23,7 +23,7 @@ stdenv.mkDerivation (finalAttrs: {
pnpmDeps = pnpm_10.fetchDeps {
inherit (finalAttrs) pname version src;
- hash = "sha256-OOWgYaGwa5PtWhFEEkRCojCDmkPIR6tJ5cfFMOLND3I=";
+ hash = "sha256-xjjkqbgjYaAGYAmlTFE+Lq3Hp6myZKaW3br0YTDNhQA=";
};
'')
];
};
headplane = import flake-compat { src = headplanesrc; };
in {
imports = [
headplane.defaultNix.nixosModules.headplane
];
services.headplane = {
enable = true;
agent.enable = false;
settings = {
server = {
host = "127.0.0.1";
port = 53874;
cookie_secret = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; # replaced in env
cookie_secure = true;
};
headscale = {
url = "https://${svc_domain}";
config_strict = false;
};
oidc = {
issuer = "https://${config.mine.shared.settings.authelia.domain}";
client_id = "headplane";
client_secret = "<from_env>";
redirect_uri = "https://${svc_domain}/admin/oidc/callback";
# headscale API key for authenticating users
headscale_api_key = "<from_env>";
# default to state directory
user_storage_file = "/var/lib/headplane/users.json";
# set to the default authelia auth method
token_endpoint_auth_method = "client_secret_basic";
# disable authenticating with headscale api key
disable_api_key_login = true;
};
};
};
# headplane module does not allow setting package,
# so we have to add headplane to pkgs
nixpkgs.overlays = [
(self: super: {
headplane = headplane.defaultNix.packages.x86_64-linux.headplane;
})
];
systemd.services.headplane.serviceConfig = {
# setup state directory
StateDirectory = "headplane";
# load configs from env file
EnvironmentFile = [ config.age.secrets.headplane-env.path ];
};
# setup for oidc
services.authelia.instances.main.settings.identity_providers.oidc.clients = [{
client_id = "headplane";
client_name = "Headplane";
client_secret = "$pbkdf2-sha512$310000$h7Te42JTu4Xsqz/8CGan7Q$qDd183LHmEsgNvVAI8Xf.1DpRMeS8DqNmDpkkjkxgRR/lZYQgAkXYzL2MyvLqNFFSVKAdMTsD/Jxk72g9fxnew";
consent_mode = "implicit";
redirect_uris = [ "https://${svc_domain}/admin/oidc/callback" ];
scopes = [
"openid"
"profile"
"email"
];
}];
# nginx
services.nginx.virtualHosts."${svc_domain}".locations."/admin" = {
proxyPass = "http://127.0.0.1:${builtins.toString config.services.headplane.settings.server.port}";
priority = 5;
};
# persistence
environment.persistence.root.directories = [
"/var/lib/headplane"
];
}

View file

@ -0,0 +1,80 @@
{ config, pkgs, ... }:
let
svc_domain = config.mine.shared.settings.headscale.domain;
svc_domain_dns_magic_domain = "ts.${config.mine.shared.settings.domain}";
grpc_port = 50443;
in {
services.headscale = {
enable = true;
settings = {
server_url = "https://${svc_domain}";
# grpc
grpc_listen_addr = "127.0.0.1:${builtins.toString grpc_port}";
grpc_allow_insecure = true;
# dns
dns.base_domain = svc_domain_dns_magic_domain;
dns.nameservers.global = [ "1.1.1.1" ];
# acl -> save in database
policy.mode = "database";
# auth
oidc = {
only_start_if_oidc_is_available = true;
issuer = "https://${config.mine.shared.settings.authelia.domain}";
client_id = "headscale";
client_secret_path = "$CREDENTIALS_DIRECTORY/authelia-secret";
};
# debug
log.level = "debug";
};
};
systemd.services.headscale.serviceConfig.LoadCredential = [
"authelia-secret:${config.age.secrets.headscale-authelia-secret.path}"
];
# setup for oidc
services.authelia.instances.main.settings.identity_providers.oidc.clients = [{
client_id = "headscale";
client_name = "Headscale";
client_secret = "$pbkdf2-sha512$310000$/xiUR1oDvUEn4OKEu31COw$Z.IMgW3Qb2.mgCyEq1UUDC0i7cX2GOiywUjY4MsNv4ixQCP1jFO7njctCW2mVCqvkgfylDpsWRM3z.uXTs89IA";
consent_mode = "implicit";
redirect_uris = [ "https://${svc_domain}/oidc/callback" ];
scopes = [
"openid"
"profile"
"email"
];
}];
# nginx
services.nginx.virtualHosts."${svc_domain}" = {
forceSSL = true;
enableACME = true;
# headscale gRPC API
locations."/headscale" = {
extraConfig = ''
grpc_pass 127.0.0.1:${builtins.toString grpc_port};
'';
priority = 0;
};
# fallback to headscale
locations."/" = {
proxyPass = "http://127.0.0.1:${builtins.toString config.services.headscale.port}";
proxyWebsockets = true;
};
};
# persistence
environment.persistence.root.directories = [
"/var/lib/headscale"
];
}

View file

@ -72,6 +72,10 @@
# vikunja # vikunja
vikunja-env.file = ./vikunja/env.age; vikunja-env.file = ./vikunja/env.age;
# headscale/headplan
headscale-authelia-secret.file = ./headscale/headscale-authelia-secret.age;
headplane-env.file = ./headscale/headplane-env.age;
}; };
users.groups.secrets-lldap-bind-user-pass = {}; users.groups.secrets-lldap-bind-user-pass = {};

View file

@ -0,0 +1,11 @@
age-encryption.org/v1
-> ssh-ed25519 QSDXqg U2hjU5FeVfd+/agny133FUmLJ47zqpww10DgzHbkKW8
k6k+WH6fZ1UZjnOwe3LS6cXYVcucE+kBhuPRMcNFabI
-> X25519 JfLnC3qBptSdDwBRo1Zj/rDqKqWFvxWqBANIKhCIVlc
iuqSt9gdPjQVRuv9+iUub1zkecSUjZD1XKvtvkNAaOE
-> ssh-ed25519 n8n9DQ eVkQODcS4wG+5xliWzqfEcRKvkHaHTzz8BWXH/ld/3k
9q0TB7ZLluGIQhFjMcXUmXlGiof5/ACrrHQRWEq4jik
-> ssh-ed25519 BTp6UA hGuGXru5pgShG15hEH6B8fYF4x1SK6blgP+3NSfvklI
UZYG5ZfErwlBtux5fWh3CPrT/9oWoDjGXX1M0ojtY8c
--- NlksmWK4pF3hQkpCkZaCBWvEv7I9TB0zgYRiJpuLB18
±±-ke(~ñ…"KktWv´&«í´~ÔúšžÝ¶û¿Žè½é HÆ)ûjQÔÅÐtRe/<2F>C_s.“ƒÓéýÚÚà/º~21ŸòÜ«"æ!á²ÎÓ<C38E>7IƒÅüÙìŒCj¥KÝÛ¼H«ˆ³o!È{ÁüÏþYhÉzcÀ¢³¬go?ßåtˆäãÔÃ<C394><s ­ì©`ÌÇñŠMZgôÙ¨R:þñ3-i@dVÕDÂ^¸…'{R6{Œ€ÑóIĹѯҬ¼`UÜSJ& E¯/WâÏ >¾JS @`Ùm±h|‰ˆ±Áe3é¨U!;sñíãÔ}õ¼©L—í Àb¿ê$<24>·-R8Vq:ÏíÚ£uûÉ&üÊK\¥™ÉÛiªð¸8¬‡TALO•ÍÂùOñõgñ3ÒfˆêàT½€

Binary file not shown.

View file

@ -82,4 +82,8 @@ in
# vikunja # vikunja
"vikunja/env.age".publicKeys = defaultAccess; "vikunja/env.age".publicKeys = defaultAccess;
# headscale/headplan
"headscale/headscale-authelia-secret.age".publicKeys = defaultAccess;
"headscale/headplane-env.age".publicKeys = defaultAccess;
} }

View file

@ -18,6 +18,17 @@ in sources // {
url = "https://github.com/NixOS/nixpkgs/pull/412054.patch"; url = "https://github.com/NixOS/nixpkgs/pull/412054.patch";
sha256 = "sha256-OExslGsrGGPWSJJFPkZgYV8DaPKq9YDlmozPf/bV6dE="; sha256 = "sha256-OExslGsrGGPWSJJFPkZgYV8DaPKq9YDlmozPf/bV6dE=";
}) })
# headscale: 0.25.1 -> 0.26.0, update nixos module and test accordingly #407644
(pkgs.fetchpatch {
url = "https://github.com/NixOS/nixpkgs/pull/407644.patch";
sha256 = "sha256-0fAB9DJ8KeocS/ZP4CPEt9VHkAu6gt025rSu3Skssqo=";
})
# # Revert "nixos/murmur: Get rid of global lib expansion" #413495
# (pkgs.fetchpatch {
# url = "https://github.com/NixOS/nixpkgs/pull/413495.patch";
# sha256 = "sha256-0QI2qn0vkFruk0sq15xLriz6iqvs2e9DjApVblsSULE=";
# })
]; ];
}; };

View file

@ -17,10 +17,10 @@
"homepage": "", "homepage": "",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "a894f2811e1ee8d10c50560551e50d6ab3c392ba", "rev": "58d6e5a83fff9982d57e0a0a994d4e5c0af441e4",
"sha256": "06gbwfkzm73xrf2brnlvg0g6dbjjry7xqmaar320dqwclq44jf83", "sha256": "0h4br7anx158shym8a812wi43qhq5qqsv3xk7vxm6s6dawnp4azw",
"type": "tarball", "type": "tarball",
"url": "https://github.com/nix-community/disko/archive/a894f2811e1ee8d10c50560551e50d6ab3c392ba.tar.gz", "url": "https://github.com/nix-community/disko/archive/58d6e5a83fff9982d57e0a0a994d4e5c0af441e4.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz" "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}, },
"drasl": { "drasl": {