{"id":13781510,"url":"https://github.com/schubergphilis/chef-acme","last_synced_at":"2025-07-31T13:32:24.436Z","repository":{"id":45132724,"uuid":"47834639","full_name":"schubergphilis/chef-acme","owner":"schubergphilis","description":"Chef cookbook to request SSL certificates at Let's Encrypt","archived":false,"fork":false,"pushed_at":"2023-12-07T09:12:01.000Z","size":242,"stargazers_count":112,"open_issues_count":3,"forks_count":74,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-05-18T22:13:49.999Z","etag":null,"topics":["acme","certificate","chef","chef-cookbook","letsencrypt"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/schubergphilis.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2015-12-11T15:34:34.000Z","updated_at":"2024-03-26T02:34:27.000Z","dependencies_parsed_at":"2023-12-07T10:29:11.923Z","dependency_job_id":"0f88a1d7-4efb-450f-b5d2-7ef26e00592d","html_url":"https://github.com/schubergphilis/chef-acme","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schubergphilis%2Fchef-acme","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schubergphilis%2Fchef-acme/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schubergphilis%2Fchef-acme/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/schubergphilis%2Fchef-acme/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/schubergphilis","download_url":"https://codeload.github.com/schubergphilis/chef-acme/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228249352,"owners_count":17891461,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["acme","certificate","chef","chef-cookbook","letsencrypt"],"created_at":"2024-08-03T18:01:26.656Z","updated_at":"2024-12-05T07:12:29.258Z","avatar_url":"https://github.com/schubergphilis.png","language":"Ruby","funding_links":[],"categories":["Resources"],"sub_categories":["Security"],"readme":"ACME cookbook\n=============\n\n[![Build Status](https://travis-ci.org/schubergphilis/chef-acme.svg)](https://travis-ci.org/schubergphilis/chef-acme)\n[![Cookbook Version](https://img.shields.io/cookbook/v/acme.svg)](https://supermarket.chef.io/cookbooks/acme)\n\nAutomatically get/renew free and trusted certificates from Let's Encrypt (letsencrypt.org).\nACME is the [Automated Certificate Management Environment protocol][1] used by [Let's Encrypt][2].\n\n```\nStarting with v4.0.0 of the acme cookbook the acme_ssl_certificate provider has been removed! The TLS-SNI-01 validation method used by this provider been disabled by Let's Encrypt due to security concerns. Please switch to the acme_certificate provider in this cookbook to request and renew your certificate using the supported HTTP-01 validation method.\n```\n\nAttributes\n----------\n\n| Attribute        | Description                                                                                                                                                                    | Default                                          |\n| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------       | --------------------------------------:          |\n| contact          | Contact information, default empty. Set to `mailto:your@email.com`                                                                                                             | []                                               |\n| dir              | ACME server endpoint, Set to `https://acme-staging-v02.api.letsencrypt.org/directory` if you want to use the Let's Encrypt staging environment and corresponding certificates. | `https://acme-v02.api.letsencrypt.org/directory` |\n| renew            | Days before the certificate expires at which the certificate will be renewed                                                                                                   | 30                                               |\n| source_ips       | IP addresses used by Let's Encrypt to verify the TLS certificates, it will change over time. This attribute is for firewall purposes. Allow these IPs for HTTP (tcp/80).       | ['66.133.109.36']                                |\n| private_key      | Private key content of registered account. Private keys identify the ACME client with the endpoint and are not transferable between staging and production endpoints.          | nil                                              |\n| private_key_file | Filename where private key will be saved. If this file exists, the contents take precedence over the value set in `private_key`.                                               | `/etc/acme/account_private_key.pem`              |\n| key_size         | Default private key size used when resource property is not. Must be one out of: 2048, 3072, 4096.                                                                             | 2048                                             |\n\n\nRecipes\n-------\n### default\nInstalls the required acme-client rubygem.\n\nUsage\n-----\nUse the `acme_certificate` resource to request a certificate with the http-01 challenge. The webserver for the domain for which you are requesting a certificate must be running on the local server. This resource only supports the http validation method. To use the tls-sni-01 challenge, please see the resource below. Provide the path to your `wwwroot` for the specified domain.\n\n```ruby\nacme_certificate 'test.example.com' do\n  crt               '/etc/ssl/test.example.com.crt'\n  key               '/etc/ssl/test.example.com.key'\n  wwwroot           '/var/www'\nend\n```\n\nIf your webserver needs an existing certificate already when installing a new server, you will have a bootstrap problem: The web server cannot start without a certificate, but the certificate cannot be requested without the running web server. To overcome this, a temporary self-signed certificate can be generated with the `acme_selfsigned` resource, allowing the web server to start.\n\n```ruby\nacme_selfsigned 'test.example.com' do\n  crt     '/etc/ssl/test.example.com.crt'\n  chain   '/etc/ssl/test.example.com-chain.crt'\n  key     '/etc/ssl/test.example.com.key'\nend\n```\n\n\nA working example can be found in the included `acme_client` test cookbook.\n\nProviders\n---------\n### certificate\n| Property            | Type           | Default  | Description                                            |\n|  ---                |  ---           |  ---     |  ---                                                   |\n| `cn`                | string         | _name_   | The common name for the certificate                    |\n| `alt_names`         | array          | []       | The common name for the certificate                    |\n| `crt`               | string         | nil      | File path to place the certificate                     |\n| `key`               | string         | nil      | File path to place the private key                     |\n| `key_size`          | integer        | 2048     | Private key size. Must be one out of: 2048, 3072, 4096 |\n| `owner`             | string,integer | root     | Owner of the created files                             |\n| `group`             | string,integer | root     | Group of the created files                             |\n| `wwwroot`           | string         | /var/www | Path to the wwwroot of the domain                      |\n| `ignore_failure`    | boolean        | false    | Whether to continue chef run if issuance fails         |\n| `retries`           | integer        | 0        | Number of times to catch exceptions and retry          |\n| `retry_delay`       | integer        | 2        | Number of seconds to wait between retries              |\n| `endpoint`          | string         | nil      | The Let's Encrypt endpoint to use                      |\n| `contact`           | array          | []       | The contact to use                                     |\n\n### selfsigned\n| Property         | Type           | Default  | Description                                            |\n|  ---             |  ---           |  ---     |  ---                                                   |\n| `cn`             | string         | _name_   | The common name for the certificate                    |\n| `crt`            | string         | nil      | File path to place the certificate                     |\n| `key`            | string         | nil      | File path to place the private key                     |\n| `key_size`       | integer        | 2048     | Private key size. Must be one out of: 2048, 3072, 4096 |\n| `chain`          | string         | nil      | File path to place the certificate chain               |\n| `owner`          | string,integer | root     | Owner of the created files                             |\n| `group`          | string,integer | root     | Group of the created files                             |\n\nExample\n-------\nTo generate a certificate for an apache2 website you can use code like this:\n\n```ruby\n# Include the recipe to install the gems\ninclude_recipe 'acme'\n\n# Set up contact information. Note the mailto: notation\nnode.override['acme']['contact'] = ['mailto:me@example.com']\n# Real certificates please...\nnode.override['acme']['endpoint'] = 'https://acme-v01.api.letsencrypt.org'\n\nsite = \"example.com\"\nsans = [\"www.#{site}\"]\n\n# Generate a self-signed if we don't have a cert to prevent bootstrap problems\nacme_selfsigned \"#{site}\" do\n  crt     \"/etc/httpd/ssl/#{site}.crt\"\n  key     \"/etc/httpd/ssl/#{site}.key\"\n  chain    \"/etc/httpd/ssl/#{site}.pem\"\n  owner   \"apache\"\n  group   \"apache\"\n  notifies :restart, \"service[apache2]\", :immediate\nend\n\n# Set up your web server here...\n\n# Get and auto-renew the certificate from Let's Encrypt\nacme_certificate \"#{site}\" do\n  crt               \"/etc/httpd/ssl/#{site}.crt\"\n  key               \"/etc/httpd/ssl/#{site}.key\"\n  wwwroot           \"/var/www/#{site}/htdocs/\"\n  notifies :restart, \"service[apache2]\"\n  alt_names sans\nend\n```\n\nDNS verification\n----------------\n\nLetsencrypt supports DNS validation. Depending on the setup there may be different ways to deploy an acme challenge to your infrastructure. If you want to use DSN validation, you have to provide two block arguments to the `acme_certificate` resource.\n\nImplement 2 methods in a library in your cookbook, each returning a `Proc` object. The following example uses a HTTP API to provide challenges to the DNS infrastructure.\n\n```ruby\n# my_cookbook/libraries/acme_dns.rb\n\nclass Chef\n  class Recipe\n    def install_dns_challenge(apitoken)\n      Proc.new do |authorization, new_resource|\n        # use DNS authorization\n        authz = authorization.dns\n        fqdn = authorization.identifier['value']\n        r = Net::HTTP.post(URI(\"https://my_awesome_dns_api/#{fqdn}\"), authz.record_content, {'Authorization' =\u003e \"Token #{apitoken}\"})\n        if r.code != '200'\n          fail \"DNS API does not want to install Challenge for #{fqdn}\"\n        else\n          # do some validation that the challenge has propagated to the infrastructure\n        end\n        # it is important that the authz and fqdn is passed back, so it can be passed to the remove_dns_challenge method\n        [authz, fqdn]\n      end\n    end\n    def remove_dns_challenge(apitoken)\n      Proc.new do |authz, fqdn|\n        uri = URI(\"https://my_awesome_dns_api/#{fqdn}\")\n        Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme=='https') do |http|\n          http.delete(uri, {'Authorization' =\u003e \"Token #{apitoken}\"})\n        end\n      end\n    end\n  end\nend\n```\n\nUse it in your recipe the following way:\n\n```ruby\napitoken = chef_vault_item(vault, item)['dns_api_token']\nacme_certificate node['fqdn'] do\n  key '/path/to/key'\n  crt '/path/to/crt'\n  install_authz_block install_dns_challenge(apitoken)\n  remove_authz_block remove_dns_challenge(apitoken)\nend\n```\n\n\n\nTesting\n-------\nThe kitchen includes a `pebble` server to run the integration tests with, so testing can run locally without interaction with the online APIs.\n\nContributing\n------------\n1. Fork the repository on Github\n2. Create a named feature branch (like `add_component_x`)\n3. Write your change\n4. Write tests for your change (if applicable)\n5. Run the tests, ensuring they all pass\n6. Submit a Pull Request using Github\n\nLicense and Authors\n-------------------\nAuthors: Thijs Houtenbos \u003cthoutenbos@schubergphilis.com\u003e\n\nCredits\n-------\nLet’s Encrypt is a trademark of the Internet Security Research Group. All rights reserved.\n\n[1]: https://ietf-wg-acme.github.io/acme/\n[2]: https://letsencrypt.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschubergphilis%2Fchef-acme","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fschubergphilis%2Fchef-acme","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fschubergphilis%2Fchef-acme/lists"}