First Steps

Selium comprises a client library and a server binary. In order to use Selium, there are 3 basic steps:

  1. Create TLS certificates for your client and server
  2. Run the server binary
  3. Integrate the client library into your project

Step 1 - TLS Certificates

First we need some certs to validate the client and server. Selium uses mutual TLS (mTLS) to validate both parties cryptographically, making things nice and secure.

We've built a tool to make this easy, so let's install that, then mint our certs:

# Install the selium-tools CLI
$ cargo install selium-tools
# Use this CLI to create our certificates
$ selium-tools gen-certs

You should now have a directory in the current path called certs/. Inside we have certs for the client and server, which you can move to a more convenient location if you like - the paths are configurable in code. Both the client/ and server/ directories include a copy of the certificate authority, which you'll need if you want to create more client certificates later.

Step 2 - Start the Selium Server

The Selium server allows us to exchange messages between clients. For this example we'll grab a copy from

For production deployments you can also download prebuilt binaries from GitHub.

Let's start a new server with our freshly minted certs. In the same directory as your certs/ folder, open a new terminal and run the following commands:

# Install Selium server
$ cargo install selium-server
# Run the server
$ selium-server --bind-addr=

The selium-server command will not produce any output by default, but that doesn't mean it isn't working! You can increase logging using the verbosity flag:

$ selium-server -v # Warnings only
$ selium-server -vv # Info
$ selium-server -vvv # Debug
$ selium-server -vvvv # Trace

Step 3 - Implement the Selium Client

Selium Client is a composable library API for the Selium Server. Let's have a look at a minimal example:

use futures::{SinkExt, StreamExt};
use selium::{prelude::*, std::codecs::StringCodec};

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let connection = selium::custom() // connect to your own Selium server
        .endpoint("") // your Selium server's address
        .with_certificate_authority("certs/client/ca.der")? // your Selium cert authority
        )? // your client certificates

    let mut publisher = connection
        .publisher("/some/topic") // choose a topic to group similar messages together
        .with_encoder(StringCodec) // allows you to exchange string messages between clients
        .open() // opens a new stream for sending data

    let mut subscriber = connection
        .subscriber("/some/topic") // subscribe to the publisher's topic
        .with_decoder(StringCodec) // use the same codec as the publisher
        .open() // opens a new stream for receiving data

    // Send a message and close the publisher
    publisher.send("Hello, world!".into()).await?;

    // Receive the message
    if let Some(Ok(message)) = {
        println!("Received message: {message}");


There's a lot to take in here, but for the moment let's just get this baby running!

# Create a new Cargo project
$ cargo new --bin hello-selium

# Move into our project
$ cd hello-selium

# Add the crate dependencies
$ cargo add futures
$ cargo add -F std selium
$ cargo add -F macros,rt tokio

Now copy and paste the code above into hello-selium/src/

Now let's execute the project and start exchanging some messages! Make sure your server is still running from the previous step.

$ cargo run
Received message: Hello, world!

Next Steps

We've just setup a working Selium publish/subscribe project, but you can also use RPC too.