Exposing a Local Pragma Engine to the outside world with ngrok
Last updated: April 15, 2026
When developing locally, your Pragma Engine runs on localhost, but external game servers (or game clients/players running elsewhere) need to reach it over the internet. https://ngrok.com/ creates public tunnels to your local ports.
This guide may be of help in a scenario where you want to keep your pragma-engine and game clients locally but spin up game servers with an external game server provider. This would speed up your development process by allowing you to validate configurations locally before deploying to a pragma shard.
Prerequisites
ngrok installed and authenticated (
ngrok config add-authtoken <token>). Installation instructions here.Pragma Engine running locally (Game Partner on port
10100, Social Partner on port11100)
Step 1: Start ngrok Tunnels
You need two separate tunnels — one for each Pragma gateway:
# Terminal 1 - Game Partner Gateway
ngrok http 10100
# Terminal 2 - Social Partner Gateway
ngrok http 11100
ngrok will output public URLs like:
Game Partner: https://<game-partner-ngrok-subdomain>.ngrok-free.app -> http://localhost:10100
Social Partner: https://<social-partner-ngrok-subdomain>.ngrok-free.app -> http://localhost:11100Note: ngrok free tier URLs change every time you restart the tunnel. You will need to update your config each time.
Note: ngrok free tier can only open 3 tunnels at a time, so if you want to also run Social Player Gateway and Game Player Gateway alongside the Partner Gateways, you will need a paid ngrok tier.
Step 2: Configure your locally running pragma-engine
This section guides you through making changes to your local-dev.yml.
Note that your local-dev.yml is located at a path of this format in your repository: pragma-engine/platform/<game-project|or|5-ext>/config/local-dev.yml
Replace the ngrok hostnames below with your actual ngrok URLs:
game:
serviceConfigs:
GamePartnerGatewayConfig:
# Protocols: ngrok terminates TLS, so clients must use https/wss
protocol: "https"
webSocketProtocol: "wss"
# Authentication backend (served by the social ngrok tunnel)
authenticateHost: <social-partner-ngrok-subdomain>.ngrok-free.app
authenticatePort: 443
# Game backend (served by the game ngrok tunnel)
gameHost: <game-partner-ngrok-subdomain>.ngrok-free.app
gameBindPort: 10100 # local port Pragma actually listens on
gamePort: 443 # port advertised to clients (ngrok's public port)
# Social backend (served by the social ngrok tunnel)
socialHost: <social-partner-ngrok-subdomain>.ngrok-free.app
socialBindPort: 11100 # local port Pragma actually listens on
socialPort: 443 # port advertised to clients (ngrok's public port)
social:
serviceConfigs:
SocialPartnerGatewayConfig:
protocol: "https"
webSocketProtocol: "wss"
authenticateHost: <social-partner-ngrok-subdomain>.ngrok-free.app
authenticatePort: 443
socialHost: <social-partner-ngrok-subdomain>.ngrok-free.app
socialBindPort: 11100
socialPort: 443
Configuration if you intend to expose Player Gateways to the internet:
game:
serviceConfigs:
GamePlayerGatewayConfig:
# Protocols: ngrok terminates TLS, so clients must use https/wss
protocol: "https"
webSocketProtocol: "wss"
# Authentication backend (served by the social-player ngrok tunnel)
authenticateHost: <social-player-ngrok-subdomain>.ngrok-free.app
authenticatePort: 443
# Game backend (served by the game-player ngrok tunnel)
gameHost: <game-player-ngrok-subdomain>.ngrok-free.app
gameBindPort: 10000 # local port Pragma actually listens on
gamePort: 443 # port advertised to clients (ngrok's public port)
# Social backend (served by the social-player ngrok tunnel)
socialHost: <social-player-ngrok-subdomain>.ngrok-free.app
socialBindPort: 11000 # local port Pragma actually listens on
socialPort: 443 # port advertised to clients (ngrok's public port)
social:
serviceConfigs:
SocialPlayerGatewayConfig:
protocol: "https"
webSocketProtocol: "wss"
authenticateHost: <social-player-ngrok-subdomain>.ngrok-free.app
authenticatePort: 443
socialHost: <social-player-ngrok-subdomain>.ngrok-free.app
socialBindPort: 11000
socialPort: 443
Understanding Port vs BindPort
This is the key concept for ngrok configuration:
Field | Purpose | Example |
| Port advertised to clients in the |
|
| Port Pragma actually listens on locally. ngrok forwards traffic from port 443 to this port. |
|
When bindPort is not set (or set to 0), it falls back to the value of port. You only need to set bindPort explicitly when the advertised port differs from the local port — which is exactly the ngrok use case.
Step 3: Verify
After restarting Pragma, hit the info endpoint to confirm everything is correct:
curl https://<game-partner-ngrok-subdomain>.ngrok-free.app/v1/infoExpected response (all ports should be 443, protocols should be https/wss):
{
"authenticateBackend": {
"host": "<social-partner-ngrok-subdomain>.ngrok-free.app",
"port": 443,
"protocol": "https",
"scheme": "https"
},
"socialBackend": {
"host": "<social-partner-ngrok-subdomain>.ngrok-free.app",
"port": 443,
"protocol": "https",
"webSocketProtocol": "wss"
},
"gameBackend": {
"host": "<game-partner-ngrok-subdomain>.ngrok-free.app",
"port": 443,
"protocol": "https",
"webSocketProtocol": "wss"
}
}
Troubleshooting
This section should guide you through some of the common misconfigurations that may occur:
/v1/infoshows port10100or11100cause:
gamePort/socialPortnot set to443fix: Set the advertised port fields to
443
/v1/infoshows"protocol":"http"cause:
protocolnot overriddenfix: Set
protocol: "https"on the gateway configs
WebSocket connection fails
cause:
webSocketProtocoliswsinstead ofwssfix: Set
webSocketProtocol: "wss"(ngrok requires TLS)
authenticateBackendshows wrong portcause:
authenticatePortnot set to443inGamePartnerGatewayConfigfix: Add
authenticatePort: 443