Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let's Encrypt Auto-Renew scripts #142

Closed
wants to merge 98 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
a424ce2
initial commit
frezbo Aug 24, 2016
7c90008
initial commit
frezbo Aug 24, 2016
346b977
Added Detailed Instructions
frezbo Aug 24, 2016
9114963
Fixed directory locations
frezbo Aug 24, 2016
2222830
Added comments and fixed location issues
frezbo Aug 24, 2016
b735b7b
Added nginx config
frezbo Aug 24, 2016
21af7cf
Fixed a typo
frezbo Aug 24, 2016
939ac56
Added patch from PR #116, thanks to andreascherbaum
frezbo Aug 26, 2016
4d4902e
Added ECDSA certificates, fixed openssl key generation issues
frezbo Aug 26, 2016
32a635c
Added missing colon in nginx config, added extra info
frezbo Aug 26, 2016
dabb8c9
Changed travis-ci
frezbo Aug 26, 2016
d7bc83b
Added python version
frezbo Aug 26, 2016
7d66a7b
Added python version
frezbo Aug 26, 2016
dbab375
Addebuild
frezbo Aug 26, 2016
3a63cd7
Addebuild
frezbo Aug 26, 2016
cab38c7
Fixed command
frezbo Aug 27, 2016
6966f63
Build
frezbo Aug 27, 2016
21c46cf
Patched test_module
frezbo Aug 27, 2016
e8ed35c
testing
frezbo Aug 27, 2016
436a444
test script
frezbo Aug 27, 2016
20ab63f
testing
frezbo Aug 27, 2016
c271544
Added missing sudo
frezbo Aug 27, 2016
5cc07d3
fixed
frezbo Aug 27, 2016
e081114
added nginx config file
frezbo Aug 27, 2016
a0922a3
added nginx config file
frezbo Aug 27, 2016
00102e0
Added sleep time
frezbo Aug 27, 2016
8f35856
Increased sleep time
frezbo Aug 27, 2016
ec1a21f
added missing -y flag with apt-get
frezbo Aug 27, 2016
e3b03fa
changed sleep time
frezbo Aug 27, 2016
b5b3477
changed sleep time
frezbo Aug 27, 2016
3d99cfa
debugging
frezbo Aug 27, 2016
5f93df3
debugging
frezbo Aug 27, 2016
930353e
debugging
frezbo Aug 27, 2016
abaa6cb
debugging
frezbo Aug 27, 2016
5cf1597
debugging
frezbo Aug 27, 2016
a9a26aa
debugging
frezbo Aug 27, 2016
4a775d4
removed non-existent domain check
frezbo Aug 28, 2016
114bfd5
removed non-existent domain check
frezbo Aug 28, 2016
c26cadc
fixed python server not serving challenges correctly
frezbo Aug 28, 2016
5817bf0
removed nginx config
frezbo Aug 28, 2016
3a2fc29
added ngrok for local testing
frezbo Aug 28, 2016
bd51e04
build
frezbo Aug 28, 2016
8d21de1
build
frezbo Aug 28, 2016
b71df0d
fixed typo
frezbo Aug 28, 2016
0054e69
corrected ENV's
frezbo Aug 29, 2016
674b5ef
corrected typo
frezbo Aug 29, 2016
73f521a
fixed running python server after setting ENV
frezbo Aug 29, 2016
6ef151f
testing on all python versions
frezbo Aug 29, 2016
043ee21
trying non-existent domain check
frezbo Aug 29, 2016
e795d55
trying non-existent domain check
frezbo Aug 29, 2016
91a3d53
trying non-existent domain check
frezbo Aug 29, 2016
f1a45b8
Added ec key generation
frezbo Aug 29, 2016
4b98adb
Updated README to reflect modified test method
frezbo Aug 29, 2016
23b9570
Changed the name of non-existent domain from default to a non-existen…
frezbo Aug 29, 2016
70e142b
added missing dot
frezbo Aug 30, 2016
16c20f7
Updated readme as per new renwal script
frezbo Aug 30, 2016
c1ad541
Removed unwanted line
frezbo Aug 30, 2016
ae16578
Added suggestions by aplanas
frezbo Aug 30, 2016
34d82a8
Removed FUSE required and added nginx to serve the files
frezbo Aug 31, 2016
b883050
Removed FUSE requirement and added nginx to serve the files
frezbo Aug 31, 2016
276b2fb
Removed fusepy
frezbo Aug 31, 2016
d122084
Removed FUSE requirement and added nginx to serve the files
frezbo Aug 31, 2016
97cdfab
Removed FUSE documentation from README
frezbo Aug 31, 2016
3e0494b
Removed server.py as it is no longer needed
frezbo Aug 31, 2016
732088b
Updated to reflect the new test method
frezbo Aug 31, 2016
6dde02e
Added missing permission for /var/www/html/.well-known
frezbo Aug 31, 2016
27e0738
Added missing permission for /var/www/html/.well-known
frezbo Aug 31, 2016
ec749b5
testing new method
frezbo Aug 31, 2016
4390744
added permissions
frezbo Aug 31, 2016
263fbbd
testing
frezbo Aug 31, 2016
1e59f0e
testing
frezbo Aug 31, 2016
b7a1941
corrected permissions
frezbo Aug 31, 2016
dfef983
corrected permissions
frezbo Aug 31, 2016
65b7fd9
Removed delay
frezbo Aug 31, 2016
9ca772e
Added check for test OS release which was causing failed builds
frezbo Aug 31, 2016
1ca2bff
Adding sleep time to debug
frezbo Aug 31, 2016
e8daf4a
Added missing sudo
frezbo Aug 31, 2016
9fb0b6b
removed sleep time
frezbo Aug 31, 2016
9953c0a
Updated README
frezbo Aug 31, 2016
62a640a
Added comments
frezbo Aug 31, 2016
bf6097e
Removed __init__.py
frezbo Aug 31, 2016
4cbaa84
Updated README
frezbo Aug 31, 2016
66f5a78
Changed default TLD from io to com
frezbo Aug 31, 2016
b85ae57
Required for python, adding back
frezbo Aug 31, 2016
fa6204f
Added codeclimate
frezbo Aug 31, 2016
79a56f6
Added codeclimate
frezbo Aug 31, 2016
4e57ec3
Changed the file to reflect updated renew.sh
frezbo Sep 1, 2016
57b9fa2
Changed the file to reflect updated renew.sh
frezbo Sep 1, 2016
8c63149
Updated renew.sh and made more parameters as variables
frezbo Sep 1, 2016
ca0d80a
Added more variables and comments
frezbo Sep 1, 2016
f5f0603
Added full path for let's encrypt intermediate certificate
frezbo Sep 1, 2016
b6ab9f7
Added codeclimate coverage
frezbo Sep 2, 2016
ac956a0
Added codeclimate coverage
frezbo Sep 2, 2016
05205f6
Updated README
frezbo Sep 5, 2016
b231b5d
Updated script to allow authorization for account, when prior authori…
Nov 12, 2016
522b723
Fixed typo
Nov 12, 2016
e92c7e0
Reverting back to 05205f6
Nov 12, 2016
9a9fcf7
Updated script to allow authorization for account, when prior authori…
Nov 12, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
engines:
duplication:
enabled: true
config:
languages:
- ruby
- javascript
- python
- php
fixme:
enabled: true
radon:
enabled: true
ratings:
paths:
- "**.inc"
- "**.js"
- "**.jsx"
- "**.module"
- "**.php"
- "**.py"
- "**.rb"
exclude_paths:
- tests/
26 changes: 16 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,23 @@ sudo: required
dist: trusty
language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "nightly"
- '2.7'
- '3.3'
- '3.4'
- '3.5'
- nightly
before_install:
- sudo apt-get install fuse
- sudo chmod a+r /etc/fuse.conf
- chmod u+x ./tests/tests.sh
- "./tests/tests.sh"
install:
- pip install -r tests/requirements.txt
- pip install -r tests/requirements.txt
script:
- coverage run --source ./ --omit ./tests/server.py -m unittest tests
- export TRAVIS_DOMAIN=$(grep -Eoi "hostname:[A-za-z0-9]+.ngrok.io" url.log| head
-1 | cut -d ":" -f2)
- coverage run --source ./ --omit ./tests/server.py -m unittest tests
after_success:
- coveralls
- coveralls
- codeclimate-test-reporter
env:
global:
secure: aBBxGeWFRSvI+9Gi6VFnNZyiXQCtS9VYugMGcJoG+kYYa9D1Q79Ecq2bwRmbd2dK9S1rRmixP1m94HknS0unls3nlVCc/nacR6LwrRfUTJmSP7/8T5T6AX4yxZ/Dzr0Tw3GjpS/Lw8k3qirc9KT5W0jFYkEAhojwproxKqEFQ+XtXlgHRjtuYHkL/t6MTuXdd1cyvZo4SuFJehebh3/OamIBmYKbivlB/5GxJIbaZws0JkUwFeuoFSSbCc5PIHZGltlJRZNPOcrhW0AATAFb9FedxCa3TEMm3SAMkRcKZdsnPghqEX0hncTSThYsg+w44sDuyWYO0wnFAwThxNyOJ3NADeycmOmPgUd0MQHHTt9aqRWEXm/crxEARl8EB9Zy6PgkQlGEiBP8yPqNBOJtyWpm/oUmBqLMcsrkqDjBDzVMLL8Rv7vvzgssAfCJEP43LPsjoaKCooZ4qBqAJvCR718YjFcdGSIFr2Wj2ZZ47KxkTad1JV8aRalfOS/X+oaXLorEiOoG2kt934duBemEbSvX1Dwol0fV0Klg1mzezNULsAH48tmGbmKjkGcqwzFh76lpRW9eFLqN7NuQ3ZjwE2gPO/gRmCXDOfFYzsvsb814otgFfUdTEbxmPgDE0FZWnD/Um8t5ClfsD3yRsBz3xTHIjT6wwkQoX9A9FRSht2g=
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# acme-tiny

[![Build Status](https://travis-ci.org/diafygi/acme-tiny.svg)](https://travis-ci.org/diafygi/acme-tiny)
[![Coverage Status](https://coveralls.io/repos/diafygi/acme-tiny/badge.svg?branch=master&service=github)](https://coveralls.io/github/diafygi/acme-tiny?branch=master)
# acme-tiny [![Build Status](https://travis-ci.org/frezbo/acme-tiny.svg?branch=master)](https://travis-ci.org/frezbo/acme-tiny) [![Coverage Status](https://coveralls.io/repos/github/frezbo/acme-tiny/badge.svg?branch=master)](https://coveralls.io/github/frezbo/acme-tiny?branch=master) [![Code Climate](https://codeclimate.com/github/frezbo/acme-tiny/badges/gpa.svg)](https://codeclimate.com/github/frezbo/acme-tiny) [![Test Coverage](https://codeclimate.com/github/frezbo/acme-tiny/badges/coverage.svg)](https://codeclimate.com/github/frezbo/acme-tiny/coverage) [![Issue Count](https://codeclimate.com/github/frezbo/acme-tiny/badges/issue_count.svg)](https://codeclimate.com/github/frezbo/acme-tiny)

This is a tiny, auditable script that you can throw on your server to issue
and renew [Let's Encrypt](https://letsencrypt.org/) certificates. Since it has
Expand Down Expand Up @@ -68,7 +65,13 @@ you can't use your account private key as your domain private key!

```
#generate a domain private key (if you haven't already)
openssl genrsa 4096 > domain.key

For rsa key
`openssl genrsa 4096 > domain.key`

For ec key

`openssl ecparam -genkey -name secp384r1 | openssl ec -out domain.key`
```

```
Expand Down Expand Up @@ -209,3 +212,5 @@ anyone who wants to run it.

If you want to add features for your own setup to make things easier for you,
please do! It's open source, so feel free to fork it and modify as necessary.

Any help regarding adding dns-01 challenge validation to the python script is appreciated
28 changes: 15 additions & 13 deletions acme_tiny.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
LOGGER.addHandler(logging.StreamHandler())
LOGGER.setLevel(logging.INFO)

def get_crt(account_key, csr, acme_dir, log=LOGGER, CA=DEFAULT_CA):
def get_crt(account_key, csr, acme_dir, verifychallenge, log=LOGGER, CA=DEFAULT_CA):
# helper function base64 encode for jose spec
def _b64(b):
return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "")
Expand Down Expand Up @@ -104,23 +104,24 @@ def _send_signed_request(url, payload):
raise ValueError("Error requesting challenges: {0} {1}".format(code, result))

# make the challenge file
challenge = [c for c in json.loads(result.decode('utf8'))['challenges'] if c['type'] == "http-01"][0]
challenge = [c for c in json.loads(result.decode('utf8'))['challenges'] if c['type'] == "http-01" or c['status'] == "valid"][0]
token = re.sub(r"[^A-Za-z0-9_\-]", "_", challenge['token'])
keyauthorization = "{0}.{1}".format(token, thumbprint)
wellknown_path = os.path.join(acme_dir, token)
with open(wellknown_path, "w") as wellknown_file:
wellknown_file.write(keyauthorization)

# check that the file is in place
wellknown_url = "http://{0}/.well-known/acme-challenge/{1}".format(domain, token)
try:
resp = urlopen(wellknown_url)
resp_data = resp.read().decode('utf8').strip()
assert resp_data == keyauthorization
except (IOError, AssertionError):
os.remove(wellknown_path)
raise ValueError("Wrote file to {0}, but couldn't download {1}".format(
wellknown_path, wellknown_url))
if verifychallenge == True:
# check that the file is in place
wellknown_url = "http://{0}/.well-known/acme-challenge/{1}".format(domain, token)
try:
resp = urlopen(wellknown_url)
resp_data = resp.read().decode('utf8').strip()
assert resp_data == keyauthorization
except (IOError, AssertionError):
os.remove(wellknown_path)
raise ValueError("Wrote file to {0}, but couldn't download {1}".format(
wellknown_path, wellknown_url))

# notify challenge are met
code, result = _send_signed_request(challenge['uri'], {
Expand Down Expand Up @@ -188,10 +189,11 @@ def main(argv):
parser.add_argument("--acme-dir", required=True, help="path to the .well-known/acme-challenge/ directory")
parser.add_argument("--quiet", action="store_const", const=logging.ERROR, help="suppress output except for errors")
parser.add_argument("--ca", default=DEFAULT_CA, help="certificate authority, default is Let's Encrypt")
parser.add_argument("--no-verify", dest="verifychallenge", action="store_false", help="do not verify the acme challenge")

args = parser.parse_args(argv)
LOGGER.setLevel(args.quiet or LOGGER.level)
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, log=LOGGER, CA=args.ca)
signed_crt = get_crt(args.account_key, args.csr, args.acme_dir, verifychallenge=args.verifychallenge, log=LOGGER, CA=args.ca)
sys.stdout.write(signed_crt)

if __name__ == "__main__": # pragma: no cover
Expand Down
81 changes: 81 additions & 0 deletions lets-encrypt_acme_renew_script/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Lets Encrypt Renewal script
* Please read the scripts before you run them.

## Setup

### Assumes that the server has already been configured with nginx with SSL as per the README in acme-tiny

1. Download the server_setup.sh script:
```
wget https://raw.githubusercontent.com/frezbo/acme-tiny/master/lets-encrypt_acme_renew_script/server_setup.sh
```
<br/>
2. Make the script executable: `chmod u+x server_setup.sh` <br/>
3. Run server_setup.sh as root: `./server_setup.sh` <br/>
4. If you did not modify the locations in your scrips, follow the steps below, otherwise make changes as necessary <br/>
5. Copy the existing certificate to /etc/nginx/ssl/certs, make sure it follows the format domain.tld.ec.crt for ec certificates or domain.tld.rsa.crt for rsa certificates. For example if your domain is domain.tld and has subdomains like subdomain.domain.tld do the following: <br/><br/> `cp <path to your certificate> /etc/nginx/ssl/certs` <br/><br/> Make sure to copy the certificates of all the subdomains too. <br/>
6. Copy the domain keys to /etc/nginx/ssl/private, make sure it follows the format domian.com.ec.key for ec keys or domain.tld.rsa.crt for rsa keys. For example if your domain is domain.tld and has subdomains like subdomain.domain.tld do the following: <br/><br/> `cp <path to your domain key> /etc/nginx/ssl/private` <br/><br/> Make sure to copy the certificates of all the subdomains too. <br/>
7. Make the necessary location changes for the domain private key and certificate location in your nginx configuration <br/>
8. Run `nginx -t` and make sure there are no errors. <br/>
9. The script creates a user named *acme* which renews the certificates, the script also creates your private key used for authenticating with lets-encrypt and signing necessary files. Please keep this key very private. The key is located in */usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script*. <br/>
10. Edit the file domains.cnf located at */usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script/domains.cnf* and add the email id at line 8, add necessary country code, state,location and organizaion info as required. <br/>
11. Edit the file domains.txt located at */usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script/domains.txt* and add your domains on each line. For example if your domain is domain.tld and has subdomains like subdomain.domain.tld do the following:
```
domain
subdomain.domain
```
<br/>
12. Edit the file renew.sh located at */usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script/renew.sh* and add your tld in quotes on line 3. <br/>
13. Make a cron job to run every month as user acme to check for renewals:
```
crontab -eu acme
```
<br/>
At the end of line add this:
```
* * 3 * * /usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script/renew.sh >> /var/log/renew.log 2>&1
```
<br/>
14. Make the script executable: `chmod u+x /usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script/renew.sh` <br/>
15. If you want to manually run the script:
```
sudo -u acme /usr/local/scripts/acme-tiny/lets-encrypt_acme_renew_script/renew.sh
```
<br/>
16. Set the nginx configuration as follows:

### nginx configuration <br/> nginx versions above 1.10.0 supports both ECDSA and RSA certificates together otherwise stick with a single type

#### Base domain
```
server {
server_name domain.tld
ssl_certificate /etc/nginx/ssl/certs/domain.tld.ec.crt;
ssl_certificate_key /etc/nginx/ssl/private/domain.tld.ec.key;
ssl_certificate /etc/nginx/ssl/certs/domain.tld.rsa.crt;
ssl_certificate_key /etc/nginx/ssl/private/domain.tld.rsa.key;
location ~ .well-known/ {
root /var/www/html; #change as per your document root
try_files $uri =404;
log_not_found off;
}
}
```

#### Sub-domain
```
server {
server_name subdomain.domain.tld
ssl_certificate /etc/nginx/ssl/certs/subdomain.domain.tld.ec.crt;
ssl_certificate_key /etc/nginx/ssl/private/subdomain.domain.tld.ec.key;
ssl_certificate /etc/nginx/ssl/certs/subdomain.domain.tld.rsa.crt;
ssl_certificate_key /etc/nginx/ssl/private/subdomain.domain.tld.rsa.key;
location ~ .well-known/ {
root /var/www/html; #change as per your document root
try_files $uri =404;
log_not_found off;
}
}
```

## Enjoy
16 changes: 16 additions & 0 deletions lets-encrypt_acme_renew_script/domains.cnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[req]
prompt = no
distinguished_name = dn
req_extensions = ext

[dn]
CN = __DOMAIN__
emailAddress = [email protected]
O = <your-organization>
C = <country-code>
L = <location>
ST = <state>

[ext]
subjectAltName = DNS:www.__DOMAIN__,DNS:__DOMAIN__

2 changes: 2 additions & 0 deletions lets-encrypt_acme_renew_script/domains.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
domain
subdomain.domain.com
67 changes: 67 additions & 0 deletions lets-encrypt_acme_renew_script/renew.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash
#Author: TechnoMan, mail: [email protected]
tld="com" #set your domain extension, eg: com, edu, org etc
days_to_expire=30 #certificates are renewed before a month of expiry
document_root=/var/www/html # change to your document root
scripts_directory=/usr/local/scripts # scripts directory
acme_directory=acme-tiny/lets-encrypt_acme_renew_script
nginx_config_location=/etc/nginx #change if this is not your config directory
#certificate file location
#private key file
priv_key_file=priv.key
certs_location=${nginx_config_location}/ssl/certs
#domain keys location
keys_location=${nginx_config_location}/ssl/private
#file containing list of domains
domain_file=${scripts_directory}/${acme_directory}/domains.txt
#file containing CSR genreation parameters
csr_params=${scripts_directory}/${acme_directory}/domains.cnf
#intermediate certificate
int_cert=${scripts_directory}/${acme_directory}/intermediate.pem
#current unix time
curr_time=$(date +%s)
touch ${scripts_directory}/${acme_directory}/.rnd
export RANDFILE=${scripts_directory}/${acme_directory}/.rnd
#check whether certifcate expires within the days specified in days_to_expire
for i in $(cat $domain_file)
do
for cert_type in {ec,rsa}
do
if [ ! -e ${keys_location}/$i.$tld.$cert_type.key ]
then
echo "$cert_type key file not found. Copy the $cert_type key file in $i.$tld.$cert_type.key format as specified in README to ${keys_location}"
fi
if [ -e ${certs_location}/$i.$tld.$cert_type.crt ]
then
#certifcate expiry unix time
((cert_expire_time=$(date -d "$(openssl x509 -in ${certs_location}/$i.$tld.$cert_type.crt -noout -enddate | sed s/notAfter=//g)" +%s)))
#days to expire
((cert_days_untill_expiry=(cert_expire_time-curr_time)/86400))
if [ $cert_days_untill_expiry -le $days_to_expire ]
then
echo "$cert_days_untill_expiry days untill expiry for $cert_type cert"
if [ $cert_type == 'ec' ]
then
openssl genrsa -out ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.key 4096
else
openssl ecparam -genkey -name secp384r1 | openssl ec -out ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.key
fi
chmod 600 ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.key
sed -i "s/__DOMAIN__/$i.$tld/g" $csr_params
openssl req -new -config $csr_params -key ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.key -out ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.csr
sed -i "s/$i.$tld/__DOMAIN__/g" $csr_params
mv ${certs_location}/$i.$tld.$cert_type.crt ${certs_location}/$i.$tld.$cert_type.crt.old
mv ${keys_location}/$i.$tld.$cert_type.key ${keys_location}/$i.$tld.$cert_type.key.old
mv ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.key ${keys_location}
python ${scripts_directory}/acme-tiny/acme_tiny.py --account-key ${scripts_directory}/${acme_directory}/$priv_key_file --csr ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.csr --acme-dir ${document_root}/.well-known/acme-challenge > ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.tmp.crt
cat ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.tmp.crt ${scripts_directory}/${acme_directory}/$int_cert > ${certs_location}/$i.$tld.$cert_type.crt
rm -f ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.tmp.crt
rm -f ${scripts_directory}/${acme_directory}/$i.$tld.$cert_type.csr
fi
else
echo "$cert_type certificate file not found. Copy the $cert_type certificate file in $i.$tld.$cert_type.crt format as specified in README to ${certs_location}"
fi
done
done
rm -f ${scripts_directory}/${acme_directory}/.rnd
sudo nginx -s reload
27 changes: 27 additions & 0 deletions lets-encrypt_acme_renew_script/server_setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
document_root=/var/www/html # change to your document root
nginx_location=$(which nginx)
nginx_config_location=/etc/nginx #change if this is not your config directory
scripts_location=/usr/local/scripts # change if necessary
renew_scripts_location=${scripts_location}/acme-tiny/lets-encrypt_acme_renew_script
key_file=priv.key #if already has a key change this and set ownership to acme
certs_location=ssl
log_file=/var/log/acme_renew.log #log file
mkdir -p ${scripts_location}
useradd -r -d /nodir -s /usr/sbin/nologin acme #creating a user acme with no home directory and no login
git clone https://github.com/frezbo/acme-tiny.git ${scripts_location}/acme-tiny
openssl genrsa -out ${renew_scripts_location}/$key_file 4096 # generating private key for registering to lets encrypt and certificate generation, keep it very secure
chmod 400 ${renew_scripts_location}/$key_file
wget -O ${renew_scripts_location}/intermediate.pem https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem
chown -R acme:acme ${scripts_location}/acme-tiny
chmod 750 ${scripts_location}/acme-tiny
mkdir -p ${document_root}/.well-known/acme-challenge
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mkdir -p ${document_root}/.well-known/acme-challenge will be enough

chown -R www-data:acme ${document_root}/.well-known
chmod -R 770 ${document_root}/.well-known
echo "acme ALL = NOPASSWD: ${nginx_location} -s reload" > /etc/sudoers.d/acme
mkdir -p ${nginx_config_location}/${certs_location}/certs
mkdir -p ${nginx_config_location}/${certs_location}/private
chown -R acme:root ${nginx_config_location}/${certs_location}
chmod -R 770 ${nginx_config_location}/${certs_location}
touch $log_file
chown acme:acme $log_file
39 changes: 6 additions & 33 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,12 @@ explains how to setup and test acme-tiny yourself.

## Setup instructions

1. Make a test subdomain for a server you control. Set it as an environmental
variable on your local test setup.
* On your local: `export TRAVIS_DOMAIN=travis-ci.gethttpsforfree.com`
2. Generate a shared secret between your local test setup and your server.
* `openssl rand -base64 32`
* On your local: `export TRAVIS_SESSION="<random_string_here>"`
3. Copy and run the test suite mini-server on your server:
* `scp server.py [email protected]`
* `ssh [email protected]`
* `export TRAVIS_SESSION="<random_string_here>"`
* `sudo server.py`
4. Install the test requirements on your local (FUSE and optionally coveralls).
* `sudo apt-get install fuse`
* `virtualenv /tmp/venv`
* `source /tmp/venv/bin/activate`
* `pip install -r requirements.txt`
5. Run the test suit on your local.
Install the test requirements on your local machine. <br/>
* install ngrok: https://ngrok.com/
* `cd /path/to/acme-tiny`
* `chmod u+x tests/tests.sh`
* `./tests/tests.sh`
* `pip install -r tests/requirements.txt`
* `export TRAVIS_DOMAIN=$(grep -Eoi "hostname:[A-za-z0-9]+.ngrok.io" url.log| head -1 | cut -d ":" -f2)`
* `coverage run --source ./ --omit ./tests/server.py -m unittest tests`

## Why use FUSE?

Acme-tiny writes the challenge files for certificate issuance. In order to do
full integration tests, we actually need to serve correct challenge files to
the Let's Encrypt staging server on a real domain that they can verify. However,
Travis-CI doesn't have domains associated with their test VMs, so we need to
send the files to the remote server that does have a real domain.

The test suite uses FUSE to do this. It creates a FUSE folder that simulates
being a real folder to acme-tiny. When acme-tiny writes the challenge files
in the mock folder, FUSE POSTs those files to the real server (which is running
the included server.py), and the server starts serving them. That way, both
acme-tiny and Let's Encrypt staging can verify and issue the test certificate.
This technique allows for high test coverage on automated test runners (e.g.
Travis-CI).

Loading