Self-Hosting
import { Steps } from ‘@astrojs/starlight/components’;
br\u016bhi Cloud is packaged as a single Docker image containing all services. Docker Compose is the recommended deployment method.
Quick Deploy (Automated Installer)
Section titled “Quick Deploy (Automated Installer)”The quickest way to install brūhi Cloud on a Linux server is using the automated interactive script from the official bruhi-deploy repository:
bash <(curl -fsSL https://raw.githubusercontent.com/bruhi-technologies/bruhi-deploy/main/install.sh)The script checks Docker prerequisites, prompts for your domain and port, auto-generates secure passwords, configures .env, and pulls the container image.
Manual Docker Compose Deployment
Section titled “Manual Docker Compose Deployment”-
Download Deployment Files
Create an installation folder and fetch the compose definitions:
Terminal window mkdir -p ~/bruhi-cloud && cd ~/bruhi-cloudcurl -fsSL https://raw.githubusercontent.com/bruhi-technologies/bruhi-deploy/main/docker-compose.yml -o docker-compose.ymlcurl -fsSL https://raw.githubusercontent.com/bruhi-technologies/bruhi-deploy/main/Caddyfile -o Caddyfilecurl -fsSL https://raw.githubusercontent.com/bruhi-technologies/bruhi-deploy/main/.env.example -o .env -
Configure Environment Variables
Edit
.envand configure your domain and credentials:# Activate bundled Icecast and Caddy HTTPS reverse proxyCOMPOSE_PROFILES=bundled-icecast,proxy# Your domain name (required for automatic SSL certificates and Passkeys)DOMAIN=radio.yourdomain.comBRUHI_URL=https://radio.yourdomain.comBRUHI_RP_ID=radio.yourdomain.com# Streaming security passwordsICECAST_SOURCE_PASSWORD=your_secure_source_passwordICECAST_ADMIN_PASSWORD=your_secure_admin_passwordICECAST_RELAY_PASSWORD=your_secure_relay_password -
Start the Stack
Terminal window docker compose up -d -
Verify Health
Terminal window curl http://localhost:8000/healthz# {"status":"ok"}
Environment Variables
Section titled “Environment Variables”| Variable | Default | Description |
|---|---|---|
PORT | 8000 | API server & web dashboard host port |
LOG_LEVEL | warning | Log verbosity (debug, info, warning, error) |
BRUHI_ENV | production | Environment mode (development or production) |
BRUHI_URL | — | Base public URL used for passkeys, reset links, etc. |
DOMAIN | — | Domain name for Caddy automatic HTTPS |
COMPOSE_PROFILES | bundled-icecast,proxy | Active Compose profiles (bundled-icecast, proxy) |
BRUHI_ICECAST_MODE | bundled | bundled (internal container) or external |
ICECAST_HOST_PORT | 8010 | Host port mapped to bundled Icecast |
ICECAST_SOURCE_PASSWORD | — | Source connection password for Icecast (Required in prod) |
ICECAST_ADMIN_PASSWORD | — | Admin web UI password for Icecast (Required in prod) |
ICECAST_RELAY_PASSWORD | — | Relay password for Icecast (Required in prod) |
ICECAST_MAX_CLIENTS | 500 | Maximum concurrent listener connections on Icecast |
ICECAST_MAX_SOURCES | 20 | Maximum concurrent streaming sources |
BRUHI_AUDIO_API_TOKEN | auto-generated | Internal communication token for Rust audio engine |
BRUHI_DB | /app/data/bruhi.db | Path to consolidated SQLite database inside container |
AUDIO_DIR | /app/audio_files | Path to uploaded audio files & recordings |
BRUHI_RP_ID | — | WebAuthn / Passkeys Relying Party ID (hostname only) |
BRUHI_RP_NAME | brūhi Cloud | WebAuthn / Passkeys application display name |
BRUHI_ADMIN_EMAIL | — | Optional initial admin/owner email for pre-seeding |
BRUHI_ADMIN_PASSWORD | — | Optional initial admin/owner password for pre-seeding |
CORS_ORIGINS | '' | Space-separated allowed CORS origins |
Docker Compose Definition (docker-compose.yml)
Section titled “Docker Compose Definition (docker-compose.yml)”The production deployment uses docker-compose.yml:
services: icecast: profiles: ["bundled-icecast"] image: libretime/icecast:2.5.0-alpine container_name: bruhi-icecast ports: - "${ICECAST_HOST_PORT:-8010}:8000" environment: ICECAST_SOURCE_PASSWORD: "${ICECAST_SOURCE_PASSWORD:?Required}" ICECAST_ADMIN_PASSWORD: "${ICECAST_ADMIN_PASSWORD:?Required}" ICECAST_RELAY_PASSWORD: "${ICECAST_RELAY_PASSWORD:?Required}" ICECAST_HOSTNAME: "${ICECAST_HOSTNAME:-localhost}" ICECAST_MAX_CLIENTS: "${ICECAST_MAX_CLIENTS:-500}" ICECAST_MAX_SOURCES: "${ICECAST_MAX_SOURCES:-20}" restart: always
bruhi-cloud: image: "${IMAGE:-ghcr.io/bruhi-technologies/bruhi-cloud:latest}" container_name: bruhi-cloud depends_on: icecast: condition: service_started required: false ports: - "${PORT:-8000}:8000" volumes: - bruhi_audio:/app/audio_files - bruhi_playlists:/tmp/liquidsoap-playlists - bruhi_db:/app/data - bruhi_audio_sockets:/tmp/bruhi-audio environment: PORT: "${PORT:-8000}" LOG_LEVEL: "${LOG_LEVEL:-warning}" BRUHI_ENV: "production" SESSION_COOKIE_SECURE: "true" CORS_ORIGINS: "${CORS_ORIGINS:-}" ICECAST_SOURCE_PASSWORD: "${ICECAST_SOURCE_PASSWORD:-${ICECAST_PASSWORD:-}}" BRUHI_AUDIO_API_TOKEN: "${BRUHI_AUDIO_API_TOKEN:-}" BRUHI_ICECAST_MODE: "${BRUHI_ICECAST_MODE:-bundled}" BRUHI_URL: "${BRUHI_URL}" BRUHI_RP_ID: "${BRUHI_RP_ID}" BRUHI_RP_NAME: "${BRUHI_RP_NAME:-brūhi Cloud}" BRUHI_DB: "/app/data/bruhi.db" AUDIO_DIR: "/app/audio_files" BRUHI_AUDIO_API: "http://localhost:7700" restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/healthz"] interval: 60s timeout: 10s retries: 3
caddy: profiles: ["proxy"] image: caddy:2.8-alpine container_name: bruhi-caddy depends_on: - bruhi-cloud ports: - "80:80" - "443:443" - "443:443/udp" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro - caddy_data:/data - caddy_config:/config environment: DOMAIN: "${DOMAIN:-localhost}" restart: always
volumes: bruhi_audio: bruhi_playlists: bruhi_db: bruhi_audio_sockets: caddy_data: caddy_config:Persistent Volumes
Section titled “Persistent Volumes”| Volume | Mount path | Contents |
|---|---|---|
bruhi_audio | /app/audio_files | Uploaded audio files and broadcast recordings |
bruhi_db | /app/data | Consolidated SQLite database (bruhi.db) |
bruhi_audio_sockets | /tmp/bruhi-audio | Shared Unix IPC sockets between API and audio engine |
caddy_data | /data | TLS certificates provisioned by Caddy |
Auto-HTTPS with Bundled Caddy
Section titled “Auto-HTTPS with Bundled Caddy”brūhi Cloud provides a zero-config reverse proxy setup powered by Caddy. When enabled, Caddy automatically obtains and renews free SSL certificates via Let’s Encrypt.
- Set
COMPOSE_PROFILES=bundled-icecast,proxyin your.envfile. - Set
DOMAIN=radio.yourdomain.comin your.envfile. - Ensure DNS
A/AAAArecords forradio.yourdomain.compoint to your server’s public IP. - Run
docker compose up -d.
Nginx Reverse Proxy (Alternative)
Section titled “Nginx Reverse Proxy (Alternative)”If you operate an existing external Nginx proxy:
server { listen 443 ssl; server_name radio.yourdomain.com;
ssl_certificate /etc/ssl/bruhi.crt; ssl_certificate_key /etc/ssl/bruhi.key;
location / { proxy_pass http://localhost:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; }}The Upgrade and Connection headers are required for WebSockets (used for WebRTC signaling, playout clock sync, and real-time station telemetry).
Production Checklist
Section titled “Production Checklist”Before exposing brūhi Cloud to the internet:
- Enable HTTPS via bundled Caddy (
COMPOSE_PROFILES=bundled-icecast,proxy) or external reverse proxy - Set
BRUHI_RP_ID(domain name) andBRUHI_URL(https://...) - Set strong secrets for
ICECAST_SOURCE_PASSWORDandICECAST_ADMIN_PASSWORD - Configure firewall rules: allow ports 80, 443 (HTTPS), 8010 (Icecast), 8100+ (harbors)
- Schedule regular volume backups for
bruhi_dbandbruhi_audio - Review the Operations & Maintenance Guide for update and backup procedures
Updating & Operations
Section titled “Updating & Operations”For day-to-day operations, updates, password resets, and maintenance CLI commands, see the dedicated Operations & Maintenance Guide.
Verified Platforms
Section titled “Verified Platforms”| Provider | Service | Status |
|---|---|---|
| AWS | EC2, Lightsail, ECS, EKS | ✅ Verified |
| Google Cloud | Compute Engine, GKE | ✅ Verified |
| DigitalOcean | Droplets, Kubernetes | ✅ Verified |
| Hetzner | Cloud, Dedicated | ✅ Community tested |
| Linode / Akamai | Compute Instances | ✅ Verified |