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
- Variables
- func CheckHealth(dir string, now time.Time, maxAge time.Duration) error
- func LoadOrCreateKey(dir string) (ed25519.PrivateKey, bool, error)
- func SaveState(dir string, st State) error
- type Agent
- type Config
- type ExecRunner
- type Health
- type Process
- type Runner
- type State
- type Supervisor
Constants ¶
const ( KeyFile = "agent.key" StateFile = "agent-state.json" HealthFile = "agent-health.json" )
Files in the agent data directory.
Variables ¶
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.
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 ¶
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.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent is one running relay agent.
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).
type ExecRunner ¶
ExecRunner runs a real hbbr binary in Dir (where it reads blacklist.txt/blocklist.txt). Output lines are logged with an "hbbr" source.
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 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.
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.