Skip to main content

Getting Started

This guide walks through setting up the mwen.io issuer server in self-hosted mode — the simplest path to issuing your first credential. If you are deploying in SaaS mode to serve multiple organisations, start here to verify the basics, then see SaaS Onboarding.


Prerequisites

ToolVersionPurpose
Node.js20+Runtime (via nvm or fnm recommended)
DockerAny recentPostgreSQL container
mkcertAnyLocal TLS certificates
Caddy2.xHTTPS reverse proxy (NextAuth requires HTTPS)

The mwen.io browser extension must be installed in your browser to complete the operator registration flow and to test credential issuance.


Step 1 — Clone and install

Clone the monorepo and install dependencies from the root:

git clone https://github.com/mwenio/mwen.io.git
cd mwen.io
npm install

Step 2 — Start PostgreSQL

The issuer requires a PostgreSQL database. A docker-compose.yml is provided in apps/issuer/:

docker-compose up -d

This starts a PostgreSQL container on port 5432 with the credentials pre-configured in .env.local.self-hosted.


Step 3 — Apply migrations and seed

From apps/issuer/:

npm run db:migrate   # applies all Prisma migrations and RLS policies
npm run db:seed # creates the default tenant and test data

Verify the migration state:

npx prisma migrate status
# Expected: "Database schema is up to date!"

Step 4 — Start the server

Use the mode-specific start script rather than npm run dev directly. The script copies the correct environment file to .env.local first:

npm run dev:self-hosted

The Next.js server starts on port 3003. In a separate terminal, start the HTTPS proxy:

npm run proxy

The issuer is now available at https://localhost:3002.


Step 5 — Register the first operator

Open https://localhost:3002/login in your browser (with the mwen.io extension installed).

  1. Click Sign in with mwen.io — the extension presents your identity to the issuer.
  2. Because no operator exists yet, you are redirected to /register.
  3. Complete the registration form. You are the first operator, so you are automatically assigned the OWNER role on the default tenant.

You are now logged in to the issuer admin portal.


Step 6 — Issue your first credential

From the admin portal:

  1. Go to Credentials → New Offer.
  2. Select a schema (e.g. employee-identity-v1).
  3. Enter the subject's details and click Create Offer.
  4. A QR code appears. Scan it with the mwen.io extension on your mobile device, or open the offer link in a browser with the extension installed.
  5. The wallet displays the credential offer preview. Accept it.
  6. The credential is stored in the wallet.

What happens next

The credential is now in the wallet. The wallet holder can present it to any relying party app that accepts verified-issuer or (if you configured a government category) government trust level credentials.


Configuration

The default self-hosted environment file at apps/issuer/.env.local.self-hosted is pre-configured for local development. For a production deployment you will need to:

  • Set ISSUER_SIGNING_KEY to a freshly-generated secret (run openssl rand -hex 32)
  • Set NEXTAUTH_SECRET to a freshly-generated secret
  • Set ISSUER_DID to your production did:web (e.g. did:web:issuer.yourorg.com)
  • Set ISSUER_DOMAIN to your production domain
  • Set DATABASE_URL to your production PostgreSQL connection string
  • Set NEXTAUTH_URL to your production base URL

See Configuration for a full reference of all variables.