{"id":28516517,"url":"https://github.com/loopholelabs/certifier","last_synced_at":"2025-10-04T02:55:33.599Z","repository":{"id":41355078,"uuid":"481680049","full_name":"loopholelabs/certifier","owner":"loopholelabs","description":"Certifier is a library designed to make it easy to obtain ACME TLS certificates using the DNS-01 Challenge. Certifier is not designed to work as a standalone-CLI, but instead it is designed to be embedded within other Golang applications.","archived":false,"fork":false,"pushed_at":"2024-10-07T12:32:53.000Z","size":173,"stargazers_count":6,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-09T04:14:29.020Z","etag":null,"topics":["acme","golang","tls"],"latest_commit_sha":null,"homepage":"https://loopholelabs.io","language":"Go","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/loopholelabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-04-14T16:50:05.000Z","updated_at":"2024-10-20T07:01:13.000Z","dependencies_parsed_at":"2022-08-27T19:00:35.920Z","dependency_job_id":null,"html_url":"https://github.com/loopholelabs/certifier","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/loopholelabs/certifier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopholelabs%2Fcertifier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopholelabs%2Fcertifier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopholelabs%2Fcertifier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopholelabs%2Fcertifier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/loopholelabs","download_url":"https://codeload.github.com/loopholelabs/certifier/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/loopholelabs%2Fcertifier/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278258417,"owners_count":25957281,"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","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","golang","tls"],"created_at":"2025-06-09T04:11:28.901Z","updated_at":"2025-10-04T02:55:33.594Z","avatar_url":"https://github.com/loopholelabs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Certifier\n\n[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-brightgreen.svg)](https://www.apache.org/licenses/LICENSE-2.0)\n[![Discord](https://dcbadge.vercel.app/api/server/JYmFhtdPeu?style=flat)](https://loopholelabs.io/discord)\n[![go-doc](https://godoc.org/github.com/loopholelabs/certifier?status.svg)](https://godoc.org/github.com/loopholelabs/certifier)\n\nCertifier is a library designed to make it easy to obtain ACME TLS certificates\nusing the DNS-01 Challenge. Certifier is not designed to work as a standalone-CLI, but instead\nit is designed to be embedded within other Golang applications.\n\n## Architecture\n\nThere are two parts to certifier - the DNS Server and the ACME manager.\n\nThe DNS Server is quite simple - it only responds to TXT Record queries for subdomains of a single given root domain.\nThis means that if the certifier is configured with the root domain `acme.mydomain.com`, it will only respond to TXT queries\nfor the domains matching `*.*.acme.mydomain.com`. It will also respond to NS Record queries and SOA Record Queries for the root domain\nand all of its subdomains.\n\nThe ACME manager makes use of the [Lego ACME](https://go-acme.github.io/lego) Library to begin and complete `DNS-01` challenges.\n\n## Requirements\n\nIn order to use certifier to obtain a TLS Certificate using an ACME provider like\nLet's Encrypt, you must first configure and run Certifier somewhere that is accessible from\nthe public internet.\n\nLet's say you configure certifier for the domain `acme.mydomain.com`. The first thing you'll need to do is create the proper A and NS Records\nto point DNS requests to certifier. We want to forward NS Queries of the form `*.*.acme.mydomain.com` to your certifier instance, so you first need to create an A record\nfor `certifier.mydomain.com` that points to the IP of your certifier instance.\n\nSomething like `certifier.mydomain.com A \u003ccertifier IP\u003e` should work great.\n\nNext you need to create an NS record for `acme.mydomain.com` setting your certifier instance as the authoritive name server. A record like `acme.mydomain.com NS certifier.mydomain.com` should work perfectly.\n\nNext, you'll need to register a user with Certifier. You will need to do this for every new user that wants to use certifier to obtain certificates.\n\nTo do this, you must provide a unique ID for the user, and it is your responsibility to guarantee that the correct user is requesting certificates using their own ID.\nOnce you have a unique ID for your user, you can register them with Certifier by doing `certifier.RegisterCID`. This will map a certifier identifier (the `CID`)\nto your user's ID.\n\nYour user should then create a CNAME record of the form `_acme-challenge.testdomain.com` pointing to `testdomain-com.\u003cCID\u003e.acme.mydomain.com`. You must replace\nthe periods in your root domain (`testdomain.com`) with hyphens (`-`), and create a CNAME record that points to `\u003croot domain with periods replaced\u003e.\u003ccid returned by certifier\u003e.acme.mydomain.com`.\nRemember that `acme.mydomain.com` is the domain who's name server is your certifier instance.\n\n### Certificate Request Flow\n\nDuring an actual Certificate Request Flow, the following happens:\n\n1. Create the CNAME record of the form `_acme-challenge.testdomain.com` (if your chosen domain is `testdomain.com`), and point it at `testdomain-com.\u003cCID\u003e.acme.mydomain.com`, replacing all the periods with hyphens (`-`).\n2. Start the renewer using the `certifier.Renew` function, passing in your [Lego ACME](https://go-acme.github.io/lego) configuration, your private key, an authorized user ID, and the domain you'd like to obtain a certificate for.\n3. Certifier begin the Certificate Request flow and will receive a Challenge Response. It will then begin to serve a TXT record containing the Challenge Response at the domain `testdomain-com.\u003cCID\u003e.acme.mydomain.com`.\n4. Certifier will manually verify that the TXT record exists and is valid before proceeding with the certificate request flow.\n5. Let's Encrypt will then look up the TXT Record at `_acme-challenge.testdomain.com` and will be told via the CNAME record you created to instead query the TXT Record at `testdomain-com.\u003cCID\u003e.acme.mydomain.com`.\n6. Let's Encrypt will then query the NS Record of `testdomain-com.\u003cCID\u003e.acme.mydomain.com` and receive the IP address of your Certifier instance. It will then query the TXT Record at `testdomain-com.\u003cCID\u003e.acme.mydomain.com` where your Certifier will respond with the ACME Challenge Response password that was stored during step 3.\n7. Let's Encrypt will then return a valid certificate, and Certifier will clean up the TXT Record at `testdomain-com.\u003cCID\u003e.acme.mydomain.com` - but you should leave the CNAME Record for `_acme-challenge.testdomain.com` pointing to your certifier instance for future renewals.\n\n## Demo Command\n\nThere is a very simple demo application in this repo that will demonstrate end-to-end how to use Certifier + [Lego ACME](https://go-acme.github.io/lego) to receive an SSL Certificate from Let's Encrypt.\n\nIt must be run on a server that is routable from the internet (a simple Digital Ocean VPS should work nicely), and it will get a valid SSL Certificate for a given domain.\n\nYou must first pick 3 separate domains:\n\n1. The domain that will point to your certifier instance (the server that certifier is running on, which is routable from the public internet) - as an example, we will use `certifier.loopholelabs.com`\n2. A certifier root domain - this will be used to tell let's encrypt which DNS Server it should query for a valid DNS-01 Challenge (in our case, that DNS Server is certifier) - as an example, we will use `acme.loopholelabs.com`\n3. The domain what you will obtain an SSL Certificate for - as an example, we will use `testdomain.loopholelabs.com`.\n\n### Set Up\n\nTo set up the demo command, begin by spinning up a VPS or any sort of server that is routable from the public internet. You'll want to make sure port `53` is open for `UDP` traffic. Note the public IP for this server - in this example, we will use `10.0.0.50`.\n\n1. Start by creating an `A` record for the first domain you picked that points to the public IP of your server - we picked `certifier.loopholelabs.com` so we'll create an `A` record that looks something like `certifier.loopholelabs.com A 10.0.0.50`\n2. Next, create the `NS` record that instructs let's encrypt to use your certifier instance as the DNS Server for DNS-01 Challenges - we picked `acme.loopholelabs.com` as our root domain, so we'll create an `NS` record that looks something like `acme.loopholelabs.com NS certifier.loopholelabs.com`\n3. Replace all the periods in the domain you'll be obtaining an SSL certificate for with hyphens (`-`) - we will call this the normalized domain - we picked `testdomain.loopholelabs.com` so our normalized domain would be `testdomain-loopholelabs-com`.\n4. For this demo application, the `CID` will always be `testcid` - however during real use of Certifier this will be an autogenerated UUID that will map to a user ID.\n5. Finally, create a `CNAME` record that points to the root domain you chose. The CNAME record should be of the form `\u003cnormalized domain\u003e.\u003cCID\u003e.\u003croot domain\u003e` - we picked `testdomain-loopholelabs-com` and `acme.loopholelabs.com`, so we'll create a `CNAME` record that looks something like `testdomain-loopholelabs-com.testcid.acme.loopholelabs.com`.\n\n## Running the Demo Command\n\nOnce you've completed the setup for running the Demo Command, you can run it like so:\n\n```bash\ngo run cmd/demo/main.go --listen \u003clisten address\u003e --root \u003croot domain\u003e --public \u003ccertifier domain\u003e --email \u003cyour email\u003e --domain \u003cthe domain you want to obtain an SSL certificate for\u003e --directory \u003cacme directory URL\u003e\n```\n\nFor this example, a working command would be\n\n```bash\ngo run cmd/demo/main.go --listen 0.0.0.0:53 --root acme.loopholelabs.com --public certifier.loopholelabs.com --email testemail@loopholelabs.io --domain testdomain.loopholelabs.com --directory https://acme-staging-v02.api.letsencrypt.org/directory\n```\n\nWe recommend testing with the Let's Encrypt Staging Directory First. It may take up to 24 hours for your DNS Records to propagate before you can run the Demo Command.\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at [https://github.com/loopholelabs/certifier][gitrepo]. For more\ncontribution information check\nout [the contribution guide](https://github.com/loopholelabs/certifier/blob/master/CONTRIBUTING.md).\n\n## License\n\nThe Certifier project is available as open source under the terms of\nthe [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0).\n\n## Code of Conduct\n\nEveryone interacting in the Certifier project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).\n\n## Project Managed By:\n\n[![https://loopholelabs.io][loopholelabs]](https://loopholelabs.io)\n\n[gitrepo]: https://github.com/loopholelabs/certifier\n[loopholelabs]: https://cdn.loopholelabs.io/loopholelabs/LoopholeLabsLogo.svg\n[loophomepage]: https://loopholelabs.io\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floopholelabs%2Fcertifier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Floopholelabs%2Fcertifier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Floopholelabs%2Fcertifier/lists"}