Docs · Get started
Self-hosting
MagpieCRM is one Docker image and one persistent volume. This page takes you from an empty server to a working copy. For every setting, see Environment variables.
What you need
- A server with Docker and Docker Compose. The container listens on port 3000 and runs as a non-root user.
- A public HTTPS address for it, such as
https://crm.example.com, behind your own reverse proxy. Links in emails, bounce webhooks and AI apps that connect from the cloud all need to reach it. - A SocialFetch API key for prospect data. You pay SocialFetch directly.
- An account with an email provider, or an SMTP server, to send from.
- For email verification, a verification server with outbound port 25, or proxies that have it. See Email verification.
Your data is a single JSON file on the volume, with uploaded images in an uploads/ folder next to it.
Run the image
The image is ghcr.io/magpiecrm/magpie-crm-app. Each release is published as a version tag, so pin one rather than latest, which follows every change to the main branch. The current version is 0.9.23; the releases page lists the rest.
Save this as compose.yaml and fill in your own values:
services:
magpie:
image: ghcr.io/magpiecrm/magpie-crm-app:0.9.23
restart: unless-stopped
ports: ["3000:3000"]
environment:
NODE_ENV: production
HOME: /data # the volume
DATABASE_PATH: /data/db.json # your data
PUBLIC_URL: https://crm.example.com
AUTH_EMAIL: you@example.com
AUTH_PASSWORD: choose-a-password
TRACKING_SECRET: generate-me # set once
SUPPRESSION_SECRET: generate-me # set once, never rotate
WEBHOOK_SECRET: generate-me # turns on bounce and complaint webhooks
SOCIALFETCH_API_KEY: sfk_...
volumes: [magpie-data:/data]
volumes:
magpie-data:Then run docker compose up -d. HOME points at the volume because the container gives its user ownership of $HOME at start, which makes the volume writable.
Generate the secrets
Generate each secret separately:
openssl rand -hex 32 # TRACKING_SECRET
openssl rand -hex 32 # SUPPRESSION_SECRET
openssl rand -hex 32 # WEBHOOK_SECRETTRACKING_SECRETis required withNODE_ENV=production. It signs tracking and unsubscribe links and encrypts the provider keys you save in Settings. Set it once: changing it makes those saved keys unreadable.SUPPRESSION_SECRETis recommended. It keys the hashes behind the opt-out, unsubscribe and bounce lists, and falls back toTRACKING_SECRET. Never rotate it, or people who opted out come back.WEBHOOK_SECRETturns on the bounce and complaint webhooks. Without it they refuse every request. See Sending and deliverability.
Secrets live in the environment
They can't be changed in the app. Set them where you deploy, before the first start.
First sign-in
Open your PUBLIC_URL (or port 3000 on the server) and sign in with AUTH_EMAIL and AUTH_PASSWORD. That's the first login. If you forget its password, change AUTH_PASSWORD and restart: the password is reset to the new value.
Set PUBLIC_URL to the address people reach the app on. It's used for links the server builds for others to open: tracking and unsubscribe links, images in emails, survey links and webhook addresses. Unset, the app uses the host of the incoming request.
Fill in Settings
- Data source: add your SocialFetch API key (it starts
sfk_) and press Test connection. A key saved here takes priority overSOCIALFETCH_API_KEY. - Sending: choose your provider, enter its credentials, set a default sender and send a test email. Add the addresses you send from under Sender addresses. Until a provider is set up, email is only logged, not sent.
- Email verification: connect your verification server with its URL and secret, then press Test verification. See Email verification.
- Team and login: add the people who should sign in, each with an email and a password, and change your own password. There are no roles: everyone can do everything.
Optional: add your own Anthropic or OpenAI API key under Copilot, and create keys for AI apps under Connect AI apps (see MCP server).
Updating
- Back up the volume first. It holds all your data.
- Change the image tag in compose.yaml to the newer version, then pull and restart:Terminal
docker compose pull docker compose up -d
A new version reads the previous version's data: data changes are additive, and there's no migration command to run. Anything you need to do yourself is in the release notes.
Running from source
You need Bun installed. Put the same variables in a .env file in the project root, then build and start:
git clone https://github.com/magpiecrm/magpie-crm-app.git
cd magpie-crm-app
bun install && bun run build && bun run startWithout DATABASE_PATH the data file is local_db.json in the working directory. The full guide, including every variable, is in the README on GitHub.
Something wrong or missing? Email pele@magpiecrm.com or open an issue.