{ "info": { "author": "Konstantin Shcherban", "author_email": "k.scherban@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "# acme-nginx\n\nSimple way to get SSL certificates for free.\n\n## Table of Contents\n\n- [Features](#features)\n- [Description](#description)\n- [ACME v2](#acme-v2)\n- [ACME v1](#acme-v1)\n- [Installation](#installation)\n- [Usage](#usage)\n * [Wildcard certificates](#wildcard-certificates)\n * [Debug](#debug)\n * [Renewal](#renewal)\n\n## Features\n\n* Supports both Python 2 and Python 3\n* Works with both ACMEv1 and ACMEv2 protocols\n* Can issue [wildcard certificates](https://en.wikipedia.org/wiki/Wildcard_certificate)!\n* Easy to use and extend\n\n## Description\n\nThis is [ACME](https://ietf-wg-acme.github.io/acme/) client implementation in\nPython originally based on https://github.com/diafygi/acme-tiny code.\nNow completely different.\nIt's written in pure Python depends on pyOpenSSL and pycrypto\nand the only binary it calls is **ps** to determine nginx master process id\nto send `SIGHUP` to it during challenge completion.\n\nAs you may not trust this script feel free to check source code,\nit's under 700 lines of code.\n\nScript should be run as root on host with running nginx server.\nDomain for which you request certificate should point to that host's IP and port\n80 should be available from outside if you use HTTP challenge.\nScript can generate all keys for you if you don't set them with command line arguments.\nKeys are RSA with length of 2048 bytes.\nYou can specify as many alternative domain names as you wish.\nThe result PEM file is a **certificate chain** containing your signed\ncertificate and letsencrypt signed chain. You can use it with nginx.\n\nShould work with Python >= 2.6\n\n## ACME v2\n\nACME v2 requires more logic so it's not as small as acme v1 script.\n\nACME v2 is supported partially: only `http-01` and `dns-01` challenges.\nCheck https://tools.ietf.org/html/draft-ietf-acme-acme-07#section-9.7.6\n\nNew protocol is used by default.\n\n`http-01` challenge is passed exactly as in v1 protocol realisation.\n\n`dns-01` currently supports only DigitalOcean, AWS Route53 DNS providers.\n\nTechnically nginx is not needed for this type of challenge but script still calls nginx reload by default\nbecause it assumes that you store certificates on the same server where you issue\nthem. To disable that behavior please specify `--no-reload-nginx` parameter.\n\nAWS Route53 uses `default` profile in session, specifying profile works with environment variables only.\nPlease check https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html#environment-variable-configuration\n\nIn case you want to add support of different DNS providers your contribution is \nhighly apprectiated.\n\nWildcard certificates can not be issued with non-wildcard for the same domain.\nI.e. it's not possible to issue certificates for `*.example.com` and\n`www.example.com` at the same time.\n\n## ACME v1\n\nStill supported with flag `--acme-v1`.\nOnly HTTP challenge is supported at the moment.\n\n## Installation\n\nPlease be informed that the quickiest and easiest way of installation is to use your OS\ninstallation way because Python way includes compilation of dependencies that\nmay take much time and CPU resources and may require you to install all build\ndependencies.\n\n### Fastest way\n\nJust download executable compiled with [pyinstaller](https://github.com/pyinstaller/pyinstaller).\n\n```\nwget https://github.com/kshcherban/acme-nginx/releases/download/v0.1.2/acme-nginx\nchmod +x acme-nginx\n```\n\n### Python way\n\nAutomatically\n```\npip install acme-nginx\n```\n\nor manually\n```\ngit clone https://github.com/kshcherban/acme-nginx\ncd acme-nginx\npython setup.py install\n```\n\n### Docker way\n\nYou can build docker image with acme-nginx inside:\n\n```\ndocker build -t acme-nginx .\ndocker run --rm -v /etc/nginx:/etc/nginx --pid=host \\\n\t-d example.com -d www.example.com\n```\n\nThere is also single binary in docker image compiled by `pyinstaller` , you can copy it like this:\n\n```\ndocker run --name acme acme-nginx\ndocker cp acme:/usr/bin/acme-runner acme-nginx\ndocker rm acme\n```\n\n\n\n### Debian/Ubuntu way\n\n```\nsudo apt-get install -y python-openssl python-crypto python-setuptools\nsudo python setup.py install\n```\n\n### CentOS/RedHat/Fedora way\n\n```\nsudo yum install -y pyOpenSSL python-crypto python-setuptools\nsudo yum groupinstall -y \"Development tools\"\nsudo python setup.py install\n```\n\n## Usage\n\nSimplest scenario: you have neither letsencrypt [account key](https://letsencrypt.org/docs/account-id/) nor domain key and want to generate\ncertificate for example.com and www.example.com\n\n```\nsudo acme-nginx -d example.com -d www.example.com\n```\n\nYou will see output similar to this:\n```\nOct 12 23:42:17 Can not open key /etc/ssl/private/letsencrypt-account.key, generating new\nOct 12 23:42:17 Can not open key /etc/ssl/private/letsencrypt-domain.key, generating new\nOct 12 23:42:17 Trying to register account key\nOct 12 23:42:18 Registered!\nOct 12 23:42:18 Requesting challenge\nOct 12 23:42:19 Adding nginx virtual host and completing challenge\nOct 12 23:42:19 Creating file /etc/nginx/sites-enabled/letsencrypt\nOct 12 23:42:21 example.com verified!\nOct 12 23:42:21 Requesting challenge\nOct 12 23:42:21 Adding nginx virtual host and completing challenge\nOct 12 23:42:21 Creating file /etc/nginx/sites-enabled/letsencrypt\nOct 12 23:42:23 www.example.com verified!\nOct 12 23:42:23 Signing certificate\nOct 12 23:42:23 Certificate signed!\nOct 12 23:42:23 Writing result file in /etc/ssl/private/letsencrypt-domain.pem\nOct 12 23:42:23 Removing /etc/nginx/sites-enabled/letsencrypt and sending HUP to nginx\n```\n\nCertificate was generated into `/etc/ssl/private/letsencrypt-domain.pem`\n\nYou can now configure nginx to use it:\n```\nserver {\n listen 443;\n ssl on;\n ssl_certificate /etc/ssl/private/letsencrypt-domain.pem;\n ssl_certificate_key /etc/ssl/private/letsencrypt-domain.key;\n ssl_protocols TLSv1 TLSv1.1 TLSv1.2;\n ...\n```\n\nTo renew it simply rerun the command! You can put it in cron, but don't forget\nabout letsencrypt [rate limits](https://letsencrypt.org/docs/rate-limits/).\n\nMore complicated scenario: you have both account, domain keys and custom virtual host\n```\nsudo acme-nginx \\\n -k /path/to/account.key \\\n --domain-private-key /path/to/domain.key \\\n --virtual-host /etc/nginx/sites-enabled/customvhost \\\n -o /path/to/signed_certificate.pem \\\n -d example.com -d www.example.com\n```\n\n### Wildcard certificates\n\nFor wildcard certificate you need to have your domain managed by DNS provider\nwith API. Currently only [DigitalOcean DNS](https://www.digitalocean.com/docs/networking/dns/) and\n[AWS Route53](https://aws.amazon.com/route53/) are supported.\n\nExample how to get wildcard certificate without nginx\n```\nsudo acme-nginx --no-reload-nginx --dns-provider route53 -d \"*.example.com\"\n```\n\n#### DigitalOcean\n\nPlease create and export your DO API token as `API_TOKEN` env variable.\nNow you can generate wildcard certificate\n```\nsudo su -\nexport API_TOKEN=yourDigitalOceanApiToken\nacme-nginx --dns-provider digitalocean -d '*.example.com'\n```\n\n### Debug\n\nTo debug please use `--debug` flag. With debug enabled all intermediate files\nwill not be removed, so you can check `/etc/nginx/sites-enabled` for temporary\nvirtual host configuration, by default it's `/etc/nginx/sites-enabled/0-letsencrypt.conf`.\n\nExecute `acme-nginx --help` to see all available flags and their default values.\n\n### Renewal\n\nPersonally i use following cronjob to renew certificates of my blog. Here's contents\nof `/etc/cron.d/renew-cert`\n\n```\nMAILTO=insider@prolinux.org\n12 11 10 * * root timeout -k 600 -s 9 3600 /usr/local/bin/acme-nginx -d prolinux.org -d www.prolinux.org >> /var/log/letsencrypt.log 2>&1 || echo \"Failed to renew certificate\"\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "https://github.com/kshcherban/acme-nginx/tarball/v0.2.1", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/kshcherban/acme-nginx", "keywords": "tls,ssl,certificate,acme,letsencrypt,nginx,wildcard certificate,wildcard", "license": "GPL v3", "maintainer": "", "maintainer_email": "", "name": "acme-nginx", "package_url": "https://pypi.org/project/acme-nginx/", "platform": "", "project_url": "https://pypi.org/project/acme-nginx/", "project_urls": { "Download": "https://github.com/kshcherban/acme-nginx/tarball/v0.2.1", "Homepage": "https://github.com/kshcherban/acme-nginx" }, "release_url": "https://pypi.org/project/acme-nginx/0.2.1/", "requires_dist": [ "pyOpenSSL (>=0.13)", "pycrypto (>=2.6)", "boto3 (~=1.9.30)" ], "requires_python": "", "summary": "A simple client/tool for Let's Encrypt or any ACME server that issues SSL certificates.", "version": "0.2.1" }, "last_serial": 5830464, "releases": { "0.0.3": [], "0.0.4": [ { "comment_text": "", "digests": { "md5": "97f7284ba55ec717eae222923e5914c9", "sha256": "31c506d509922192f3a9efadaba6118656974d03118e5bbd268095fb1c5d6d84" }, "downloads": -1, "filename": "acme-nginx-0.0.4.tar.gz", "has_sig": false, "md5_digest": "97f7284ba55ec717eae222923e5914c9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4755, "upload_time": "2016-12-16T07:43:34", "url": "https://files.pythonhosted.org/packages/65/ea/26fb8dc06fe2f4b420455e50eef78079f9d1964b682e269dcb06da850009/acme-nginx-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "0ca5595efa9feaf1620eb76fbfd1a31a", "sha256": "7befa47636448484e70095fe9af6416865487a3c5f91c936c253f0e4632719e9" }, "downloads": -1, "filename": "acme-nginx-0.0.5.tar.gz", "has_sig": false, "md5_digest": "0ca5595efa9feaf1620eb76fbfd1a31a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4858, "upload_time": "2017-03-04T16:48:09", "url": "https://files.pythonhosted.org/packages/56/90/3e2274ce84dbf936b215e0a1141216278572c78b9d2a26f5a4218c3f2bdc/acme-nginx-0.0.5.tar.gz" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "fe23eb7d143f60a457010b2539f8bfb0", "sha256": "4f53b6070cc45d22719d95899de14f51accc8b58bebae65af3db06ae9b68ef2f" }, "downloads": -1, "filename": "acme-nginx-0.0.6.tar.gz", "has_sig": false, "md5_digest": "fe23eb7d143f60a457010b2539f8bfb0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4889, "upload_time": "2017-06-10T22:02:57", "url": "https://files.pythonhosted.org/packages/45/32/64ae987b552ecfc2f0cd5db8faf4bdf69563270c686668da955c90e1a381/acme-nginx-0.0.6.tar.gz" } ], "0.0.7": [ { "comment_text": "", "digests": { "md5": "a938f058609672ec28194c4e1f6f3147", "sha256": "ad0c1f1feff6d2210c06d07e1537632a85072b972ef1a3d640a2d32cd55c8fe4" }, "downloads": -1, "filename": "acme-nginx-0.0.7.tar.gz", "has_sig": false, "md5_digest": "a938f058609672ec28194c4e1f6f3147", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4891, "upload_time": "2017-06-29T10:59:06", "url": "https://files.pythonhosted.org/packages/11/0a/641d81be69cae342a149800f4cb2c12f35b34e6bbad16f25fe842812246f/acme-nginx-0.0.7.tar.gz" } ], "0.0.8": [ { "comment_text": "", "digests": { "md5": "e434e58bc2076986a4104d6b3d243a6e", "sha256": "c061c9237f378e42508b3c06f8620f08b08c54497e09574918522eccf86cc778" }, "downloads": -1, "filename": "acme_nginx-0.0.8-py2-none-any.whl", "has_sig": false, "md5_digest": "e434e58bc2076986a4104d6b3d243a6e", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 6462, "upload_time": "2017-11-21T21:10:59", "url": "https://files.pythonhosted.org/packages/eb/73/f8f7ed9899792fcab666193cffb7c122d74d55e6417cc587e2f26700adb4/acme_nginx-0.0.8-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7ae6cab3152f6a54eb9281de3b8bbe1b", "sha256": "f19f31b50706fc2554298303934ed7df853e946c2573fed40d2f80a8314ff513" }, "downloads": -1, "filename": "acme_nginx-0.0.8-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7ae6cab3152f6a54eb9281de3b8bbe1b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 6465, "upload_time": "2017-11-21T21:19:23", "url": "https://files.pythonhosted.org/packages/f8/d4/8520f5d11588b601e2d2b899ecc69992c360ea5080249ccf2cfeca4380f0/acme_nginx-0.0.8-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b02c50643f25dc17b1855677d8e177f0", "sha256": "287ae49425193a97f4ec614691148ae786b09ac8309511c3a8f951d788c87732" }, "downloads": -1, "filename": "acme-nginx-0.0.8.tar.gz", "has_sig": false, "md5_digest": "b02c50643f25dc17b1855677d8e177f0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4913, "upload_time": "2017-11-21T21:11:26", "url": "https://files.pythonhosted.org/packages/86/b4/c9430346b0a31eb9056e0d0bba2fbb470f610f51ae4fe0969e7327bbcca5/acme-nginx-0.0.8.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "efb73a1e4ad2ee3da7c6af28c6024be4", "sha256": "0242cc673c6c43f4a1685570d64db896dcc3ce66c0f6af9f79a8217ac87ac4dd" }, "downloads": -1, "filename": "acme_nginx-0.1.1-3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "efb73a1e4ad2ee3da7c6af28c6024be4", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13157, "upload_time": "2018-07-29T11:09:36", "url": "https://files.pythonhosted.org/packages/22/7d/2f61f31051f274755b20a7c1053242cc32d872fd081d5b36e1d0ec441fed/acme_nginx-0.1.1-3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7e93c01667a34cce049457a854e36d6b", "sha256": "c280cfcfa9c7573b6db72d40cc504bf86b3e1f4c9cffa44638e54df982a4cc47" }, "downloads": -1, "filename": "acme-nginx-0.1.1-3.tar.gz", "has_sig": false, "md5_digest": "7e93c01667a34cce049457a854e36d6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13429, "upload_time": "2018-07-29T11:09:37", "url": "https://files.pythonhosted.org/packages/f0/60/26650053a6a3c620067b4dafa1754a751238de1a08c4f0cd42d107e27a75/acme-nginx-0.1.1-3.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "886166d99b5d0ebde93623b50c810996", "sha256": "17240fdbb1c7be4aaef319d95c28b8a121a68128465789d15c7187b3eb41ede9" }, "downloads": -1, "filename": "acme_nginx-0.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "886166d99b5d0ebde93623b50c810996", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13158, "upload_time": "2018-07-29T11:11:23", "url": "https://files.pythonhosted.org/packages/5c/6f/3331f4f832d478154ac39471c0ce4fbbec33ac57e3a61aa0a465ebbb63b9/acme_nginx-0.1.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "83aa3fecf8b45c21f21b752e77e488fb", "sha256": "ec822e841165c3efb5b8f9fc69d0da4f4ab654aadecf5b7c9b269acbb9ea3b5e" }, "downloads": -1, "filename": "acme-nginx-0.1.2.tar.gz", "has_sig": false, "md5_digest": "83aa3fecf8b45c21f21b752e77e488fb", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13428, "upload_time": "2018-07-29T11:11:25", "url": "https://files.pythonhosted.org/packages/a9/f4/cea71388f6123d5f4ceba6dee5667b832645987941b97a605ae940e306b1/acme-nginx-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "410dba6af4a3503e45e8f2e7925c32c8", "sha256": "a0b6c6cd39cc796a19d251ad65c79a0b36b642f79b876df385f0f4dbe3dcc50c" }, "downloads": -1, "filename": "acme_nginx-0.1.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "410dba6af4a3503e45e8f2e7925c32c8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13301, "upload_time": "2018-07-30T19:59:23", "url": "https://files.pythonhosted.org/packages/b4/77/d837f6b8bbf4a94ec7b3f27f2b9f9f57692a8757ca6ff7a7a21bf8c7fe3b/acme_nginx-0.1.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9ab3c6c3ee800248c45964cb518534df", "sha256": "2f32303ef450a952a5dca72093b7cd3545ec66f1a2855dd5faff97d54c222e9b" }, "downloads": -1, "filename": "acme-nginx-0.1.3.tar.gz", "has_sig": false, "md5_digest": "9ab3c6c3ee800248c45964cb518534df", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13640, "upload_time": "2018-07-30T19:59:25", "url": "https://files.pythonhosted.org/packages/0c/51/996b49125a4144d25a4737ca891bf3ab888ffbd976881b953714234ab147/acme-nginx-0.1.3.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "1e7b9d0d274dff2e3dec30f18d0419c8", "sha256": "4e84b930af4eee9f1755ab71ab3adf1c34ff9e5ff4df7320aa34c0e9fd6fb1c0" }, "downloads": -1, "filename": "acme_nginx-0.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "1e7b9d0d274dff2e3dec30f18d0419c8", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 14716, "upload_time": "2018-11-08T13:07:03", "url": "https://files.pythonhosted.org/packages/e1/7a/eac35f8952e92b2238939c0a0523b08f48fc8874f06f893cafe9bee18115/acme_nginx-0.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c8211c295cb5ddfff8a182d248192764", "sha256": "364df2c24b68eac42bb28384a06b1b09ce7b923af552107fcc0a3615ba13497c" }, "downloads": -1, "filename": "acme-nginx-0.2.0.tar.gz", "has_sig": false, "md5_digest": "c8211c295cb5ddfff8a182d248192764", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14923, "upload_time": "2018-11-08T13:06:37", "url": "https://files.pythonhosted.org/packages/32/6a/8f4a7a5354f442eca250c33153ed1741443ea7347835cd9d1ba53639352e/acme-nginx-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "8107c9932a541b684dd23ca741a62f49", "sha256": "b7fb28cc35112d1db5c4b879dc76304be9245c9387b55c40fa6d303ef1b82d2b" }, "downloads": -1, "filename": "acme_nginx-0.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "8107c9932a541b684dd23ca741a62f49", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 27129, "upload_time": "2019-09-14T23:17:53", "url": "https://files.pythonhosted.org/packages/59/6c/4be95135a861c0386971d56c1fca2c9627a612ee5b05e112a9fbb957aefa/acme_nginx-0.2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7554e944d8dbc9ae0d99f79d9289db76", "sha256": "c9d8472fc1f1b621a18f9c2a2cc53b99d6bc35b930c328b3d9fd86e921c10bc0" }, "downloads": -1, "filename": "acme-nginx-0.2.1.tar.gz", "has_sig": false, "md5_digest": "7554e944d8dbc9ae0d99f79d9289db76", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15082, "upload_time": "2019-09-14T23:17:55", "url": "https://files.pythonhosted.org/packages/62/36/69c56147347655b4b0101e65a4e96334181fd5b87068e6094e33896db303/acme-nginx-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "8107c9932a541b684dd23ca741a62f49", "sha256": "b7fb28cc35112d1db5c4b879dc76304be9245c9387b55c40fa6d303ef1b82d2b" }, "downloads": -1, "filename": "acme_nginx-0.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "8107c9932a541b684dd23ca741a62f49", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 27129, "upload_time": "2019-09-14T23:17:53", "url": "https://files.pythonhosted.org/packages/59/6c/4be95135a861c0386971d56c1fca2c9627a612ee5b05e112a9fbb957aefa/acme_nginx-0.2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7554e944d8dbc9ae0d99f79d9289db76", "sha256": "c9d8472fc1f1b621a18f9c2a2cc53b99d6bc35b930c328b3d9fd86e921c10bc0" }, "downloads": -1, "filename": "acme-nginx-0.2.1.tar.gz", "has_sig": false, "md5_digest": "7554e944d8dbc9ae0d99f79d9289db76", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15082, "upload_time": "2019-09-14T23:17:55", "url": "https://files.pythonhosted.org/packages/62/36/69c56147347655b4b0101e65a4e96334181fd5b87068e6094e33896db303/acme-nginx-0.2.1.tar.gz" } ] }