Configuration
Set up environment variables and authentication for your LinkDen instance.
⚙️ Configuration
LinkDen keeps its .env file minimal on purpose. You only need five environment variables to get running. Everything else -- email, CAPTCHA, branding, and more -- is configured through the admin panel and stored in the database.
⚡ TL;DR
- Required: 5 variables (
BETTER_AUTH_SECRET,BETTER_AUTH_URL,CORS_ORIGIN,NEXT_PUBLIC_SERVER_URL,NEXT_PUBLIC_SITE_URL). - Config Location: Most settings are in
/admin/settings(DB), not.env. - Auth: Built-in email/password (Better Auth). No external provider needed.
1. 🔑 Environment Variables
Create your .env file from the example:
cp .env.example .envRequired Variables Checklist
-
BETTER_AUTH_SECRET- Private. Signs session cookies. -
BETTER_AUTH_URL- Public. URL where the API server runs. -
CORS_ORIGIN- Public. URL where the web frontend runs. -
NEXT_PUBLIC_SERVER_URL- Public. Same asBETTER_AUTH_URL. -
NEXT_PUBLIC_SITE_URL- Public. URL of the site itself (used forrobots.txt,sitemap.xml, and Open Graph links).
Generating a Secret
Run this to generate a strong, random secret:
openssl rand -base64 32Paste the output as your BETTER_AUTH_SECRET. Use a different secret for production. Outside localhost the secret must be at least 32 characters and not a placeholder: with a weak or empty secret, sign-in and the admin API answer 503, and bun ship refuses to deploy.
2. 📝 Examples
💻 Local Development
BETTER_AUTH_SECRET=your-generated-secret
BETTER_AUTH_URL=http://localhost:3000
CORS_ORIGIN=http://localhost:3001
NEXT_PUBLIC_SERVER_URL=http://localhost:3000
NEXT_PUBLIC_SITE_URL=http://localhost:3001🌍 Production
SITE_DOMAIN=links.yourdomain.com
BETTER_AUTH_SECRET=your-production-secret
BETTER_AUTH_URL=https://links.yourdomain.com
CORS_ORIGIN=https://links.yourdomain.com
NEXT_PUBLIC_SERVER_URL=https://links.yourdomain.com
NEXT_PUBLIC_SITE_URL=https://links.yourdomain.comTip: In production all four URLs are the same hostname. The web app owns
SITE_DOMAINand the API is routed under it at/api/*and/trpc/*, so there is no separate API domain. Locally the API (:3000) and web app (:3001) are different origins, which is why the local values differ. See Environment Variables for the deploy-only variables.
3. 🔐 Authentication
LinkDen uses email and password authentication, with optional two-factor (TOTP) and magic link sign-in.
- 🚫 No OAuth needed.
- 🚫 No external auth service needed.
How it works:
- Navigate to
/admin/setup. - Create your admin account (enter the Setup token if your deploy sets
SETUP_TOKEN). - The first user becomes the admin.
- Registration locks automatically.
- Sign in at
/admin/login. With two-factor on, you are then asked for the 6-digit code from your authenticator app or one of your backup codes.
Two-factor authentication
Turn it on under Settings → Account → Two-factor authentication: scan the QR code (or type the key), enter a code to confirm, and save the backup codes somewhere safe. 2FA only switches on once the first code verifies. You can tick "trust this device for 30 days" at login. Lost both your authenticator and your codes? Run bun reset:password -- --email you@example.com --remote --disable-2fa.
Magic link
Optional passwordless sign-in under Settings → Account. It can only be turned on once email is configured and while two-factor is off, links expire after 10 minutes, and only your admin address can receive one.
Note: Unauthenticated visitors only see your public link page.
4. 🎛️ Admin Settings (Runtime Config)
Most configuration lives in the admin panel (/admin/design for the page, /admin/settings for account, email, integrations, wallet and data), not in environment variables. This means you can change settings without redeploying:
- 📧 Email provider -- Resend (Cloudflare Email Workers coming soon), plus where contact-form messages go (Inbox, email, or both).
- 🛡️ CAPTCHA -- Cloudflare Turnstile, Google reCAPTCHA (v2 checkbox), or hCaptcha on the contact form.
- 🏷️ Branding -- Whitelabel footer text, link, logo, site name, and admin panel branding.
- 📇 vCard -- Enable or disable the downloadable contact card.
- 🍏 Apple Wallet -- Pass design, Team ID, Pass Type ID, signing keys, and custom QR URL.
- 🔍 SEO -- Page title, meta description, and OG image.
- 🗺️ MapKit -- Apple Maps token (stored for a planned map embed; Location blocks currently link out to a map).
- 🍪 Consent Banner -- On by default. Asks visitors before analytics and embedded media load.
- 🖥️ Admin Branding -- Show or hide LinkDen branding inside the admin panel itself.
Next Steps
- 🚀 Quick Start -- Walk through the setup wizard.
- ☁️ Self-Hosting -- Deploy to Cloudflare.