Skip to content
NeuroDynamic Account Download free

Set up your own Whisper server for LexVoca

A voice-to-text server on Ubuntu, connected privately to LexVoca.

AdvancedStep-by-stepAllow about an hourUpdated 23 October 2026WhisperUbuntuLexVoca

Before you start

You'll end up withDictate in Windows. Process speech on your Ubuntu computer.

Build and test a CPU speech server, then connect LexVoca through a private SSH tunnel.

TimeAllow about an hourInstallation and the first model download can take longer. Work through one check at a time.
CostYour hardware and running costsThis path uses your own CPU, storage, electricity and connection. Any rented server and LexVoca licence are separate costs; no speed or price is guaranteed.
You'll need
  • An Ubuntu 24.04 LTS computer with a 64-bit Intel/AMD processor and an account that can use sudo. This walkthrough uses the CPU; no NVIDIA card or GPU software is needed. Other platforms need their own installation instructions.
  • Some spare capacity. An 8 GB machine with several CPU cores is a reasonable starting point for this small-model setup, not a guaranteed minimum or speed target. Leave several gigabytes of free disk space for Docker, the image and model cache. Other running applications also need memory.
  • Internet access for installation. Docker downloads the image, and the server downloads its model on first use. Keep the model volume between restarts.
  • A Windows PC with LexVoca and a working SSH login to Ubuntu. First complete Connect from Windows with SSH. You should already be able to sign in before starting the tunnel in Step 5. SSH keys are a useful follow-up.
  • A short, non-sensitive recording with a few spoken words. Use a WAV file for the first check.
  • Start here: Steps 1–4 happen in the Ubuntu terminal. Step 5 moves to Windows PowerShell, then LexVoca. You can use an SSH terminal to run the Ubuntu commands.
  • Keep the Ubuntu computer on and reachable while dictating. Use a short, non-sensitive recording for your first test.
  • This walkthrough has been checked against upstream source, but has not had a fresh end-to-end installation test. The checks below let you establish whether each part works on your computer.
Who this is for

People who want to run their own speech recognition server and connect a desktop client.

The steps

1

Prepare Docker on the Ubuntu computer

Run the Linux commands in an Ubuntu terminal. If Docker Engine already works, keep your installation and continue to Step 2. On a new machine, follow Docker’s official Ubuntu installation instructions: add its signing key and apt repository, install the Engine packages, then run its hello-world check. The site’s Docker guide explains the steps in more detail.

Do not paste a second installation recipe over an existing Docker setup. The official instructions explain conflicting packages and upgrades. Once installed, check both the client and server versions:

Ubuntu · terminal
(
set -eu
sudo docker version
sudo apt update
sudo apt install -y curl openssl
)

Using sudo avoids adding your account to Docker’s administrator-equivalent group. If Docker reports a connection error, finish its installation checks before continuing.

Check it worked: The Docker version output includes both Client and Server, and package installation finishes without an error. If either fails, stay on this step.
2

Create the private key on Ubuntu

Ubuntu terminal. Copy this whole block once, including its brackets. It creates ~/murmur-whisper and a private whisper.env file. If that path already exists, it stops and keeps the existing key. The brackets keep a failed command from closing your terminal. If setup stops part-way, inspect the folder before trying again; do not delete an existing working configuration.

Ubuntu · terminal
(
set -eu
umask 077
target="$HOME/murmur-whisper"
if [ -e "$target" ] || [ -L "$target" ]; then
  printf '%s\n' 'STOP: ~/murmur-whisper already exists. Inspect it; keep your existing key.' >&2
  exit 1
fi
WHISPER_KEY=$(openssl rand -hex 32)
test "${#WHISPER_KEY}" -eq 64
printf '%s\n' "$WHISPER_KEY" | LC_ALL=C grep -Eq '^[0-9a-f]{64}$'
mkdir -m 700 "$target"
cd "$target"
set -C
printf 'WHISPER_API_KEY=%s\n' "$WHISPER_KEY" > whisper.env
cat >> whisper.env <<'EOF'
WHISPER_MODEL=small
WHISPER_DEVICE=cpu
WHISPER_COMPUTE_TYPE=int8
WHISPER_THREADS=2
WHISPER_MAX_UPLOAD_MB=25
WHISPER_DISABLE_USAGE_COUNTS=1
EOF
chmod 600 whisper.env
printf '%s\n' 'Created private configuration. The API key has not been printed.'
)

The pinned configuration reference documents these settings. small chooses the speech model; CPU int8 and two threads are a conservative starting point. The file limits each upload to 25 MiB and disables optional anonymous aggregate usage counts.

Keep the file private and backed up securely. Anyone who can administer Docker can inspect container settings, including the key. Do not put this file in a shared folder or source repository.

Check it worked: You see “Created private configuration”. An existing-path warning means nothing was replaced: inspect and reuse your existing configuration instead of rerunning this step.
3

Download and start the server on Ubuntu

Ubuntu terminal. First download the CPU image and save the immutable digest that identifies this particular download. This block stops if an image reference already exists, so a repeat does not silently replace your saved version.

Ubuntu · terminal
(
set -eu
cd "$HOME/murmur-whisper"
test -f whisper.env
test -r whisper.env
WHISPER_KEY=$(sed -n 's/^WHISPER_API_KEY=//p' whisper.env)
test "${#WHISPER_KEY}" -eq 64
printf '%s\n' "$WHISPER_KEY" | LC_ALL=C grep -Eq '^[0-9a-f]{64}$'
if [ -e image-reference.txt ] || [ -L image-reference.txt ]; then
  printf '%s\n' 'STOP: image-reference.txt already exists. Use the saved version below, or follow the update section.' >&2
  exit 1
fi
sudo docker pull hwdsl2/whisper-server:latest
WHISPER_IMAGE=$(sudo docker image inspect --format '{{index .RepoDigests 0}}' hwdsl2/whisper-server:latest)
test "${#WHISPER_IMAGE}" -eq 93
printf '%s\n' "$WHISPER_IMAGE" | LC_ALL=C grep -Eq '^hwdsl2/whisper-server@sha256:[0-9a-f]{64}$'
set -C
printf '%s\n' "$WHISPER_IMAGE" > image-reference.txt
printf '%s\n' 'Image downloaded and its exact reference saved.'
)

Now start the saved version. This is also the block to reuse after deliberately removing a stopped container to change its configuration. It reads the private file directly; you do not need to paste your key into a command.

Ubuntu · terminal
(
set -eu
cd "$HOME/murmur-whisper"
test -f whisper.env
test -r whisper.env
WHISPER_KEY=$(sed -n 's/^WHISPER_API_KEY=//p' whisper.env)
test "${#WHISPER_KEY}" -eq 64
printf '%s\n' "$WHISPER_KEY" | LC_ALL=C grep -Eq '^[0-9a-f]{64}$'
test -r image-reference.txt
WHISPER_IMAGE=$(cat image-reference.txt)
test "${#WHISPER_IMAGE}" -eq 93
printf '%s\n' "$WHISPER_IMAGE" | LC_ALL=C grep -Eq '^hwdsl2/whisper-server@sha256:[0-9a-f]{64}$'
sudo docker run -d --name murmur-whisper \
  --restart unless-stopped \
  --env-file "$PWD/whisper.env" \
  -v murmur-whisper-models:/var/lib/whisper \
  -p 127.0.0.1:9000:9000 \
  "$WHISPER_IMAGE"
sudo docker logs --tail 40 murmur-whisper
)

The first start includes a separate model download. A downloaded Docker image is not yet a ready recogniser. The server loads small at startup, using internet access and disk space; wait for the model-ready message. To look again, run sudo docker logs --tail 40 murmur-whisper in Ubuntu. The named model volume keeps the cache between container replacements. A different model may need another download. unless-stopped brings the container back after a reboot unless you deliberately stopped it.

Keep the port binding as shown. It restricts the speech API to the Ubuntu computer’s loopback address. Do not change it to -p 9000:9000 or forward port 9000 on your router. Docker documents both port publishing and the localhost limitations of older Engine versions; use a maintained Engine. A firewall setting alone may not control a Docker-published port as you expect.

Check it worked: The logs report that the model is ready, with no repeated startup failure. A container ID alone does not prove readiness. Confirm the API in Step 4.
4

Prove transcription works on Ubuntu

Put a few seconds of clear, non-sensitive speech in ~/murmur-whisper/test-dictation.wav on Ubuntu. A recording that exists only on Windows must be copied first.

Windows PowerShell: use an existing genuine short WAV recording in Downloads, or replace the source path with its actual location. Do not rename another audio format to .wav. Replace YOUR_USER and YOUR_SERVER with the same SSH user and server from the prerequisite, then run scp "$env:USERPROFILE\Downloads\test-dictation.wav" YOUR_USER@YOUR_SERVER:murmur-whisper/test-dictation.wav. scp copies files over SSH. Wait for a successful copy, then return to the Ubuntu terminal and ask the running server for its model list:

Ubuntu · terminal
(
set -eu
cd "$HOME/murmur-whisper"
test -f whisper.env
test -r whisper.env
WHISPER_KEY=$(sed -n 's/^WHISPER_API_KEY=//p' whisper.env)
test "${#WHISPER_KEY}" -eq 64
printf '%s\n' "$WHISPER_KEY" | LC_ALL=C grep -Eq '^[0-9a-f]{64}$'
curl --fail-with-body -sS http://127.0.0.1:9000/v1/models \
  -H "Authorization: Bearer $WHISPER_KEY"
)

You should receive JSON containing a data list of model IDs. If this fails, fix it before connecting LexVoca. Then send the recording:

Ubuntu · terminal
(
set -eu
cd "$HOME/murmur-whisper"
test -f whisper.env
test -r whisper.env
WHISPER_KEY=$(sed -n 's/^WHISPER_API_KEY=//p' whisper.env)
test "${#WHISPER_KEY}" -eq 64
printf '%s\n' "$WHISPER_KEY" | LC_ALL=C grep -Eq '^[0-9a-f]{64}$'
test -r test-dictation.wav
curl --fail-with-body -sS http://127.0.0.1:9000/v1/audio/transcriptions \
  -H "Authorization: Bearer $WHISPER_KEY" \
  -F file=@test-dictation.wav \
  -F model=whisper-1 \
  -F response_format=json
)

The response should be a JSON object with a text field containing your words. It need not match perfectly: check names, numbers and missing negatives. The whisper-1 request name is accepted by this image; its configured WHISPER_MODEL determines the model that actually runs. Changing that request name does not download or select a different model.

This path sends a completed recording and waits for its text. It does not show live words as you speak. A short clip can take longer than the clip itself on a CPU. For a later hardware project, see the GPU guide and its compatibility notes.

Check it worked: The model request returns JSON with a data list, and the recording request returns a text field with recognisable words. Check names, numbers and negatives before moving to Windows.
5

Connect from Windows and try LexVoca

Windows LexVoca sends a completed recording to Windows loopback port 19000. An encrypted SSH tunnel carries it to Ubuntu loopback port 9000 and the CPU speech server. Text returns along the same connection.
Connection diagram, not an app screenshot. The speech port stays on Ubuntu loopback; only your existing SSH connection crosses the network. Open full-size image (new tab)

Keep the speech service bound to loopback and carry the connection over SSH. In Windows PowerShell, replace YOUR_USER and YOUR_SERVER with the Ubuntu account and the private address or hostname you already use for SSH:

Windows · PowerShell
ssh -N -o ExitOnForwardFailure=yes -L 127.0.0.1:19000:127.0.0.1:9000 YOUR_USER@YOUR_SERVER

Check the server’s host-key fingerprint through a trusted route on first connection. Sign in normally. The terminal may then stay blank: leave it open while you use LexVoca. It forwards Windows port 19000 through the encrypted connection to Ubuntu port 9000. Closing it or pressing Ctrl+C ends the tunnel, not the speech server. No speech port needs to be open to your LAN or the internet. The OpenSSH manual explains local forwarding.

  1. Open LexVoca’s settings. Under Connection → Process speech with, choose My own server. Other versions may call this “Your own server” or place it under Speech.
  2. In Speech server, set the base URL to http://127.0.0.1:19000/v1. Include /v1, but not /audio/transcriptions; LexVoca appends that part itself. Here, 127.0.0.1 means the Windows end of your tunnel.
  3. Enter the key from whisper.env in the speech API-key field, without the WHISPER_API_KEY= prefix. Read it privately on the Ubuntu computer. Do not use a LexVoca hosted-service key.
  4. Set the speech model to whisper-1, or use Refresh and select the model offered by this server. Leave Language blank for automatic detection, or use a language code such as en.
  5. Turn off Clean up transcripts with an LLM for this setup. Do not point the AI cleanup URL at the Whisper server: it is not a chat or correction model. A separate AI correction guide is coming soon.
  6. Save the settings, use Test connection, then Start speech test. Dictate a short, non-sensitive sentence into a blank document and check the returned text.

What makes this compatible? LexVoca’s own-server path reads /v1/models, sends a bearer-authenticated multipart file to /v1/audio/transcriptions, requests JSON and reads its text field. The reviewed server implements that contract. Some extra recognition controls sent by LexVoca are not applied by this server, so compatibility does not mean identical behaviour to the hosted service. A model-list check alone does not prove microphone capture or dictation quality.

Only the speech step is covered here. Audio goes to the server you selected; LexVoca may retain local history or failed recordings according to its settings. Review those settings and the server’s storage and logs before using sensitive material.

Check it worked: With the tunnel open, LexVoca connects and its speech test returns your sentence. Read back the text in your document; a connection check alone is not enough.

What stays private, and what still needs care

The intended speech path is Windows → encrypted SSH tunnel → your Ubuntu CPU → text back to Windows. The HTTP endpoints are loopback addresses on each computer; SSH encrypts the part crossing the network. This guide does not expose the speech API on a public address.

Installation and model downloads contact external providers. Aggregate server usage counts are disabled here, but that is not a complete privacy audit. LexVoca history, failed recordings, server temporary files, logs and backups need their own retention review. A rented Ubuntu server is still a computer operated by its provider. Confirm settings before sending sensitive speech.

There is no separate per-minute hosted transcription service in this path. You pay your own hardware or hosting, electricity, storage and network costs, plus any applicable LexVoca licensing. CPU speed varies; a completed recording may take longer to process than it took to speak. AI cleanup remains off, and transcription still needs checking.

Stop, restart or update

To pause the service without deleting the model cache:

Ubuntu · terminal
sudo docker stop murmur-whisper

To use it again:

Ubuntu · terminal
sudo docker start murmur-whisper

To change configuration, stop the container, edit whisper.env, then remove only the stopped container with sudo docker rm murmur-whisper. Repeat the docker run command from Step 3 using your saved image reference. The named model volume remains.

For an update, finish any recording and keep a secure backup of whisper.env. Preserve image-reference.txt as previous-image-reference.txt without overwriting an earlier backup. Read upstream change notes. Only then move the current reference out of the way and repeat the download block in Step 3 to save a new digest. Stop and remove only your old murmur-whisper container, then use Step 3’s start block. Repeat the model-list, audio and LexVoca checks. Retain the old local image and its digest: to roll back, stop/remove the replacement, restore the previous reference as image-reference.txt, and reuse the start block. Do not delete the model volume during either operation.

To retire this practice setup, stop and remove its container. The murmur-whisper-models volume and private configuration folder remain deliberately. Delete them only after checking that you no longer need the models or key; Docker itself can stay installed for other uses.

For everyday app controls, return to LexVoca’s Speech help.

Related reading

Sources and confidence

Reviewed 23 October 2026: upstream README and configuration, container build and API implementation, commit dated 21 October 2026. They support the image name, WHISPER settings, model cache and API contract used here. Source review and safe shell checks do not prove a live Docker installation, network isolation or recognition quality. LexVoca 2.31.6 labels reflect the earlier source check, not a fresh app walkthrough.

Something went wrong?

Cannot connect to the Docker daemon

Docker cannot connect: check sudo systemctl status docker and that you used sudo. Complete Docker’s installation checks first.

“already exists” or a copy block stops early

Do not remove a working folder or regenerate its key. Step 2 deliberately refuses an existing path; Step 3 refuses an existing image reference. For later steps, confirm you are using the same Ubuntu account, that ~/murmur-whisper contains readable whisper.env and image-reference.txt, and that the saved key is one 64-character hexadecimal value. A missing file or malformed value stops the block before a request. If setup is incomplete, inspect it before deciding what to repair; do not paste commands into another directory.

Container name “murmur-whisper” is already in use

The container name is already in use: inspect sudo docker ps -a. If this is your existing setup, start it with sudo docker start murmur-whisper; do not delete an unfamiliar container.

Connection refused or SSH “address already in use”

Connection refused: check sudo docker ps and the container logs. First get the Ubuntu curl check working, then check the SSH tunnel. A Windows “address already in use” error means port 19000 is occupied; choose another unused local port and use that same port in LexVoca.

401 / unauthorised

401 / unauthorised: the key is missing or different. Read the key from your private file and update LexVoca’s own-server profile. Changing the file alone does not change an existing container; recreate it as described below.

404 / not found

404 / not found: check the base URL ends with exactly one /v1. A different Whisper implementation may expose another API.

Long wait, model download or timeout

A long wait or timeout: check download progress, free memory, CPU use and clip length. Start with a few seconds of audio. For a smaller model, change WHISPER_MODEL to base, then recreate the container; accuracy may change. On Ubuntu, inspect sudo docker logs --tail 40 murmur-whisper for a failed download or memory error. Do not repeatedly restart a download that is progressing.

413 / upload too large

413 / upload too large: this configuration limits a file to 25 MB. Use a shorter recording for the initial check.

Empty or inaccurate text

Empty or inaccurate text: listen to the original recording, check the microphone and language setting, and try a quiet room. Do not treat uncertain text as a reliable command or instruction.

Speech works but AI cleanup fails

Speech works but cleanup fails: keep LLM cleanup off. This server provides transcription, not AI correction.

Finished? What next

You might also like

Did this work for you?Stuck on a step? Tell us which one.
Written by NeuroDynamic team. We build, break and fix things on our own systems and home labs, then write down what worked.

· Report a problem