Secrets & environment
HiveCFM reads two .env files: one in hivecfm-core/, one in hivecfm-hub/. Neither is committed. Pick the right path for you:
- Local-only dev (most devs, most days): generate throwaway secrets with OpenSSL — works fully offline, no team-lead handoff required.
- Staging / shared dev / anything talking to real third parties: pull values from 1Password.
The two paths share Steps 1–2; Step 3 splits.
Steps
Copy the templates
cd ~/AG-DEV/hivecfm-core
cp .env.example .env
cd ../hivecfm-hub
cp .env.example .env- Expected: Two new
.envfiles, identical to the.env.examplesiblings. - Verify:
ls -la .envin each repo shows a file with non-zero size. - If
cpis not recognised in PowerShell: useCopy-Item .env.example .envinstead. PowerShell does not aliascpby default in older sessions. - search-hint:
powershell cp not recognized
Source paths if you’re auditing later:
F:\ISt\HiveFormbricks\hivecfm-core\.env.example
F:\ISt\HiveFormbricks\hivecfm-hub\.env.example
Generate local-only secrets
Run in Git Bash on Windows, or bash on Linux/EC2 (so openssl is on PATH). Run from ~/AG-DEV (the parent directory that contains both repo folders).
Three traps the naive echo >> .env flow falls into. Skip them by following the steps below in order — they are designed to be safe to re-run if anything goes sideways.
.env.examplemay not end with a newline. The firstecho >>then glues your new key onto the last existing line (e.g.HIVECFM_PORT=3000HUB_SHARED_SECRET=...). dotenv silently ignores the merged half..env.exampleships with empty placeholders (NEXTAUTH_SECRET=,ENCRYPTION_KEY=). Appended real values land below them. dotenv takes the first match top-down → it reads the empty placeholder, ignores your value.- Calling
$(openssl rand -hex 32)twice forHUB_SHARED_SECRETgives you two different strings — core signs with one, hub verifies with the other, every Hub call returns 401.
Run one line at a time. Each step is its own command — do not concatenate.
1. Reset both .env files from their templates (overwrites whatever junk got in there during earlier attempts):
cp hivecfm-core/.env.example hivecfm-core/.envcp hivecfm-hub/.env.example hivecfm-hub/.env- Expected: no output.
- Verify:
ls -la hivecfm-core/.env hivecfm-hub/.envshows both files non-empty.
2. Strip any stale or empty placeholder lines for the keys you’re about to set (idempotent — safe on a fresh .env.example too):
sed -i '/^NEXTAUTH_SECRET=/d; /^ENCRYPTION_KEY=/d; /^SUPERSET_ADMIN_PASSWORD=/d; /HUB_SHARED_SECRET=/d' hivecfm-core/.envsed -i '/HUB_SHARED_SECRET=/d' hivecfm-hub/.env- What this does:
sed -i '/pattern/d'deletes every line matchingpattern, in place. The 4-pattern form for core strips the emptyKEY=placeholders and any merged-onto-port garbage from a prior attempt. TheHUB_SHARED_SECRET=pattern is intentionally unanchored (no^) so it also catches theHIVECFM_PORT=3000HUB_SHARED_SECRET=...merged case. - Expected: no output.
- Verify:
grep -c HUB_SHARED_SECRET hivecfm-core/.envprints0.
3. Add a safety trailing newline to each file so future appends start on a fresh line:
echo "" >> hivecfm-core/.envecho "" >> hivecfm-hub/.env- Expected: no output.
- Why: even if
.env.examplewas missing its final\n,echo ""writes a single\n, giving you a clean separator before the next append. Harmless if the file already ended cleanly.
4. Generate the shared secret ONCE into a shell variable:
HUB_SHARED_SECRET=$(openssl rand -hex 32)- Expected: no output.
- Verify:
echo $HUB_SHARED_SECRETprints a 64-character hex string. - If empty: OpenSSL is not on
PATH. On Amazon Linux:sudo dnf install -y openssl. On Ubuntu:sudo apt install -y openssl. On Windows: open Git Bash, not PowerShell — OpenSSL ships with Git for Windows. - Why a variable: so the same value goes into both
.envfiles in the next steps. Calling$(openssl rand -hex 32)twice gives two different strings → 401.
5. Append the four secrets to hivecfm-core/.env (one line each — runnable independently):
echo "NEXTAUTH_SECRET=$(openssl rand -hex 32)" >> hivecfm-core/.envecho "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> hivecfm-core/.envecho "SUPERSET_ADMIN_PASSWORD=$(openssl rand -hex 16)" >> hivecfm-core/.envecho "HUB_SHARED_SECRET=$HUB_SHARED_SECRET" >> hivecfm-core/.env- Expected: no output from any of the four.
- Why the last one uses the variable, not
$(openssl ...): so step 6 writes the identical value to hub.
6. Append the matching shared secret to hivecfm-hub/.env:
echo "HUB_SHARED_SECRET=$HUB_SHARED_SECRET" >> hivecfm-hub/.env- Expected: no output.
Verify A — shared secret matches in both files:
grep HUB_SHARED_SECRET hivecfm-core/.env hivecfm-hub/.env- Expected: exactly 2 lines, with the same 64-character hex after
=. - If you see
HIVECFM_PORT=3000HUB_SHARED_SECRET=...merged on one line: step 2 didn’t strip it (the variable was empty at sed time, e.g. you ransed -i ''with a stray quote). Redo from step 1. - If only
hivecfm-core/.envshows up: step 1 or step 6 was skipped for hub. Redo step 1 second command, then step 6.
Verify B — core has exactly 4 secret keys, no empty duplicates:
grep -E "^(NEXTAUTH_SECRET|ENCRYPTION_KEY|SUPERSET_ADMIN_PASSWORD|HUB_SHARED_SECRET)=" hivecfm-core/.env-
Expected: exactly 4 lines, each with a non-empty value (64 hex chars for the 32-byte keys, 32 hex chars for
SUPERSET_ADMIN_PASSWORD). -
If any line shows
KEY=(empty after=): step 2 didn’t strip that placeholder. Re-run step 2’s first command, then re-run the matching line from step 5. -
If you see 5+ lines: duplicates from a prior partial attempt. Open
hivecfm-core/.envand delete the older empty/wrong entry, or redo from step 1 (cleaner). -
Why
HUB_SHARED_SECRETmust match across both files: the Go Hub signs every request with it;hivecfm-coreverifies the HMAC. Different values → 401 on every Hub call (you’ll seesignature mismatchin the Hub log). -
If you’re using PowerShell, not bash: the
$(...)syntax is different ($(...)works, but>>andsed -idon’t behave the same). Switch to Git Bash for this step (C:\Program Files\Git\bin\bash.exe), or open the WSL prompt. -
search-hint:
nextauth NEXTAUTH_SECRET missing hub signature mismatch dotenv first match wins
These secrets are valid only for your laptop. Never push a .env to git and never reuse them outside local dev. .env is already in .gitignore — confirm with git check-ignore -v .env.
Pull real secrets from 1Password
Skip this step if you only need local dev.
For shared dev, staging, or production-adjacent work, the real values live in the HiveCFM — Dev 1Password vault. You’ll need:
- 1Password account in the team workspace — request from your team lead.
- The
opCLI installed:winget install --id AgileBits.1Password.CLI -e.
Then sign in and pull each item:
op signin
op item get "hivecfm-core .env" --vault "HiveCFM — Dev" --format json- Expected: JSON with a
fieldsarray; each field haslabelandvalue. - Verify: the labels match the keys in
.env.example. - If “no item found”: you don’t have access to that vault. Ask your team lead to add you —
opcannot bypass ACLs. - search-hint:
1password op cli vault access denied
Copy each value into the matching key in your .env. Do this once, then go back to local-only OpenSSL secrets for day-to-day work — there is no reason to keep production keys on a dev laptop.
What goes where
Most env vars are documented in the auto-generated catalog:
→ Full env var catalog — every key from both .env.example files, regenerated on every CI run.
The handful that always need attention:
| Key | Where to set | Source |
|---|---|---|
NEXTAUTH_SECRET | hivecfm-core/.env | openssl rand -hex 32 |
ENCRYPTION_KEY | hivecfm-core/.env | openssl rand -hex 32 |
HUB_SHARED_SECRET | both .env files | openssl rand -hex 32 — must match |
SUPERSET_ADMIN_PASSWORD | hivecfm-core/.env | openssl rand -hex 16 |
DATABASE_URL | hivecfm-core/.env | Default points at localhost:5433 — leave as-is for Docker Postgres |
| OAuth/OpenAI/Stripe keys | hivecfm-core/.env | 1Password only — leave blank for local-only |
Done — what’s next
→ Back to Run it locally — docker compose up -d and pnpm dev.