Documentation
¶
Overview ¶
Package config locates and manages flue's on-disk configuration, including the loopback authentication token.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DeleteCloudflare ¶
func DeleteCloudflare() error
DeleteCloudflare removes the stored credential; absent is success.
func LoadOrCreateToken ¶
LoadOrCreateToken returns the daemon's loopback token, generating and persisting one at mode 0600 on first use.
func MintMachineID ¶
MintMachineID makes the id a machine joins the relay under: `<hostname sanitized, truncated to 24>-<4 lowercase hex>`.
The hostname part is for the human reading a machine list; the hex is for the relay, where the id is the routing key and a collision means the second machine evicts the first from its hub. r is crypto/rand.Reader everywhere but tests, which inject fixed bytes to pin the format.
func SaveCloudflare ¶
func SaveCloudflare(c Cloudflare) error
SaveCloudflare writes cloudflare.json at 0600, replacing whatever was there — the same fresh-inode rename dance SaveRelay does, for the same concurrent-reader reasons.
func SaveRelay ¶
SaveRelay writes relay.json at 0600, replacing whatever was there.
It goes through the same write-temp-then-rename path as the token, and for the same two reasons: the new secret is never visible at a mode the old file happened to carry, and a crash mid-write cannot leave a truncated file behind where a complete one was. See writeSecretAtomically.
Types ¶
type Cloudflare ¶
type Cloudflare struct {
// Token is the API token setup verified. Never logged, never echoed into
// an error, never carried by any endpoint response — reads of this file
// hand it to the Cloudflare API and nowhere else.
Token string `json:"token"`
// AccountID and AccountName are the account the relay was deployed into,
// recorded so the UI can say where the relay lives and so an update needs
// no account picker.
AccountID string `json:"account_id"`
AccountName string `json:"account_name,omitempty"`
}
Cloudflare is the stored Cloudflare credential and the account it deploys into: what makes "update the relay" a click instead of a trip to the token page.
Stored by explicit product decision: the token is an account-level Workers credential and flue keeps it the way it keeps the relay secret — one 0600 file in the config directory, owner-readable and nothing else. The user is doing this on their own machine for their own account; the file is theirs to delete, and everything that reads it works (by asking again) when it is gone.
func LoadCloudflare ¶
func LoadCloudflare() (Cloudflare, bool, error)
LoadCloudflare reads cloudflare.json. ok is false when nothing is stored.
type Relay ¶
type Relay struct {
// URL is the bare wss:// address of the relay — host only, no path. The
// transport appends /daemon/<machine id> itself, so the file never holds a
// path that could disagree with the id beside it.
URL string `json:"url"`
Origin string `json:"origin"`
// Secret is the relay's shared DAEMON_SECRET: the deploy set it on the
// user's own Worker, and the daemon presents it on every dial. Never
// logged, and the reason this file is 0600. It does ride argv exactly
// once — `flue relay join --secret`, the hand-off line setup prints —
// and that is deliberate: argv and the shell history that keeps it are
// the accepted cost of moving the secret to the next machine
// (docs/RELAY.md says so where the line is printed).
Secret string `json:"secret,omitempty"`
// MachineID is the slot this machine holds on the relay: the <id> in the
// /daemon/<id> leg the daemon dials and the /client/<id> URLs browsers
// open. Minted by `flue relay setup` and `flue relay join` (MintMachineID),
// never typed by hand — which is why it is a slug and the name below is
// not.
MachineID string `json:"machine_id"`
// MachineName is the human label for this machine — free text, shown in
// machine lists; it rides the pairing link's query (`n=`, so the pairing
// browser can label the machine), never any path the relay routes on.
MachineName string `json:"machine_name"`
// Worker is the Cloudflare script name the relay was deployed under —
// `flue relay setup --worker`, or the default. `flue relay update` reads
// it back so a redeploy names the same script without re-deriving it from
// the URL. Empty in files written by `flue relay join` (join deploys
// nothing and does not know) and in files from before the field existed;
// readers must treat empty as "derive or ask", never as a name.
Worker string `json:"worker,omitempty"`
}
Relay is how this daemon reaches a deployed relay: where to dial, what authenticates the dial, and the origin the relay serves browsers on.
It is written by `flue relay setup` and read by `flue serve` at startup. This package deliberately does not decide whether a file is *complete* — see transport/relay.New, which is where that lives — because a file that exists says the user meant to have a relay, and telling them which field is missing is a better answer than pretending they never configured one.
func LoadRelay ¶
LoadRelay reads relay.json. ok is false when there is no relay configured at all, which is the ordinary state and not an error.
An unreadable or unparseable file *is* an error, and the distinction matters: "there is no relay" and "there is a relay and I cannot read it" lead to the same daemon — one serving loopback only — but only the second is something the operator has to be told about, and reporting it as absence would hide a typo in a file they just edited.
The file's mode is not policed the way the token's is. A loose mode on the token is evidence the secret leaked *and* a reason to mint a new one, which costs one browser session; the relay secret's other copy lives in a deployed Worker, so this process cannot regenerate it and refusing to read it would only take remote access away without making anything safer. SaveRelay writes 0600, and rotating a secret that has been exposed is the operator's move.