CodeWithMe Help

Separate components manual setup

There are two key components for hosting the Code With Me on-premises: a lobby server and relay servers. Currently, the supported configuration is that the servers provide an HTTP/WS endpoint which should be wrapped as an SSL traffic by the reverse proxy (such as nginx, apache, caddy).

Configuration

A simple configuration consists of the following components:

  • One lobby server - follow this link to download the lobby server distribution

  • One relay server - follow this link to download the relay server distribution

  • Redis server, which is used for persisting the session data in case the lobby server goes offline

  • Nginx acting as an SSL frontend for the lobby and relay servers

  • License file

  • Docker-compose version 1.27+

Let's use the following assumptions:

  • SSL URI of the relay server is wss://relay.cwm.internal

  • You have the distribution of the relay server in the relay folder (for example, ws-relayd1.0)

  • SSL URI of the lobby server is https://lobby.cwm.internal

  • You have the distribution of the lobby server in the lobby folder (for example, code-with-me-lobby-linux-x86_64-1.tar.gz)

Configure servers

  1. Obtain your license file and save it in the same directory as a Dockerfile for your lobby server.

  2. Generate an ECDSA private key without the passphrase to prevent unauthorized to access the relay server. Lobby server expects an ECDSA private key file with 384-bit length in PEM format which can be generated with openssl.

    openssl ecparam -name secp384r1 -genkey -noout -out lobby/lobby_private.pem openssl ec -in lobby/lobby_private.pem -pubout -out relay/lobby_public.pem
  3. Create a Dockerfile for the relay server in the relay directory.

    The contents of the Dockerfile are as follows:

    FROM alpine:latest ARG DISTRIBUTION_VERSION="" ADD code-with-me-relay-linux-x86_64-${DISTRIBUTION_VERSION}.tar.gz /tmp/ws-relayd RUN mv /tmp/ws-relayd/code-with-me-relay-linux-x86_64-${DISTRIBUTION_VERSION} /ws-relayd && chmod +x /ws-relayd/ws-relayd COPY lobby_public.pem /ws-relayd/lobby_public.pem CMD /ws-relayd/ws-relayd -addr relay:3274 -jwt-key-type ecdsa -jwt-key-file /ws-relayd/lobby_public.pem
  4. Create a config.json file for providing the lobby server with proper relay URIs.

    { "relays": [ { "regionName": "internal", "latitude": 0, "longitude": 0, "servers": [ "wss://relay.cwm.internal" ] } ] }
  5. Create a Dockerfile for the lobby server in the lobby directory and add the license key file to it.

    FROM debian:buster-slim ARG DISTRIBUTION_VERSION="" ADD code-with-me-lobby-linux-x86_64-${DISTRIBUTION_VERSION}.tar.gz /tmp/lobby/ RUN mv /tmp/lobby/code-with-me-lobby-linux-x86_64-${DISTRIBUTION_VERSION} /home/lobby-server && chmod +x /home/lobby-server/bin/lobby-server COPY lobby_private.pem /home/lobby-server/lobby_private.pem COPY config.json /home/lobby-server/config.json COPY license.key /home/lobby-server/license.key WORKDIR /home/lobby-server ENV JAVA_HOME /home/lobby-server/jbr ENV SERVER_PORT 2093 ENV BASE_URL https://lobby.cwm.internal ENV ENABLED_FEATURES direct_tcp,ws_relay ENV CONFIG_JSON /home/lobby-server/config.json ENV RELAYS_ECDSA_JWT_KEY_FILE /home/lobby-server/lobby_private.pem ENV REDIS_HOST redis ENV REDIS_PORT 6379 ENV LICENSE_BUNDLES /home/lobby-server/license.key ENTRYPOINT ["bin/lobby-server"]

    In case you deploy the docker image for lobby-server to Kubernetes, pay attention to the names given to services to avoid names collision with environment variables already set for the lobby server (for example, REDIS_PORT). For more information, refer to the Kubernetes Service documentation.

  6. Write the nginx.conf file in the nginx directory.

    events {} http { server { listen 443 ssl; server_name relay.cwm.internal; ssl_certificate /etc/ssl/nginx/relay.cwm.internal.crt; ssl_certificate_key /etc/ssl/nginx/relay.cwm.internal.key; location / { proxy_pass http://relay:3274; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; } } server { listen 443 ssl; server_name lobby.cwm.internal; ssl_certificate /etc/ssl/nginx/lobby.cwm.internal.crt; ssl_certificate_key /etc/ssl/nginx/lobby.cwm.internal.key; location / { proxy_pass http://lobby:2093; } } }
  7. Copy the certificates and keys to the nginx/ssl directory.

  8. Create a docker-compose file. We're assuming the following:

    • Lobby server Dockerfile and distribution are in the lobby directory

    • Lobby server version is 1636

    • Relay server Dockerfile and distribution are in the relay directory

    • Relay server version is 1114

    • nginx.conf is in the nginx directory

    • Certificates and keys are in the nginx/ssl folder

    • Redis data is persisted in /redis/data. If you don't need that, remove the command and volumes subsections from the redis container configuration.

    The content of the docker-compose.yaml file is as follows:

    version: 3.8 services: nginx: image: nginx:latest volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/ssl:/etc/ssl/nginx:ro ports: - 443:443 relay: build: context: ./relay args: DISTRIBUTION_VERSION: 1114 lobby: volumes: - /home/ubuntu/storage:/home/CWM/storage build: context: ./lobby args: DISTRIBUTION_VERSION: 1636 redis: image: redis:latest
  9. $ docker-compose up and make sure your host is listening on the relay.cwm.internal and lobby.cwm.internal at the 443 port.

Lobby server

A lobby server is responsible for the following:

  • Generating a link that can be used to join the Code With Me session

  • Reporting a list of supported features to a client (for example, whether P2P is allowed or not)

  • Selecting a relay server in case P2P does not work or is forbidden

The lobby server is distributed in the binary form for the linux-x64 platform with all the dependencies (for example, the runtime) included:

bin/lobby-server [OPTIONS]

Lobby server configuration

You can configure the lobby server with the following environment variables:

Environment variable

Description

SERVER_PORT

Use this option as the port at which the server will listen for incoming request.

SERVER_LISTEN_ON

Use this option as the interface at which the server will listen.

By default, it listens on all interfaces. For example, set it to 127.0.0.1 to listen on the localhost only.

BASE_URL

Use this option as base URL at which the server is hosted.

For example, https://code-with-me.jetbrains.com This will be used for creating the Code With Me session URLs.

ROOT_PREFIX

Use this option as a prefix for which to listen for HTTP requests (for example, /$ROOT_PREFIX/version). Must start with the / and must not end with the /. E.g. https://code-with-me.jetbrains.com/some-other-prefix instead of https://code-with-me.jetbrains.com

DIAGNOSTICS_PORT

Optional variable is set, when is set, the following port can be used by Prometheus to access the various metrics of the server.

JSON_CONSOLE_LOGGING

Optional variable; when is set to "true", lobby logs output will be JSON-formatted.

VERBOSE

Optional variable; when is set to "true", enables debuglogs level

CONFIG_JSON

Use this option as a path to the json file that contains the list of relays from which the lobby server can choose if there's no P2P.

The following is the sample configuration with the geolocation enabled (json):

{ "relays": [ { "regionName": "eu", "latitude": 60.571442, "longitude": 27.187427, "servers": [ "wss://relay-1.eu.example.com", "wss://relay-2.eu.example.com" ] }, { "regionName": "na", "latitude": 33.220572, "longitude": -80.008131, "servers": [ "wss://relay-1.us.example.com", "wss://relay-2.us.example.com" ] } ] }

The following is a sample configuration with the geolocation disabled (json):

{ "relays": [ { "regionName": "internal", "latitude": 0, "longitude": 0, "servers": [ "wss://relay-1.internal", "wss://relay-2.internal" ] } ] }

RELAYS_ECDSA_JWT_KEY_FILE

Use this option as the ECDSA private key file that is used to prevent unathroized access to the relay servers. Must have 384-bit key length and be in the PEM format.

REDIS_HOST

Deprecated since the build 1614. If it is set, it will use the specified Redis host for persisting the session data. It is strongly recommended using one instead of relying on the in-memory approach.

REDIS_PORT

Deprecated since the build 1614. This is the port used with the REDIS_HOST.

The port defaults to 6379.

REDIS_URL

Since the build 1614, the lobby server supports work with a password-protected Redis.

You can use this environment variable in one of the following formats:

  • redis://user:secret@localhost:6379/0

  • redis://user:secret@localhost:6379

  • redis://127.0.0.1:6379

  • rediss:// scheme for TLS support

For more information about the scheme, refer to Redis scheme and Rediss scheme.

JSON_CONSOLE_LOGGING

This variable is optional; can be true or false. Default value is false. If it is set as true, lobby logs will be written in JSON format what makes them more suitable for parsing.

ENABLED_FEATURES

Use this option as the comma-separated list of the following features that are supported by this server instance.

  • ws_relay

    use relays in case if the P2P connection does not work or is forbidden

  • p2p_quic

    use the QUIC protocol for the P2P connections

  • direct_tcp

    use the P2P connection between the clients using TCP

  • project_names

    use this flag to allow clients to see the name of the project that they are joining

  • user_names

    use this flag to allow clients to see the user of the project that they are joining. It is also shows usernames on the lobby session page.

LICENSE_BUNDLES

Use this option for specifying the license.key for your lobby server. To obtain the license, visit the JetBrains website.

If you have more than one license key, specify each license key separating them with comma ,.

The information about the license expiration dates and a number of concurrent sessions are available during the server start.

Generate a key for the lobby server

The lobby server expects the ECDSA private key file with the 384-bit length in the PEM format.

It can be generated using the $ openssl tool as follows:

$ openssl ecparam -name secp384r1 -genkey -noout -out jwtES384key.pem $ openssl ec -in jwtES384key.pem -pubout -out jwtES384pubkey.pem

The public key counterpart should be used on the relay server for verification.

Relay server

A relay server is responsible for relaying the traffic between the host and guests in cases when the P2P connection does not work or is forbidden. The relay server has a functionality of verifying whether the incoming request is coming from the genuine lobby server via a JWT token.

The relay server is distributed as a single binary and is available for the linux-x64 platform:

ws-relayd [OPTIONS]

The relay server configuration

You can configure the relay server with the following command-line arguments:

Argument

Description

-addr

Use this argument as the address on which to listen for incoming connections.

For example, 127.0.0.1:8099.

Use the :port syntax to listen on all available interfaces. For example, :8099 to listen on all available interfaces at port 8099.

-prometheus-addr

Use this argument as the address on which to listen for the Prometheus metrics request.

For example, 127.0.0.1:4422.

Use the :port syntax to listen on all available interfaces. For example, :4422 to listen on all available interfaces at port 4422.

-jwtKeyType

Use this argument as the type of key provided for the verification of requests.

The supported values are as follows:

  • hmac

  • rsa

  • ecdsa

Note that the lobby server only supports the 384-bit ECDSA keys.

For the information on how to set up a key, see Generate keys.

-jwtKeyFile

Use this argument as a file from which to read the JWT public key. This must be in the PEM format.

For the information on how to set up a key, see Generate keys.

-allow-server-without-authentication

Use this optional argument as an explicit flag that allows the relay server to run in a mode which skips the request verification.

Last modified: 05 April 2024