Piper is a fast, local neural text-to-speech engine designed to run well on modest CPU hardware (it was built with Raspberry Pi in mind), so it's an easy, low-resource deployment on nearly any RamNode VPS.
1. Choose and size the VPS
Piper is lightweight — it is one of the least demanding services you can self-host.
| Use case | Recommended RamNode plan specs |
|---|---|
| Light/personal use, single low-quality voice | 1 vCPU, 1–2 GB RAM |
| Regular use, multiple voices/medium quality | 2 vCPU, 2–4 GB RAM |
| Higher throughput / concurrent requests | 4 vCPU, 4–8 GB RAM |
Recommended OS: Ubuntu 24.04 LTS.
2. Initial server setup
apt update && apt -y upgrade
apt -y install build-essential python3 python3-venv python3-pip wget unzip ufw ca-certificates
ufw allow OpenSSH
ufw allow 5000/tcp # the port the wrapper API will use below
ufw enableCreate a dedicated service user and directory layout:
adduser --system --group --home /opt/piper piper
mkdir -p /opt/piper/voices
chown -R piper:piper /opt/piper3. Install Piper
The simplest path on Linux x86_64 is the prebuilt release binary rather than compiling from source:
su - piper -s /bin/bash
cd /opt/piper
# Check https://github.com/OHF-Voice/piper1-gpl/releases (or rhasspy/piper) for the latest tag
wget https://github.com/rhasspy/piper/releases/latest/download/piper_linux_x86_64.tar.gz
tar -xzf piper_linux_x86_64.tar.gzThis extracts a piper/ directory containing the piper binary and its shared libraries. Verify it before continuing:
cd piper
./piper --helpIf you'd rather install as a Python package for easier scripting/integration:
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install piper-tts fastapi "uvicorn[standard]"Both approaches can coexist; the wrapper API below assumes the piper-tts Python package.
4. Download a voice model
Piper voices are distributed as an .onnx model plus a .onnx.json config file, per language/speaker, at varying quality tiers (x_low, low, medium, high).
mkdir -p /opt/piper/voices/en_US-lessac-medium
cd /opt/piper/voices/en_US-lessac-medium
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx
wget https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/en_US-lessac-medium.onnx.jsonBrowse the full voice catalog at the piper-voices Hugging Face repo and repeat for any additional languages/speakers you want to serve.
Test synthesis directly from the CLI:
echo "Hello from RamNode." | ./piper/piper \
--model /opt/piper/voices/en_US-lessac-medium/en_US-lessac-medium.onnx \
--output_file /opt/piper/test.wav5. Wrap it in a small HTTP API
Create /opt/piper/server.py:
from fastapi import FastAPI
from fastapi.responses import Response
from pydantic import BaseModel
from piper import PiperVoice
import io, wave, os
VOICE_PATH = os.environ.get(
"PIPER_VOICE",
"/opt/piper/voices/en_US-lessac-medium/en_US-lessac-medium.onnx",
)
app = FastAPI()
voice = PiperVoice.load(VOICE_PATH)
class SpeakRequest(BaseModel):
text: str
@app.post("/speak")
async def speak(req: SpeakRequest):
buf = io.BytesIO()
with wave.open(buf, "wb") as wav_file:
voice.synthesize(req.text, wav_file)
return Response(content=buf.getvalue(), media_type="audio/wav")
@app.get("/health")
async def health():
return {"status": "ok", "voice": VOICE_PATH}Test it:
uvicorn server:app --host 127.0.0.1 --port 50006. Run it as a systemd service
As root, create /etc/systemd/system/piper.service:
[Unit]
Description=Piper text-to-speech API
After=network.target
[Service]
Type=simple
User=piper
Group=piper
WorkingDirectory=/opt/piper
Environment=PIPER_VOICE=/opt/piper/voices/en_US-lessac-medium/en_US-lessac-medium.onnx
ExecStart=/opt/piper/venv/bin/uvicorn server:app --host 127.0.0.1 --port 5000
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetsystemctl daemon-reload
systemctl enable --now piper
systemctl status piper7. Put nginx in front (recommended)
server {
listen 80;
server_name tts.example.com;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}apt -y install certbot python3-certbot-nginx
certbot --nginx -d tts.example.com
ufw delete allow 5000/tcp
ufw allow "Nginx Full"8. Operational notes
- Multiple voices: load several
PiperVoiceinstances keyed by name/language in the wrapper if you need more than one voice served from the same API; keep each model in its own subdirectory under/opt/piper/voices/. - Quality vs. speed:
mediumquality voices are a good default;highsounds noticeably better but is slower per character — test on your actual vCPU count before committing. - Streaming: for long text, synthesize sentence-by-sentence and stream chunks back rather than buffering the whole response, if your client supports chunked audio.
- Monitoring: add an HTTP check against
/health. - Updates:
pip install -U piper-tts(Python route) or re-download the latest release tarball (binary route), thensystemctl restart piper.
