Skip to content

Backend Configuration (appsettings.json)

The EZY WMS Service is configured via appsettings.json, located in the ezy-wms-backend/Service/ directory. This file controls CORS, logging, database connections, JWT authentication, session management, licensing, background services, email, and health checks. All settings are required unless marked optional.

Defines which origins can make cross-origin requests to the API.

FieldTypeDefaultDescription
AllowedOriginsArray of strings["http://localhost:5001"]List of allowed origin URLs (e.g., Portal frontend). Wildcard * is not recommended for production.

Note: Ensure Portal and other frontend clients are included. Requests from unlisted origins will be rejected.

Structured logging configuration. Logs are written to console and rolling files.

FieldTypeDefaultDescription
UsingArray["Serilog.Sinks.Console", "Serilog.Sinks.File"]Enabled log sinks.
MinimumLevel.DefaultStringWarningMinimum log level for all loggers (e.g., Debug, Information, Warning, Error).
MinimumLevel.OverrideObjectSee examplePer-namespace overrides (e.g., Microsoft.Hosting.Lifetime: Information).
WriteTo[0].NameStringConsoleLog output to console.
WriteTo[1].NameStringFileLog output to rotating file.
WriteTo[1].Args.pathString./logs/log-.txtLog file path with {Date} placeholder for daily rotation.
WriteTo[1].Args.rollingIntervalStringDayRotate logs daily. Options: Day, Hour, Month.
WriteTo[1].Args.retainedFileCountLimitInteger7Keep this many log files. Older files are deleted.
WriteTo[1].Args.fileSizeLimitBytesInteger10485760 (10 MB)Maximum size per log file before rollover.
WriteTo[1].Args.rollOnFileSizeLimitBooleantrueRotate log files when size limit is reached.
EnrichArray["FromLogContext", "WithMachineName", "WithThreadId"]Add context info to logs (machine name, thread ID).

Notes:

  • Logs are stored in ./logs/ (relative to service executable).
  • Production deployments should use at least Warning level to reduce noise.
  • Entity Framework Core logs are set to Warning by default to reduce verbosity.

Legacy .NET logging configuration. Serilog is preferred but both coexist.

FieldTypeDefaultDescription
LogLevel.DefaultStringErrorDefault level for all loggers.
LogLevel.MicrosoftStringErrorLevel for Microsoft framework logs.
LogLevel.Microsoft.Hosting.LifetimeStringErrorLevel for service startup/shutdown logs.

Security setting to restrict which Host headers the service will accept.

FieldTypeDefaultDescription
AllowedHostsString*Allowed Host header values. Use * to allow all, or list specific hostnames (comma-separated).

Note: In production, replace * with actual hostnames or IP addresses to prevent host-based attacks.

HTTP server configuration.

FieldTypeDefaultDescription
Kestrel.Endpoints.Http.UrlStringhttp://localhost:5000HTTP endpoint URL. Use http://0.0.0.0:5000 to listen on all interfaces.

Note: Change the port or bind address to match your deployment network. Default localhost only accepts local connections.

Database connection strings for the service and external adapters.

FieldTypeDefaultDescription
DefaultConnectionStringSQL Server connection stringPrimary WMS database. Includes server, database name, user, password, and certificate trust settings.
ExternalAdapterConnectionStringSQL Server connection stringOptional database for external system adapters. Can point to the same or different SQL Server.

Note: Both use SQL Server connection string format. For cloud SQL (Azure, etc.), adjust Server, User Id, and Password. TrustServerCertificate=true is for development; for production, use proper certificates.

JWT authentication settings for Bearer tokens.

FieldTypeDefaultDescription
KeyStringJwtToken (example)Secret key for signing JWT tokens. Must be a long, random string (at least 32 bytes).
IssuerStringYourIssuer (example)Token issuer claim (e.g., EzyWMS).
AudienceStringYourAudience (example)Token audience claim (e.g., EzyWMS-Client).
ExpiresInMinutesInteger60Token expiration time in minutes. After this, tokens are invalid.

Critical: Replace Key with a cryptographically secure random string. The example value JwtToken is for demonstration only and must not be used in production.

Configures session storage backend (in-memory or Redis).

FieldTypeDefaultDescription
TypeStringRedis (example) or InMemorySession storage type. Options: InMemory (single-instance only), Redis (distributed).
Redis.HostStringlocalhostRedis server hostname or IP. Required if Type: Redis.
Redis.PortInteger6379Redis server port. Default is 6379.
Cookie.DomainString or nullnullCookie domain (e.g., .example.com). Leave null for current domain only.
Cookie.SecureBooleanfalseSend cookie only over HTTPS. Set true in production.
Cookie.SameSiteStringLaxCSRF protection mode. Options: Strict, Lax, None. Use Lax for typical deployments.
Cookie.HttpOnlyBooleantruePrevent JavaScript access to session cookie. Keep true for security.

Critical Notes:

  • If Type: Redis, a Redis server must be running and accessible at the specified host and port. Without Redis, session operations will fail.
  • For single-instance deployments without Redis, use InMemory, but sessions are lost on restart.
  • In production, always set Cookie.Secure: true and use HTTPS.

License validation and caching settings.

FieldTypeDefaultDescription
EncryptionKeyString (base64)See exampleBase64-encoded 32-byte key for encrypting license data. Must match the key used by the licensing cloud.
CloudEndpointString (URL)http://localhost:3001Licensing cloud service URL.
BearerTokenStringSee exampleBearer token for authenticating requests to the licensing cloud.
CacheExpirationHoursInteger24How long to cache valid licenses locally before re-checking with cloud.
GracePeriodDaysInteger7Days the service can operate with an expired or invalid license before blocking operations.
DemoExpirationDaysInteger30Validity period for demo licenses.
WarningThresholdDaysInteger3Days remaining until license expires when warnings begin.

Critical Notes:

  • EncryptionKey must be exactly a base64-encoded 32-byte value. Incorrect format will cause license decryption failures.
  • CloudEndpoint and BearerToken must point to the licensing service. Invalid values prevent license validation.
  • During the grace period, the service continues operating with a warning, but after grace period expires, features are locked.

Long-running background tasks.

Synchronizes pick list operations with inventory.

FieldTypeDefaultDescription
IntervalSecondsInteger60How often to check for pick list updates (in seconds).
EnabledBooleantrueEnable or disable the pick list sync service.
CheckClosedPickListsBooleantrueMonitor closed pick lists for completion.
ProcessPackageMovementsBooleantrueUpdate inventory when packages are moved.

Synchronizes data with the licensing/management cloud.

FieldTypeDefaultDescription
SyncIntervalMinutesInteger10How often to sync with cloud (in minutes).
ValidationIntervalHoursInteger24How often to perform full validation against cloud (in hours).
EnabledBooleantrueEnable or disable cloud sync.

Note: CloudSync requires network connectivity to the cloud endpoint. If the cloud is unreachable, the service continues with cached data but will log warnings.

Email settings for sending notifications (optional).

FieldTypeDefaultDescription
EnabledBooleanfalseEnable or disable email functionality.
HostStringEmptySMTP server hostname (e.g., smtp.gmail.com). Required if Enabled: true.
PortInteger587SMTP port (typically 587 for TLS or 25 for unencrypted).
EnableSslBooleantrueUse TLS/SSL for the SMTP connection.
UsernameStringEmptySMTP authentication username.
PasswordStringEmptySMTP authentication password.
FromEmailStringEmptySender email address (e.g., noreply@example.com).
FromNameStringEzyWMSDisplay name for the sender.
TimeoutSecondsInteger30Timeout for SMTP operations (in seconds).
TimeZoneIdStringAmerica/PanamaTimezone for email timestamps and scheduling.

Notes:

  • Email is optional. Set Enabled: false to disable (emails are not sent).
  • If enabled, all SMTP fields must be filled. Invalid credentials will cause email send failures and errors in logs.

Health check integration with UptimeKuma monitoring service (optional).

FieldTypeDefaultDescription
EnabledBooleanfalseEnable or disable UptimeKuma heartbeats.
PushUrlStringSee exampleUptimeKuma push monitor endpoint URL. Format: https://uptime.example.com/api/push/YOUR_PUSH_KEY.
HeartbeatIntervalSecondsInteger60How often to send a heartbeat to UptimeKuma (in seconds).
SendOnStartupBooleantrueSend a heartbeat when the service starts.
SendOnShutdownBooleantrueSend a heartbeat when the service shuts down.

Notes:

  • UptimeKuma monitoring is optional. Set Enabled: false to disable.
  • If enabled, the PushUrl must be valid and accessible. Unreachable URLs will cause connection timeouts in logs but will not block service startup.

Below is a fully annotated example appsettings.json file suitable for a production deployment. Replace all placeholder values with your environment’s actual settings.

{
"Cors": {
"AllowedOrigins": [
"https://portal.example.com",
"https://admin.example.com"
]
},
"Serilog": {
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
"MinimumLevel": {
"Default": "Warning",
"Override": {
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.EntityFrameworkCore": "Warning"
}
},
"WriteTo": [
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "./logs/log-.txt",
"rollingInterval": "Day",
"retainedFileCountLimit": 7,
"fileSizeLimitBytes": 10485760,
"rollOnFileSizeLimit": true
}
}
],
"Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
},
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Error",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "portal.example.com,admin.example.com,your-db-server",
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://0.0.0.0:5000"
}
}
},
"ConnectionStrings": {
"DefaultConnection": "Server=your-db-server;Database=EZY_WMS;User Id=sa;Password=YOUR_DB_PASSWORD;TrustServerCertificate=false;Encrypt=true;",
"ExternalAdapterConnection": "Server=your-db-server;Database=EZY_ADAPTERS;User Id=sa;Password=YOUR_DB_PASSWORD;TrustServerCertificate=false;Encrypt=true;"
},
"Jwt": {
"Key": "REPLACE_WITH_RANDOM_SECRET_AT_LEAST_32_BYTES_LONG_AND_CRYPTOGRAPHICALLY_SECURE",
"Issuer": "EzyWMS",
"Audience": "EzyWMS-Client",
"ExpiresInMinutes": 60
},
"SessionManagement": {
"Type": "Redis",
"Redis": {
"Host": "your-redis-server",
"Port": 6379
},
"Cookie": {
"Domain": null,
"Secure": true,
"SameSite": "Lax",
"HttpOnly": true
}
},
"PresenceTracking": {
"Type": "Redis"
},
"Licensing": {
"EncryptionKey": "REPLACE_WITH_BASE64_ENCODED_32_BYTE_KEY",
"CloudEndpoint": "https://licensing.example.com:3453",
"BearerToken": "REPLACE_WITH_BEARER_TOKEN",
"CacheExpirationHours": 24,
"GracePeriodDays": 7,
"DemoExpirationDays": 30,
"WarningThresholdDays": 3
},
"BackgroundServices": {
"PickListSync": {
"IntervalSeconds": 60,
"Enabled": true,
"CheckClosedPickLists": true,
"ProcessPackageMovements": true
},
"CloudSync": {
"SyncIntervalMinutes": 10,
"ValidationIntervalHours": 24,
"Enabled": true
}
},
"Smtp": {
"Enabled": true,
"Host": "smtp.example.com",
"Port": 587,
"EnableSsl": true,
"Username": "noreply@example.com",
"Password": "YOUR_SMTP_PASSWORD",
"FromEmail": "noreply@example.com",
"FromName": "EZY WMS",
"TimeoutSeconds": 30,
"TimeZoneId": "America/Panama"
},
"UptimeKuma": {
"Enabled": true,
"PushUrl": "https://uptime.example.com/api/push/REPLACE_ME",
"HeartbeatIntervalSeconds": 60,
"SendOnStartup": true,
"SendOnShutdown": true
}
}