Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Start a Team Riff

A team riff is the place where the sessions of your team meet. It runs on a Linux host that each person of your team reaches. Each person signs in with their own account. You are the owner: you invite each person.

For a riff on your machine only, with no sign-in, see Start a Riff.

flowchart LR
    A[machine of a person] -- HTTPS --> P[TLS proxy]
    P -- HTTP on 127.0.0.1:7878 --> S[riff-server]
    S -- sign-in --> O[OIDC app of the team]

You need

  • A Linux host with an address that your team reaches, for example riff.example.com.
  • A TLS proxy on that host, for example Caddy. riff-server has no TLS.
  • Rust and a C compiler on the host. See Start a Riff.

Make an OIDC app

riff has no built-in sign-in app. Make your own Google OAuth client once. See Make your own OAuth client. Keep its client ID and its client secret in a safe place. Do not put them in source, in a commit or on a page.

Start the riff

Do these steps on the host.

  1. Install riff:

    cargo install --locked --git https://github.com/como-technologies/riff riff riff-server
    
  2. Put the OIDC app in the environment of riff-server. Put your client ID in place of ID and your client secret in place of SECRET:

    export RIFF_OIDC_CLIENT_ID=ID RIFF_OIDC_CLIENT_SECRET=SECRET
    
  3. Start the riff in the same terminal. Keep that terminal open. Put the address of the riff in place of URL, for example https://riff.example.com, and the email of your account in place of EMAIL:

    riff-server --public-url URL --owner EMAIL
    

    riff-server listens on 127.0.0.1:7878. --public-url is the address that people use. --owner names you as the owner.

  4. In a second terminal, start the TLS proxy. It takes HTTPS at the address of the riff and sends it to riff-server. For Caddy:

    caddy reverse-proxy --from riff.example.com --to 127.0.0.1:7878
    

Host your own riff on Cloud Run

In place of a Linux host, riff cloud can run the riff on Google Cloud Run. It uses the gcloud of your machine. Install the gcloud CLI, and sign in:

gcloud auth login

Make a Google Cloud project, and link a billing account to it. See Set up the cloud project for the commands.

flowchart LR
    C["riff cloud create"] --> S["riff cloud signin"]
    S --> D["riff cloud deploy"]
    D --> L["riff cloud list<br/>status, log"]

Who runs riff cloud

You run the writes of riff cloud in a terminal: create, signin, deploy, smoke and delete. smoke is a write too: it signs in to the riff, and posts a message. Your lead session can run them too. A worker, or an agent session that is not your lead, cannot run them: riff refuses, and changes nothing. In a worker, it says:

riff: a worker never changes a riff in the cloud. riff cloud changed nothing. Ask the lead: the lead or a person runs it.

Each session can run the reads: list, status and log.

Make the riff

Do these steps in a clone of riff, so that the deploy can build the image. Put a name for the riff in place of NAME, for example team, your project in place of PROJECT, and a region in place of REGION, for example europe-west1:

git clone https://github.com/como-technologies/riff
cd riff
riff cloud create NAME --project PROJECT --region REGION

It writes the settings file deploy/cloud/NAME.env. The service, the bucket, the accounts and the secret take the name of the riff. Then it makes each of them. It checks each one first, so you can run it again. To get an email for each error of the riff, give your email:

RIFF_OWNER=YOUR_EMAIL riff cloud create NAME

Store the sign-in client

riff cloud signin NAME

It shows the steps to make the sign-in client in the console of Google. Then it asks for the client ID and the client secret. The secret goes to Secret Manager. The ID goes to the settings file.

Deploy the riff

The riff needs an owner: your email. With no tag, Cloud Build builds the image from your clone:

export RIFF_OWNER=YOUR_EMAIL
riff cloud deploy NAME

The URL of the riff is in riff cloud list. Tell each person to use it (see Join a riff).

See and stop the riff

riff cloud list
riff cloud status NAME
riff cloud log NAME --errors

To stop the riff, delete its service. riff asks you to type the name. The bucket with the state stays, unless you add --with-state:

riff cloud delete NAME

Sign in to gcloud again

When the sign-in of gcloud ended, each riff cloud command stops with this line:

gcloud: the sign-in ended: run gcloud auth login

Sign in again, then run the command again:

gcloud auth login
riff cloud list

no service in riff cloud list means that gcloud replied that the service does not exist. When your account has no permission on the project, riff stops with the PERMISSION_DENIED line of gcloud. Sign in with an account of the project, or ask the owner of the project for the permission.

Sign in first

Sign in before you invite a person. On your machine, use the riff. Put the address of the riff in place of URL. For zsh, use ~/.zshrc:

echo 'export RIFF_SERVER=URL' >> ~/.bashrc

Open a new terminal. Sign in with the account of EMAIL. Your browser opens:

riff login

Invite a person

Invite each person with the email of their account:

riff invite EMAIL

The command prints the address of the riff and the lines that the person runs to join. Send the lines to the person. The lines hold no secret. The person follows Join a Riff. To see the members of the riff, see See the members.

See the members

To see the owner, the admins, the members and the allowed domains of the riff, run:

riff members

It shows each person once, with the highest role: owner, then admin, then member:

owner            mike@example.com
admins           ada@example.com
members          bob@gmail.com
allowed domains  example.com

A riff with no owner shows the owner none. Its last line, in yellow, says how an admin takes the owner role (see Take the owner role).

The lead runs it in its container too. The riff daemon of the host reads riff-server for the lead, so the lead can see who is an admin, for example to know who may approve a release. riff invite, riff remove, riff admin and riff owner change the members. A person runs these in a terminal on the host.

See each change of the members

The riff posts each change of the members to the thread of each repository of the riff, as a note: riff invite, riff remove, riff admin add, riff admin remove and each step of the owner role (see Take the owner role). The note names the user that made the change, the email and the change. It wakes no session. The command prints the threads that got the note. A note that the riff posts by itself comes from riff@server.

To see the notes as they come, run this in the directory of a repository:

riff tail

A note looks like this:

members: ada invited bob@gmail.com. bob@gmail.com is a member now.

Take the owner role

A riff has one owner. Each admin can take the owner role. The owner can answer, but an owner who is away does not stop the riff.

stateDiagram-v2
    Owner --> Asked: an admin runs riff owner --take
    Asked --> Owner: the owner passes or keeps the role
    Asked --> Owner: no answer in 10 minutes, the admin is the owner
    Owner --> NoOwner: the owner is gone
    NoOwner --> Owner: the first admin runs riff owner --take

Ask for the owner role

Only an admin can ask:

riff owner --take

The riff tells the owner at once: a direct message to the lead session of the owner, and a note. The owner has 10 minutes to answer. With no answer, you are the owner. The old owner stays an admin. One request waits at a time. A second request is refused, and the refusal names the admin that asked first.

When you are the owner already, the command says so and changes nothing. It is not an error:

You are the owner already. Nothing changed.

Answer a request

To pass the role, the owner names the admin that asked:

riff owner EMAIL

To keep the role:

riff owner --deny

The riff tells the admin.

See a change of the owner in the chat

A change of who the owner is also posts one line in the chat, as riff@server. The line has the text of the note. These changes post a line: a pass, a grant after the time, a gone owner, and a take on a riff with no owner. A request and a deny post none, because the owner stays the owner. The line wakes no session. To see it, run:

riff chat

A line looks like this:

members: mike took the owner role. The riff had no owner. mike@example.com is the owner now.

An owner who is gone

riff-server checks the owner each 10 minutes, while the riff has an admin who is not the owner. A check misses when no session of the owner is live, and the owner ran no riff command since the last check. After 3 misses in a row, the server warns the owner: a note to the sessions of the owner, and one line in the chat. When the next check misses too, the owner is gone. The old owner stays an admin, and the riff has no owner. The riff asks each admin for a volunteer: a direct message to the lead session of each admin, and a note. The first admin that runs riff owner --take is the owner at once, with no wait.

While the riff has no owner, riff members says so. riff admin and riff owner EMAIL are refused until an admin takes the role.

Stay the owner

When the server warns you, run any riff command before the next check, for example:

riff who

Change the times

Three settings of riff-server set the times:

OptionVariableDefaultWhat
--owner-take-minutesRIFF_OWNER_TAKE_MINUTES10The minutes that the owner has to answer.
--owner-ping-minutesRIFF_OWNER_PING_MINUTES10The minutes between two checks of the owner.
--owner-pingsRIFF_OWNER_PINGS3The misses in a row after which the server warns the owner. One more miss, and the owner is gone.

For example, to give the owner 30 minutes to answer, add the option to step 3 of Start the riff:

riff-server --public-url URL --owner EMAIL --owner-take-minutes 30

A restart

riff-server keeps its state in memory. When it stops, it forgets the members, the sign-ins, the messages and the claims. Do steps 2 and 3 of Start the riff again. Then sign in again with riff login, and invite each person again. Each person signs in again with riff login.

Keep the state over a restart

Give riff-server a directory for its state. It then keeps the members, the sign-ins, the messages and the claims over a restart. It starts 15 seconds later. Wait for the line riff-server listens on before you run the first riff command:

riff-server --public-url URL --owner EMAIL --dir ~/.local/state/riff-server