#Configuration reference
The server reads standard ASP.NET Core configuration: appsettings.json, then environment variables (the way the Docker setup does it). In environment variables, a nested key uses a double underscore: SignetMail:Portal:ClientId becomes SignetMail__Portal__ClientId.
In the cloud setup you normally touch only .env; docker-compose.yml maps it to the settings below.
#.env (cloud deployment)
| Variable |
Required |
Description |
SIGNETMAIL_VERSION |
no |
Image tag, default latest. |
SIGNETMAIL_HOST |
yes |
Public host name. |
ENTRA_TENANT_ID |
yes |
Entra directory (tenant) ID. |
ENTRA_CLIENT_ID |
yes |
App registration (client) ID. |
PORTAL_OWNER |
yes |
UPN of the first Owner. |
GRAPH_CERT_PASSWORD |
yes |
Password of certs/graph.pfx. |
PORTAL_ALLOWED_IPS |
no |
Space-separated IPs/CIDRs allowed to reach /portal/* and /api/portal/*. Default: everyone. |
BACKUP_GIT_REMOTE |
no |
SSH URL for encrypted backups. |
Warning. .env contains secrets. Keep it readable by the admin only (chmod 600 .env) and never commit it.
#Application settings
#Authentication — AzureAd
| Key |
Description |
Instance |
https://login.microsoftonline.com/ |
TenantId |
Tenant ID. |
ClientId |
App registration ID. |
Audience |
Optional; set it only if you use a non-default Application ID URI. |
#General — SignetMail
| Key |
Default |
Description |
PublicUrl |
from request |
Public base address, for example https://app.example.com. Used in the add-in manifest, /portal/config.json and campaign links. Behind a proxy also set ASPNETCORE_FORWARDEDHEADERS_ENABLED=true. |
EnableDevelopmentAuth |
false |
Allows sign-in by header. Works only in the Development environment; never enable on a public server. |
CorsOrigins |
[] |
Origins allowed to call the API from a browser. Empty = CORS off (the hosted add-in and portal are same-origin and need nothing). |
TemplatesPath |
templates |
Folder with initial templates used to seed an empty database. |
DefaultTemplate |
default |
Identifier of the fallback signature. |
#Directory — SignetMail:Directory
| Key |
Default |
Description |
Source |
Sample |
Graph (Entra ID) or Google (Google Workspace) in production; Sample reads a JSON file for development. |
SyncIntervalMinutes |
60 |
How often the directory is re-read. |
SampleFile |
sample-users.json |
Development data. |
#Microsoft Graph — SignetMail:Graph
| Key |
Description |
TenantId, ClientId |
Same app registration as sign-in. |
CertificatePath |
Path to the .pfx (in the container: /certs/graph.pfx). |
CertificatePassword |
Password of the .pfx. |
CertificateThumbprint |
Alternative on Windows: use a certificate from the My store. |
#Google Workspace — SignetMail:Google
Used when Directory:Source is Google. See Google Workspace.
| Key |
Default |
Description |
ServiceAccountKeyFile |
|
Path to the service account JSON key (in the container: /google/service-account.json). |
ServiceAccountKeyJson |
|
The key's content instead of a file (for secret stores). |
AdminEmail |
|
Super admin the service account acts as when reading the directory. |
ClientId |
|
OAuth Client ID for Google sign-in to the portal. Empty = Google sign-in off. |
AllowedDomains |
|
Domains whose accounts may sign in (required when ClientId is set). |
PushSignatures |
false |
Automatically write signatures into Gmail. |
PushIntervalMinutes |
60 |
How often to check for changed signatures (minimum 5). |
#Portal — SignetMail:Portal
| Key |
Description |
Owners |
List of UPNs that are Owners on every start. |
ClientId, TenantId |
Handed to the browser through /portal/config.json. |
ApiScope |
api://<ClientId>/access_as_user. |
RootOrganizationSlug |
Slug of the root organization created on first start (default default). |
UploadsPath |
Where uploaded images are stored (default data/uploads). |
#Database — SignetMail:Database
| Key |
Default |
Description |
Provider |
Sqlite |
Sqlite or Postgres. |
ConnectionString |
Data Source=data/signetmail.db |
Connection string for the chosen provider. |
SQLite is perfectly adequate for a single server. Choose PostgreSQL when you want managed backups or run several instances.
Note. The schema is created automatically on first start. There are no automatic migrations yet: after an update that changes the data model, release notes will say what to do. Always take a backup before updating.
#Security limits — SignetMail:Security
| Key |
Default |
Description |
RateLimitPerMinute |
600 |
Requests per minute per client address for the whole API. |
AnonymousRateLimitPerMinute |
120 |
Stricter limit for public paths (/c/…, /uploads/…). Exceeding either returns HTTP 429. |
#License — SignetMail:License
| Key |
Description |
Key |
Optional license key (see Licensing). A key applied in the portal takes precedence and is stored in the database. |
PublicKey |
Optional override of the vendor's public key used to verify license keys. Leave empty to use the built-in key. |
#Seeding settings (first start only)
Organization, Organizations and Rules in appsettings.json fill an empty database on the very first start and are ignored afterwards; after that, everything is managed in the portal. A fresh production install starts with one organization, My company.
#Endpoints at a glance
| Path |
Purpose |
Access |
/portal/ |
Administration portal |
Entra sign-in; optionally IP-restricted |
/docs/ |
This documentation |
Public, static |
/addin/manifest.xml, /addin/… |
Outlook add-in |
Public (Microsoft downloads it) |
/api/v1/signature |
Signature for the signed-in user |
Entra token (add-in) or Kerberos (agent) |
/api/portal/… |
Portal API |
Entra token + role |
/c/<id> |
Campaign click redirect |
Public |
/uploads/<hash>.png |
Uploaded logos and banners |
Public (recipients load them) |
/health |
{status, lastSyncUtc} |
Public, no sensitive data |