Help us shape the future of Go! Take the 2026 Go Developer Survey

agent

package
v0.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 25, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Package agent implements `rdpanel agent`: it runs next to (as the parent of) hbbr on a relay host, enrolls with the central panel using a one-time token, keeps an outbound ed25519-authenticated WebSocket session to <panel>/agent/v1/connect, persists the desired hbbr config it receives, applies it through hbbr's loopback admin channel (the hbbr half of the panel's reconciler, unchanged) and reports status. See docs/relay-agents.md.

Index

Constants

View Source
const (
	KeyFile    = "agent.key"
	StateFile  = "agent-state.json"
	HealthFile = "agent-health.json"
)

Files in the agent data directory.

Variables

View Source
var ErrNoKey = errors.New("agent: no hbbs public key yet; hbbr is not started")

ErrNoKey refuses to start hbbr without an explicit hbbs public key: `-k _` or no key would make hbbr generate a foreign key pair on a fresh host.

View Source
var ErrTokenRejected = errors.New("agent: the panel rejected the enrollment token (invalid, expired or already used); create a new one in the panel")

ErrTokenRejected means the panel refused the enrollment token.

Functions

func CheckHealth

func CheckHealth(dir string, now time.Time, maxAge time.Duration) error

CheckHealth reads the health file: it must be fresh, and hbbr must be up whenever it should run.

func LoadOrCreateKey

func LoadOrCreateKey(dir string) (ed25519.PrivateKey, bool, error)

LoadOrCreateKey returns the agent's ed25519 identity from dir/agent.key (base64 of the 32-byte seed, 0600), generating it on first start.

func SaveState

func SaveState(dir string, st State) error

SaveState writes dir/agent-state.json atomically (0600).

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

Agent is one running relay agent.

func New

func New(cfg Config) (*Agent, error)

New prepares an agent: data dir, identity key and persisted state.

func (*Agent) ApplyNow

func (a *Agent) ApplyNow(ctx context.Context)

ApplyNow runs one forced apply pass (tests).

func (*Agent) Run

func (a *Agent) Run(ctx context.Context) error

Run enrolls if needed and then runs until ctx ends.

func (*Agent) State

func (a *Agent) State() State

State returns a copy of the persisted state.

func (*Agent) Supervisor

func (a *Agent) Supervisor() *Supervisor

Supervisor exposes the hbbr supervisor (tests).

type Config

type Config struct {
	// PanelURL is the panel's public (client API) base URL.
	PanelURL string
	// EnrollToken is the one-time token; ignored once enrolled.
	EnrollToken string
	// DataDir holds agent.key, agent-state.json and hbbr's list files.
	DataDir string
	// HBBRBin is the hbbr executable.
	HBBRBin string
	// RelayPort is hbbr's TCP port (its loopback admin channel too).
	RelayPort int
	// PanelCA is an optional PEM file with extra CAs to trust for the panel.
	PanelCA string
	// Hostname overrides the reported host name.
	Hostname string
	// StatusInterval is how often status is reported (default 10 s).
	StatusInterval time.Duration
	// ApplyInterval is the drift-check period (default 15 s).
	ApplyInterval time.Duration
	Log           *slog.Logger

	// Test hooks.
	Runner     Runner
	HTTPClient *http.Client
	// ControlAddr overrides the hbbr admin address (default 127.0.0.1:RelayPort).
	ControlAddr string
	// ProcDir is /proc (host sampling).
	ProcDir string
	// MaxBackoff caps reconnect delays (default 60 s).
	MaxBackoff time.Duration
	// HealthInterval is how often agent-health.json is written (default 10 s).
	HealthInterval time.Duration
}

Config configures the agent (environment: see FromEnv).

func FromEnv

func FromEnv(lookup func(string) (string, bool)) (Config, error)

FromEnv reads the agent configuration from RDPANEL_AGENT_* variables.

type ExecRunner

type ExecRunner struct {
	Bin string
	Dir string
	Log *slog.Logger
}

ExecRunner runs a real hbbr binary in Dir (where it reads blacklist.txt/blocklist.txt). Output lines are logged with an "hbbr" source.

func (ExecRunner) Start

func (r ExecRunner) Start(_ context.Context, args []string) (Process, error)

Start implements Runner.

type Health

type Health struct {
	Time      time.Time `json:"time"`
	Connected bool      `json:"connected"`
	// Run is the desired hbbr state; HBBRUp the observed one.
	Run    bool `json:"run"`
	HBBRUp bool `json:"hbbr_up"`
}

Health is written to dir/agent-health.json for `rdpanel agent health`.

type Process

type Process interface {
	PID() int
	// Wait blocks until the process exits.
	Wait() error
	// Stop asks the process to exit (SIGTERM) and kills it after grace.
	Stop(grace time.Duration)
}

Process is a running hbbr.

type Runner

type Runner interface {
	Start(ctx context.Context, args []string) (Process, error)
}

Runner starts hbbr processes (injectable for tests).

type State

type State struct {
	PanelURL  string             `json:"panel_url"`
	AgentID   int64              `json:"agent_id"`
	RelayName string             `json:"relay_name,omitempty"`
	Config    *agentproto.Config `json:"config,omitempty"`
}

State is persisted across restarts: the agent keeps enforcing its last config while the panel is unreachable.

func LoadState

func LoadState(dir string) (State, error)

LoadState reads dir/agent-state.json (zero State when missing).

type Supervisor

type Supervisor struct {

	// MinBackoff/MaxBackoff bound restart delays; StableAfter resets them.
	MinBackoff, MaxBackoff, StableAfter time.Duration
	// contains filtered or unexported fields
}

Supervisor runs hbbr as a child process and restarts it with backoff. It is deliberately small and independent of the WebSocket session, so a session problem never touches running relays (design §5.1, option 1).

func NewSupervisor

func NewSupervisor(r Runner, port int, log *slog.Logger) *Supervisor

NewSupervisor builds a supervisor for hbbr on port.

func (*Supervisor) Restart

func (s *Supervisor) Restart()

Restart restarts a running hbbr (the "restart-hbbr" command).

func (*Supervisor) Run

func (s *Supervisor) Run(ctx context.Context)

Run supervises until ctx ends; hbbr is stopped on return.

func (*Supervisor) Set

func (s *Supervisor) Set(key string, run bool)

Set changes the desired state: run hbbr with key, or stop it.

func (*Supervisor) Started

func (s *Supervisor) Started() <-chan struct{}

Started fires after every hbbr start (the agent then re-applies its config).

func (*Supervisor) Status

func (s *Supervisor) Status() agentproto.HBBRStatus

Status returns the hbbr status.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL