ODIN Hosting Options

At 4Players, we understand that different businesses have different hosting needs. That’s why we offer both managed cloud hosting and on-premise hosting options for ODIN. The choice is yours.

With our managed cloud hosting, you can enjoy the benefits of a scalable, reliable, and secure hosting environment without the overhead of managing your own infrastructure. Our team of experienced professionals will handle all the technical details, allowing you to focus on your business.

For businesses that prefer to have complete control over their hosting environment, we also offer on-premise hosting. This allows you to install and run our software on your own servers, giving you full control over your setup and infrastructure.

No matter which hosting option you choose, you can trust that our team will provide top-notch support and ensure a seamless experience. Contact us today to learn more about our hosting options and see which one is right for you.

Managed Cloud Hosting

When using ODIN manage cloud hosting, you can leverage our global server network. With over 20 years of experience in the industry, our team of experts is ready to handle all the technical details, allowing you to focus on your business.

ODIN cloud servers are available in different locations all over the world, ensuring that you have the resources you need to serve your customers, no matter where they are located. With our managed cloud hosting, you can take advantage of the latest technology, including high-speed networking and powerful hardware, all backed by our top-notch support team.

Register your Access Key

Info

Please note that you need to have an active ODIN subscription to use our managed cloud hosting and the following features. You can purchase a subscription on our website.

When working with a hosted ODIN project, you need to register your access key to be able to use the service with more than 25 users. To do this, navigate to our customer control panel and select your project.

Open Control Panel

Manage Access Keys of an On-Premise Project

Manage Access Keys of an On-Premise Project

Next, click the Add access key button to either generate a new access key, or register an existing key you previously created using our command-line utility.

Available Gateways

Currently, we provide ODIN Gateways in the following regions for you to choose from:

Europe
https://gateway.odin.4players.io
US Central
https://us-central.gateway.odin.4players.io
US East
https://us-east.gateway.odin.4players.io
US West
https://us-west.gateway.odin.4players.io
South America
https://southamerica.gateway.odin.4players.io
Asia North East
https://asia-northeast.gateway.odin.4players.io
Oceania
https://oceania.gateway.odin.4players.io

If you need ODIN servers in additional locations, please contact us.

Firewall settings

ODIN uses a proprietary protocol built on QUIC/HTTP3. As this is latest technology, not all Office IT administrators have made the necessary adjustments to their firewalls to allow this traffic. If you are experiencing connection issues please ensure that your firewall allows traffic on these ports:

Gateway

gateway.odin.4players.io *.gateway.odin.4players.io

PortProtocolDescription
443TCPHTTPS for client authorization (JSON RPC)

Voice/Data Server

*.server.4netplayers.com

PortProtocolDescription
4433UDPHTTP/3 (QUIC) connections for native ODIN clients
4433TCPSecure WebSocket connections for web-based ODIN clients
8844UDPWebRTC data channel for web-based ODIN clients

On-Premise Self Hosting

ODIN is the result from years of expertise and experience. We combined business and industry insight with a very modern technology stack to drive growth for your projects. We understand the importance of having a stable and reliable hosting environment for your business. That’s why we offer on-premise hosting of the ODIN server software, giving you the control and flexibility you need to run your business smoothly.

To ensure that your ODIN servers can handle even the most demanding workloads, we also offer an optional gateway that can be installed on your premises. The gateway helps distributing clients and rooms across multiple servers, ensuring that your system remains stable and responsive, even during peak usage times.

With our on-premise hosting solutions, you can trust that your business will have the resources it needs to succeed.

graph BT
    S[Standalone Server]

    G[Gateway]
    S1[Server 1] --> G
    S2[Server 2] --> G
    S3[Server 3] --> G
    S4[Server 4] --> G

Setup your Project

When working with an on-premise ODIN project, you need to configure your gateway and server instances accordingly so your signed JWT are accepted when joining rooms. To do this, navigate to our customer control panel and select your project.

Open Control Panel

Generate Server Configuration

To generate a code snippet to add to your ODIN server configuration file (config.toml), simply enter your access key and hit the Server tab below.

Generate Configuration for On-Premise Servers

Generate Configuration for On-Premise Servers

Open Server Documentation

Generate Gateway Configuration

To generate a code snippet to add to your ODIN gateway configuration file (config.ts), simply enter your access key and hit the Gateway tab below.

Generate Configuration for On-Premise Gateways

Generate Configuration for On-Premise Gateways

Open Gateway Documentation

System Requirements

To run ODIN on-premise, you need to meet the following system requirements:

Windows

  • Operating System: Windows 7 (64-bit) or later
  • Processor: Intel Pentium 4 with EM64T support or AMD Athlon 64
  • Memory: 25 MB RAM
  • Storage: 15 MB available hard disk space
  • Microsoft Visual C++ Redistributable: Latest version

Linux

  • Operating System: Linux distribution (64-bit) with kernel version 3.2 or later
  • Processor: Intel Pentium 4 with EM64T support or AMD Athlon 64
  • Memory: 25 MB RAM
  • Storage: 15 MB available hard disk space
  • GLIBC: 2.23 or later

macOS

  • Operating System: macOS High Sierra 10.13 or later
  • Memory: 25 MB RAM
  • Storage: 15 MB available hard disk space

ODIN Gateway

This ODIN gateway server is written in Deno. It regulates access by spreading ODIN clients over available ODIN servers based on current and future usage. It also performs basic checks on customer license conditions.

sequenceDiagram
  participant Client
  participant Gateway
  participant Server

  Server ->> Gateway: sfu.GridConfig RPC
  activate Gateway
  Gateway -->> Server: Receive recommended settings
  deactivate Gateway

  loop every n seconds
  Server ->> Gateway: sfu.Report RPC
  activate Gateway
  Gateway -->> Server: Receive enqueued tasks
  deactivate Gateway
  end

  autonumber 1

  Client ->> Gateway: Connect RPC
  activate Gateway
  Gateway -->> Client: Receive signed room token 
  deactivate Gateway

  Client ->> Server: Join Room

Setup Development Environment

The following prerequisites are necessary to start development:

Configuration

The gateway is configured using a TypeScript configuration file (config.ts). In addition, the following optional command-line arguments are available to enforce specific options:

OptionDescription
--hostThe IP address to listen on
--portThe TCP port number to listen on
--sslEnable HTTPS
--certificateThe certificate file to use
--privatekeyThe private key file to use

Note: For local testing, using mkcert is recommended.

Importing Customer Keys

Instead of providing a static list of customer keys in the gateway configuration file, you can also write your own custom import function, which needs to return a Promise<Customer[]> value.

customerApi: {
  updateFunction: myFunction, // async function returning a list of customers
  updateInterval: 300,        // interval in seconds
},

This function can be used to either fetch your customer keys from a RESTful API or a reload file on disk. Here’s an example:

async function myFunction(): Promise<Customer[]> {
  try {
    const response = await fetch("https://domain.tld/api/customer-keys");
    if (response.status !== 200) {
      throw "something went wrong";
    }
    return await response.json();
  } catch (_e) {
    // handle error
  }
  return [];
}

How to Start

# start a HTTP server on port 7000
deno run --unstable --allow-net --import-map=imports.json main.ts

# start a HTTPS server on port 7000
deno run --unstable --allow-net --allow-read=. --import-map=imports.json main.ts --ssl

Note: If you don’t want to install Deno on the target system, you can also compile the scripts into a self-containing executable. Click here for details.

Public API

Authentication

Authentication for the public API is done using a Bearer token signed with an ODIN access key. When specified, the audience claim (aud) in the token must be set to gateway. The payload of a decoded JWT looks like this:

{
  "rid": "foo",
  "uid": "bar",
  "aud": "gateway",
  "sub": "connect",
  "exp": 1669852860,
  "nbf": 1669852800
}

For details on generating tokens, please refer to @4players/odin-tokens.

RPC Methods

To use any of the following methods, the JWT used to authorize must have its name listed in the subject claim (sub).

Connect

Authorizes ODIN clients to access the room specified in the Bearer token and responds with a new JWT signed with the gateway master key, which can be used to join a room on an attached ODIN server.

curl --request POST \
  --url http://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "Connect",
    "params": {},
    "id": 1
  }'

RoomClose

Closes the specified room (if available) and prevents it from being joined again until ban_time is expired.

curl --request POST \
  --url http://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomClose",
    "params": {
      "room_id": "${ROOM_ID}",
      "ban_time": ${OPTIONAL_TIME_IN_SECONDS},
    },
    "id": 1
  }'

RoomUpdate

Updates the global user data of the specified room using the given user_data byte array.

curl --request POST \
  --url https://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomUpdate",
    "params": {
      "room_id": "${ROOM_ID}",
      "user_data": ${ARRAY_OF_BYTES}
    },
    "id": 1
  }'

RoomBanClient

Kicks all clients matching the specified user_id from the specified room and prevents them from joining again until ban_time is expired.

curl --request POST \
  --url http://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomBanClient",
    "params": {
      "room_id": "${ROOM_ID}",
      "user_id": "${PEER_USER_ID}",
      "ban_time": ${OPTIONAL_TIME_IN_SECONDS},
    },
    "id": 1
  }'

RoomSendMessage

Sends arbitrary data to all clients matching the specified user_id in the specified room.

curl --request POST \
  --url https://localhost:7000/ \
  --header 'Authorization: Bearer ${JWT}' \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "method": "RoomSendMessage",
    "params": {
      "room_id": "${ROOM_ID}",
      "user_id": "${PEER_USER_ID}",
      "message": ${ARRAY_OF_BYTES}
    },
    "id": 1
  }'

ODIN Server

The ODIN server is a Selective Forwarding Unit (SFU), which connects users in mutual rooms by acting as a relay for media and data.

graph BT
  subgraph ODIN Server
    OR2[Odin Room 1]
    OR[Odin Room 2]        
  end
  subgraph Mobile
    ClientA[Client D] <--> OR
    ClientB[Client C] <--> OR
  end
  subgraph Desktop 
    ClientB[Client C] <--> OR2   
    ClientC[Client B] <--> OR2
  end
  subgraph Consoles*
    ClientD[Client A] <--> OR2
  end

Configuration

The server is configured using a configuration file and optional command-line arguments.

Note: For local testing, using mkcert is recommended to generate certificates.

Command-Line arguments

OptionDescriptionDefault Value
--configPath to the config fileconfig.toml
--licensePath to the license filelicense.toml

Here’s an example on how to start the server using a custom config path.

./grid --config /etc/grid/config.toml

The config.toml file

You can change the behavior of your ODIN server by modifying its configuration file called config.toml, which uses the TOML format.

verbosity

The verbosity level [0-3] to define how much information should be written to logs.

verbosity = 1

public_address Required

The FQDN and port number where the server can be reached from the Internet.

public_address = "localhost:4433"

The [supervisor] section

The [supervisor] section allows you to attach your server instance to an external gateway, which can be used for scalability in your hosting infrastructure. It is expected to be specified on the root level.

url Required

The full web address of the supervisor to contact and send reports to.

url = "http://localhost:7000/internal"

report_interval

The time in milliseconds between consecutive reports to the supervisor.

report_interval = 5_000

no_warmup

When true, the server wait for one report cycle before starting to send reports to the supervisor.

no_warmup = false

version

A freely pickable number to send with reports. This is currently unused, but reserved for future usage.

version = 123456

The [authorization] section

The ODIN server uses JSON Web Tokens (JWT) with EdDSA/Ed25519 signature for client authorization. The [authorization] section can be used to change the behavior of this process.

allow_unsigned

Then true, the server will accept logins using unsigned tokens. It is strongly recommended, that you do NOT enable this in a production environment.

allow_unsigned = false

leeway

The number of milliseconds a login token can be before or beyond its valid time period and still pass.

leeway = 5_000

The [[authorization.keys]] section

The [[authorization.keys]] section is used to define a list of keys allowed to sign login tokens. When using a [supervisor], this section can be omitted as it will be automatically generated by the gateway.

[[authorization.keys]]
kid = "Afkwfu4BVHDh"
kty = "OKP"
crv = "Ed25519"
x = "a5J2bhmU7vsY0LrW1zt56iUdmhRUNz7Pl9eBoCy29d8"
d = "5FYw1qdABjE0qEKEe821L7UPl_DZfO-PavpaiLsGDR0"

Note: You can use the @4players/odin-cli package to generate this section for you.

The [quic] section

The [quic] section is used to enable and configure the HTTP/3 socket listener for native ODIN core SDK clients.

binding Required

The socket where incoming connections are accepted from.

binding = "0.0.0.0:4433"

certificate_file Required

The path to a PEM-encoded leaf certificate followed by optional intermediate certificates.

certificate_file = "fullchain.pem"

privatekey_file Required

The path to a PEM-encoded private key.

privatekey_file = "privkey.pem"

migration

When enabled, the server accept IP address changes from clients.

migration = true

keep_alive_interval

Time in milliseconds between keep-alive packets sent by the server.

keep_alive_interval = 5_000 # ms

idle_timeout

Drop a connection if no packets have been received in this time span in milliseconds.

idle_timeout = 30_000 # ms

pre_send_timeout

The maximum time the sender waits for a packet to be inserted into the send buffer.

pre_send_timeout = 500 # ms

connect_timeout

The maximum time in milliseconds a connection can take to finish the HTTP/3 setup, until a client is created.

connect_timeout = 1_000 # ms

no_peers_timeout

The maximum time in milliseconds a client can stay connected, after leaving all rooms.

no_peers_timeout = 1_000 # ms

The [http] section

The [http] section is used to enable and configure the socket listener for ODIN web SDK clients.

binding Required

The socket where incoming connections are accepted from.

binding = "0.0.0.0:4433"

certificate_file Required

The path to a PEM-encoded leaf certificate followed by optional intermediate certificates.

certificate_file = "fullchain.pem"

privatekey_file Required

The path to a PEM-encoded private key.

privatekey_file = "privkey.pem"

webrtc_candidates

The list of IP addresses to be offered as candidates.

webrtc_candidates = ["127.0.0.1", "::1"]

webrtc_binding

The socket where WebRTC connections are accepted from.

webrtc_binding = "0.0.0.0:5000"

timeout

Drop connections after this much inactivity in milliseconds.

timeout = 10_000 # ms

ping_interval

Send a ping to the client using this interval in milliseconds.

ping_interval = 5_000 # ms

The [metrics] section

The [metrics] section is used to enable and configure a Prometheus metrics listener.

binding Required

The socket where incoming connections are accepted from.

binding = "0.0.0.0:9000"

idle_timeout

How long after the last change a metric value is reported.

idle_timeout = 3_600_000 # ms

global_labels

Labels that are added to all reported metrics.

global_labels = {deployment = "foo"}

allowed

List of IP subnets that are allowed to query metrics from the server.

allowed = ["0.0.0.0/0"]

The [limit] section

The [limit] section is used to configure concurrency limits.

max_clients

The maximum number of concurrent clients accepted by the server.

max_clients = 25

max_rooms

The maximum number of concurrent rooms accepted by the server.

max_rooms = 25

max_peers

The maximum number of concurrent peers accepted by the server.

max_peers = 25

The [limit.network] section

The [limit.network] section is used to configure network rate limits.

incoming_media_packets

The number of packets a media can send to the server every second.

incoming_media_packets = {rate = 50, capacity = 100}

The [limit.peer] section

The [limit.peer] section is used to configure limits per individual peer.

incoming_messages

The number of command packets of a peer that are processed by the server every second.

incoming_messages = {rate = 10, capacity = 50, overflow = 20}

medias

The number of medias a peer can create.

medias = 5

The [telemetry] section

The [telemetry] section is used to enable a telemetry client used for licensing.

address Required

The web address of the telemetry server to contact and send reports to.

address = "http://localhost/"

interval

The interval in milliseconds how often the telemetry data is being sent.

interval = 5_000 # ms

max_consecutive_failures

When set, this defines the maximum number of times sending telemetry data can fail before the server shuts down.

max_consecutive_failures = 4

data

Data from the [license] section to send to the telemetry server.

data = ["LicenseValidUntil", "LicenseLicensee", "LicenseSerialNumber", "LicenseIssuer"]

The [license] section

The optional [license] section is used to identify the licensee of the ODIN server. This section is used in a separate license.toml file.

signature Required

The signature of the license used to verify its validity.

signature = ""

issuer

An optional field to identify the issuer of the license.

issuer = "4Players"

licensee

An optional field to identify the licensee. Usually, this is your 4Players customer number (CID).

licensee = "622012345"

serial_number

An optional serial number of the license. Usually, this is the ID of your on-premise hosting subscription project.

serial_number = "b0FBTWZ2Rj3OY25uZWtYRlpoekVBUT09"

valid_until

An optional expiration date for the license. When set, the server can’t be used after his date.

valid_until = 1987-07-05T17:45:00Z

The [internal] section

The [internal] section is used to configure internal settings for debugging.

log_hanging_api_calls

A debug option to emit warnings if RPC calls take longer then the threshold in milliseconds.

log_hanging_api_calls = 1_000 # ms

Examples

Create a configuration file and use the grid executable to start the ODIN server.

Minimal config.toml for Supervised Server

When running the ODIN server in combination with a gateway, you only need to specify the web address of the supervisor. The server will register with the supervisor and automatically receive recommended settings, which will be used to extend the local config.toml file.

The recommended configuration of the gateway can be defined here.

[supervisor]
url = "http://localhost:7000/internal"

Minimal config.toml for Standalone Server

When running the ODIN server in standalone mode, you need to specify at least one JWK used for authorization pair as well as the binding and certificate configuration for incoming client connections.

[[authorization.keys]]
kid = "Afkwfu4BVHDh"
kty = "OKP"
crv = "Ed25519"
x = "a5J2bhmU7vsY0LrW1zt56iUdmhRUNz7Pl9eBoCy29d8"
d = "5FYw1qdABjE0qEKEe821L7UPl_DZfO-PavpaiLsGDR0"

[quic]
binding = "0.0.0.0:4433"
certificate_file = "fullchain.pem"
privatekey_file = "privkey.pem"

[http]
binding = "0.0.0.0:4433"
certificate_file = "fullchain.pem"
privatekey_file = "privkey.pem"