Configure Centrifugo
Centrifugo can start without any configuration. In most cases though, you need to configure it to set options for server API, connection JWT authentication or maybe authentication over connect proxy, describe the desired channel behaviour, and so on.
This chapter describes configuration principles and some important configuration options. There are more options not mentioned here but described throughout the doc in the context of each individual server feature.
Configuration sources
Centrifugo can be configured in several ways:
- using command-line flags (highest priority, i.e. flags overwrite everything)
- environment variables (medium priority, i.e. env vars overwrite config file options)
- configuration file (lowest priority).
This chapter describes configuration principles and some important configuration options. There are more options not mentioned here but described throughout the doc in the context of each individual server feature.
Command-line flags
Centrifugo supports several command-line flags. See centrifugo -h
for available flags. Command-line flags limited to most frequently used. Mostly useful for development. In general, we recommend to avoid using flags for configuring Centrifugo in a production environment – prefer using environment variables or configuration file.
Command-line options have the highest priority when set than other ways to configure Centrifugo.
OS environment variables
All Centrifugo options can be set over env in the format CENTRIFUGO_<OPTION_NAME>
(i.e. option name with CENTRIFUGO_
prefix, all in uppercase).
Setting options over env is mostly straightforward except namespaces – see how to set namespaces via env. Environment variables have the second priority after flags.
Boolean options can be set using strings according to Go language ParseBool function. I.e. to set true
you can just use "true"
value for an environment variable (or simply "1"
). To set false
use "false"
or "0"
. Example:
export CENTRIFUGO_PROMETHEUS="1"
Also, array options, like allowed_origins
can be set over environment variables as a single string where values separated by a space. For example:
export CENTRIFUGO_ALLOWED_ORIGINS="https://mysite1.example.com https://mysite2.example.com"
For a nested object configuration (which we have, for example, in Centrifugo PRO ClickHouse analytics) it's still possible to use environment variables to set options. In this case replace nesting with _
when constructing environment variable name.
Empty environment variables are considered unset (!) and will fall back to the next configuration source.
Configuration file
Configuration file supports all options mentioned in Centrifugo documentation and can be in one of three supported formats: JSON, YAML, or TOML. Config file options have the lowest priority among configuration sources (i.e. option set over environment variable is preferred over the same option in config file).
A simple way to start with Centrifugo is to run:
centrifugo genconfig
This command generates config.json
configuration file in a current directory. This file already has the minimal number of options set. So it's then possible to start Centrifugo:
centrifugo -c config.json
Config file formats
Centrifugo supports three configuration file formats: JSON, YAML, or TOML.
JSON config format
Here is an example of Centrifugo JSON configuration file:
{
"allowed_origins": ["http://localhost:3000"],
"token_hmac_secret_key": "<YOUR-SECRET-STRING-HERE>",
"api_key": "<YOUR-API-KEY-HERE>"
}
token_hmac_secret_key
used to check JWT signature (more info about JWT in authentication chapter). If you are using connect proxy then you may use Centrifugo without JWT.
api_key
used for Centrifugo API endpoint authorization, see more in chapter about server HTTP API. Keep both values secret and never reveal them to clients.
allowed_origins
option described below.
TOML config format
Centrifugo also supports TOML format for configuration file:
centrifugo --config=config.toml
Where config.toml
contains:
allowed_origins: [ "http://localhost:3000" ]
token_hmac_secret_key = "<YOUR-SECRET-STRING-HERE>"
api_key = "<YOUR-API-KEY-HERE>"
log_level = "debug"
In the example above we also defined logging level to be debug
which is useful to have while developing an application. In the production environment debug logging can be too chatty.
YAML config format
YAML format is also supported:
allowed_origins:
- "http://localhost:3000"
token_hmac_secret_key: "<YOUR-SECRET-STRING-HERE>"
api_key: "<YOUR-API-KEY-HERE>"
log_level: debug
With YAML remember to use spaces, not tabs when writing a configuration file.
Important options
Let's describe some important options you can configure when running Centrifugo.
allowed_origins
This option allows setting an array of allowed origin patterns (array of strings) for WebSocket and SockJS endpoints to prevent CSRF or WebSocket hijacking attacks. Also, it's used for HTTP-based unidirectional transports to enable CORS for configured origins.
As soon as allowed_origins
is defined every connection request with Origin
set will be checked against each pattern in an array.
Connection requests without Origin
header set are passing through without any checks (i.e. always allowed).
For example, a client connects to Centrifugo from a web browser application on http://localhost:3000
. In this case, allowed_origins
should be configured in this way:
"allowed_origins": [
"http://localhost:3000"
]
When connecting from https://example.com
:
"allowed_origins": [
"https://example.com"
]
Origin pattern can contain wildcard symbol *
to match subdomains:
"allowed_origins": [
"https://*.example.com"
]
– in this case requests with Origin
header like https://foo.example.com
or https://bar.example.com
will pass the check.
It's also possible to allow all origins in the following way (but this is discouraged and insecure when using connect proxy feature):
"allowed_origins": [
"*"
]
address
Bind your Centrifugo to a specific interface address (string, by default ""
- listen on all available interfaces).
port
Port to bind Centrifugo to (string, by default "8000"
).
engine
Engine to use - memory
, redis
or tarantool
. It's a string option, by default memory
. Read more about engines in special chapter.
Advanced options
These options allow tweaking server behavior, in most cases default values are good to start with.
client_channel_limit
Default: 128
Sets the maximum number of different channel subscriptions a single client can have.
When designing an application avoid subscribing to an unlimited number of channels per one client. Keep number of subscriptions for each client reasonably small – this will help keeping handshake process lightweight and fast.
channel_max_length
Default: 255
Sets the maximum length of the channel name.
client_user_connection_limit
Default: 0
The maximum number of connections from a user (with known user ID) to Centrifugo node. By default, unlimited.
The important thing to emphasize is that client_user_connection_limit
works only per one Centrifugo node and exists mostly to protect Centrifugo from many connections from a single user – but not for business logic limitations. This means that if you set this to 1 and scale nodes – say run 10 Centrifugo nodes – then a user will be able to create 10 connections (one to each node).
client_connection_limit
Default: 0
When set to a value > 0 client_connection_limit
limits the max number of connections single Centrifugo node can handle. It acts on HTTP middleware level and stops processing request if the condition met. It logs a warning into logs in this case and increments centrifugo_node_client_connection_limit
Prometheus counter. Client SDKs will attempt reconnecting.
Some motivation behind this option may be found in this issue.
Note, that at this point client_connection_limit
does not affect connections coming over GRPC unidirectional transport.
client_connection_rate_limit
Default: 0
client_connection_rate_limit
sets the maximum number of HTTP requests to establish a new real-time connection a single Centrifugo node will accept per second (on real-time transport endpoints). All requests outside the limit will get 503 Service Unavailable code in response. Our SDKs handle this with backoff reconnection.
By default, no limit is used.
Note, that at this point client_connection_rate_limit
does not affect connections coming over GRPC unidirectional transport.
client_queue_max_size
Default: 1048576
Maximum client message queue size in bytes to close slow reader connections. By default - 1mb.
client_concurrency
Default: 0
client_concurrency
when set tells Centrifugo that commands from a client must be processed concurrently.
By default, concurrency disabled – Centrifugo processes commands received from a client one by one. This means that if a client issues two RPC requests to a server then Centrifugo will process the first one, then the second one. If the first RPC call is slow then the client will wait for the second RPC response much longer than it could (even if the second RPC is very fast). If you set client_concurrency
to some value greater than 1 then commands will be processed concurrently (in parallel) in separate goroutines (with maximum concurrency level capped by client_concurrency
value). Thus, this option can effectively reduce the latency of individual requests. Since separate goroutines are involved in processing this mode adds some performance and memory overhead – though it should be pretty negligible in most cases. This option applies to all commands from a client (including subscribe, publish, presence, etc).
client_stale_close_delay
Duration, default: 10s
This option allows tuning the maximum time Centrifugo will wait for the connect frame (which contains authentication information) from the client after establishing connection. Default value should be reasonable for most use cases.
client_user_id_http_header
String, default: ""
Available since v5.1.1
Usually to authenticate client connections with Centrifugo you need to use JWT authentication or connect proxy. Sometimes though it may be convenient to pass user ID information in incoming HTTP request headers. This is usually the case when application backend infrastructure has some authentication proxy (like Envoy, etc). This proxy may set authenticated user ID to some header and proxy requests further to Centrifugo.
When client_user_id_http_header
is set to some non-empty header name Centrifugo will try to extract the authenticated user ID for client connections from that header. This mechanism works for all real-time transports based on HTTP (this also includes WebSocket since it starts with HTTP Upgrade request). Example:
{
...
"client_user_id_http_header": "X-User-Id"
}
When using this way for user authentication – you can not set connection expiration and additional connection info which is possible to do using other authentication ways mentioned above.
When using authentication over proxy ensure your proxy strips the header you are using for auth if it comes from the client or forbids such requests to avoid malicious usage. Only your authentication proxy must set the header with user ID.
client_connect_include_server_time
Boolean, default: false
When enabled, Centrifugo attaches time
field to the connect reply (or connect push in the unidirectional transport case). This field contains current server time as Unix milliseconds. Ex. 1716198604052
.
Available since Centrifugo v5.4.0
allow_anonymous_connect_without_token
Boolean, default: false
Enable a mode when all clients can connect to Centrifugo without JWT. In this case, all connections without a token will be treated as anonymous (i.e. with empty user ID). Access to channel operations should be explicitly enabled for anonymous connections.
disallow_anonymous_connection_tokens
Boolean, default: false
When the option is set Centrifugo won't accept connections from anonymous users even if they provided a valid JWT. I.e. if token is valid, but sub
claim is empty – then Centrifugo closes connection with advice to not reconnect again.
gomaxprocs
Integer, default: 0
By default, Centrifugo runs on all available CPU cores (also Centrifugo can look at cgroup limits when rnning in Docker/Kubernetes). To limit the number of cores Centrifugo can utilize in one moment use this option.
Endpoint configuration
After Centrifugo started there are several endpoints available.
Default endpoints
Bidirectional WebSocket default endpoint:
ws://localhost:8000/connection/websocket
Bidirectional emulation with HTTP-streaming (disabled by default):
ws://localhost:8000/connection/http_stream
Bidirectional emulation with SSE (EventSource) (disabled by default):
ws://localhost:8000/connection/sse
Bidirectional SockJS default endpoint (disabled by default):
http://localhost:8000/connection/sockjs
Unidirectional EventSource endpoint (disabled by default):
http://localhost:8000/connection/uni_sse
Unidirectional HTTP streaming endpoint (disabled by default):
http://localhost:8000/connection/uni_http_stream
Unidirectional WebSocket endpoint (disabled by default):
http://localhost:8000/connection/uni_websocket
Unidirectional SSE (EventSource) endpoint (disabled by default):
http://localhost:8000/connection/uni_sse
Server HTTP API endpoint:
http://localhost:8000/api
By default, all endpoints work on port 8000
. This can be changed with port
option:
{
"port": 9000
}
In production setup, you may have a proper domain name in endpoint addresses above instead of localhost
. While domain name and port parts can differ depending on setup – URL paths stay the same: /connection/sockjs
, /connection/websocket
, /api
etc.
Admin endpoints
Admin web UI endpoint works on root path by default, i.e. http://localhost:8000
.
For more details about admin web UI, refer to the Admin web UI documentation.
Debug endpoints
Next, when Centrifugo started in debug mode some extra debug endpoints become available. To start in debug mode add debug
option to config:
{
...
"debug": true
}
And endpoint:
http://localhost:8000/debug/pprof/
– will show useful information about the internal state of Centrifugo instance. This info is especially helpful when troubleshooting. See wiki page for more info.
Health check endpoint
Use health
boolean option (by default false
) to enable the health check endpoint which will be available on path /health
. Also available over command-line flag:
centrifugo -c config.json --health
Swagger UI for server API
Use swagger
boolean option (by default false
) to enable Swagger UI for server HTTP API. UI will be available on path /swagger
. Also available over command-line flag:
centrifugo -c config.json --swagger
Custom internal ports
We strongly recommend not expose API, admin, debug, health, and Prometheus endpoints to the Internet. The following Centrifugo endpoints are considered internal:
- API endpoint (
/api
) - for HTTP API requests - Admin web interface endpoints (
/
,/admin/auth
,/admin/api
) - used by web interface - Prometheus endpoint (
/metrics
) - used for exposing server metrics in Prometheus format - Health check endpoint (
/health
) - used to do health checks - Debug endpoints (
/debug/pprof
) - used to inspect internal server state - Swagger UI endpoint (
/swagger
) - used for showing embedded Swagger UI for server HTTP API
It's a good practice to protect all these endpoints with a firewall. For example, it's possible to configure in location
section of the Nginx configuration.
Though sometimes you don't have access to a per-location configuration in your proxy/load balancer software. For example when using Amazon ELB. In this case, you can change ports on which your internal endpoints work.
To run internal endpoints on custom port use internal_port
option:
{
...
"internal_port": 9000
}
So admin web interface will work on address:
http://localhost:9000
Also, debug page will be available on a new custom port too:
http://localhost:9000/debug/pprof/
The same for API and Prometheus endpoints.
Disable default endpoints
To disable websocket endpoint set websocket_disable
boolean option to true
.
To disable API endpoint set api_disable
boolean option to true
.
Customize handler endpoints
It's possible to customize server HTTP handler endpoints. To do this Centrifugo supports several options:
admin_handler_prefix
(default""
) - to control Admin panel URL prefixwebsocket_handler_prefix
(default"/connection/websocket"
) - to control WebSocket URL prefixhttp_stream_handler_prefix
(default"/connection/http_stream"
) - to control HTTP-streaming URL prefixsse_handler_prefix
(default"/connection/sse"
) - to control SSE/EventSource URL prefixemulation_handler_prefix
(default"/emulation"
) - to control emulation endpoint prefixsockjs_handler_prefix
(default"/connection/sockjs"
) - to control SockJS URL prefixuni_sse_handler_prefix
(default"/connection/uni_sse"
) - to control unidirectional Eventsource URL prefixuni_http_stream_handler_prefix
(default"/connection/uni_http_stream"
) - to control unidirectional HTTP streaming URL prefixuni_websocket_handler_prefix
(default"/connection/uni_websocket"
) - to control unidirectional WebSocket URL prefixapi_handler_prefix
(default"/api"
) - to control HTTP API URL prefixprometheus_handler_prefix
(default"/metrics"
) - to control Prometheus URL prefixhealth_handler_prefix
(default"/health"
) - to control health check URL prefix
Signal handling
It's possible to send HUP signal to Centrifugo to reload a configuration:
kill -HUP <PID>
Though at moment this will only reload token secrets and channel options (top-level and namespaces).
Centrifugo tries to gracefully shut down client connections when SIGINT or SIGTERM signals are received. By default, the maximum graceful shutdown period is 30 seconds but can be changed using shutdown_timeout
(integer, in seconds) configuration option.
Insecure modes
Insecure client connection
The boolean option client_insecure
(default false
) allows connecting to Centrifugo without JWT token. In this mode, there is no user authentication involved. It also disables permission checks on client API level - for presence and history calls. This mode can be useful for demo projects based on Centrifugo, integration tests, local projects, or real-time application prototyping. Don't use it in production until you 100% know what you are doing.
Disable client token signature check
Available since Centrifugo v5.0.4
The boolean option client_insecure_skip_token_signature_verify
(default false
), if enabled – tells Centrifugo to skip JWT signature verification - for both connection and subscription tokens. This is absolutely insecure and must only be used for development and testing purposes. Token claims are parsed as usual - so token should still follow JWT format.
Insecure API mode
This mode can be enabled using the boolean option api_insecure
(default false
). When on there is no need to provide API key in HTTP requests. When using this mode everyone that has access to /api
endpoint can send any command to server. Enabling this option can be reasonable if /api
endpoint is protected by firewall rules.
The option is also useful in development to simplify sending API commands to Centrifugo using CURL for example without specifying Authorization
header in requests.
Insecure admin mode
This mode can be enabled using the boolean option admin_insecure
(default false
). When on there is no authentication in the admin web interface. Again - this is not secure but can be justified if you protected the admin interface by firewall rules or you want to use basic authentication for the Centrifugo admin interface (configured on proxy level).
Setting time duration options
Time durations in Centrifugo can be set using strings where duration value and unit are both provided. For example, to set 5 seconds duration use "5s"
.
The minimal time resolution is 1ms. Some options of Centrifugo only support second precision (for example history_ttl
channel option).
Valid time units are "ms" (milliseconds), "s" (seconds), "m" (minutes), "h" (hours).
Some examples:
"1000ms" // 1000 milliseconds
"1s" // 1 second
"12h" // 12 hours
"720h" // 30 days
Setting namespaces over env
While setting most options in Centrifugo over env is pretty straightforward setting namespaces is a bit special:
CENTRIFUGO_NAMESPACES='[{"name": "ns1"}, {"name": "ns2"}]' ./centrifugo
I.e. CENTRIFUGO_NAMESPACES
environment variable should be a valid JSON string that represents namespaces array.
Enable RPC ping extension
New in Centrifugo v5.4.2
Sometimes you may need a way to just ping Centrifugo server from the client-side. For example, some Centrifugo users wanted this to show RTT time to server in UI. It's possible to enable RPC extension which simply returns an empty reply to RPC ping
:
{
...
"rpc_ping": true
}
After that, on SDK side you can do sth like this:
const startTime = performance.now();
centrifuge.rpc('ping', {}).then(function() {
const endTime = performance.now();
console.log('rtt', ((endTime - startTime)).toFixed(2).toString(), 'ms'); // Output: rtt 0.90 ms
})
If you are not happy with method name ping
– you can use a different one by setting rpc_ping_method
option to a string you want.
Anonymous usage stats
Centrifugo periodically sends anonymous usage information (once in 24 hours). That information is impersonal and does not include sensitive data, passwords, IP addresses, hostnames, etc. Only counters to estimate version and installation size distribution, and feature usage.
Please do not disable usage stats sending without reason. If you depend on Centrifugo – sure you are interested in further project improvements. Usage stats help us understand Centrifugo use cases better, concentrate on widely-used features, and be confident we are moving in the right direction. Developing in the dark is hard, and decisions may be non-optimal.
To disable sending usage stats set usage_stats_disable
option:
{
"usage_stats_disable": true
}