Code With Me 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 1.0

    • Relay server Dockerfile and distribution are in the relay directory

    • Relay server version is 1.0

    • 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: 1.0 lobby: build: context: ./lobby args: DISTRIBUTION_VERSION: 1.0 redis: image: redis:latest command: ["redis-server", "--appendonly", "yes"] volumes: - ./redis/data:/data
  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

Lobby server configuration

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

Environment variableDescription
SERVER_PORTUse this option as the port at which the server will listen for incoming request.
SERVER_LISTEN_ONUse 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_URLUse 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_PREFIXUse 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 /.
DIAGNOSTICS_PORTThis is optional. If this variable is set, the following port can be used by Prometheus to access the various metrics of the server.
CONFIG_JSONUse 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_FILEUse 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_HOSTThis variable is optional. 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_PORTThis variable is optional. This is the port used with the REDIS_HOST.

The port defaults to 6379.

REDIS_URLSince 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 details, refer to Redis scheme and Rediss scheme.

GEOLITE_MMDB_FILEThis variable is optional. If it is set, the Geolite2 file will be read and used for selecting the relays on the proximity basis to the user.
ENABLED_FEATURESUse 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

  • jitsi_telephony:

    use this flag for the video/audio conference functionality

  • 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 user names on the lobby session page.

LICENSE_BUNDLESUse 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

The relay server configuration

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

ArgumentDescription
-addrUse 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-addrUse 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.

-jwtKeyTypeUse 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.

-jwtKeyFileUse this argument as a file from which to read the JWT public key. This must be in the PEM format.
-allow-server-without-authenticationUse this argument as an explicit flag that allows the relay server to run in a mode which skips the request verification.
Last modified: 01 September 2021