Skip to content

Secret

Source: src/Fly/Secret.ts

A Fly.Secret is an App vault entry. Fly injects it as an environment variable on every Machine. Use it when the value is shared and managed in one place by Fly.

For a secret only this Service reads from .env at deploy time, yield Config.redacted instead. Do not pass env: { ... } on a Service.

Most secrets in a Service come from your .env. Yield Config.redacted in init. Alchemy binds the value onto the Machine.

import * as Config from "effect/Config";
import * as Redacted from "effect/Redacted";
export default class Api extends Fly.Service<Api>()(
"Api",
{ app: Site, main: import.meta.url, port: 3000 },
Effect.gen(function* () {
const apiKey = yield* Config.redacted("API_KEY");
return {
fetch: Effect.gen(function* () {
const token = Redacted.value(apiKey);
return HttpServerResponse.text("ok");
}),
};
}),
) {}

Wrap the value with Redacted.make so it is never logged. The plaintext is never stored in attributes. Omit name and Alchemy generates an ownership-stamped name.

const dbUrl = yield* Fly.Secret("DatabaseUrl", {
app: Site,
value: Redacted.make("postgres://…"),
});

name is the env-var Machines see. It is stored as-is (case-sensitive).

export const ApiToken = Fly.Secret("ApiToken", {
app: Site,
name: "API_TOKEN",
value: Redacted.make("sk_live_…"),
});

Updating value is in place via updateSecrets.

export const ApiToken = Fly.Secret("ApiToken", {
app: Site,
name: "API_TOKEN",
value: Redacted.make("sk_live_rotated"),
});

GetSecret is bound to one Secret. Provide GetSecretHttp. Fly only returns plaintext from a Machine in the same App. From a deploy-time Action you get metadata (name, digest, timestamps).

const get = yield* Fly.GetSecret(ApiToken);
const got = yield* get();

ListSecrets is bound to an App. From an Action, the org token can list any App in the org. From a Machine, deploy tokens are per-App. Mixing Apps on one Machine shares one FLY_API_TOKEN and is not supported.

const list = yield* Fly.ListSecrets(Site);
const { secrets } = yield* list();

WriteSecret creates, updates, and deletes by name. Provide WriteSecretHttp on the Action or Service Effect.

const Seed = Alchemy.Action(
"Seed",
Effect.gen(function* () {
const secrets = yield* Fly.WriteSecret(ApiToken);
return Effect.fn(function* () {
yield* secrets.update("API_TOKEN", Redacted.make("sk_live_rotated"));
});
}).pipe(Effect.provide(Fly.WriteSecretHttp)),
);