Skip to content

HTTPS and proxies ​

Most listeners and encoders should reach your station over HTTPS. You have two good options: let Quikcast serve HTTPS itself, or put a reverse proxy in front. This page covers both, and how to keep listener addresses accurate when a proxy is involved.

Option A: HTTPS directly from Quikcast ​

Point Quikcast at a certificate and key in PEM format. A Let's Encrypt fullchain.pem and privkey.pem are exactly right.

toml
listen = "0.0.0.0:443"

[tls]
cert_file = "secrets/tls/fullchain.pem"
key_file = "secrets/tls/privkey.pem"
  • The admin address stays plain HTTP on localhost. Only the public listener uses TLS.
  • A plain http:// request to the TLS port is closed without an answer. There is no automatic redirect, so send people to https://.
  • Encoders must connect with TLS too. BUTT and Liquidsoap have an HTTPS/TLS option for Icecast servers.
  • To bind port 443 without running as root on Linux, either use a higher port behind a firewall rule, or grant the binary the capability: setcap 'cap_net_bind_service=+ep' /usr/local/bin/quikcast.

Renewing certificates ​

Replace the files, then ask Quikcast to reload:

sh
kill -HUP "$(pidof quikcast)"

New connections use the new certificate straight away and existing listeners are not interrupted. If a file is missing or the key does not match, the reload is refused and the old certificate stays active. Certbot users can add the kill -HUP line as a deploy hook.

Turning TLS on or off needs a restart

Only the certificate files reload. Enabling or disabling [tls] changes what the port speaks, so restart for that.

Option B: A reverse proxy in front ​

If you already run nginx, Caddy, Traefik or a cloud load balancer, let it handle certificates and forward plain HTTP to Quikcast on localhost.

toml
listen = "127.0.0.1:8000"   # only the proxy can reach it

A live audio stream is a very long download, so a proxy must not buffer it and must allow long timeouts.

nginx ​

nginx
location /radio.mp3 {
    proxy_pass http://127.0.0.1:8000;
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header Connection "";
    proxy_set_header X-Forwarded-For $remote_addr;

    proxy_buffering off;
    proxy_cache off;
    proxy_request_buffering off;
    proxy_read_timeout 1h;
    proxy_send_timeout 1h;
    client_max_body_size 0;      # encoders upload forever
}

Expose only the paths you need: your mounts, /hls/ if you use HLS, and /api/metadata only if your encoder sends titles that way. Never forward /api (except that one path), /internal, /health or /metrics to the internet; they are served by the private admin address anyway.

Encoders and proxies ​

Some encoders use the older Icecast SOURCE request instead of standard HTTP PUT. A plain HTTP proxy may not pass that through. If a particular encoder fails only through the proxy, connect it directly to Quikcast, use a TCP (layer 4) proxy, or switch the encoder to its HTTP PUT mode.

Real listener addresses ​

Rules like country and IP restrictions, statistics and logs all depend on the listener's address. Behind a proxy, Quikcast would see the proxy's address for everyone unless you tell it which proxies to believe.

With an HTTP proxy: X-Forwarded-For ​

List the proxies you control. Quikcast then reads the X-Forwarded-For header, but only from those addresses:

toml
[trusted_proxies]
ips = ["127.0.0.1", "10.0.0.0/8"]

Anyone else sending that header is ignored. Quikcast reads the header from right to left and stops at the first address that is not trusted, so a visitor cannot invent their own address. Configure your proxy to replace an incoming X-Forwarded-For or append to it.

Behind Cloudflare ​

toml
[trusted_proxies]
providers = ["cloudflare"]

Quikcast has Cloudflare's published address ranges built in. A connection that really comes from Cloudflare may then supply the visitor's address in CF-Connecting-IP. The ranges are refreshed by upgrading Quikcast.

With a TCP load balancer: PROXY protocol ​

Layer-4 balancers (HAProxy in TCP mode, nginx stream, cloud network load balancers) cannot add HTTP headers, but they can send the PROXY protocol header, which carries the real address:

toml
[trusted_proxies]
ips = ["10.0.0.0/8"]       # the balancer
proxy_protocol = true

With this on, every public connection must begin with a PROXY v1 or v2 header, and only the listed addresses may send one. Connections from anywhere else are closed. That includes your own health checks and quick curl tests, which must now go through the balancer.

Only trust what you control

Everything you list under trusted_proxies can claim any listener address. Listing a network you do not control lets strangers dodge your IP and country rules.

Which option should I pick? ​

SituationPick
One server, you want the simplest setupQuikcast [tls]
You already run a proxy for other sitesReverse proxy, with trusted_proxies.ips
Behind CloudflareCloudflare provider
A TCP load balancer or cloud NLBproxy_protocol = true
Docker with Traefik or DokployLet it terminate TLS, list its network under trusted_proxies

Documentation for Quikcast.