ssh101+ — what it does, how to use it, and how to test it

Written for somebody who has never seen this system: a feature list you can hand to a QA person, with the exact steps to prove each feature works and what a failure looks like. Every check below is something you can do from a browser and a terminal in a few minutes.

How to use this page. Work top to bottom — later sections assume a channel exists and is publishing. Each check says what to do, what you should see, and what it means if you see something else. If a check fails, note the section number; that is enough for an engineer to reproduce it.

0. Before you start

You need: this server's address, an operator password, OBS (or ffmpeg), and VLC. Nothing else.

CheckYou should seeIf not
Open /healthzokThe server is not running or the address is wrong. Stop here.
Open Admin → HealthA list of green rows, some blue INFOAny BAD row is a real problem — read its "→" line, which says what to do
Find the Database row on HealthMariaDB with a host"In-memory only" means every channel, account and invoice is lost on the next restart. Do not run a business on this. See the admin guide, "Are you running a real database?"

1. Signing up and signing in

What it is for. Anyone can create an account and be streaming in about a minute, without an operator doing anything.

  1. Open the site, press Sign up, enter an email and a password of at least 8 characters.
  2. You land on the dashboard, already signed in. There is no email confirmation step to complete before streaming.
  3. Press Log out, then sign in again with the same details.
CheckExpected
Sign up with an email that already existsRefused, with a message saying so
Sign up with a 4-character passwordRefused
Sign in with the wrong passwordRefused, and the message does not say whether the email exists
Log out, then press the browser's Back buttonYou are not signed in. A logout ends the session on the server, not only in the browser

2. Creating a channel and going live

What it is for. A channel is one stream: an ingest key to publish to, and a set of URLs to watch it on.

  1. Channels → enter a slug (test1) → Create.
  2. Copy the RTMP server and stream key from the channel row.
  3. In OBS: Settings → Stream → Custom → paste both → Start Streaming.
  4. Within a few seconds the channel shows ON AIR.
# or without OBS
ffmpeg -re -f lavfi -i testsrc2=size=1280x720:rate=30 \
  -c:v libx264 -b:v 2500k -preset veryfast -g 60 \
  -f flv rtmp://YOUR-HOST:1935/live/YOUR-STREAM-KEY
CheckExpected
Open the channel's player linkPicture within a few seconds
Open the .m3u8 in VLCSame picture. This proves it is a real HLS stream, not a browser trick
Publish with a wrong stream keyRefused at the door. The channel stays off air and nothing appears
Stop OBS, wait, start it againThe channel returns to ON AIR by itself
Try to create a second channelRefused — every plan includes one channel. This is deliberate

3. Recording and catch-up (VOD)

What it is for. Keeping what went out so viewers can watch it later. Two different settings, and confusing them is the most common mistake:

  1. On the channel page tick Record broadcasts to VOD, set Keep recordings for to 7, save.
  2. Publish for a minute, then stop.
  3. The recording appears in the channel's recordings list.
CheckExpected
Play the recordingIt plays start to finish
Reload the channel pageKeep recordings for still says 7. If it reverted to 0 the form is discarding your input — report it
Stop the encoder mid-broadcast, restart it within two minutesOne recording covering both halves, not two. It plays through the join without stopping
Stop the encoder and leave it off for five minutesA new recording starts. Yesterday's broadcast must not be appended to today's

4. DVR / nDVR — the rewind window

What it is for. Letting a viewer scrub backwards through a live stream — they arrive late and watch from the start of the programme.

RAM or disk. RAM is fast and limited by a memory budget; disk allows much longer windows. On this server disk spools can live on their own volume (-dvr-dir), because DVR is the one thing that writes continuously.

  1. Set DVR rewind window to 5 minutes and DVR storage to disk.
  2. Publish for six minutes.
  3. Open the player and drag the scrub bar backwards.
CheckExpected
Scrub back four minutesIt plays from there
Scrub back further than the windowIt clamps to the oldest point it still has, rather than stalling
Leave it publishing for an hour with a 5-minute windowDisk use stops growing. A window that grows forever is a bug
Set the window to 0Live only, no scrub bar

5. Protecting a channel (AES-128 and access rules)

What it is for. Making a stream unusable to anyone you have not allowed.

Important and easy to miss: switching on any access rule — even just a viewer cap — makes the channel token-protected. Plain .m3u8 links that worked before will start returning 403. Use the embed code from the channel's player code page, which handles tokens for you.
CheckExpected
Tick Secure, then open the raw .m3u8 with no token403
Open the channel's embed linkPlays — it fetches a token itself
Take a working token and change one character403
Wait for the token to expire, keep watchingPlayback continues — the player fetches a new one before the old expires
Set a viewer cap of 1 and open two playersThe second is refused

6. Embed code — live, recording, and rewind

What it is for. Putting the stream on somebody else's website. The channel's player code page gives ready-made snippets:

SnippetUse it for
Web (hls.js)Any website. Handles tokens and reports playback quality
iOS / Android / RokuNative apps
VLC / ffmpegProving a channel works without a browser
Recording / catch-upEmbedding one past broadcast
Live with rewind (nDVR)Live with a seekable timeline
CheckExpected
Paste the web snippet into a blank HTML file and open itPlays
Do the same on a channel with Secure onStill plays — the snippet fetches a token. If it 403s, the snippet is missing token handling; report it
Use the catch-up snippet with a real recording idPlays that recording
Play through the web snippet, then look at the channel's analyticsA start time appears. Viewers on embedded players must be counted

7. Analytics

Per channel (customer's own dashboard): viewers now, peak, bytes, watch time, where viewers are, and playback quality — startup time, stalls, errors, broken down per rendition.

Across all customers (Admin → All customers): the whole box added up, then split per account — channels, live channels, viewers, egress, watch hours. This is the operator's view; a customer never sees it.

CheckExpected
Watch a channel from two browsersViewers reaches 2 within a few seconds
Close bothIt returns to 0 within a minute or so
Admin → All customersThe customer publishing shows live channels and viewers; idle customers show zero
Restart the server, reopen analyticsYesterday's per-minute history is still there. Live counters restart from zero, which is correct

8. Provisioning several channels at once (operator)

What it is for. Standing up a lineup — a set of channels that all get the same treatment — without configuring each by hand. Admin → CapacityProvision a lineup.

Enter comma-separated names, pick a profile (OTT switches on recording, catch-up, low latency, a public listing and a DVR window), pick protection (AES-128, DRM or none), a DVR length, and optionally an owner account. Each channel comes back with its own ingest key and embed code.

CheckExpected
Provision three channels with the OTT profile and AESThree channels, each with its own key, all with Secure on and the DVR window set
Run the same request againExisting names are reported as already taken rather than being duplicated or overwritten
Leave Owner blankThe channels belong to the operator
Put a customer's user id in OwnerThey appear on that customer's dashboard, even though their plan includes one channel — an operator may provision beyond a plan

9. Support

CheckExpected
As a customer: Support → open a ticketIt appears in your tickets as open
As operator: Admin → Support inboxThe ticket is there
Reply as operatorThe customer sees the reply on their own support page
Sign in as a different customerThey cannot see the first customer's ticket

10. Billing

Until a payment provider is configured on Admin → Payments, checkout is simulated: subscriptions activate and invoices appear with method dev, and no money moves. Health says so. Any revenue figure you see before then is test data.
CheckExpected
Upgrade a test account to BusinessIts plan changes and paid features unlock
Try a Business-only feature (DVR) on a Pro accountRefused, naming the plan needed
Downgrade that account back to FreeThe paid feature is switched off, not left running
Admin → Billing consoleThe account, its plan, its channel count and its invoices

11. Things that need real hardware or a real third party

These cannot be tested on a laptop, and a tester should not record them as failures:

FeatureNeeds
Server-side ABR, live barA GPU node (gpunode or GPUFF) reachable from this server
Widevine / FairPlay DRMA licence server
Push to YouTube / FacebookA real stream key on that platform
Per-customer S3 storageA real bucket and credentials
Geo blockingViewers with real public addresses — everything is "local" from one office
HTTP/3 advertisementUDP/443 reachable from outside; prove it with ssh101 -h3check from another machine first

12. Reporting a problem

An engineer needs four things, and rarely gets them: the section number above, the channel slug, what you saw instead, and the time (so the audit log and the server log can be lined up). A screenshot of the whole browser window — including the address bar — is worth more than a description.