Code With Me Help

Code With Me administration guide

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

  • One relay server

  • 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

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, lobby-server-linux-x64.1.0.tar.gz)

Configure servers

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

  2. 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="" COPY ws-relayd$DISTRIBUTION_VERSION /ws-relayd RUN chmod +x /ws-relayd COPY lobby_public.pem /lobby_public.pem CMD /ws-relayd -addr relay:3274 -jwt-key-type ecdsa -jwt-key-file /lobby_public.pem
  3. Create a Dockerfile for the lobby server in the lobby directory.
    FROM debian:buster-slim ARG DISTRIBUTION_VERSION="" ADD lobby-server-linux-x64.${DISTRIBUTION_VERSION}.tar.gz /home/lobby-server COPY lobby_private.pem /home/lobby-server/lobby_private.pem RUN apt-get update && apt-get install -y unzip net-tools procps && apt-get clean 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 p2p_quic,direct_tcp,ws_relay ENV FORCE_RELAY_URI wss://relay.cwm.internal ENV RELAYS_ECDSA_JWT_KEY_FILE /home/lobby-server/lobby_private.pem ENV REDIS_HOST redis ENV REDIS_PORT 6379 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.

  4. 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; } } }

  5. Copy the certificates and keys to the nginx/ssl directory.

  6. 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
  7. $ 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_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_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.
RELAYS_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" ] } ] }
FORCE_RELAY_URIUse this option to force a lobby server to ignore the relays config file and use the URI provided as this variable.
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.

GEOLITE_MMDB_FILE This 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 features that are supported by this server instance.

If all flags are disabled, Code With Me will not work as there are no means of communication available.

ws_relayUse relays in case if the P2P connection does not work or is forbidden.
p2p_quicUse the QUIC protocol for the P2P connections.
direct_tcpUse the P2P connection between the clients using TCP.

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.

For -addr 8099, use :port syntax to listen at all available interfaces. For example, :8099 to listen at all available interfaces on port 8099.

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

For example, 127.0.0.1:4422.

For prometheusAddr 4422, use :port syntax to listen at all available interfaces. For example, :8099 to listen at all available interfaces on port 8099.

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

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