Post

Automate Gitlab certs with Let's Encrypt and acme.sh

I have been using Let’s Encrypt to create certs for my internal services, including my self-hosted gitlab server, for quite a while. I had been using an ansible playbook by Bendews to create Lets Encrypt certificates with a DNS challenge with my Cloudflare account. This was done with an automated ansible process that renewed the certificate every couple of months. Recently, I have been running into issues with the DNS challenge verification and was looking for a different approach that took even less time and maintenance. Enter Acme.sh. This has shown to offer an automated bash script that would handle the initial lets encrypt challenge as well as automated renewals via a DNS challenge without intervention. This is exactly what I was looking for.

I use Ansible to install my core homelab services. I wanted to see if someone has already made an Ansible role for acme.sh in order to integrate the tool into my services. Most of the times in tech, someone has already done what you are trying to do. Why reinvent the wheel when it already exists? The acme role by noobient fit the bill.

Modify Gitlab Ansible playbook to use noobient’s acme.sh script

Adding the new playbook was quite easy. This is my main install-gitlab.yml I use Geerlingguy’s gitlab role to install gitlab-ce on ubuntu 22.04. This role has been deprecated but still fits my needs so I will continue maintaining it for myself.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- hosts: gitlab.schenk.tech
  become: yes
  remote_user: ansible
  become_user: root
  vars_files:
    - vault.yml
    - vars.yml
  tasks:
    - name: Create GitLab SSL configuration folder.
      file:
        path: /etc/gitlab/ssl
        state: directory
        owner: root
        group: root
        mode: 0700
  roles:
    - role: geerlingguy.gitlab

The relevant config to add the new role is:

1
2
3
4
5
6
7
8
9
10
11
12
13
roles:
  - role: noobient.acme
    vars:
      domain: gitlab.schenk.tech
      acme_deploy_dir: "/etc/gitlab/ssl"
      provider: cf
      credential:
        CF_Key: ""
        CF_Email: "my_cloudflare@email.domain"
      cronjob: true
      sleep: 60
      min_days: 45
      reload_cmd: gitlab-ctl restart

This configuration:

  1. Passes in my cloudflare credentials for the DNS challenge
  2. Configure the deployment directory to be the usual /etc/gitlab/ssl path
  3. Enable the cron job to automate certificate renewals
  4. Reload command to restart gitlab after the certificate renewal

The ansible playbook will install the acme.sh script and enable a cron job in /etc/cron.d/ that will renew the certificate every 45 days (based on the min_days variable):

1
2
3
4
# Minutes are pseudo-random, to ensure idempotency, but still don't flood ACME with all certs at once.
08 07 1 * * root /opt/acme.sh/acme.sh --server letsencrypt --ecc --renew --dns dns_cf --dnssleep 60 --force --domain gitlab.schenk.tech >> /var/log/letsencrypt 2>&1

08 08 1 * * root gitlab-ctl restart

Re-running my ansible playbook for gitlab installs:

1
ansible-playbook install-gitlab.yml -i hosts

Once the playbook has completed the certificate will be installed and ready for automated renewals!

This post is licensed under CC BY 4.0 by the author.