Soundscape - a personal music streaming server
Switch branches/tags
Nothing to show
Clone or download

Soundscape - a personal music streaming server


Screenshot - Playlists Screenshot - Library Screenshot - Import


  • Import from YouTube
    • Save any YouTube video as a song in your library
  • Keep your entire music collection in the cloud
    • Store thousands of songs on your private server
  • Listen to your music anywhere
    • Stream from any desktop or mobile device
  • Create custom playlists
    • Add your music to multiple playlists
  • Share your playlists
    • Let your friends listen to any playlist using the private URL

Help / Reporting Bugs


Run Soundscape on a VPS

Running Soundscape on a VPS is designed to be as simple as possible.

  • Public Docker image
  • Single static Go binary with assets bundled
  • Automatic TLS using Let's Encrypt
  • Redirects http to https
  • Works with a reverse proxy or standalone

1. Get a server

Recommended Specs

  • Type: VPS or dedicated
  • Distribution: Ubuntu 16.04 (Xenial)
  • Memory: 512MB
  • Storage: 5GB+

Recommended Providers

2. Add a DNS record

Create a DNS A record in your domain pointing to your server's IP address.

Example: A

3. Enabling Let's Encrypt (optional)

When enabled with the --letsencrypt flag, soundscape runs a TLS ("SSL") https server on port 443. It also runs a standard web server on port 80 to redirect clients to the secure server.


  • Your server must have a publicly resolvable DNS record.
  • Your server must be reachable over the internet on ports 80 and 443.

4. Run the static binary

Replace amd64 with arm64 or armv7 depending on your architecture.

# Install ffmpeg.
$ sudo apt-get update
$ sudo apt-get install -y wget ffmpeg

# Download the soundscape binary.
$ sudo wget -O /usr/bin/soundscape

# Make it executable.
$ sudo chmod +x /usr/bin/soundscape

# Allow it to bind to privileged ports 80 and 443 as non-root (this is also a potential risk).
$ sudo setcap cap_net_bind_service=+ep /usr/bin/soundscape

# Create your soundscape directory.
$ mkdir $HOME/Music

# (optional) Set a password (or one will be generated and printed in the log)
$ echo "mypassword" >$HOME/Music/.authsecret

# Run with Let's Encrypt enabled for automatic TLS setup (your server must be internet accessible).
$ soundscape --http-host --http-username $USER --data-dir $HOME/Music --letsencrypt
1.503869865804371e+09    info    Soundscape URL:
1.503869865804527e+09    info    Login credentials:  <username>  /  <password>

Run behind an nginx reverse proxy

Configure nginx

1. Basic auth with htpasswd

# Create the htpassword file, setting a password.
$ sudo htpasswd -c /etc/nginx/soundscape.htpasswd <username>
New password: 
Re-type new password: 
Adding password for user <username>

# Verify that you've created your htpasswd file correctly.
$ sudo cat /etc/nginx/soundscape.htpasswd

2. Reverse proxying with authentication

Run soundscape on localhost port 8000 with reverse proxy authentication, using Docker or not.

Note: You must specify --reverse-proxy-ip to disable basic auth and enable X-Authenticated-User header auth.

$ soundscape --http-addr --http-host --reverse-proxy-ip

You might edit /etc/nginx/sites-enabled/default or wherever your nginx config lives.

server {
    listen 80;

    # Using TLS (recommended)
    # listen 443;
    # ssl_certificate;
    # ssl_certificate_key;

    # Redirect requests for "/" to "/soundscape/" (or use "location / {}" below)
    # rewrite ^/$ /soundscape/ permanent;

    location /soundscape/ {
        auth_basic "Soundscape";
        auth_basic_user_file /etc/nginx/soundscape.htpasswd;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Forwards username to Soundscape backend (required for auth)
        proxy_set_header X-Authenticated-User $remote_user;

        proxy_pass http://localhost:8000;

Run the Docker Image

Probably the easiest way to run Soundscape is using the Docker image.

1. Install Docker

# Update apt
$ sudo apt-get update

# Remove old docker install.
$ sudo apt-get remove docker docker-engine

# Ensure we have basics for apt-get.
$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \

# Add Docker's public key.
$ curl -fsSL | sudo apt-key add -

# Add Docker's apt repo
$ sudo add-apt-repository \
    "deb [arch=amd64] \
    $(lsb_release -cs) \

# Update apt
$ sudo apt-get update

# Install Docker
$ sudo apt-get install docker-ce

# Run the hello-world test image
$ sudo docker run hello-world

2. Run the Docker image

The official image is soundscapecloud/soundscape, which should run in any up-to-date Docker environment.

# Your download directory should be bind-mounted as `/data`
# inside the container using the `--volume` flag (see below).
$ mkdir $HOME/Music

# Set a password (default: a password is generated and printed in the log output)
$ echo "mypassword" >$HOME/Music/.authsecret

# Create the container.
$ sudo docker create \
    --name soundscape \
    --init \
    --restart always \
    --publish 80:80 \
    --publish 443:443 \
    --volume $HOME/Music:/data \
    soundscapecloud/soundscape:latest --http-host --http-username $USER --letsencrypt

# Run the container
$ sudo docker start soundscape

# View logs for the container
$ sudo docker logs -f soundscape
1.503869865804371e+09    info    Soundscape URL:
1.503869865804527e+09    info    Login credentials:  <username> /  <password>

3. Updating the container image

Pull the latest image, remove the container, and re-create the container as explained above.

# Pull the latest image
$ sudo docker pull soundscapecloud/soundscape

# Stop the container
$ sudo docker stop soundscape

# Remove the container (data is stored on the mounted volume)
$ sudo docker rm soundscape

# Re-create and start the container
$ sudo docker create ... (see above)


$ soundscape --help
Usage of soundscape:
  -backlink string
        backlink (optional)
  -data-dir string
        data directory (default "/data")
        debug mode
  -http-addr string
        listen address (default ":80")
  -http-host string
        HTTP host
  -http-prefix string
        HTTP URL prefix (not actually supported yet!) (default "/soundscape")
  -http-username string
        HTTP basic auth username (default "soundscape")
        enable TLS using Let's Encrypt
  -reverse-proxy-header string
        reverse proxy auth header (default "X-Authenticated-User")
  -reverse-proxy-ip string
        reverse proxy auth IP


The easiest way to build the static binary is using the file.

# Clone the git repo
$ git clone

$ cd soundscape/

# Compile the code and create a Docker image for it.
$ sudo docker build --build-arg BUILD_VERSION=$(git rev-parse --short HEAD) -t soundscape:build -f .

# Create a container based on the image we just built.
$ sudo docker create --name soundscapebuild soundscape:build

# Extract the binary from the image.
$ sudo docker cp soundscapebuild:/usr/bin/soundscape-linux-amd64 soundscape-linux-amd64

# armv7
# $ sudo docker cp soundscapebuild:/usr/bin/soundscape-linux-amd64 soundscape-linux-armv7

# arm64
# $ sudo docker cp soundscapebuild:/usr/bin/soundscape-linux-amd64 soundscape-linux-arm64

# We're done with the build container.
$ sudo docker rm soundscapebuild

# Inspect the binary.
$ file soundscape-linux-amd64
soundscape-linux-amd64: ELF 64-bit LSB  executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=c5a6f3a2e15c8ca511bec52c357ebf8f4g542233, stripped

# Run the binary.
$ ./soundscape-linux-amd64 --help

# Build a tiny alpine "runner" image.
# $ sudo docker build -t soundscape:latest .