Environments
The environment segment in /api/{environment}/{endpoint} selects a folder under environments/ with the connection string, server name, headers and authentication for that target.
Directory structure
environments/
├── settings.json # Global: allowed environment names and server name
├── network-access-policy.json # SSRF protection for Proxy endpoints
├── prod/
│ └── settings.json # Production connection string, headers, auth
├── test/
│ └── settings.json
└── dev/
└── settings.jsonINFO
Environment names are free-form (e.g. dev, prod, WMS, 500). The folder name is the URL segment.
Global settings
The global file environments/settings.json lists the routable environments:
{
"Environment": {
"ServerName": "SERVERNAME",
"AllowedEnvironments": ["prod", "dev", "test"]
}
}ServerName is the default server name in forwarded headers. Property reference: Environment settings.
WARNING
An environment folder is routed only when its name is listed in AllowedEnvironments.
Environment settings
Per-environment settings.json:
{
"ServerName": "PROD-SQL-CLUSTER",
"ConnectionString": "Server=PROD-SQL-CLUSTER;Database=ProductionDB;Integrated Security=True;TrustServerCertificate=true;",
"Headers": {
"DatabaseName": "ProductionDB",
"Origin": "Portway"
}
}| Field | Required | Description |
|---|---|---|
ServerName |
No | Overrides the global server name for this environment |
ConnectionString |
No | Database connection string. Required for SQL and Webhook endpoints |
Headers |
No | Headers added to forwarded proxy requests; they replace client headers of the same name |
SQL provider detection
The SQL provider is detected from the connection string. Detection rules and provider differences: SQL Providers.
TIP
An SQLite environment needs no database server:
{ "ConnectionString": "Data Source=environments/demo/demo.db;" }Configuration examples
SQL Server with Windows Authentication:
{
"ServerName": "PROD-SQL-CLUSTER",
"ConnectionString": "Server=PROD-SQL-CLUSTER;Database=ProductionDB;Integrated Security=True;MultiSubnetFailover=True;TrustServerCertificate=true;"
}SQL Server with SQL authentication:
{
"ServerName": "DEV-SQL-01",
"ConnectionString": "Server=DEV-SQL-01;Database=DevelopmentDB;User Id=dev_user;Password=dev_password;TrustServerCertificate=true;"
}PostgreSQL:
{
"ServerName": "pg-host",
"ConnectionString": "Host=pg-host;Port=5432;Database=mydb;Username=portway;Password=your-password;"
}MySQL:
{
"ServerName": "mysql-host",
"ConnectionString": "Server=mysql-host;Port=3306;Database=mydb;Uid=portway;Pwd=your-password;SslMode=Preferred;"
}Access control
A request must pass both the token and the endpoint environment restrictions.
Token-level restrictions
A token lists its environments: * for all, a comma-separated list, or a prefix pattern such as pro*:
{
"Username": "api-user",
"Token": "your-token-here",
"AllowedEnvironments": "prod,dev"
}Endpoint-level restrictions
An endpoint lists the environments it serves:
{
"DatabaseObjectName": "ServiceRequests",
"AllowedEnvironments": ["prod"]
}| Token environments | Endpoint AllowedEnvironments |
Request environment | Result |
|---|---|---|---|
* |
(not set) | Any | Allowed |
* |
["prod"] |
prod |
Allowed |
* |
["prod"] |
dev |
Blocked |
prod,dev |
(not set) | prod |
Allowed |
prod,dev |
(not set) | test |
Blocked |
prod,dev |
["prod"] |
prod |
Allowed |
prod,dev |
["prod"] |
dev |
Blocked |
Per-environment authentication
An Authentication block in the environment's settings.json adds API key, Basic, Bearer, JWT or HMAC authentication for that environment:
{
"ServerName": "PROD-SQL",
"ConnectionString": "...",
"Authentication": {
"Enabled": true,
"Methods": [
{
"Type": "ApiKey",
"Name": "X-Custom-Auth",
"Value": "your-secret-key",
"In": "Header"
}
]
}
}| Field | Required | Type | Description |
|---|---|---|---|
Enabled |
Yes | boolean | Enables the methods; false ignores the block |
OverrideGlobalToken |
No | boolean | true rejects Portway bearer tokens and accepts only these methods (default false) |
Methods |
Yes (when enabled) | array | Authentication method definitions |
Method Type |
Key fields |
|---|---|
ApiKey |
Name, Value, In (Header or Query) |
Basic |
Name, Value |
Bearer |
Value |
JWT |
Issuer, Secret, PublicKey |
HMAC |
Name, Secret |
TIP
Plaintext secrets in settings.json are encrypted at the next start (PWENC:...). The keys are stored in .core/ next to the installation; back it up and keep it while encrypted environments exist.
With "Encrypt": false in its settings.json, an environment stays plaintext; use it for non-production credentials only.
Requests authenticated by these methods have no Portway token and are refused on endpoints with Tenancy. JWT and HMAC configuration: Environment Authentication.
Azure Key Vault
Connection strings and other secrets can be read from Azure Key Vault instead of settings.json:
Set the Key Vault URI:
Create secrets per environment:
{environment}-ConnectionString{environment}-ServerName{environment}-Headers(JSON string)
The secrets are read at startup and used like file-based values.
Network access policy
The file environments/network-access-policy.json lists the upstream hosts proxy endpoints may call (SSRF protection). It is created at first start.
{
"allowedHosts": [
"localhost",
"127.0.0.1",
"api.internal.example.com",
"*.services.corp"
],
"blockedIpRanges": [
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
"169.254.0.0/16"
]
}| Field | Description |
|---|---|
allowedHosts |
Hosts proxy endpoints may call; * matches one label (e.g. *.corp) |
blockedIpRanges |
CIDR ranges refused after DNS resolution |
A proxy request is allowed when the target host matches allowedHosts and no resolved address is in blockedIpRanges.
With only the two default localhost entries in allowedHosts, the machine's host name and interface addresses are added at startup. Explicit entries disable this.
Wildcard examples (* does not cross dots):
*.corpmatchesapi.corpanddb.corpapi.*.corpmatchesapi.v1.corpandapi.v2.corp
WARNING
Set allowedHosts explicitly in production. Auto-discovery adds every local address.
TIP
The ASPNETCORE_DOMAIN environment variable adds a host name to the allowed list at runtime.
Troubleshooting
| Symptom | Resolution |
|---|---|
| "Environment not in the allowed list" | Add the name to AllowedEnvironments in environments/settings.json. |
| "Settings.json not found for environment" | Create environments/{name}/settings.json. |
| "Access denied to environment" | Grant the environment to the token in the console under Access Tokens. |
| Proxy blocked, host not allowed | Add the host to allowedHosts in network-access-policy.json and restart. |
| Proxy blocked, IP in blocked range | The host resolves to an address in blockedIpRanges; change the range only for a trusted target. |
| Unexpected SQL syntax errors | The connection string does not identify the provider; required keywords: SQL Providers. |
Debug logging:
{
"Serilog": {
"MinimumLevel": {
"Default": "Debug"
}
}
}
Portway