Appearance
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 tohttps://. - 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 itA 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 = trueWith 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?
| Situation | Pick |
|---|---|
| One server, you want the simplest setup | Quikcast [tls] |
| You already run a proxy for other sites | Reverse proxy, with trusted_proxies.ips |
| Behind Cloudflare | Cloudflare provider |
| A TCP load balancer or cloud NLB | proxy_protocol = true |
| Docker with Traefik or Dokploy | Let it terminate TLS, list its network under trusted_proxies |