pub struct HeadscaleClient { /* private fields */ }Expand description
HTTP client for a running Headscale coordinator.
The Headscale REST API lives at <server_url>/api/v1/…. Requests are
authenticated with an API key in the Authorization: Bearer <key> header.
The API key must be created on the coordinator with headscale apikeys create
or the equivalent API call; store it in the vault as headscale-api-key.
Implementations§
Source§impl HeadscaleClient
impl HeadscaleClient
Sourcepub fn new(
base_url: impl Into<String>,
api_key: impl Into<String>,
) -> Result<Self>
pub fn new( base_url: impl Into<String>, api_key: impl Into<String>, ) -> Result<Self>
Construct a client from explicit credentials.
Sourcepub fn from_vault_or_env() -> Result<Option<Self>>
pub fn from_vault_or_env() -> Result<Option<Self>>
Open a client from the vault (slot headscale-api-key + mesh-url)
with env-var fallbacks (HEADSCALE_API_KEY + HEADSCALE_URL).
Returns Ok(None) when either credential is absent — callers can
decide whether that’s fatal.
Sourcepub async fn create_preauth_key(
&self,
user: &str,
tags: &[String],
) -> Result<PreauthKey>
pub async fn create_preauth_key( &self, user: &str, tags: &[String], ) -> Result<PreauthKey>
Generate a single-use pre-auth key for the given ACL tags.
The key expires in 1 hour and is non-reusable — suitable for one-shot
machine onboarding via cloud-init. Each yah cloud machine provision
call that uses Headscale mesh should request its own key.
Sourcepub async fn list_nodes(&self) -> Result<Vec<NodeInfo>>
pub async fn list_nodes(&self) -> Result<Vec<NodeInfo>>
List all nodes currently in the tailnet.
Uses Headscale’s GET /api/v1/node (the endpoint was renamed from the
pre-v0.23 /api/v1/machine, with the response key machines → nodes,
when Headscale retired “machine” for “node”). The per-node JSON shape is
otherwise unchanged (id, name, ipAddresses, online).
Sourcepub async fn list_users(&self) -> Result<Vec<String>>
pub async fn list_users(&self) -> Result<Vec<String>>
List the Headscale users (namespaces) preauth keys can be minted against.
GET /api/v1/user. Headscale scopes every preauth key to a user, and a
key minted against a user that does not exist fails at mint time.
Sourcepub async fn resolve_user(&self, preferred: Option<&str>) -> Result<String>
pub async fn resolve_user(&self, preferred: Option<&str>) -> Result<String>
Resolve the user to mint a preauth key against, asking the coordinator instead of assuming a name.
R608-B19: this used to be the literal "default" at the
yah cloud machine provision call site, and against the live
coordinator that is simply wrong — POST /api/v1/preauthkey answers
500 for a user that does not exist. The two halves of the system
disagree on the name: crate::mesh’s camp-local yah mesh start path
creates default (its --user default), while yah mesh bootstrap
creates yah (mint_bootstrap_preauth_key in yubaba’s lib.rs runs
headscale users create yah). The production coordinator was
bootstrapped, so it has only yah — every provision against it would
have failed at the preauth step with an opaque 500.
Rather than swap one hardcoded guess for the other:
preferredpresent and known to the coordinator → use it;preferredabsent and the coordinator has exactly one user → use it, which is every yah mesh in existence today;- otherwise → error naming the users that DO exist, so the operator can pick, instead of a 500 that names nothing.
Sourcepub async fn health(&self) -> HeadscaleHealth
pub async fn health(&self) -> HeadscaleHealth
Light health check — HEAD or GET the Headscale root, no auth required.
Auto Trait Implementations§
impl !RefUnwindSafe for HeadscaleClient
impl !UnwindSafe for HeadscaleClient
impl Freeze for HeadscaleClient
impl Send for HeadscaleClient
impl Sync for HeadscaleClient
impl Unpin for HeadscaleClient
impl UnsafeUnpin for HeadscaleClient
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<T> ErasedDestructor for Twhere
T: 'static,
impl<T> Fruit for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more