Fly.Secret reference
GetSecret
Section titled “GetSecret”Source:
src/Fly/GetSecret.ts
Fetch one Fly.io App secret. The App and name are fixed by
GetSecret(secret). Calls take no app_name.
GetSecret: Read a secret
Section titled “GetSecret: Read a secret”Bind the client in init. Call it from fetch or an Action body.
Provide GetSecretHttp. Alchemy transports the bound App name,
secret name, and deployment’s org token automatically. There is no
need to configure FLY_SECRET_* environment variables.
Fly only returns plaintext from a Machine in the same App. From a deploy-time Action you get metadata (name, digest, timestamps).
export default class Api extends Fly.Service<Api>()( "Api", { app: Site, main: import.meta.url, port: 3000 }, Effect.gen(function* () { const get = yield* Fly.GetSecret(ApiToken);
return { fetch: Effect.gen(function* () { const got = yield* get().pipe(Effect.orDie); return HttpServerResponse.json({ name: got.name }); }), }; }).pipe(Effect.provide(Fly.GetSecretHttp)),) {}GetSecretHttp
Section titled “GetSecretHttp”Source:
src/Fly/GetSecretHttp.tsKind: Layer · Provides:Fly.GetSecret
HTTP implementation of GetSecret. Provide it on the
Service or Action Effect.
GetSecretHttp: Provide the layer
Section titled “GetSecretHttp: Provide the layer”Effect.gen(function* () { const get = yield* Fly.GetSecret(ApiToken); // ...}).pipe(Effect.provide(Fly.GetSecretHttp))ListSecrets
Section titled “ListSecrets”Source:
src/Fly/ListSecrets.ts
List Fly.io App secrets. Scoped to an App. Fly’s list API
is GET /apps/{app}/secrets, not a single Secret.
ListSecrets: List this App
Section titled “ListSecrets: List this App”The App is fixed by ListSecrets(app). Calls take no app_name.
Provide ListSecretsHttp.
Plaintext is only returned from inside a Machine in the same App. From a deploy-time Action you get metadata (name, digest, timestamps).
const list = yield* Fly.ListSecrets(Site);const { secrets } = yield* list();ListSecrets: List another App
Section titled “ListSecrets: List another App”From an Action, the org FLY_API_TOKEN can list any App in the
org. ListSecrets(other) is how you reach across Apps.
From a Machine, deploy tokens are per-App. Mixing Apps on one host
shares one FLY_API_TOKEN and is not supported.
const Seed = Alchemy.Action( "Seed", Effect.gen(function* () { const list = yield* Fly.ListSecrets(Other);
return Effect.fn(function* () { const { secrets } = yield* list(); return secrets; }); }).pipe(Effect.provide(Fly.ListSecretsHttp)),);ListSecretsHttp
Section titled “ListSecretsHttp”Source:
src/Fly/ListSecretsHttp.tsKind: Layer · Provides:Fly.ListSecrets
HTTP implementation of ListSecrets. Provide it on the
Service or Action Effect.
ListSecretsHttp: Provide the layer
Section titled “ListSecretsHttp: Provide the layer”Effect.gen(function* () { const list = yield* Fly.ListSecrets(Site); // ...}).pipe(Effect.provide(Fly.ListSecretsHttp))Secret
Section titled “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.
Secret: Config.Redacted on a Service
Section titled “Secret: Config.Redacted 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"); }), }; }),) {}Secret: Create a Secret
Section titled “Secret: Create a Secret”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://…"),});Secret: Env-var name
Section titled “Secret: Env-var name”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_…"),});Secret: Rotate the value
Section titled “Secret: Rotate the value”Updating value is in place via updateSecrets.
export const ApiToken = Fly.Secret("ApiToken", { app: Site, name: "API_TOKEN", value: Redacted.make("sk_live_rotated"),});Secret: Get a secret at runtime
Section titled “Secret: Get a secret at runtime”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();Secret: List secrets
Section titled “Secret: List secrets”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();Secret: Write secrets
Section titled “Secret: Write secrets”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)),);WriteSecret
Section titled “WriteSecret”Source:
src/Fly/WriteSecret.ts
Create, update, and delete Fly.io App secrets at runtime.
The App is fixed by WriteSecret(secret). Calls take no
app_name. Inside a Machine or Service, Alchemy
mints an App deploy token. Inside an Action, the ambient
FLY_API_TOKEN is used.
WriteSecret: Create
Section titled “WriteSecret: Create”Bind the client in init. Provide WriteSecretHttp. Wrap
values with Redacted.make.
const Seed = Alchemy.Action( "Seed", Effect.gen(function* () { const secrets = yield* Fly.WriteSecret(ApiToken);
return Effect.fn(function* () { yield* secrets.create("API_KEY", Redacted.make("sk_live")); }); }).pipe(Effect.provide(Fly.WriteSecretHttp)),);WriteSecret: Update
Section titled “WriteSecret: Update”update rotates by name (batch of one).
yield* secrets.update("API_KEY", Redacted.make("sk_live_rotated"));WriteSecret: Delete
Section titled “WriteSecret: Delete”delete removes a secret by name.
yield* secrets.delete("API_KEY");WriteSecretHttp
Section titled “WriteSecretHttp”Source:
src/Fly/WriteSecretHttp.tsKind: Layer · Provides:Fly.WriteSecret
HTTP implementation of WriteSecret. Provide it on the
Service or Action Effect.
WriteSecretHttp: Provide the layer
Section titled “WriteSecretHttp: Provide the layer”Effect.gen(function* () { const secrets = yield* Fly.WriteSecret(ApiToken); // ...}).pipe(Effect.provide(Fly.WriteSecretHttp))