Lightning Fast
Written in Rust for maximum performance with minimal resources
Audioserve is a simple, lightweight, self-hosted audiobook server written in Rust. Designed with a minimalist approach, it serves audio files directly from your folder structure—no complex database setup or metadata management required. Just point it at your audiobook collection and start listening.
With a modern Progressive Web App (PWA) client built with Svelte and TypeScript, Audioserve offers offline listening, shared playback positions across devices, and on-the-fly transcoding to save bandwidth. It’s perfect for personal audio collections where simplicity and performance matter most.
Lightning Fast
Written in Rust for maximum performance with minimal resources
PWA Client
Install as an app with offline support and track caching
Position Sync
Share playback positions across all your devices
Transcoding
On-the-fly conversion to opus/mp3/aac for bandwidth savings
Audioserve provides a focused feature set for audiobook enthusiasts:
| Feature | Description |
|---|---|
| Folder-Based | Browse your library exactly as it’s organized on disk |
| Chapter Support | M4B files and similar formats display chapters as virtual files |
| Multiple Collections | Serve separate libraries (e.g., different languages) |
| Shared Positions | Continue listening on any device from where you left off |
| Smart Caching | Fast search and browsing via embedded key-value database |
| Transcoding | Convert audio on-the-fly to lower bitrates |
| Folder Download | Download entire audiobooks as tar/zip archives |
| Tags Display | Optionally show audio metadata tags |
| Feature | Audioserve | Full-Featured Servers |
|---|---|---|
| Complexity | Minimal, folder-based | Database-driven, complex metadata |
| Resource Usage | Very lightweight | Higher requirements |
| Setup Time | Minutes | Hours of configuration |
| Philosophy | ”Your folders, your way" | "Organized by tags/metadata” |
| Best For | Personal use, well-organized collections | Large multi-user libraries |
Before deploying Audioserve on Klutch.sh, ensure you have:
Set up your Audioserve deployment:
Create a Dockerfile for your Audioserve deployment:
FROM izderadicka/audioserve:latest
# Set environment variablesENV AUDIOSERVE_SHARED_SECRET=your-secure-secret-hereENV RUST_LOG=info
# Expose the default portEXPOSE 3000
# Create directoriesRUN mkdir -p /audiobooks /home/audioserve/.audioserve
# Default entrypoint runs audioserve with provided argumentsCMD ["--tags", "--behind-proxy", "/audiobooks"]For a more feature-rich deployment:
FROM izderadicka/audioserve:latest
# Environment configurationENV AUDIOSERVE_SHARED_SECRET=your-secure-secret-hereENV RUST_LOG=info
# Create necessary directoriesRUN mkdir -p /audiobooks /podcasts /home/audioserve/.audioserve
# Expose portEXPOSE 3000
# Run audioserve with multiple collections and featuresCMD ["--tags", \ "--behind-proxy", \ "--compress-responses", \ "--positions-backup-file", "/home/audioserve/.audioserve/positions-backup.json", \ "--positions-backup-schedule", "0 3 * * *", \ "/audiobooks", "/podcasts"]Audioserve is configured primarily through command-line arguments and environment variables:
| Variable | Description |
|---|---|
AUDIOSERVE_SHARED_SECRET | Authentication secret (required for secure access) |
RUST_LOG | Log level (error, warn, info, debug, trace) |
PORT | HTTP port (defaults to 3000) |
Key arguments for audioserve:
| Argument | Description |
|---|---|
--tags | Scan and display audio metadata tags |
--behind-proxy | Log real client IP when behind reverse proxy |
--compress-responses | Enable gzip compression for responses |
--no-authentication | Disable authentication (testing only!) |
--transcoding-max-parallel-processes N | Max concurrent transcodings |
--positions-backup-file PATH | Backup playback positions to JSON file |
--positions-backup-schedule CRON | Backup schedule in cron format |
--data-dir PATH | Directory for audioserve data |
--collapse-cd-folders | Merge CD subfolders into parent |
For complex setups, use a YAML config file:
# Transcoding configurationtranscoding: low: opus-in-ogg: bitrate: 32 compression_level: 3 cutoff: WideBand mono: true medium: opus-in-ogg: bitrate: 48 compression_level: 6 cutoff: SuperWideBand high: opus-in-ogg: bitrate: 64 compression_level: 9 cutoff: FullBand
# Apple device support (Safari)# transcoding:# alt_configs:# "iPhone|iPad|Mac OS":# low:# aac-in-adts:# bitrate: 32# mono: true# medium:# aac-in-adts:# bitrate: 48# high:# aac-in-adts:# bitrate: 64Test your Audioserve setup locally:
services: audioserve: image: izderadicka/audioserve:latest container_name: audioserve ports: - "3000:3000" volumes: - ./audiobooks:/audiobooks:ro - audioserve-data:/home/audioserve/.audioserve environment: - AUDIOSERVE_SHARED_SECRET=mydevpassword - RUST_LOG=info command: ["--tags", "/audiobooks"] restart: unless-stopped
volumes: audioserve-data:Push your repository to GitHub
git initgit add .git commit -m "Initial Audioserve configuration"git remote add origin https://github.com/yourusername/audioserve.gitgit push -u origin mainCreate a new app on Klutch.sh
Configure environment variables
| Variable | Value |
|---|---|
AUDIOSERVE_SHARED_SECRET | A strong secret phrase (14+ characters recommended) |
RUST_LOG | info |
Configure the internal port
Set up persistent storage
| Mount Path | Size | Purpose |
|---|---|---|
/audiobooks | 100 GB+ | Your audiobook collection |
/home/audioserve/.audioserve | 5 GB | Cache, positions, server secret |
Deploy your application
https://your-app.klutch.shAccess your server
Audioserve works best with well-organized folders:
/audiobooks/├── Asimov, Isaac/│ └── Foundation Series/│ ├── 01 - Foundation/│ │ ├── 001 - First Chapter.mp3│ │ ├── 002 - Second Chapter.mp3│ │ └── cover.jpg│ └── 02 - Foundation and Empire/│ └── audiobook.m4b├── Tolkien, J.R.R./│ └── The Lord of the Rings/│ ├── 01 - Fellowship of the Ring/│ └── 02 - The Two Towers/└── Single Audiobook.m4b| Tip | Description |
|---|---|
| Author folders | Use “Last Name, First Name” format |
| Series folders | Group related books together |
| Numbered prefixes | Ensure correct file ordering (001, 002, etc.) |
| Cover images | Add cover.jpg or cover.png to folders |
| Descriptions | Add description.txt or description.html |
M4B and similar files with chapter metadata are displayed as virtual folders:
The Hobbit.m4b → displays as:└── The Hobbit.m4b/ ├── Chapter 01 - An Unexpected Party ├── Chapter 02 - Roast Mutton └── ...The web client can be installed as a Progressive Web App:
To sync positions across devices:
Select quality levels during playback:
| Level | Default Bitrate | Best For |
|---|---|---|
| Low | 32 kbps opus | Mobile data, slow connections |
| Medium | 48 kbps opus | Balanced quality/bandwidth |
| High | 64 kbps opus | Good connections |
| Original | No transcoding | Local network, unlimited data |
Add multiple libraries by modifying your Dockerfile:
FROM izderadicka/audioserve:latest
ENV AUDIOSERVE_SHARED_SECRET=your-secure-secret
EXPOSE 3000
RUN mkdir -p /audiobooks /podcasts /lectures /home/audioserve/.audioserve
CMD ["--tags", "--behind-proxy", "/audiobooks", "/podcasts", "/lectures"]Each collection appears as a separate library in the client.
Safari and iOS require AAC transcoding instead of Opus. Add this configuration:
transcoding: alt_configs: "iPhone|iPad|Mac OS": low: aac-in-adts: bitrate: 32 sr: "24kHz" mono: true medium: aac-in-adts: bitrate: 48 high: aac-in-adts: bitrate: 64Then update your Dockerfile to use the config:
CMD ["--config", "/config.yaml", "--tags", "--behind-proxy", "/audiobooks"]Strong Secret
Use 14+ character shared secret phrase
HTTPS Only
Klutch.sh provides automatic SSL certificates
No Auth = No Production
Never use —no-authentication on the internet
Regular Updates
Keep audioserve updated for security fixes
If you suspect your secret is compromised:
/home/audioserve/.audioserve/audioserve.secret fileAUDIOSERVE_SHARED_SECRET environment variableEnable automatic position backups in your Dockerfile:
CMD ["--tags", \ "--positions-backup-file", "/home/audioserve/.audioserve/positions.json", \ "--positions-backup-schedule", "0 3 * * *", \ "/audiobooks"]To restore from a backup:
# One-time restore commandaudioserve --positions-restore=v1 \ --positions-backup-file /path/to/positions.json \ /audiobooksCommon issues and solutions:
| Issue | Cause | Solution |
|---|---|---|
| Can’t authenticate | Wrong shared secret | Verify AUDIOSERVE_SHARED_SECRET matches |
| Slow initial load | Cache being built | Wait for initial scan to complete |
| Search not working | Cache incomplete | Allow full scan to finish |
| Files not showing | Wrong permissions | Ensure files are readable |
| No cover art | Missing image file | Add cover.jpg to folder |
| Apple devices no audio | Opus not supported | Configure AAC transcoding |
Monitor server activity:
# Set verbose loggingENV RUST_LOG=debugIf the cache becomes inconsistent, trigger a full rescan by redeploying with:
CMD ["--force-cache-update", "--tags", "/audiobooks"]Remove --force-cache-update after the first successful scan.
Audioserve provides a simple REST API for custom clients:
# Get collection contentscurl "https://your-app.klutch.sh/0/folder" \ -H "Authorization: Bearer YOUR_TOKEN"
# Search collectioncurl "https://your-app.klutch.sh/0/search?q=foundation" \ -H "Authorization: Bearer YOUR_TOKEN"API documentation: Audioserve API