{"id":19592249,"url":"https://github.com/catalyst/acmeproxy","last_synced_at":"2025-04-27T14:33:38.725Z","repository":{"id":14625204,"uuid":"70022629","full_name":"catalyst/acmeproxy","owner":"catalyst","description":"PowerDNS backend for serving ACME dns-01 challenge responses","archived":false,"fork":false,"pushed_at":"2022-11-07T01:34:08.000Z","size":104,"stargazers_count":17,"open_issues_count":6,"forks_count":4,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-05T00:51:14.165Z","etag":null,"topics":["acme-client","dns"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/catalyst.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":"2016-10-05T02:02:21.000Z","updated_at":"2025-01-08T19:18:39.000Z","dependencies_parsed_at":"2023-01-11T20:22:14.985Z","dependency_job_id":null,"html_url":"https://github.com/catalyst/acmeproxy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catalyst%2Facmeproxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catalyst%2Facmeproxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catalyst%2Facmeproxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catalyst%2Facmeproxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/catalyst","download_url":"https://codeload.github.com/catalyst/acmeproxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251154702,"owners_count":21544545,"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-client","dns"],"created_at":"2024-11-11T08:34:19.452Z","updated_at":"2025-04-27T14:33:37.872Z","avatar_url":"https://github.com/catalyst.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# acmeproxy\n\nThis PowerDNS backend only serves [ACME dns-01 challenge responses](https://letsencrypt.org/docs/acme-protocol-updates/), and exposes an HTTPS API to permit those challenge responses to be published by automated certificate renewal tools.\n\n## Dev environment\n\nYou can start a dev environemnt with\n\n    docker-compose up\n\nThe app will now be available at http://localhost:8080\n\n## Use with dehydrated or certbot\n\nExample plugins for [dehydrated](http://dehydrated.de/) and [certbot](https://certbot.eff.org/) are supplied in the `plugins` directory. Edit these plugin to specify the location of your acmeproxy installation and authorisation key registered with the API, then call them as a dns-01 hook.\n\nFor instance, with dehydrated:\n\n    dehydrated -c -t dns-01 -k ./acmeproxy-dehydrated.sh -d secure.example.com\n\n## Deployment\n\nInstall the app in a virtual environemnt with\n\n    pip install .\n\nIn a new directory make  a copy of `example_settings.py` called `acmeproxy_settings.py`. Then fill in all the values.\n\nWith your working directory set as the newly created directory you can now run the app as a wsgi app. With the environment variable `DJANGO_SETTINGS_MODULE` set to `acmeproxy_settings`. and the wsgi app at `acmeproxy.acmeproxy.wsgi:application`.\n\n### Example Apache configuration when certbot is used for the API certificate\n\n    \u003cVirtualHost *:443\u003e\n      ServerName acme-proxy-ns1.example.com\n      DocumentRoot /var/www/html\n\n      ErrorLog ${APACHE_LOG_DIR}/error.log\n      CustomLog ${APACHE_LOG_DIR}/access.log combined\n\n      ProxyPass / http://127.0.0.1:8000/\n      ProxyPassReverse / http://127.0.0.1:8000/\n\n      \u003cLocation /admin\u003e\n          Require ip 127.0.0.1\n      \u003c/Location\u003e\n\n      SSLCertificateFile /etc/letsencrypt/live/acme-proxy-ns1.example.com/fullchain.pem\n      SSLCertificateKeyFile /etc/letsencrypt/live/acme-proxy-ns1.example.com/privkey.pem\n      Include /etc/letsencrypt/options-ssl-apache.conf\n    \u003c/VirtualHost\u003e\n\n### Example PowerDNS configuration\n\nIn the directory with your settings file make a new file called `backend`.\n\nIn it put\n\n    #!/bin/sh\n    export DJANGO_SETTINGS_MODULE=acmeproxy_settings\n    /path/to/venv/django-admin pipeapi\n\n#### /etc/powerdns/pdns.conf\n\n    config-dir=/etc/powerdns\n    include-dir=/etc/powerdns/pdns.d\n    setgid=pdns\n    setuid=pdns\n\n#### /etc/powerdns/pdns.d/acmeproxy.conf\n\n    launch=pipe\n    pipe-command=/opt/acmeproxy/backend\n    pipe-timeout=4000\n\n## API documentation\n\n### HTTPS API usage\n\nAll API endpoints will return JSON containing a `result` key describing the result of the operation. If an operation fails this will be `false`, and the HTTP response code will indicate the nature of the failure.\n\n#### Authorisations\n\nBefore delegating any names an **authorisation** should be requested using the `create_authorisation` endpoint.\n\n    $ curl --data \"name=secure.example.com\" https://acme-proxy-ns1.example.com/create_authorisation\n    {\"result\": {\"secret\": \"52f562aedc99383c6af848bc7016380a\", \"authorisation\": \"secure.example.com\", \"suffix_match\": false}}\n\nIf authentication is enabled in your installation (with the `ACMEPROXY_AUTHORISATION_CREATION_SECRETS` setting configured to something other than `None`) you will also need to supply a `secret` field corresponding to the account being used.\n\nThe randomly generated `secret` returned by this call is then used to identify this authorisation in further calls to the API.\n\nTo re-generate the authentication secret for a given authorisation the `expire_authorisation` endpoint may be used.\n\n    $ curl --data \"name=secure.example.com\u0026secret=52f562aedc99383c6af848bc7016380a\" https://acme-proxy-ns1.example.com/expire_authorisation\n    {\"result\": {\"secret\": \"e04541b1d63bc68d296137bc2ee86923\", \"authorisation\": \"secure.example.com\", \"suffix_match\": false}}\n\n#### Challenge responses\n\nDuring an ACME dns-01 challenge it is necessary to publish a **challenge response** string supplied by the ACME client. The `publish_response` endpoint allows a response to be published for a name that has been registered with an authorisation.\n\n    $ curl --data \"name=secure.example.com\u0026response=evaGxfADs6pSRb2LAv9IZf17Dt3juxGJ-PCt92wr-oA\u0026secret=52f562aedc99383c6af848bc7016380a\" https://acme-proxy-ns1.example.com/publish_response\n    {\"result\": {\"authorisation\": \"secure.example.com\", \"suffix_match\": false, \"published\": true}}\n\nOptionally a client may request that all challenge responses for a name be expired once they are no longer required, however the backend will expire them regardless after five minutes.\n\n    $ curl --data \"name=secure.example.com\u0026secret=52f562aedc99383c6af848bc7016380a\" https://acme-proxy-ns1.example.com/expire_response\n    {\"result\": {\"authorisation\": \"secure.example.com\", \"suffix_match\": false, \"expired\": true}}\n\n### DNS usage\n\nSuppose you have a domain `example.com` and wish to issue certificates for `secure.example.com` without having an HTTP server running and without giving full control of the `example.com` zone to an ACME client.\n\nBy registering an authorisation through the HTTPS API then adding a delegation for the expected challenge, `_acme-challenge.secure.example.com` it is possible to response to those challenges with data supplied using an HTTPS POST to the server.\n\n    _acme-challenge.secure.example.com. IN NS acme-proxy-ns1.example.com\n\nIt should also be possible to load this backend along side your existing backends, though that functionality is not yet fully tested.\n\nOnce the delegation is made a response can be published using the `publish_response` endpoint of the HTTPS API during ACME certification issuance.\n\n### Command line tools\n\nThere are several Django management commands available in the `proxy` app.\n\n#### listauthorisations \n\nLists all authorisations present in the database.\n\n    $ python manage.py listauthorisations\n    name                   created_by_ip    created_at                        account\n    ---------------------  ---------------  --------------------------------  ---------\n    secure.example.com     192.0.2.1        2016-10-10 03:11:18.525111+00:00  operations\n    test.example.org       192.0.2.1        2016-10-10 03:50:35.827334+00:00  test\n    host1.example.com      192.0.2.1        2016-10-10 03:51:38.185688+00:00  operations\n\n#### deleteauthorisation\n\nPermanently remove an authorisation from the database.\n\n    $ python manage.py deleteauthorisation test.example.org\n    Successfully deleted authorisation \"test.example.org\"\n\n#### listresponses\n\nList the audit log of challenge responses that have been published, optionally between any two dates.\n\n    $ python manage.py listresponses --start=2016-09-01 --end=2016-12-30\n    name                 expired_at                        created_by_ip    created_at\n    -------------------  --------------------------------  ---------------  --------------------------------\n    secure.example.com   2016-10-10 03:12:05.984890+00:00  192.0.2.1        2016-10-09 21:47:24.236299+00:00\n    test.example.org     2016-10-10 03:12:05.984890+00:00  192.0.2.1        2016-10-10 03:12:04.833764+00:00\n\nA response will have an `expired_at` value if the ACME client explicitly marked all challenges for a name as complete.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatalyst%2Facmeproxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcatalyst%2Facmeproxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatalyst%2Facmeproxy/lists"}