Getting StartedSecrets & Environment

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 .env files, identical to the .env.example siblings.
  • Verify: ls -la .env in each repo shows a file with non-zero size.
  • If cp is not recognised in PowerShell: use Copy-Item .env.example .env instead. PowerShell does not alias cp by 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.

  1. .env.example may not end with a newline. The first echo >> then glues your new key onto the last existing line (e.g. HIVECFM_PORT=3000HUB_SHARED_SECRET=...). dotenv silently ignores the merged half.
  2. .env.example ships 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.
  3. Calling $(openssl rand -hex 32) twice for HUB_SHARED_SECRET gives 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/.env
cp hivecfm-hub/.env.example hivecfm-hub/.env
  • Expected: no output.
  • Verify: ls -la hivecfm-core/.env hivecfm-hub/.env shows 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/.env
sed -i '/HUB_SHARED_SECRET=/d' hivecfm-hub/.env
  • What this does: sed -i '/pattern/d' deletes every line matching pattern, in place. The 4-pattern form for core strips the empty KEY= placeholders and any merged-onto-port garbage from a prior attempt. The HUB_SHARED_SECRET= pattern is intentionally unanchored (no ^) so it also catches the HIVECFM_PORT=3000HUB_SHARED_SECRET=... merged case.
  • Expected: no output.
  • Verify: grep -c HUB_SHARED_SECRET hivecfm-core/.env prints 0.

3. Add a safety trailing newline to each file so future appends start on a fresh line:

echo "" >> hivecfm-core/.env
echo "" >> hivecfm-hub/.env
  • Expected: no output.
  • Why: even if .env.example was 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_SECRET prints 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 .env files 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/.env
echo "ENCRYPTION_KEY=$(openssl rand -hex 32)" >> hivecfm-core/.env
echo "SUPERSET_ADMIN_PASSWORD=$(openssl rand -hex 16)" >> hivecfm-core/.env
echo "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 ran sed -i '' with a stray quote). Redo from step 1.
  • If only hivecfm-core/.env shows 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/.env and delete the older empty/wrong entry, or redo from step 1 (cleaner).

  • Why HUB_SHARED_SECRET must match across both files: the Go Hub signs every request with it; hivecfm-core verifies the HMAC. Different values → 401 on every Hub call (you’ll see signature mismatch in the Hub log).

  • If you’re using PowerShell, not bash: the $(...) syntax is different ($(...) works, but >> and sed -i don’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:

  1. 1Password account in the team workspace — request from your team lead.
  2. The op CLI 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 fields array; each field has label and value.
  • 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 — op cannot 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:

KeyWhere to setSource
NEXTAUTH_SECREThivecfm-core/.envopenssl rand -hex 32
ENCRYPTION_KEYhivecfm-core/.envopenssl rand -hex 32
HUB_SHARED_SECRETboth .env filesopenssl rand -hex 32 — must match
SUPERSET_ADMIN_PASSWORDhivecfm-core/.envopenssl rand -hex 16
DATABASE_URLhivecfm-core/.envDefault points at localhost:5433 — leave as-is for Docker Postgres
OAuth/OpenAI/Stripe keyshivecfm-core/.env1Password only — leave blank for local-only

Done — what’s next

→ Back to Run it locallydocker compose up -d and pnpm dev.