When you host ForgeHub with us, your instance connects to services that are yours, not ours — your GitHub, your S3 bucket, your email sender. A hosting platform should never put its own credentials inside your application, and it should never ask you to guess which ones yours needs.
We got the first half right by accident and the second half wrong by omission.
What your instance actually receives
A provisioned instance gets exactly five values from us:
- its application ID
- a signed entitlement document describing your plan
- the key to verify that document, derived per instance
- the single-sign-on issuer
- the SSO secret, also derived per instance
That is the whole list. Our Stripe keys, our mail credentials, our cloud credentials — none of them are forwarded, and none of them can be, because nothing in the provisioning path reads them. Two instances cannot reach each other’s secrets because neither holds anything shared.
That isolation was correct. The problem was the consequence.
Twenty-three keys, all undefined
ForgeHub reads seventeen integration credentials — GitHub, S3 and AWS, email,
Google, browser push. In a real instance every single one was undefined.
And the settings pages told you so, without offering anywhere to fix it. The payment page read the environment, reported “not configured”, and its Save button persisted exactly one field: your currency. Storage did the same. They looked editable. They were status displays.
You could set these variables — through the control panel’s environment editor,
which writes to your instance and restarts it. That worked the whole time. But
nothing anywhere told you ForgeHub wanted RESEND_API_KEY or VAPID_PRIVATE_KEY.
A capability nobody can discover is not a feature.
Settings → Integrations
Your instance now stores its own credentials, in its own database, encrypted with AES-256-GCM. Five integrations, each explaining plainly what it enables and what breaks without it — because “not configured” is useless next to “no email leaves this instance, so nobody is notified of approvals”.
Three details worth stating:
We cannot show you a key back. Once saved, the interface returns only the last four characters. Replacing means typing a new one. There is no read path, for us or for you.
A Test button that makes a real call. Each integration runs the cheapest
authenticated read its provider offers — a bucket HEAD, a token check, a domain
list. Nothing is created, sent or deleted. It reports the provider’s own message,
because “invalid api key” and “bucket does not exist” send you to different fixes,
and collapsing both into “test failed” wastes your afternoon. Before this, a
mistyped key failed at the moment it first mattered, while the page still showed a
confident tick.
You cannot break your own instance from this page. Writes are restricted to the seventeen keys that belong to you. Platform values — the database URL, the authentication secret, our per-instance derived keys — are refused. That last one matters more than it looks: the authentication secret is what your stored credentials are encrypted with.
What we deliberately left out
SMTP. ForgeHub’s SMTP sender is an unimplemented stub that logs a warning and discards the message. We could have shipped a full SMTP form; it would have been a setup flow that appears to succeed and delivers nothing. That is the same class of bug as the dialog in our first post, and we are not adding a second one. Email runs through Resend until the transport is real.
Stripe. You will own your Stripe keys eventually, for invoicing your own clients. We have not settled how that interacts with our billing yet, so rather than ship a half-answer it is absent, and says so.
Why this delayed us
None of this was on the roadmap. It came out of asking a narrow question — what does a real instance actually receive? — and finding that the honest answer was “five values and no way to add more”.
We would rather find that ourselves than have you find it on day three, holding an instance that cannot send an email and a settings page that shrugs.



