Skip to main content

How to use Let's Encrypt certificates with Keycloak

Let's Encrypt + Keycloak

Keycloak provides user federation, strong authentication, user management, fine-grained authorization, and more.

Here is a guide to enable HTTPS access to your Keycloak server using a free Let's Encrypt SSL certificate. The beauty of Let's Encrypt is its ease of use and the fact that it's free!

This guide assumes you have already installed Keycloak at /opt/keycloak/ using the official guide for bare metal installs, and now you want to enable HTTPS access. You need to have version 20 or higher.

In all the instructions below, be sure to replace <DOMAIN> with the actual domain you will be using. All commands in this guide must be run as root.

1. Install certbot

First you will need to install certbot. This depends on the Linux distro you are using.

For example, for apt-based distros such as Debian or Ubuntu, you can just run the following:

apt install certbot

2. Create HTTPS certificates

  • Set up certificates:
$ certbot certonly --standalone --preferred-challenges http -d <DOMAIN>

3. Configure Keycloak to use Let's Encrypt certificates

  • Change configuration:
vi /opt/keycloak/conf/keycloak.conf
  • Add or update the following lines in that file:

  • Update keycloak config:
$ /opt/keycloak/bin/ build
  • You're done! Now you can run the following command and Keycloak should now be accessible from the browser via HTTPS:
$ /opt/keycloak/bin/ start

4. Optional: Set up Keycloak as a systemd service

The official guide purposely leaves this open-ended because there are many ways in which you might want to handle the lifecycle of the Keycloak server. However, I think a good approach is to just use systemd.

4.1. Set up systemd service

  • Create user and group:
$ useradd -g keycloak keycloak
  • Give access to certificates:
$ chmod 0755 /etc/letsencrypt/{live,archive}
$ chgrp keycloak /etc/letsencrypt/{live,archive}
$ chgrp -h keycloak /etc/letsencrypt/live/<DOMAIN>/privkey.pem
  • Give access to Keycloak directory:
$ chown -R keycloak:keycloak /opt/keycloak/
  • Create systemd service:
$ vi /etc/systemd/system/keycloak.service
  • Write the following contents into the file. You might need to add your chosen database service to the After line, for example postgresql.service or mysql.service.
Description=Keycloak Application Server

ExecStart=/opt/keycloak/bin/ start --optimized

  • Reload systemd config and start service:
$ systemctl daemon-reload
$ systemctl start keycloak.service

4.2. Automatic Keycloak server restart when certificates are updated

  • Make certbot restart Keycloak after updating certificates:
$ cd /etc/letsencrypt/renewal-hooks/deploy
$ vi
  • Write these contents:
systemctl restart keycloak
  • Make the script executable:
$ chmod +x

You're done! Now Keycloak is set up as a systemd service and will start when your machine boots up.

Free Static Web Hosts for Frontend Developers


Nowadays it's very easy to publish on the web for free.

There are countless blogging platforms and website creators. But these platforms usually end up controlling your content. Sometimes you cannot even export your own data!

The other extreme is to set up your own server by yourself. Buy a VPS (virtual private server) or a shared hosting somewhere, install a web server, and upload your files. This is a lot of work already! Specially if all you want is to publish a static website.

You already know HTML and CSS, and maybe a bit of JavaScript. You just want a place where you can drop your files and see it on the web!

Here is a list of services that allow you to do that, in no specific order:


Netlify allows you to drag & drop a zip with your files. You can also connect it to your project from Github, Gitlab or Bitbucket. I use Netlify for a lot of my projects, such as


Vercel is very similar to Netlify. They are also the company behing Next.js, so they have many integrations with it. I use Vercel for my personal website and for


Surge allows you to easily publish your static website from the command line.

Github Pages

Github Pages allows you to directly from your GitHub repository. Just edit, push, and your changes are live. This blog itself is hosted on Github Pages.

GitLab Pages

GitLab Pages allows you to publish static websites directly from a repository in GitLab.

Closing Words

With these services, you can host your own static website for free. If having your own domain is important, then you will have to buy one, but that's the only thing you need, as many of these services allow you to use your own custom domain as well.

I recommend you familiarize yourself with the options and not to put all your eggs in one basket. The beauty of static website is that something happens to the provider, you can just copy your files to another one, and you're done! Keep it simple.

Publishing an App on F-Droid


I made some small apps for Android and I wanted to distribute them. I also care a lot about software freedom, so F-Droid is the best place for me to publish my apps.

Disclaimer! You are not able to sell your app on F-Droid. If you want to make money with it, you would need to allow users to pay through another method. Please see this StackExchange question if you're interested in monetization.

What's F-Droid?

F-Droid is an alternative for the Play Store and other Android stores focused on software freedom and privacy.

The biggest difference is that F-Droid only allows Free and Open Source (FOSS) software. F-Droid also respects your privacy and discourages application which do not.

In an age where privacy and software freedom matters most, F-Droid is the perfect replacement for other Android stores.

Why publish on F-Droid?

F-Droid is a great way of distributing your FOSS Android application. It makes it very easy for your users to install your app and keep it up to date, without requiring them to side-load it.

There is also a higher level of trust since every apk published on F-Droid is built from source.

How to submit your app to F-Droid

I've broken this down into two big steps:

  • Preparing your app
  • Submitting it to F-Droid

Preparing your app's repo

F-Droid needs some metadata about your app so it can show something to the users. For example: app name, description, screenshots, and the changelog.

Makes sure you have good screenshots and good explanatory texts about your app. This makes people more interested in it, and speeds up the review process.

The best way to get this metadata to F-Droid is to put it in your app's repo. You only need to create a few files, following either of these methods. I recommend Fastlane.

Submitting your app's build metadata to F-Droid

Getting your app on F-Droid is as easy as sending them a merge request to their data repo.

To summarize, you need to:

  1. Fork the repo on GitLab
  2. Create a new branch for your changes
  3. Create a metadata .yml file for your app. You should name it using your app's id, for example: com.kaeruct.raumballer.yml. There are some templates here.
  4. Submit the merge request to F-Droid's data repo.
  5. Wait for the automated build to finish.
  6. Fix any errors in the build or feedback to your merge request.

There are details instructions in the repo's file.

I highly recommend you also set up auto updates. This allows F-Droid to automatically know when you have released a new version. It will then update your app's metadata .yml file automatically and publish the new version of your app on the store.

My experience

Each of the apps I submitted were approved around 2 or 3 weeks, but this may vary depending on the complexity of your app. The contributors are very friendly and always give you helpful feedback to get your app on F-Droid as soon as possible.

Here is one of my app's metadata file on the F-Droid data repo and the source code on GitHub.

Closing words

F-Droid is a very valuable resource for people who care about software freedom and privacy. It is also run by volunteers. Please donate if you are able to!

My top tips for junior developers

Last year, I was tasked with mentoring an intern. It wasn't my first time mentoring, but it was my first time being fully in charge of a new employee. In the end, the intern was hired as a full-time employee, and I thought it would be helpful to compile all the advice I've been giving them, for future reference.

The following tips come from my experience and my way of working, as well as my own personal opinions.

Tip 1: Learn how to search effectively

Knowing what to search and how to search is an essential skill. Usually, I don't remember or know most of the things my colleagues ask me. Yet, after 5 minutes I can usually figure it out or at least point them in the right direction. All thanks to the power of search.

How to search

As with most things in life, Google will probably have an answer for you. Make sure to type it in a way that makes sense for Google. For example, if you have an error, copy-paste it word-for-word and put it inside double (") quotes. This might take you to Github issues, Stack Overflow answers, or blogs like this one!

If you don't find anything, try different variations of your search. You can try removing specifics (line numbers are often useless, and also data values). For example, if you get an error like this:

TypeError [ERR_INVALID_ARG_TYPE]: The "msecs" argument must be of type number. Received type string
    at validateNumber (internal/validators.js:130:11)
    at validateTimerDuration (internal/timers.js:146:3)
    at ClientRequest.setTimeout (_http_client.js:735:11)

You could be searching the following instead:

TypeError [ERR_INVALID_ARG_TYPE]: The "msecs" argument must be of type number. Received type string

If that's still too long, you can try only

The "msecs" argument must be of type number

If you still can't find anything useful, take advantage of your company's resources. Try the same search on your company's internal systems. Try everything: Slack, bug tracker (e.g.: JIRA), wiki, emails, Google Docs. If you still don't find anything, try reaching out to your more senior colleagues. They will surely know how to help or at least point you in the right direction.

How to navigate codebases

Sometimes your search will guide you to the source code that is throwing the error you were searching for. This is a bit sad since it means probably no one has found a solution yet for the problem you're having. In these cases you will need to read the code you found and try to understand it.

I think the best way to understand code is to see the flow of the data in the code. For example, let's say you have an app that let's you search movies by actor name.

I would first try to understand where the movie data is coming from. An external API? A database? A file?

Then I would see what happens when I type "Nicolas Cage" into the search box and click "Search". Does the app do an external network request? Is the data already available locally? If I search "Search" in the source code, will I be able to find the code for the button that triggers the search?

I would keep asking myself questions and answering them, until I have a better understanding of where the data is going to and coming from.

How to deal with Github issues

You might get lucky and find someone that had the same issue and opened a Github issue for it. If you're even luckier, someone else (or the original reporter) might have found a solution and shared it there. Then, the repository's maintainers may have merged the solution. Or maybe not yet.

If you don't want to wait for the repository's maintainers to merge the fix, there's always the option of forking the repository and merging the fix yourself. This is usually not a good idea unless you need this fix very urgently, since your fork will quickly become outdated. It's up to you and/or your team to decide if this is worth the risks.

Tip 2: Don't copy-paste code without understanding it

I have noticed way too many junior developers copy & paste code without understanding what it's doing. I've been guilty of this as well but I don't remember it, maybe because I rely on copy-pasting so much!

The problem with this: it can cause unintended consequences. If the copy-pasted code breaks you will not know how to fix it since you didn't understand it in the first place. This means sooner or later you will have to come back to this code and understand it.

If you are doing unit testing (which you should), you will need to understand the code first, to be able to write tests for it. You will need to identify every execution path it might take and think about the inputs that might break it.

One thing that has worked for me is to avoid copy-pasting the code and try to write it on my own. Grok what the code is doing and writing it using variable/function/class names that match your project and business logic. Once you have done this you might understand it a bit better.

Tip 3: Know your tools

With tools, I mean everything that helps you get your work done. A few examples:

Shell, text editor, IDE, compiler, package manager, version control, CI/CD (continuous integration/continuous delivery).

Notice I am using the generic terms and not the specific tools you or your company might be using. Why is that? Because you should be able to pick up tools and work with them.

To have a good productivity, you need to become familiar with the tools used by your colleagues, so make sure to ask around for recommendations.

In some cases you will need to use tools that you don't necessarily enjoy using, and that's okay. Tools are a means to an end. Tools should help you build your final product. They should not be your main focus - unless you work for a software company that builds software development tools.

Here are some of my favorite tools at the moment:

  • Bash
  • Visual Studio Code
  • IntelliJ IDEA
  • yarn
  • Git
  • Gitlab CI

Why are they my favorite tools? Because I'm used to them. Only looking at them, many developers will know I am primarily a frontend developer. There's always going to be something better and everyone has different preferences. But it doesn't matter, as long as the tools help you get the job done. Still, always be open to new tools and ask other people why they chose theirs. They might change your mind and you will become even more productive! A good way to quickly get to know a tool is to do a search like this: "<tool> tips and tricks".

Know your programming language(s)

It's also very important to know all the fundamental concepts of the programming language(s) you are using at work. Again, make sure to ask your more experienced colleagues for recommendations. There are tons of books, online courses, and tutorials for every mainstream programming language out there.

You need to be fluent in your language. This will allow you to focus on solving the business problems instead of fighting against the language to make the code work. You don't have to be an expert immediately, it will take time. But make sure to keep learning and aim to become an expert in the language within the first two years of your career.

Tip 4: Know how and when to ask for help

When you are new, you will have a lot of questions, and that's okay. Asking questions is how we learn.

Ask yourself first

Before you ask the question to someone else, ask it to yourself. Then try to come up with a few guesses and try to validate them. This will lead to more and more questions.

This helps you understand what you really need to know to solve the problem, and when you go to someone else you will have a much better question to ask. Good questions breed good answers.

For example, let's say you have to change the href of a link in the footer of your company's website. I would ask myself: "where is the code for this link?"

Then I would come up with a few hypotheses:

  • I can find it if I search for the current href on the codebase.
  • If I change it here and deploy the code, the link will change.

After that, I would try to prove my first hypothesis by searching for the current href. Let's say I could not find it in the code. Then I would come up with a different hypothesis:

  • It is not in the code, so the content must come from somewhere else.

Then I would ask myself more questions:

  • Where is the content for the footer stored?
  • How can I change it?

Once I have these questions, I can go to a more experienced colleague, and they will be able to quickly point me in the right direction: "Oh, that content is stored in our content management system. I will show you how to change it".

If I had asked them my first question instead: "where is the code for this link", they would have given me a very simple answer that would take me straight to the code and that would have not been as helpful.

Fighting forgetfulness

I am very forgetful, so I like to keep notes. Whenever I find the answer to a an important question, I make sure to write it down somewhere. This has several benefits:

  • You don't need to remember everything.
  • You can share your notes with others (this is usually called documentation).
  • You can easily keep track of how much you have learned over time.

You can keep your notes on paper or digitally. Make sure to try both and see what works best for you.

Tip 5: Maintain a healthy work-life balance

When you're starting out you always want to keep learning more and more while also delivering your work. This means you will probably work many hours a day if you're very passionate. This is fine if you are enjoying yourself, but you should be careful and aware of burn out. A good way to avoid this is to have a routine you follow every work day, and make sure you have enough breaks throughout the day. In the end it all comes down to a matter of discipline and knowing yourself.

Remember life is about living, not about working! It's a good idea to have other things outside going on in your life aside from work. There's no right or wrong here because it depends on you, but make sure you manage your stress in a healthy way.

Starry Sky in HTML5 Canvas - Part 2

This is part of a series! Please make sure you have read Part 1 first!

IMPORTANT -- you can try out the result of this tutorial by visiting this CodeSandbox. However, I encourage you to read the blog post and try to follow along to understand how and why it works.

Last time we left off with a very nice starry sky, but it's a bit dead. We need to add some animation to it! The way animation is done on HTML5 canvas is by drawing something else every frame.

For our case, we can use the requestAnimationFrame() function to call our render() function.

First, we will add a counter variable. We will increment this every time we draw. This is useful because we will have a number that will change with every render.

let counter = 0;

Then, we will update our render() function so it uses requestAnimationFrame(). We will also make it increment the counter.

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star) {
    const x = star.x;
    const y = star.y;
    const r = star.r;
    fillCircle(ctx, x, y, r, "rgb(255, 255, 255)");

For now, this will look exactly the same as before, because we always render the same thing. But let's begin to change that now.

We'll make a small change to make the stars look like they're flickering.

First, let's add a function to generate an opacity value. This value will go from 0 to 1 and will determine the opacity of our star.

The use of Math.sin() in the function below is just to make sure we get a value that changes smoothly.

const minStarOpacity = 0.1;
const maxStarOpacity = 0.7;

function getOpacity(factor) {
  const opacityIncrement =
    (maxStarOpacity - minStarOpacity) * Math.abs(Math.sin(factor));
  const opacity = minStarOpacity + opacityIncrement;
  return opacity;

Then, we will use this function when rendering our stars. Also notice how we change the color from rgb(255, 255, 255) to rgba(255, 255, 255, opacity).

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star, i) {
    // factor will be a different number for every star
    const factor = counter * i; 
    const x = star.x;
    const y = star.y;
    const opacity = getOpacity(factor);
    fillCircle(ctx, x, y, star.r, `rgba(255, 255, 255, ${opacity}`);

Animated Starry Sky

Now the sky is looking really nice and animated. But it's still missing a nice big moon. Let's add it next.

We will create a function to render our moon, and call it from render().

const moon = {
  color: "#fea",
  x: height / 3,
  y: width / 3,
  r: 40

function renderMoon(ctx, blur) {
  fillCircle(ctx, moon.x, moon.y, moon.r, moon.color);
  // render a smaller circle above the moon to give it that well-known moon-shape
    moon.x - moon.r / 3,
    moon.y - moon.r / 3,

And our updated render() function:

function render() {
  ctx.fillStyle = backgroundColor;
  ctx.fillRect(0, 0, width, height);
  stars.forEach(function(star, i) {
    const factor = counter * i;
    const x = star.x;
    const y = star.y;
    const opacity = getOpacity(factor);
    fillCircle(ctx, x, y, star.r, `rgba(255, 255, 255, ${opacity}`);



That leaves us with the finished product: Animated Starry Sky with Moon

Thanks for following this tutorial to the end! Remember you can look at a working example in the CodeSandbox.

Have fun experimenting and tweaking the values used to render the stars and the moon. Some ideas you may want to try to learn more and improve your skills:

  • Make the stars more colorful.
  • Make the moon move across the sky.
  • Add shooting stars.
  • Add a gradient background instead of a solid color.
  • Add multiple moons.

Don't hesitate to contact me at @KaeruCT if you have any questions, suggestions, or improvements for this tutorial!