From ab99bc577fa7df83fcad9cc5bfb3bd7670fc2b54 Mon Sep 17 00:00:00 2001 From: Santeri Kainulainen Date: Mon, 1 Dec 2025 15:51:30 +0200 Subject: [PATCH] Add functionality by copy-pasting pre-generated certs to vm and update README.md This commit includes the pre-generated certs in the files/certs directory. README.md was thoroughly updated to include an example of using certbot with this role and how to import the root.crt to Firefox. --- README.MD | 37 ++++++++++++++++++++++++++++++++---- defaults/main.yml | 25 +++++++++++++++++++++++- files/certs/intermediate.crt | 12 ++++++++++++ files/certs/intermediate.key | 5 +++++ files/certs/root.crt | 11 +++++++++++ files/certs/root.key | 5 +++++ tasks/main.yml | 35 ++++++++++++++++++++++++++++++++-- templates/Caddyfile.j2 | 7 ++----- 8 files changed, 125 insertions(+), 12 deletions(-) create mode 100644 files/certs/intermediate.crt create mode 100644 files/certs/intermediate.key create mode 100644 files/certs/root.crt create mode 100644 files/certs/root.key diff --git a/README.MD b/README.MD index ed72ced..c112245 100644 --- a/README.MD +++ b/README.MD @@ -1,15 +1,44 @@ # Kifi Caddy -Installs and configures Caddy for use as a local ACME CA server allowing certificates to be issued in testing +Installs and configures Caddy for use as a local ACME CA server allowing certificates to be issued in testing. +This role should function as of now, but for example certificate lifetime changes don't work (defaults to 12h). ## Example usage In your playbook, define the role and config paths. Most likely the defaults are fine, so you can just simply add the role. Remember to add this before any certbot role. The ACME server is hosted at port 8443. You can also change the `templates/Caddyfile.j2` to fit your own needs. -Example: +Example for tilastot.kirjastot.fi.local: ``` -- role: caddy +- role: kifi.caddy caddy_config_path: /etc/caddy/Caddyfile caddy_root: /var/www/caddy caddy_service_name: caddy -``` \ No newline at end of file +``` + +Another example of how to use this in combination with the kifi.certbot role: +``` +tasks: + - name: Run Certbot role + include_role: + name: kifi.certbot + vars: + certbot_disable_certbot_cron: yes + certbot_host_with_certs: tilastot.kirjastot.fi.local + certbot_create_if_missing: yes + certbot_admin_email: tekniikka@kirjastot.fi + certbot_certs: + - domains: + - tilastot.kirjastot.fi.local + certbot_create_command: > + sudo -E REQUESTS_CA_BUNDLE=/var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt + certbot certonly --server https://localhost:8443/acme/local/directory + --standalone + --email {{ certbot_admin_email }} + --agree-tos + --non-interactive + -d {{ certbot_certs | map(attribute='domains') | flatten | join(' -d ') }} + tags: certbot, ssl +``` + +Note that the domains get looped over, so you can have multiple of them. +Certificates for domains can be found in the folder /etc/letsencrypt/live/domainname though it might be wise to change this \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml index bc475db..7ed2f4e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -2,4 +2,27 @@ caddy_root: /usr/share/caddy caddy_config_path: /etc/caddy/Caddyfile -caddy_service_name: caddy \ No newline at end of file +caddy_service_name: caddy + +caddy_trust_local_ca: false + +# system user/group for Caddy runtime files +caddy_user: caddy +caddy_group: caddy + +# path where role will deploy Caddy authority certs +caddy_authorities_path: /var/lib/caddy/.local/share/caddy/pki/authorities/local +caddy_authorities_mode: '0700' + +# templates subdirectory that contains the cert files (role/templates//...) +caddy_certs_template_dir: certs + +# ownership/mode for deployed cert files +caddy_cert_owner: "{{ caddy_user }}" +caddy_cert_group: "{{ caddy_group }}" +caddy_cert_mode: '0600' + +# ownership/mode for caddy_root +caddy_root_owner: www-data +caddy_root_group: www-data +caddy_root_mode: '0755' \ No newline at end of file diff --git a/files/certs/intermediate.crt b/files/certs/intermediate.crt new file mode 100644 index 0000000..5ef5a67 --- /dev/null +++ b/files/certs/intermediate.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtDCCAVqgAwIBAgIRAMHp+q/ddqH+S9fE5V7QhhkwCgYIKoZIzj0EAwIwJjEk +MCIGA1UEAxMbTXkgTG9jYWwgQ0EgLSAyMDI1IEVDQyBSb290MB4XDTI1MTIwMTEz +MTg1M1oXDTI1MTIwODEzMTg1M1owKTEnMCUGA1UEAxMeTXkgTG9jYWwgQ0EgLSBF +Q0MgSW50ZXJtZWRpYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZL83Hyar +iIsBkRtRNxRtHoiW7KEUuxq4gVyNrJjtdYZwlfZE+qOCYo5I6E99zZiVD2SZNe1x +uVXYV6mcERDnC6NmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C +AQAwHQYDVR0OBBYEFJII7wjwySNFSJWt700GYE1JfsGxMB8GA1UdIwQYMBaAFHCv +EafSET7wyiMUOd3eZrQx3lw8MAoGCCqGSM49BAMCA0gAMEUCIQCCj54nwceSHHJ+ +RCN2CyEByqMh/RdDd/FijJ800x3J6gIgemnp9J3CrKN/Fzy3JOhetVCRkVqjDNLc +ZH4K1pYnDBA= +-----END CERTIFICATE----- diff --git a/files/certs/intermediate.key b/files/certs/intermediate.key new file mode 100644 index 0000000..4c6898d --- /dev/null +++ b/files/certs/intermediate.key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIDLfKjCXLIseInlVmkL1dx6K/Iv6uxjhJjRmI4xr9kXNoAoGCCqGSM49 +AwEHoUQDQgAEZL83HyariIsBkRtRNxRtHoiW7KEUuxq4gVyNrJjtdYZwlfZE+qOC +Yo5I6E99zZiVD2SZNe1xuVXYV6mcERDnCw== +-----END EC PRIVATE KEY----- diff --git a/files/certs/root.crt b/files/certs/root.crt new file mode 100644 index 0000000..55ab77e --- /dev/null +++ b/files/certs/root.crt @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBjzCCATWgAwIBAgIQMNAFWqphrzOxuSOWVbSr4jAKBggqhkjOPQQDAjAmMSQw +IgYDVQQDExtNeSBMb2NhbCBDQSAtIDIwMjUgRUNDIFJvb3QwHhcNMjUxMjAxMTMx +ODUzWhcNMzUxMDEwMTMxODUzWjAmMSQwIgYDVQQDExtNeSBMb2NhbCBDQSAtIDIw +MjUgRUNDIFJvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASD2byYNpauRUOg +LggkyrY/ZRMZIQMT+rXlQMctxnV77VOdaXccTC2vfpOS2tqwcwySyP1NYg1DqvD0 +L4VjUb/To0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd +BgNVHQ4EFgQUcK8Rp9IRPvDKIxQ53d5mtDHeXDwwCgYIKoZIzj0EAwIDSAAwRQIh +AI4rOGX/GNjlUnwixzcXM1FFrBrarzRZd/6+z99I+1yhAiAqxxK69h4ae0nylgVO +pKlmiO5bk38ZfwjN6qAIqMaCcg== +-----END CERTIFICATE----- diff --git a/files/certs/root.key b/files/certs/root.key new file mode 100644 index 0000000..173930c --- /dev/null +++ b/files/certs/root.key @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEICFWtuowkCW/82uhRaJUuisuQFQ3kQc6WH2xopi6aID8oAoGCCqGSM49 +AwEHoUQDQgAEg9m8mDaWrkVDoC4IJMq2P2UTGSEDE/q15UDHLcZ1e+1TnWl3HEwt +r36TktrasHMMksj9TWINQ6rw9C+FY1G/0w== +-----END EC PRIVATE KEY----- diff --git a/tasks/main.yml b/tasks/main.yml index d0b25e6..1c2f001 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -18,8 +18,31 @@ owner: root group: root mode: '0644' - notify: Restart Caddy +- name: Ensure Caddy authorities directory exists + ansible.builtin.file: + path: /var/lib/caddy/.local/share/caddy/pki/authorities/local + state: directory + owner: caddy + group: caddy + mode: '0700' + become: yes + +# Copy the pre-generated certs from files/certs folder to Caddy, +# so that you only need to import the root.crt once for all .local domains +- name: Deploy Caddy root certificates + vars: + cert_list: "{{ lookup('fileglob', role_path + '/files/certs/*', wantlist=True) | map('basename') | list }}" + ansible.builtin.copy: + src: "certs/{{ item }}" + dest: "{{ caddy_authorities_path }}/{{ item }}" + owner: caddy + group: caddy + mode: '0600' + force: yes + + loop: "{{ cert_list }}" + become: yes - name: Ensure Caddy root directory exists ansible.builtin.file: path: "{{ caddy_root }}" @@ -34,9 +57,17 @@ state: started enabled: true +- name: Restart Caddy + become: yes + ansible.builtin.service: + name: "{{ caddy_service_name }}" + state: restarted + +# By default don't trust as its not usually needed - name: Trust Caddy local CA copy: src: /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt dest: /usr/local/share/ca-certificates/caddy-local.crt remote_src: yes - notify: Update CA trust \ No newline at end of file + notify: Update CA trust + when: caddy_trust_local_ca | default(false) | bool \ No newline at end of file diff --git a/templates/Caddyfile.j2 b/templates/Caddyfile.j2 index fd0b6f9..0ed25e9 100644 --- a/templates/Caddyfile.j2 +++ b/templates/Caddyfile.j2 @@ -11,9 +11,6 @@ localhost:8443 { acme_server { ca local + lifetime 720h } -} - -# Refer to the Caddy docs for more information: -# https://caddyserver.com/docs/caddyfile - +} \ No newline at end of file