• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

tests/H03-May-2022-378312

.gitignoreH A D07-Jul-2019702 5848

.travis.ymlH A D07-Jul-2019579 2827

LICENSEH A D07-Jul-20191.1 KiB2317

README.mdH A D07-Jul-20198.3 KiB214162

acme_tiny.pyH A D03-May-202211.2 KiB199154

setup.cfgH A D07-Jul-201923 32

setup.pyH A D07-Jul-20191.1 KiB3230

README.md

1# acme-tiny
2
3[![Build Status](https://travis-ci.org/diafygi/acme-tiny.svg)](https://travis-ci.org/diafygi/acme-tiny)
4[![Coverage Status](https://coveralls.io/repos/diafygi/acme-tiny/badge.svg?branch=master&service=github)](https://coveralls.io/github/diafygi/acme-tiny?branch=master)
5
6This is a tiny, auditable script that you can throw on your server to issue
7and renew [Let's Encrypt](https://letsencrypt.org/) certificates. Since it has
8to be run on your server and have access to your private Let's Encrypt account
9key, I tried to make it as tiny as possible (currently less than 200 lines).
10The only prerequisites are python and openssl.
11
12**PLEASE READ THE SOURCE CODE! YOU MUST TRUST IT WITH YOUR PRIVATE ACCOUNT KEY!**
13
14## Donate
15
16If this script is useful to you, please donate to the EFF. I don't work there,
17but they do fantastic work.
18
19[https://eff.org/donate/](https://eff.org/donate/)
20
21## How to use this script
22
23If you already have a Let's Encrypt issued certificate and just want to renew,
24you should only have to do Steps 3 and 6.
25
26### Step 1: Create a Let's Encrypt account private key (if you haven't already)
27
28You must have a public key registered with Let's Encrypt and sign your requests
29with the corresponding private key. If you don't understand what I just said,
30this script likely isn't for you! Please use the official Let's Encrypt
31[client](https://github.com/letsencrypt/letsencrypt).
32To accomplish this you need to initially create a key, that can be used by
33acme-tiny, to register an account for you and sign all following requests.
34
35```
36openssl genrsa 4096 > account.key
37```
38
39#### Use existing Let's Encrypt key
40
41Alternatively you can convert your key, previously generated by the original
42Let's Encrypt client.
43
44The private account key from the Let's Encrypt client is saved in the
45[JWK](https://tools.ietf.org/html/rfc7517) format. `acme-tiny` is using the PEM
46key format. To convert the key, you can use the tool
47[conversion script](https://gist.github.com/JonLundy/f25c99ee0770e19dc595) by JonLundy:
48
49```sh
50# Download the script
51wget -O - "https://gist.githubusercontent.com/JonLundy/f25c99ee0770e19dc595/raw/6035c1c8938fae85810de6aad1ecf6e2db663e26/conv.py" > conv.py
52
53# Copy your private key to your working directory
54cp /etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/<id>/private_key.json private_key.json
55
56# Create a DER encoded private key
57openssl asn1parse -noout -out private_key.der -genconf <(python conv.py private_key.json)
58
59# Convert to PEM
60openssl rsa -in private_key.der -inform der > account.key
61```
62
63### Step 2: Create a certificate signing request (CSR) for your domains.
64
65The ACME protocol (what Let's Encrypt uses) requires a CSR file to be submitted
66to it, even for renewals. You can use the same CSR for multiple renewals. NOTE:
67you can't use your account private key as your domain private key!
68
69```
70# Generate a domain private key (if you haven't already)
71openssl genrsa 4096 > domain.key
72```
73
74```
75# For a single domain
76openssl req -new -sha256 -key domain.key -subj "/CN=yoursite.com" > domain.csr
77
78# For multiple domains (use this one if you want both www.yoursite.com and yoursite.com)
79openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:yoursite.com,DNS:www.yoursite.com")) > domain.csr
80```
81
82### Step 3: Make your website host challenge files
83
84You must prove you own the domains you want a certificate for, so Let's Encrypt
85requires you host some files on them. This script will generate and write those
86files in the folder you specify, so all you need to do is make sure that this
87folder is served under the ".well-known/acme-challenge/" url path. NOTE: Let's
88Encrypt will perform a plain HTTP request to port 80 on your server, so you
89must serve the challenge files via HTTP (a redirect to HTTPS is fine too).
90
91```
92# Make some challenge folder (modify to suit your needs)
93mkdir -p /var/www/challenges/
94```
95
96```nginx
97# Example for nginx
98server {
99    listen 80;
100    server_name yoursite.com www.yoursite.com;
101
102    location /.well-known/acme-challenge/ {
103        alias /var/www/challenges/;
104        try_files $uri =404;
105    }
106
107    ...the rest of your config
108}
109```
110
111### Step 4: Get a signed certificate!
112
113Now that you have setup your server and generated all the needed files, run this
114script on your server with the permissions needed to write to the above folder
115and read your private account key and CSR.
116
117```
118# Run the script on your server
119python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ > ./signed_chain.crt
120```
121
122### Step 5: Install the certificate
123
124The signed https certificate chain that is output by this script can be used along
125with your private key to run an https server. You need to include them in the
126https settings in your web server's configuration. Here's an example on how to
127configure an nginx server:
128
129```nginx
130server {
131    listen 443 ssl;
132    server_name yoursite.com, www.yoursite.com;
133
134    ssl_certificate /path/to/signed_chain.crt;
135    ssl_certificate_key /path/to/domain.key;
136    ssl_session_timeout 5m;
137    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
138    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
139    ssl_session_cache shared:SSL:50m;
140    ssl_dhparam /path/to/server.dhparam;
141    ssl_prefer_server_ciphers on;
142
143    ...the rest of your config
144}
145
146server {
147    listen 80;
148    server_name yoursite.com, www.yoursite.com;
149
150    location /.well-known/acme-challenge/ {
151        alias /var/www/challenges/;
152        try_files $uri =404;
153    }
154
155    ...the rest of your config
156}
157```
158
159### Step 6: Setup an auto-renew cronjob
160
161Congrats! Your website is now using https! Unfortunately, Let's Encrypt
162certificates only last for 90 days, so you need to renew them often. No worries!
163It's automated! Just make a bash script and add it to your crontab (see below
164for example script).
165
166Example of a `renew_cert.sh`:
167```sh
168#!/usr/bin/sh
169python /path/to/acme_tiny.py --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /var/www/challenges/ > /path/to/signed_chain.crt.tmp || exit
170mv /path/to/signed_chain.crt.tmp /path/to/signed_chain.crt
171service nginx reload
172```
173
174```
175# Example line in your crontab (runs once per month)
1760 0 1 * * /path/to/renew_cert.sh 2>> /var/log/acme_tiny.log
177```
178
179NOTE: Since Let's Encrypt's ACME v2 release (acme-tiny 4.0.0+), the intermediate
180certificate is included in the issued certificate download, so you no longer have
181to independently download the intermediate certificate and concatenate it to your
182signed certificate. If you have an bash script using acme-tiny &lt;4.0 (e.g. before
1832018-03-17) with acme-tiny 4.0.0+, then you may be adding the intermediate
184certificate to your signed_chain.crt twice (not a big deal, it should still work fine,
185but just makes the certificate slightly larger than it needs to be). To fix,
186simply remove the bash code where you're downloading the intermediate and adding
187it to the acme-tiny certificate output.
188
189## Permissions
190
191The biggest problem you'll likely come across while setting up and running this
192script is permissions. You want to limit access to your account private key and
193challenge web folder as much as possible. I'd recommend creating a user
194specifically for handling this script, the account private key, and the
195challenge folder. Then add the ability for that user to write to your installed
196certificate file (e.g. `/path/to/signed_chain.crt`) and reload your webserver. That
197way, the cron script will do its thing, overwrite your old certificate, and
198reload your webserver without having permission to do anything else.
199
200**BE SURE TO:**
201* Backup your account private key (e.g. `account.key`)
202* Don't allow this script to be able to read your domain private key!
203* Don't allow this script to be run as root!
204
205## Feedback/Contributing
206
207This project has a very, very limited scope and codebase. I'm happy to receive
208bug reports and pull requests, but please don't add any new features. This
209script must stay under 200 lines of code to ensure it can be easily audited by
210anyone who wants to run it.
211
212If you want to add features for your own setup to make things easier for you,
213please do! It's open source, so feel free to fork it and modify as necessary.
214