{"id":23134899,"url":"https://github.com/4players/odin-server","last_synced_at":"2026-03-02T07:31:52.690Z","repository":{"id":113887299,"uuid":"574741981","full_name":"4Players/odin-server","owner":"4Players","description":"Collection of scripts and configuration files for running an on-premise ODIN server","archived":false,"fork":false,"pushed_at":"2026-01-12T14:52:05.000Z","size":182,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-12T21:26:53.817Z","etag":null,"topics":["config","docs","http3","quic","server","toml","voip","webrtc"],"latest_commit_sha":null,"homepage":"https://www.4players.io","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/4Players.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-12-06T01:13:05.000Z","updated_at":"2026-01-12T14:52:09.000Z","dependencies_parsed_at":"2024-09-09T23:24:58.567Z","dependency_job_id":"85430fc5-3981-48dc-a680-a0d126ea13f9","html_url":"https://github.com/4Players/odin-server","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/4Players/odin-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4Players%2Fodin-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4Players%2Fodin-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4Players%2Fodin-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4Players%2Fodin-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4Players","download_url":"https://codeload.github.com/4Players/odin-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4Players%2Fodin-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29994993,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T01:47:34.672Z","status":"online","status_checked_at":"2026-03-02T02:00:07.342Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["config","docs","http3","quic","server","toml","voip","webrtc"],"created_at":"2024-12-17T12:13:37.663Z","updated_at":"2026-03-02T07:31:52.683Z","avatar_url":"https://github.com/4Players.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"![ODIN](https://docs.4players.io/img/odin/banner.jpg)\n\n# ODIN Voice Server\n\n![v1.6.15](https://img.shields.io/badge/version-1.6.15-blue?style=for-the-badge)\n\nODIN is a versatile cross-platform Software Development Kit (SDK) engineered to seamlessly integrate real-time voice chat into multiplayer games, applications, and websites. Regardless of whether you're employing a native application or your preferred web browser, ODIN simplifies the process of maintaining connections with your significant contacts. Through its intuitive interface and robust functionality, ODIN enhances interactive experiences, fostering real-time engagement and collaboration across various digital platforms.\n\n[Online Documentation](https://docs.4players.io/voice/server/)\n\nThis repository provides a collection of scripts and configuration files for running an on-premise 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.\n\n```mermaid\nflowchart BT\n  subgraph Server\n    R2(\"Room #quot;Team 1#quot;\")\n    R1(\"Room #quot;World Map#quot;\")\n    R3(\"Room #quot;Team 2#quot;\")\n  end\n\n  C1(\"Client 1\")\n  C2(\"Client 2\")\n  C3(\"Client 3\")\n  C4(\"Client 4\")\n\n  C1 --\u003e R1 \u0026 R2\n  C2 --\u003e R1 \u0026 R2\n  C3 --\u003e R1 \u0026 R3\n  C4 --\u003e R1 \u0026 R3\n```\n\n\n## Configuration\n\nThe server is configured using a configuration file and optional command-line arguments.\n\n**Note:** For local testing, using [mkcert][mkcert] is recommended to generate certificates.\n\n\n### Command-Line arguments\n\n| Option      | Description              | Default Value  | \n| :---------- | :----------------------- | :------------- |\n| `--config`  | Path to the config file  | `config.toml`  |\n| `--license` | Path to the license file | `license.toml` |\n\nHere's an example on how to start the server using a custom config path.\n\n```bash\n./grid --config /etc/grid/config.toml\n```\n\n\n### The `config.toml` file\n\nYou can change the behavior of your ODIN voice server by modifying its configuration file called `config.toml`, which uses the [TOML][toml] format.\n\n#### `public_address` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe FQDN and port number where the server can be reached from the Internet.\n\n```toml\npublic_address = \"localhost:4433\"\n```\n\n\n### The `[supervisor]` section\n\nThe `[supervisor]` section allows you to attach your server instance to an external [gateway][odin-gateway-url], which can be used for scalability in your hosting infrastructure. It is expected to be specified on the root level.\n\n#### `url` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe full web address of the supervisor to contact and send reports to.\n\n```toml\nurl = \"http://localhost:7000/internal\"\n```\n\n#### `report_interval`\n\nThe time in milliseconds between consecutive reports to the supervisor.\n\n```toml\nreport_interval = 5_000\n```\n\n#### `no_warmup`\n\nWhen true, the server wait for one report cycle before starting to send reports to the supervisor.\n\n```toml\nno_warmup = false\n```\n\n\n### The `[authorization]` section\n\nThe 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.\n\n#### `allow_unsigned`\n\nThen true, the server will accept logins using unsigned tokens. It is strongly recommended, that you do **NOT** enable this in a production environment.\n\n```toml\nallow_unsigned = false\n```\n\n#### `leeway`\n\nThe number of milliseconds a login token can be before or beyond its valid time period and still pass.\n\n```toml\nleeway = 5_000\n```\n\n\n### The `[[authorization.keys]]` section\n\nThe `[[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][odin-gateway-url].\n\n```toml\n[[authorization.keys]]\nkid = \"Afkwfu4BVHDh\"\nkty = \"OKP\"\ncrv = \"Ed25519\"\nx = \"a5J2bhmU7vsY0LrW1zt56iUdmhRUNz7Pl9eBoCy29d8\"\nd = \"5FYw1qdABjE0qEKEe821L7UPl_DZfO-PavpaiLsGDR0\"\n```\n\n**Note:** You can use the [@4players/odin-cli][odin-cli-url] package to generate this section for you.\n\n\n### The `[database]` section\n\nThe `[database]` section is used to enable and configure an optional database backend using [Redis][redis] to store room/peer state information.\n\n#### `address` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nFQDN and port number of the database server to use.\n\n```toml\naddress = \"127.0.0.1:6379\"\n```\n\n#### `use_tls`\n\nEstablish a secure TLS connection.\n\n```toml\nuse_tls = true\n```\n\n#### `username`\n\nOptional username to use ACL style authentication when connecting to the server (requires a password).\n\n```toml\nusername = \"admin\"\n```\n\n#### `password`\n\nOptional password to use when connecting to the server.\n\n```toml\npassword = \"secret\"\n```\n\n#### `server_id`\n\nOptional identifier of the server to use when adding state information to the database.\n\n```toml\nserver_id = \"foo\"\n```\n\n#### `command_timeout`\n\nOptional command timeout after which commands in the pipeline will fail.\n\n```toml\ncommand_timeout = 500\n```\n\n\n### The `[quic]` section\n\nThe `[quic]` section is used to enable and configure the HTTP/3 socket listener for native ODIN core SDK clients.\n\n#### `public_address_override`\n\nOptional FQDN and port number where the server can be reached from the Internet specifically for QUIC clients.\n\n```toml\npublic_address_override = \"localhost:4433\"\n```\n\n#### `binding` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe socket where incoming connections are accepted from. \n\n```toml\nbinding = \"0.0.0.0:4433\"\n```\n\n#### `certificate_file` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe path to a PEM-encoded leaf certificate followed by optional intermediate certificates.\n\n```toml\ncertificate_file = \"fullchain.pem\"\n```\n\n#### `privatekey_file` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe path to a PEM-encoded private key.\n\n```toml\nprivatekey_file = \"privkey.pem\"\n```\n\n#### `migration`\n\nWhen enabled, the server accept IP address changes from clients.\n\n```toml\nmigration = true\n```\n\n#### `keep_alive_interval`\n\nTime in milliseconds between keep-alive packets sent by the server.\n\n```toml\nkeep_alive_interval = 5_000 # ms\n```\n\n#### `idle_timeout`\n\nDrop a connection if no packets have been received in this time span in milliseconds.\n\n```toml\nidle_timeout = 30_000 # ms\n```\n\n#### `pre_send_timeout`\n\nThe maximum time the sender waits for a packet to be inserted into the send buffer.\n\n```toml\npre_send_timeout = 500 # ms\n```\n\n#### `connect_timeout`\n\nThe maximum time in milliseconds a connection can take to finish the HTTP/3 setup, until a client is created.\n\n```toml\nconnect_timeout = 1_000 # ms\n```\n\n#### `no_peers_timeout`\n\nThe maximum time in milliseconds a client can stay connected, after leaving all rooms.\n\n```toml\nno_peers_timeout = 1_000 # ms\n```\n\n\n### The `[http]` section\n\nThe `[http]` section is used to enable and configure the socket listener for ODIN web SDK clients.\n\n#### `public_address_override`\n\nOptional FQDN and port number where the server can be reached from the Internet specifically for WebSocket clients.\n\n```toml\npublic_address_override = \"localhost:4433\"\n```\n\n#### `binding` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe socket where incoming connections are accepted from. \n\n```toml\nbinding = \"0.0.0.0:4433\"\n```\n\n#### `certificate_file` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe path to a PEM-encoded leaf certificate followed by optional intermediate certificates.\n\n```toml\ncertificate_file = \"fullchain.pem\"\n```\n\n#### `privatekey_file` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe path to a PEM-encoded private key.\n\n```toml\nprivatekey_file = \"privkey.pem\"\n```\n\n#### `webrtc_candidates`\n\nThe list of IP addresses to be offered as candidates.\n\n```toml\nwebrtc_candidates = [\"127.0.0.1\", \"::1\"]\n```\n\n#### `webrtc_binding`\n\nThe socket where WebRTC connections are accepted from.\n\n```toml\nwebrtc_binding = \"0.0.0.0:8844\"\n```\n\n#### `webrtc_enforce_tcp`\n\nOptionally force WebRTC to use only TCP transport candidates.\n\n```toml\nwebrtc_enforce_tcp = false\n```\n\n#### `timeout`\n\nDrop connections after this much inactivity in milliseconds.\n\n```toml\ntimeout = 10_000 # ms\n```\n\n#### `ping_interval`\n\nSend a ping to the client using this interval in milliseconds.\n\n```toml\nping_interval = 5_000 # ms\n```\n\n#### `no_peers_timeout`\n\nThe maximum time in milliseconds a client can stay connected, after leaving all rooms.\n\n```toml\nno_peers_timeout = 1_000 # ms\n```\n\n\n### The `[log.terminal]` section\n\nThe `[log.terminal]` section is used to configure terminal specific logging options.\n\n#### `verbosity` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe verbosity level `[0-3]` to define how much information should be written to logs.\n\n```toml\nverbosity = 1\n```\n\n#### `format`\n\nThe output format for terminal logs. Available options are `json` and `text`.\n\n```toml\nformat = \"text\"\n```\n\n#### `filters`\n\nOptional list of modules filtered from logs to prevent unnecessary noise, except for error messages.\n\n```toml\nfilters = [\"webrtc\", \"webrtc_ice\"]\n```\n\n\n### The `[log.loki]` section\n\nThe `[log.loki]` section is used to configure [Grafana Loki][loki] specific logging options.\n\n#### `url` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe base URL where the external log aggregation system is running.\n\n```toml\nurl = \"http://localhost/\"\n```\n\n#### `labels`\n\nLabels to describe the log stream.\n\n```toml\nlabels = {job = \"foo\", instance = \"bar\"}\n```\n\n\n### The `[metrics]` section\n\nThe `[metrics]` section is used to enable and configure a [Prometheus][prometheus] metrics listener.\n\n#### `binding` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe socket where incoming connections are accepted from. \n\n```toml\nbinding = \"0.0.0.0:9000\"\n```\n\n#### `idle_timeout`\n\nHow long after the last change a metric value is reported.\n\n```toml\nidle_timeout = 3_600_000 # ms\n```\n\n#### `global_labels`\n\nLabels that are added to all reported metrics.\n\n```toml\nglobal_labels = {deployment = \"foo\"}\n```\n\n#### `allowed`\n\nList of IP subnets that are allowed to query metrics from the server.\n\n```toml\nallowed = [\"0.0.0.0/0\"]\n```\n\n\n### The `[limit]` section\n\nThe `[limit]` section is used to configure concurrency limits.\n\n#### `max_clients`\n\nThe maximum number of concurrent clients accepted by the server.\n\n```toml\nmax_clients = 25\n```\n\n#### `max_rooms`\n\nThe maximum number of concurrent rooms accepted by the server.\n\n```toml\nmax_rooms = 25\n```\n\n#### `max_peers`\n\nThe maximum number of concurrent peers accepted by the server.\n\n```toml\nmax_peers = 25\n```\n\n\n### The `[limit.network]` section\n\nThe `[limit.network]` section is used to configure network rate limits.\n\n#### `incoming_media_packets`\n\nThe number of packets a media can send to the server every second.\n\n```toml\nincoming_media_packets = {rate = 50, capacity = 100}\n```\n\n\n### The `[limit.peer]` section\n\nThe `[limit.peer]` section is used to configure limits per individual peer.\n\n#### `incoming_messages`\n\nThe number of command packets of a peer that are processed by the server every second.\n\n```toml\nincoming_messages = {rate = 10, capacity = 50, overflow = 20}\n```\n\n#### `concurrent_streams`\n\nThe number of concurrent audio streams [0-8] a peer can receive. A value of 0 means unlimited.\n\n```toml\nconcurrent_streams = 8\n```\n\n#### `medias`\n\nThe number of medias a peer can create.\n\n```toml\nmedias = 5\n```\n\n\n### The `[telemetry]` section\n\nThe `[telemetry]` section is used to enable a telemetry client used for licensing.\n\n#### `address` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe web address of the telemetry server to contact and send reports to.\n\n```toml\naddress = \"http://localhost/\"\n```\n\n#### `interval`\n\nThe interval in milliseconds how often the telemetry data is being sent.\n\n```toml\ninterval = 5_000 # ms\n```\n\n#### `max_consecutive_failures`\n\nWhen set, this defines the maximum number of times sending telemetry data can fail before the server shuts down.\n\n```toml\nmax_consecutive_failures = 4\n```\n\n#### `data`\n\nOptional data from the `[license]` section to send to the telemetry server.\n\n```toml\ndata = [\n  \"LicenseValidUntil\",\n  \"LicenseLicensee\",\n  \"LicenseSerialNumber\",\n  \"LicenseIssuer\",\n  \"LicenseClientLimit\",\n  \"LicenseClientUsage\",\n  \"LicensePeerLimit\",\n  \"LicensePeerUsage\",\n  \"LicenseRoomLimit\",\n  \"LicenseRoomUsage\"\n]\n```\n\n\n### The `[http_client]` section\n\nThe optional `[http_client]` section is used to configure the behavior of the internal HTTP client for outbound requests.\n\n#### `proxy` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nOptional HTTP/HTTPS proxy server to use for outbound requests.\n\n```toml\nproxy = \"http://localhost:3128\"\n```\n\n#### `accept_invalid_certificates`\n\nAllows acceptance of SSL/TLS certificates signed by unknown authorities during outbound requests.\n\n```toml\naccept_invalid_certificates = false\n```\n\n\n### The `[license]` section\n\nThe optional `[license]` section is used to identify the licensee of the ODIN server. This section is used in a separate `license.toml` file.\n\n#### `signature` \u003csub\u003e\u003csup\u003e*Required*\u003c/sub\u003e\u003c/sup\u003e\n\nThe signature of the license used to verify its validity.\n\n```toml\nsignature = \"\"\n```\n\n#### `issuer`\n\nAn optional field to identify the issuer of the license.\n\n```toml\nissuer = \"4Players\"\n```\n\n#### `licensee`\n\nAn optional field to identify the licensee. Usually, this is your 4Players customer number (CID).\n\n```toml\nlicensee = \"622012345\"\n```\n\n#### `serial_number`\n\nAn optional serial number of the license. Usually, this is the ID of your on-premise hosting subscription project.\n\n```toml\nserial_number = \"b0FBTWZ2Rj3OY25uZWtYRlpoekVBUT09\"\n```\n\n#### `valid_until`\n\nAn optional expiration date for the license. When set, the server can't be used after his date.\n\n```toml\nvalid_until = 1987-07-05T17:45:00Z\n```\n\n\n### The `[internal]` section\n\nThe `[internal]` section is used to configure internal settings for debugging.\n\n#### `log_hanging_api_calls`\n\nA debug option to emit warnings if RPC calls take longer then the threshold in milliseconds.\n\n```toml\nlog_hanging_api_calls = 1_000 # ms\n```\n\n#### `log_rejected_api_calls`\n\nA debug option to emit warnings if RPC calls are rejected.\n\n```toml\nlog_rejected_api_calls = false\n```\n\n\n## Examples\n\nCreate a configuration file and use the `grid` executable to start the ODIN server.\n\n\n### Minimal `config.toml` for Supervised Server\n\nWhen running the ODIN server in combination with a [gateway][odin-gateway-url], 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.\n\nThe recommended configuration of the gateway can be defined [here][odin-gateway-config-url].\n\n```toml\npublic_address = \"server.tld:4433\"\n\n[supervisor]\nurl = \"http://username:password@localhost:7000/internal\"\n```\n\n\n### Minimal `config.toml` for Standalone Server\n\nWhen 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.\n\n```toml\npublic_address = \"server.tld:4433\"\n\n[[authorization.keys]]\nkid = \"Afkwfu4BVHDh\"\nkty = \"OKP\"\ncrv = \"Ed25519\"\nx = \"a5J2bhmU7vsY0LrW1zt56iUdmhRUNz7Pl9eBoCy29d8\"\nd = \"5FYw1qdABjE0qEKEe821L7UPl_DZfO-PavpaiLsGDR0\"\n\n[quic]\nbinding = \"0.0.0.0:4433\"\ncertificate_file = \"fullchain.pem\"\nprivatekey_file = \"privkey.pem\"\n```\n\n## Online Documentation\n\n[ODIN Voice]: https://docs.4players.io/voice/\n[ODIN Voice Server]: https://docs.4players.io/voice/server/\n\n\n## Troubleshooting\n\nContact us through the listed methods below to receive answers to your questions and learn more about ODIN.\n\n\n### Discord\n\nJoin our official Discord server to chat with us directly and become a part of the 4Players ODIN community.\n\n[![Join us on Discord](https://docs.4players.io/img/join_discord.png)](https://4np.de/discord)\n\n\n### Twitter\n\nHave a quick question? Tweet us at [@ODIN4Players](https://twitter.com/ODIN4Players) and we’ll help you resolve any issues.\n\n\n### Email\n\nDon’t use Discord or Twitter? Send us an [email](mailto:odin@4players.io) and we’ll get back to you as soon as possible.\n\n\n[toml]: https://github.com/toml-lang/toml\n[mkcert]: https://github.com/FiloSottile/mkcert\n[loki]: https://grafana.com/oss/loki/\n[prometheus]: https://prometheus.io\n[redis]: https://redis.io\n[odin-cli-url]: https://www.npmjs.com/package/@4players/odin-cli\n[odin-gateway-url]: https://github.com/4Players/odin-gateway\n[odin-gateway-config-url]: https://github.com/4Players/odin-gateway/blob/main/gridConfig.ts\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4players%2Fodin-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4players%2Fodin-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4players%2Fodin-server/lists"}