diff --git a/README.org b/README.org index 18916ec..62fc0e3 100644 --- a/README.org +++ b/README.org @@ -9,10 +9,12 @@ This role installs and configures a [[https://docs.gitea.com/][Gitea]] server. It uses SQLite as its default database service - with optional PostgreSQL support. The role can set up a reverse proxy with SSL using Nginx. +Self-signed certificates and Let's Encrypt with =certbot= are supported. - Use the =ds-ufw= role to configure the firewall. - Use the =ds-posgresql= role to configure the database. - Use the =ds-nginx= role to install the proxy server. +- Use the =ds-act_runner= role to configure and register Actions runners. * Role Behavior @@ -40,7 +42,7 @@ gitea_reverse_proxy: '' * Requirements - Ansible >= 2.12 -- Debian-based OS (Bookworm, Trixie) +- Debian 12+ or compatible - git - sudo - ca-certificates @@ -72,6 +74,8 @@ gitea_reverse_proxy: '' | gitea_ssl_key | string | SSL key | | gitea_enable_http_redirect | boolean | Redirect HTTP to HTTPS | | gitea_self_signed | boolean | Generate a self-signed cert and key | +| gitea_lets_encrypt | boolean | Use certbot to configure the SSL | +| gitea_certbot_email | string | Email to register the certificates | * Handlers @@ -109,20 +113,25 @@ Then re-run the playbook to finish the installation. gitea_ssh_domain: gitea.tomsitcafe.com gitea_domain: gitea.tomsitcafe.com gitea_http_port: 3000 - gitea_root_url: http://gitea.tomsitcafe.com:3000 + gitea_root_url: https://gitea.tomsitcafe.com # Optional Postgresql database backend gitea_database_server: postgresql # Optional Nginx reverse proxy configuration gitea_reverse_proxy: nginx - gitea_enable_https: true - gitea_self_signed: true - gitea_ssl_cert: /var/lib/gitea/certs/cert.pem - gitea_ssl_key: /var/lib/gitea/certs/key.pem - gitea_enable_http_redirect: true + gitea_enable_https: true # Use HTTPS + gitea_self_signed: false # Don't generate self-signed certs + gitea_lets_encrypt: true # Use certbot + gitea_enable_http_redirect: true # Redirect HTTP to HTTPS - # In prod put these secrets in SOPS: + # Certbot configuration + gitea_certbot_email: email@domain.tld + gitea_ssl_cert: /etc/letsencrypt/live/{{ gitea_domain }}/fullchain.pem + gitea_ssl_key: /etc/letsencrypt/live/{{ gitea_domain }}/privkey.pem + gitea_ssl_trusted_certificate: /etc/letsencrypt/live/{{ gitea_domain }}/chain.pem + + # In prod put the secrets in SOPS: gitea_lfs_jwt_secret: G9bZrRHMhRQ8w4R0KkH2VLnx2rzq81ROQ951IQjlMs4 gitea_internal_token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3NzA2Mzk1Njh9.ybbaeNLFiLbyvxfj4vkqhXSAXKRGpwvP8jIm9YLPgXw gitea_jwt_secret: uJni4x4e0AzpkLYc-t4keRJKOB6EaLzwVsdLeamkFyU diff --git a/tasks/lets-encrypt.yml b/tasks/lets-encrypt.yml new file mode 100644 index 0000000..e387d4b --- /dev/null +++ b/tasks/lets-encrypt.yml @@ -0,0 +1,29 @@ +--- +- name: Install certbot + ansible.builtin.apt: + name: + - certbot + state: present + +- name: Ensure webroot directory exists + ansible.builtin.file: + path: /var/www/html/.well-known/acme-challenge + state: directory + owner: www-data + group: www-data + mode: '0755' + +- name: Obtain or renew TLS certificate (non-destructive) + ansible.builtin.command: + cmd: > + certbot certonly + --webroot + -w /var/www/html + -d {{ gitea_domain }} + --agree-tos + --email {{ gitea_certbot_email }} + --non-interactive + --keep-until-expiring + register: certbot_result + changed_when: "'Congratulations' in certbot_result.stdout" + notify: Reload_nginx diff --git a/tasks/main.yml b/tasks/main.yml index 1d194de..6618cdf 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -99,6 +99,11 @@ file: self-signed-cert.yml when: gitea_self_signed | default(false) +- name: Configure the Let's Encrypt certificates + ansible.builtin.include_tasks: + file: lets-encrypt.yml + when: gitea_lets_encrypt | default(false) + - name: Pause to generate and save the secrets in SOPS ansible.builtin.pause: prompt: | diff --git a/templates/gitea.j2 b/templates/gitea.j2 index e11ed6a..0565c09 100644 --- a/templates/gitea.j2 +++ b/templates/gitea.j2 @@ -8,9 +8,11 @@ server { ssl_certificate {{ gitea_ssl_cert }}; ssl_certificate_key {{ gitea_ssl_key }}; +{% if gitea_lets_encrypt | default(false) %} + ssl_trusted_certificate {{ gitea_ssl_trusted_certificate }}; +{% endif %} - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers HIGH:!aNULL:!MD5; + ssl_protocols TLSv1.2 TLSv1.3; client_max_body_size 50M; @@ -30,7 +32,21 @@ server { server { listen 80; server_name {{ gitea_domain }}; + + {% if gitea_lets_encrypt | default(false) %} + # Allow Let's Encrypt to verify certificates + location ^~ /.well-known/acme-challenge/ { + root /var/www/html; + allow all; + } + + # Redirect everything else to HTTPS + location / { + return 301 https://$host$request_uri; + } + {% else %} return 301 https://$host$request_uri; + {% endif %} } {% endif %}