Files
Aarnav Tale b3c0c1c691 fix(agent): always spawn agent with pre-auth key and auto-approve
- Generate a fresh pre-auth key for every agent startup
- Preserve existing tailscale state to avoid creating a new host
- Auto-approve pending auth requests via /api/v1/auth/approve
- Show approval link in settings UI as fallback

Closes HP-558
2026-07-13 11:00:43 -04:00

76 lines
1.5 KiB
Go

package main
import (
"bufio"
"context"
"encoding/json"
"os"
"os/signal"
"syscall"
"github.com/tale/headplane/internal/config"
"github.com/tale/headplane/internal/tsnet"
"github.com/tale/headplane/internal/util"
)
type output struct {
Self string `json:"self"`
Hosts map[string]json.RawMessage `json:"hosts"`
}
type errorOutput struct {
Error string `json:"error"`
}
func main() {
log := util.GetLogger()
cfg, err := config.Load()
if err != nil {
log.Fatal("Failed to load config: %s", err)
}
log.SetDebug(cfg.Debug)
if cfg.TSAuthKey == "" {
log.Info("No TS_AUTHKEY provided; tsnet will use existing state or prompt for interactive login")
} else {
prefix := cfg.TSAuthKey
if len(prefix) > 16 {
prefix = prefix[:16]
}
log.Info("TS_AUTHKEY provided (prefix: %s); connecting with pre-auth key", prefix)
}
agent := tsnet.NewAgent(cfg)
defer agent.Shutdown()
agent.Connect()
enc := json.NewEncoder(os.Stdout)
scanner := bufio.NewScanner(os.Stdin)
// Shut down cleanly on signal or stdin close
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
go func() {
<-sigCh
agent.Shutdown()
os.Exit(0)
}()
// Each line on stdin triggers a sync. The line content is ignored.
for scanner.Scan() {
hosts, err := agent.FetchAllHostInfo(context.Background())
if err != nil {
enc.Encode(errorOutput{Error: err.Error()})
continue
}
enc.Encode(output{
Self: agent.ID,
Hosts: hosts,
})
}
}