• Civo Cloud k3s: Traefik v2 and Let's Encrypt

    Traefik Dashboard on Civo k3s with SSL

    I’ve continued to play around with the K3S Beta cluster from Civo Cloud (you can request to join the beta), the aim was to also try out the new Traefik V2 which was released some time ago.

    In this post we will:

    • Update the default traefik install on k3s to v2.0.1
    • Secure the k3s install
    • Create and secure the ingress to the traefik dashboard
    • Enable Let's Encrypt certs for traefik
    • Some thoughts after the journey

    Let’s start.

    Read on →

  • Civo Cloud k3s: Enable Traefik Dashboard

    In this post I wanted to showcase how you can get the traefik dashboard enabled on the default civo cloud kubernetes k3s cluster. (It’s currently in beta, you can request access here). I must add, I’ve only played around with this for around an hour, I’m sure there are better ways (I don’t have that much experience with helm, I couldn’t edit the deployed version.)

    The k3s cluster has been setup following the civo kubernetes guide.

    The default helm chart has the dashboard disabled by default. The default options can be seen on the helm chart github page. The toml file is stored as a configmap, we can just simply overwrite it:

    Read on →

  • Airapi Tunein From Golang

    Just a small snipet on how to send data to TuneIn’s AirAPI from golang. This way you can update your metadata information directly from your API, if you wish.

    import (
    func tuneinAPI(artist string, title string) {
    	partnerid := os.Getenv("TUNEIN_PARTNER_ID")
    	partnerkey := os.Getenv("TUNEIN_PARTNER_KEY")
    	stationid := os.Getenv("TUNEIN_STATION_ID")
    	if partnerid == "" || partnerkey == "" || stationid == "" {
    		fmt.Println(time.Now(), "No tunein creds, skipping.")
    	var URL *url.URL
    	URL, err := url.Parse("http://air.radiotime.com/Playing.ashx?")
    	if err != nil {
    		fmt.Println(time.Now(), "Tunein URL unavailable")
    	parameters := url.Values{}
    	parameters.Add("partnerId", partnerid)
    	parameters.Add("partnerKey", partnerkey)
    	parameters.Add("id", stationid)
    	parameters.Add("artist", artist)
    	parameters.Add("title", title)
    	URL.RawQuery = parameters.Encode()
    	fmt.Printf("Encoded URL is %q\n", URL.String())
    	res, err := http.Get(URL.String())
    	if err != nil {
    	if res.StatusCode == 200 {
    		fmt.Println(time.Now(), "TuneIn: "+artist+" - "+title)
    	} else {
    		fmt.Println(time.Now(), "Tunein submission failed.")

    Make sure you export the TUNEIN environment variables. This code is currently used over at XTRadio

  • Stream Icecast Stream To Youtube

    At XTRadio we thought of taking our stream to a new platform (or even more), the first obvious choice was Youtube Live. Facebook Live could be another option but it only allows 4 continous hours of stream, so it wouldn’t allow us to stream our 24/7 broadcast.

    Youtube Live has been easy enough to setup, we’ve used ffmpeg on a Debian server, it takes an image and our stream, puts them together and it pushes to Youtube. Easy peasy, eh? One thing to keep in ming: make the image HD, then the stream will be HD as well, of course use the best stream you have. Here’s our way of running things:

    avconv -loop 1 -i /MUSIC/xt-hd.png -i http://localhost:8080/mp3 -r 30 -acodec aac -strict -2 -c:v libx264 -strict experimental -b:a 128k -pix_fmt yuvj444p -b:v 256k -minrate 128k -maxrate 512k -bufsize 768k -f flv rtmp://a.rtmp.youtube.com/live2/[KEY]

    (code is still WIP)

    You can listen to the XTRadio Youtube Live Stream if you please, the next step is to bake this in to Liquidsoap and have the image display the song information as well, eventually have some sort of live equalizer. And run all of this dockerized, but that’s another post.

  • Oh Hello Jekyll

    It would be about time to get some portions of my blog back online, there are also some docker and radio related stuff I want to post.

    A little about Jekyll? It’s not a CMS as it doesn’t have a DB in the background, it is all file based. The posts are in a directory called “_posts”, css, js files are all static. Jekyll’s magic starts when you want to generate static html files from all, combined. Jekyll takes care of putting it all together, it sounds all hectic, but this serves the purpose better. You can save your posts to some public git, so it is source controlled, if your site gets “hacked”, regenerate it and your’re good to go, no wordpress, so no stupid holes and bugs. Clean, fast and straightforward. You can read more about Jekyll.

    I’ll write a “How To” soon on how this blog was setup with docker + gitlab/github public pages.

    ‘till then, woot woot, hello Blog again! (and hosted on github pages!)