{"id":16725749,"url":"https://github.com/coolaj86/greenlock","last_synced_at":"2025-03-21T21:31:03.902Z","repository":{"id":41280884,"uuid":"133098855","full_name":"coolaj86/greenlock","owner":"coolaj86","description":"Automatic SSL renewal for NodeJS","archived":false,"fork":false,"pushed_at":"2020-08-03T07:01:25.000Z","size":655,"stargazers_count":48,"open_issues_count":0,"forks_count":8,"subscribers_count":5,"default_branch":"github","last_synced_at":"2025-03-18T05:12:55.851Z","etag":null,"topics":["acme","greenlock","https","letsencrypt","nodejs","ssl","tls"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coolaj86.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-05-11T23:52:22.000Z","updated_at":"2024-04-02T19:10:19.000Z","dependencies_parsed_at":"2022-09-21T00:20:47.890Z","dependency_job_id":null,"html_url":"https://github.com/coolaj86/greenlock","commit_stats":null,"previous_names":[],"tags_count":100,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolaj86%2Fgreenlock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolaj86%2Fgreenlock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolaj86%2Fgreenlock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolaj86%2Fgreenlock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coolaj86","download_url":"https://codeload.github.com/coolaj86/greenlock/tar.gz/refs/heads/github","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244874154,"owners_count":20524576,"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","greenlock","https","letsencrypt","nodejs","ssl","tls"],"created_at":"2024-10-12T22:50:51.417Z","updated_at":"2025-03-21T21:31:03.042Z","avatar_url":"https://github.com/coolaj86.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mirror of git.rootprojects.org/root/greenlock.js\n\nGithub does not expose the ability to automatically update mirrors,\nso this may lag behind the official repository which is found at:\n\n-   \u003chttps://git.rootprojects.org/root/greenlock.js\u003e\n\n# New Documentation \u0026amp; [v4 Migration Guide](https://git.rootprojects.org/root/greenlock.js/src/branch/master/MIGRATION_GUIDE.md)\n\nWe're still working on the full documentation for this new version,\nso please be patient.\n\nTo start, check out the\n[Migration Guide](https://git.rootprojects.org/root/greenlock.js/src/branch/master/MIGRATION_GUIDE.md).\n\n![\"Greenlock Logo\"](https://git.rootprojects.org/root/greenlock.js/raw/branch/master/logo/greenlock-1063x250.png 'Greenlock lock logo and work mark')\n\n![\"Greenlock Function\"](https://git.rootprojects.org/root/greenlock.js/raw/branch/master/logo/from-not-secure-to-secure-url-bar.png 'from url bar showing not secure to url bar showing secure')\n\n# [Greenlock](https://git.rootprojects.org/root/greenlock.js) is Let's Encrypt for JavaScript\n\n| Built by [Root](https://rootprojects.org) for [Hub](https://rootprojects.org/hub/)\n\nGreenlock\u0026trade; is an Automated Certificate Management Environement 🔐.\n\n| **Greenlock** | [Greenlock Express](https://git.rootprojects.org/root/greenlock-express.js) | [ACME.js](https://git.rootprojects.org/root/acme.js) |\n\nIt uses **Let's Encrypt** to generate Free SSL Certificates, including **Wildcard** SSL.\nIt supports **Automated Renewal** of certs for Fully Automated HTTPS.\n\nIt's written in plain JavaScript and works in Node, Browsers, and WebPack.\n\nthe easiest way to integrate Let's Encrypt into your projects, products, and infrastructure.\n\n-   [x] **Wildcard** Certificates\n-   [x] **IoT** Environments\n-   [x] **Enterprise** and **On-Prem**\n-   [x] **Private** Networks\n-   [x] **Localhost** Development\n-   [x] **Web Hosting** Providers\n-   [x] **Commercial** support\n\nWe've built it simple enough for Hobbyists, and robust enough for the Enterprise.\n\n\u003c!--\n# Localhost Development\n\n\u003cdetails\u003e\n\u003csummary\u003eHTTPS on Localhost\u003c/summary\u003e\nTODO\n\n\u003c/details\u003e\n\n# WebServer with Automatic HTTPS\n\n\u003cdetails\u003e\n\u003csummary\u003eLearn more about the Greenlock Web Server\u003c/summary\u003e\nTODO\n\u003c/details\u003e\n\n# Commandline\n\n\u003cdetails\u003e\n\u003csummary\u003eLearn more about the Greenlock CLI\u003c/summary\u003e\nTODO\n\u003c/details\u003e\n\n--\u003e\n\n# Quick Start\n\nGreenlock is fully-automated, **SSL Certificate Manager** for IoT, Web Hosting, and Enterprise On-Prem, Edge, and Hybrid Cloud.\n\n(though we started building it for [Home Servers](https://rootprojects.org/hub/))\n\nYou can use it for one-off certificates, like `certbot`,\nbut it is _much_ more powerful than that.\n\nBy setting just a few callbacks to let it know where it should store private keys and certificates,\nit will automatically renew any certificate that you add to it, as long as the process is running.\n\nCertificates are renewed every 45 days by default, and renewal checks will happen several times a day.\n\n\u003cdetails\u003e\n\u003csummary\u003e1. Configure\u003c/summary\u003e\n\n```js\n'use strict';\n\nvar pkg = require('./package.json');\nvar Greenlock = require('greenlock');\nvar greenlock = Greenlock.create({\n    configDir: './greenlock.d/config.json',\n    packageAgent: pkg.name + '/' + pkg.version,\n    maintainerEmail: pkg.author,\n    staging: true,\n    notify: function (event, details) {\n        if ('error' === event) {\n            // `details` is an error object in this case\n            console.error(details);\n        }\n    }\n});\n\ngreenlock.manager\n    .defaults({\n        agreeToTerms: true,\n        subscriberEmail: 'webhosting@example.com'\n    })\n    .then(function (fullConfig) {\n        // ...\n    });\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e2. Add Domains\u003c/summary\u003e\n\nThe `subject` (primary domain on certificate) will be the id,\nso it's very important that the order of the given domains\nbe deterministic.\n\n```js\nvar altnames = ['example.com', 'www.example.com'];\n\ngreenlock\n    .add({\n        subject: altnames[0],\n        altnames: altnames\n    })\n    .then(function () {\n        // saved config to db (or file system)\n    });\n```\n\nIssuance and renewal will start immediately, and run continually.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e3. Test for Success\u003c/summary\u003e\n\nThe `store` callbacks will be called every any of your certificates\nare renewed.\n\nHowever, you can do a quick one-off check with `get`.\n\nIt will return a certificate immediately (if available),\nor wait for the renewal to complete (or for it to fail again).\n\n```js\ngreenlock\n    .get({ servername: subject })\n    .then(function (pems) {\n        if (pems \u0026\u0026 pems.privkey \u0026\u0026 pems.cert \u0026\u0026 pems.chain) {\n            console.info('Success');\n        }\n        //console.log(pems);\n    })\n    .catch(function (e) {\n        console.error('Big bad error:', e.code);\n        console.error(e);\n    });\n```\n\n\u003c/details\u003e\n\n# JavaScript API\n\n\u003c!--\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock API (shared among JS implementations)\u003c/summary\u003e\n--\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock.create({ configDir, packageAgent, maintainerEmail, staging })\u003c/summary\u003e\n\n## Greenlock.create()\n\nCreates an instance of greenlock with _environment_-level values.\n\n```js\n\nvar pkg = require('./package.json');\nvar gl = Greenlock.create({\n    configDir: './greenlock.d/config.json',\n\n    // Staging for testing environments\n    staging: true,\n\n    // This should be the contact who receives critical bug and security notifications\n    // Optionally, you may receive other (very few) updates, such as important new features\n    maintainerEmail: 'jon@example.com',\n\n    // for an RFC 8555 / RFC 7231 ACME client user agent\n    packageAgent: pkg.name + '/' pkg.version\n});\n```\n\n| Parameter       | Description                                                                          |\n| --------------- | ------------------------------------------------------------------------------------ |\n| configDir       | the directory to use for file-based plugins                                          |\n| maintainerEmail | the developer contact for critical bug and security notifications                    |\n| packageAgent    | if you publish your package for others to use, `require('./package.json').name` here |\n| staging         | use the Let's Encrypt staging URL instead of the production URL                      |\n| directoryUrl    | for use with other (not Let's Encrypt) ACME services, and the Pebble test server     |\n\n\u003c!--\n| maintainerUpdates         | (default: false) receive occasional non-critical notifications                                                                                             |\n    maintainerUpdates: true // default: false\n--\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock#manager.defaults()\u003c/summary\u003e\n\n## Greenlock#manager.defaults()\n\nActs as a getter when given no arguments.\n\nOtherwise sets default, site-wide values as described below.\n\n```js\ngreenlock.manager.defaults({\n    // The \"Let's Encrypt Subscriber\" (often the same as the maintainer)\n    // NOT the end customer (except where that is also the maintainer)\n    subscriberEmail: 'jon@example.com',\n    agreeToTerms: true\n    challenges: {\n      \"http-01\": {\n        module: \"acme-http-01-webroot\",\n        webroot: \"/path/to/webroot\"\n      }\n    }\n});\n```\n\n| Parameter                 | Description                                                                                                                                                                        |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| agreeToTerms              | (default: false) either 'true' or a function that presents the Terms of Service and returns it once accepted                                                                       |\n| challenges['http-01']     | provide an http-01 challenge module                                                                                                                                                |\n| challenges['dns-01']      | provide a dns-01 challenge module                                                                                                                                                  |\n| challenges['tls-alpn-01'] | provide a tls-alpn-01 challenge module                                                                                                                                             |\n| challenges[type].module   | the name of your challenge module                                                                                                                                                  |\n| challenges[type].xxxx     | module-specific options                                                                                                                                                            |\n| renewOffset               | **leave the default** Other than for testing, leave this at the default of 45 days before expiration date (`'-45d'`) . Can also be set like `5w`, meaning 5 weeks after issue date |\n| servername                | the default servername to use for non-sni requests (many IoT clients)                                                                                                              |\n| subscriberEmail           | the contact who agrees to the Let's Encrypt Subscriber Agreement and the Greenlock Terms of Service\u003cbr\u003ethis contact receives renewal failure notifications                         |\n| store                     | override the default storage module                                                                                                                                                |\n| store.module              | the name of your storage module                                                                                                                                                    |\n| store.xxxx                | options specific to your storage module                                                                                                                                            |\n\n\u003c!--\n\n| serverId        | an arbitrary name to distinguish this server within a cluster of servers |\n\n--\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock#add({ subject, altnames })\u003c/summary\u003e\n\n## Greenlock#add()\n\nGreenlock is a **Automated Certificate Management Environment**.\n\nOnce you add a \"site\", it will begin to automatically renew, immediately.\n\nThe certificates will provided to the `store` callbacks as soon as they are ready, and whenever they renew.\nFailure to renew will be reported to the `notify` callback.\n\nYou can also retrieve them one-off with `get`.\n\n```js\ngl.add({\n    subject: 'example.com',\n    altnames: ['example.com', 'www.example.com', 'exampleapi.com']\n});\n```\n\n| Parameter       | Description                                                                                  |\n| --------------- | -------------------------------------------------------------------------------------------- |\n| subject         | the first domain on, and identifier of the certificate                                       |\n| altnames        | first domain, plus additional domains\u003cbr\u003enote: the order should always be the same           |\n| subscriberEmail | if different from the default (i.e. multi-tenant, whitelabel)                                |\n| challenges      | (same as main config) use if this site needs to use non-default http-01 or dns-01 validation |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock#get({ servername })\u003c/summary\u003e\n\n## Greenlock#get()\n\n**Disclaimer**: This is only intended for testing, demos, and SNICallback\n(in [Greenlock Express](https://git.rootprojects.org/root/greenlock-express.js)).\n\nGreenlock is intended to be left running to allow it to fetech and renew certifictates automatically.\n\nIt is intended that you use the `store` callbacks to new certificates instantly as soon as they renew.\nThis also protects you from accidentally stampeding the Let's Encrypt API with hundreds (or thousands)\nof certificate requests.\n\n-   [Store Callback Documentation](https://git.rootprojects.org/root/greenlock-store-test.js)\n\n```js\nreturn greenlock.get({ servername }).then(function (site) {\n    if (!site) {\n        console.log(servername + ' was not found in any site config');\n        return;\n    }\n\n    var privkey = site.pems.privkey;\n    var fullchain = site.pems.cert + '\\n' + site.pems.chain + '\\n';\n    console.log(privkey);\n    console.log(fullchain);\n});\n```\n\n| Parameter  | Description                                                   |\n| ---------- | ------------------------------------------------------------- |\n| servername | any altname listed on the certificate (including the subject) |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock#renew({ renewBefore })\u003c/summary\u003e\n\n## Greenlock#renew()\n\nThis will renew only domains that have reached their `renewAt` or are within the befault `renewOffset`.\n\n**Note**: This runs at regular intervals, multiple times a day, in the background.\nYou are not required to call it. If you implement the `store` callbacks, the certificates\nwill automatically be saved (and if you don't implement them, they all get saved to disk).\n\n```js\nreturn greenlock.renew({}).then(function (results) {\n    results.forEach(function (site) {\n        if (site.error) {\n            console.error(site.subject, site.error);\n            return;\n        }\n        console.log('Renewed certificate for', site.subject, site.altnames);\n    });\n});\n```\n\n| Parameter   | Type | Description                                                                     |\n| ----------- | ---- | ------------------------------------------------------------------------------- |\n| (optional)  |      | ALL parameters are optional, but some should be paired                          |\n| force       | bool | force silly options, such as tiny durations                                     |\n| renewBefore | ms   | Check domains that are scheduled to renew before the given date in milliseconds |\n\n\u003c!--\n| issuedBefore  | ms   | Check domains issued before the given date in milliseconds                      |\n| expiresBefore | ms   | Check domains that expire before the given date in milliseconds                 |\n--\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGreenlock#remove({ subject })\u003c/summary\u003e\n\n## Greenlock#manager.remove()\n\nTo stop certificates from being renewed, you must remove them.\n\nIf you are implementing your own `manager` callbacks, I recommend that you mark them as deleted\n(i.e. `deleted_at` in your database) rather than actually removing them. Just in case.\n\n```js\ngl.remove({\n    subject: 'example.com'\n}).then(function (siteConfig) {\n    // save the old site config elsewhere, just in case you need it again\n});\n```\n\n| Parameter | Description                                            |\n| --------- | ------------------------------------------------------ |\n| subject   | the first domain on, and identifier of the certificate |\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eEvents\u003c/summary\u003e\n\nMost of the events bubble from ACME.js.\n\nSee https://git.rootprojects.org/root/acme.js#api-overview\n\n_TODO_: document the greenlock-specific events.\n\n\u003c/details\u003e\n\n\u003c!--\n\n\u003cdetails\u003e\n\u003csummary\u003eNode.js\u003c/summary\u003e\n--\u003e\n\n# Install\n\nGreenlock comes with reasonable defaults but when you install it,\nyou should also install any plugins that you need.\n\n```bash\nnpm install --save @root/greenlock@v4\nnpm install --save @greenlock/manager\nnpm install --save greenlock-store-fs\nnpm install --save acme-http-01-standalone\n```\n\n\u003c!--\n\nTODO\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eExpress.js\u003c/summary\u003e\n\n```js\n'use strict';\n\nvar Greenlock = require(@root/greenlock-express);\n\nvar greenlock = Greenlock.create({\n// for security and critical bug notices\nmaintainerEmail: 'jon@example.com'\n\n// for\nmaintainerNewsletter: true\n});\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eWebPack\u003c/summary\u003e\nTODO\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eVanillaJS for Browsers\u003c/summary\u003e\nTODO\n\u003c/details\u003e\n\n--\u003e\n\n# Easy to Customize\n\n\u003c!-- greenlock-manager-test =\u003e greenlock-manager-custom --\u003e\n\n\u003c!--\n- [greenlock.js/examples/](https://git.rootprojects.org/root/greenlock.js/src/branch/master/examples)\n--\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSSL Cert \u0026 Domain Management\u003c/summary\u003e\n\n## SSL Certificate \u0026 Domain Management\n\nFull Docs: https://git.rootprojects.org/root/greenlock-manager-test.js\n\nThis is what keeps the mapping of domains \u003c-\u003e certificates.\nIn many cases it will interact with the same database as the Key \u0026 Cert Store, and probably the code as well.\n\n-   set({ subject, altnames, renewAt })\n-   find({ servernames, renewBefore })\n    ```js\n    // should return a list of site configs:\n    [\n        {\n            subject: 'example.com',\n            altnames: ['example.com', 'exampleapi.com'],\n            renewAt: 1575197231760\n        },\n        {\n            subject: '*.example.com',\n            altnames: ['*.example.com'],\n            renewAt: 1575197231760,\n            challenges: {\n                'dns-01': {\n                    module: 'acme-dns-01-dnsimple',\n                    apikey: 'xxxx'\n                }\n            }\n        }\n    ];\n    ```\n-   remove({ subject })\n-   defaults() (both getter and setter)\n    ```json\n    {\n        \"subscriberEmail\": \"jane@example.com\",\n        \"agreeToTerms\": true,\n        \"challenges\": {\n            \"http-01\": {\n                \"module\": \"acme-http-01-standalone\"\n            }\n        }\n    }\n    ```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eKey \u0026 Cert Storage\u003c/summary\u003e\n\n## Key and Certificate Store\n\nFull Docs: https://git.rootprojects.org/root/greenlock-store-test.js\n\nThis set of callbacks update your service with new certificates and keypairs.\n\n### Account Keys (JWK)\n\n(though typically you only have one account key - because you only have one subscriber email)\n\n-   accounts.setKeypair({ email, keypair })\n-   accounts.checkKeypair({ email })\n\n### Certificate Keys (JWK + PEM)\n\n(typically you have one for each set of domains, and each load balancer)\n\n-   certificates.setKeypair({ subject, keypair })\n-   certificates.checkKeypair({ subject })\n    (these are fine to implement the same as above, swapping subject/email)\n\n### Certificate PEMs\n\n-   certificates.set({ subject, pems })\n-   certificates.check({ subject })\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eACME HTTP-01 Challenges\u003c/summary\u003e\n\n## ACME Challenge HTTP-01 Strategies\n\nFull Docs: https://git.rootprojects.org/root/acme-http-01-test.js\n\nThis validation and authorization strategy is done over plain HTTP on Port 80.\n\nThese are used to set files containing tokens that Let's Encrypt will fetch from each domain\nbefore authorizing a certificate.\n\n**NOT for Wildcards**.\n\n-   init({ request })\n-   set({ challenge: { type, token, keyAuthorization, challengeUrl } })\n-   get({ challenge: { type, token } })\n-   remove({ challenge: { type, token } })\n\n\u003c!--\nTODO: getAcmeHttp01Challenge\n--\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eACME DNS-01 Challenges\u003c/summary\u003e\n\n## ACME Challenge DNS-01 Strategies\n\nFull Docs https://git.rootprojects.org/root/acme-dns-01-test.js\n\nThis validation and authorization strategy is done over DNS on UDP and TCP ports 53.\n\n**For Wildcards**\n\nThese are used to set TXT records containing tokens that Let's Encrypt will fetch for\neach domain before authorizing a certificate.\n\n-   init({ request })\n-   zones()\n-   set({ challenge: { type, dnsZone, dnsPrefix, dnsHost, keyAuthorizationDigest } })\n-   get({ challenge: { type, dnsZone, dnsPrefix, dnsHost } })\n-   remove({ challenge: { type, dnsZone, dnsPrefix, dnsHost } })\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eNotes on HTTP-01 \u0026amp; DNS-01 Integrations\u003c/summary\u003e\n\n## Notes on HTTP-01 \u0026amp; DNS-01 Integrations\n\nFor Public Web Servers running on a VPS, the **default HTTP-01 challenge plugin**\nwill work just fine, for most people.\n\nHowever, for environments that cannot be verified via public HTTP, such as\n\n-   **Wildcard Certificates**\n-   **IoT Environments**\n-   **Enterprise On-Prem**\n-   **Private Networks**\n\nGreenlock provides an easy way to integrate Let's Encrypt with your existing services\nthrough a variety of **DNS-01** challenges.\n\n### Why not use dns01 for everything?\n\nTypically file propagation is faster and more reliably than DNS propagation.\nTherefore, http-01 will be preferred to dns-01 except when wildcards or **private domains** are in use.\n\nhttp-01 will only be supplied as a defaut if no other challenge is provided.\n\n\u003c/details\u003e\n\n# Ready-made Integrations\n\nGreenlock Express integrates between Let's Encrypt's ACME Challenges and many popular services.\n\n| Type        | Service                                                                             | Plugin                   |\n| ----------- | ----------------------------------------------------------------------------------- | ------------------------ |\n| dns-01      | CloudFlare                                                                          | acme-dns-01-cloudflare   |\n| dns-01      | [Digital Ocean](https://git.rootprojects.org/root/acme-dns-01-digitalocean.js)      | acme-dns-01-digitalocean |\n| dns-01      | [DNSimple](https://git.rootprojects.org/root/acme-dns-01-dnsimple.js)               | acme-dns-01-dnsimple     |\n| dns-01      | [DuckDNS](https://git.rootprojects.org/root/acme-dns-01-duckdns.js)                 | acme-dns-01-duckdns      |\n| http-01     | File System / [Web Root](https://git.rootprojects.org/root/acme-http-01-webroot.js) | acme-http-01-webroot     |\n| dns-01      | [GoDaddy](https://git.rootprojects.org/root/acme-dns-01-godaddy.js)                 | acme-dns-01-godaddy      |\n| dns-01      | [Gandi](https://git.rootprojects.org/root/acme-dns-01-gandi.js)                     | acme-dns-01-gandi        |\n| dns-01      | [NameCheap](https://git.rootprojects.org/root/acme-dns-01-namecheap.js)             | acme-dns-01-namecheap    |\n| dns-01      | [Name\u0026#46;com](https://git.rootprojects.org/root/acme-dns-01-namedotcom.js)         | acme-dns-01-namedotcom   |\n| dns-01      | Route53 (AWS)                                                                       | acme-dns-01-route53      |\n| http-01     | S3 (AWS, Digital Ocean, Scaleway)                                                   | acme-http-01-s3          |\n| dns-01      | [Vultr](https://git.rootprojects.org/root/acme-dns-01-vultr.js)                     | acme-dns-01-vultr        |\n| dns-01      | [Build your own](https://git.rootprojects.org/root/acme-dns-01-test.js)             | acme-dns-01-test         |\n| http-01     | [Build your own](https://git.rootprojects.org/root/acme-http-01-test.js)            | acme-http-01-test        |\n| tls-alpn-01 | [Contact us](mailto:support@therootcompany.com)                                     | -                        |\n\nSearch `acme-http-01-` or `acme-dns-01-` on npm to find more.\n\n# Commercial Support\n\nDo you need...\n\n-   training?\n-   specific features?\n-   different integrations?\n-   bugfixes, on _your_ timeline?\n-   custom code, built by experts?\n-   commercial support and licensing?\n\nYou're welcome to [contact us](mailto:aj@therootcompany.com) in regards to IoT, On-Prem,\nEnterprise, and Internal installations, integrations, and deployments.\n\nWe have both commercial support and commercial licensing available.\n\nWe also offer consulting for all-things-ACME and Let's Encrypt.\n\n# Legal \u0026amp; Rules of the Road\n\nGreenlock\u0026trade; is a [trademark](https://rootprojects.org/legal/#trademark) of AJ ONeal\n\nThe rule of thumb is \"attribute, but don't confuse\". For example:\n\n\u003e Built with [Greenlock Express](https://git.rootprojects.org/root/greenlock.js) (a [Root](https://rootprojects.org) project).\n\nPlease [contact us](mailto:aj@therootcompany.com) if you have any questions in regards to our trademark,\nattribution, and/or visible source policies. We want to build great software and a great community.\n\n[Greenlock\u0026trade;](https://git.rootprojects.org/root/greenlock.js) |\nMPL-2.0 |\n[Terms of Use](https://therootcompany.com/legal/#terms) |\n[Privacy Policy](https://therootcompany.com/legal/#privacy)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoolaj86%2Fgreenlock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoolaj86%2Fgreenlock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoolaj86%2Fgreenlock/lists"}