diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..2ce8a8209 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +# this file uses slightly different syntax than .gitignore, +# e.g. ".tox/" will not ignore .tox directory + +# well, official docker build should be done on clean git checkout +# anyway, so .tox should be empty... But I'm sure people will try to +# test docker on their git working directories. + +.git +.tox +venv +docs diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..b6a07388c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,61 @@ +# https://github.com/letsencrypt/lets-encrypt-preview/pull/431#issuecomment-103659297 +# it is more likely developers will already have ubuntu:trusty rather +# than e.g. debian:jessie and image size differences are negligible +FROM ubuntu:trusty +MAINTAINER Jakub Warmuz +MAINTAINER William Budington + +# Note: this only exposes the port to other docker containers. You +# still have to bind to 443@host at runtime, as per the ACME spec. +EXPOSE 443 + +# TODO: make sure --config-dir and --work-dir cannot be changed +# through the CLI (letsencrypt-docker wrapper that uses standalone +# authenticator and text mode only?) +VOLUME /etc/letsencrypt /var/lib/letsencrypt + +WORKDIR /opt/letsencrypt + +# no need to mkdir anything: +# https://docs.docker.com/reference/builder/#copy +# If doesn't exist, it is created along with all missing +# directories in its path. + +COPY bootstrap/ubuntu.sh /opt/letsencrypt/src/ +RUN /opt/letsencrypt/src/ubuntu.sh && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* \ + /tmp/* \ + /var/tmp/* + +# the above is not likely to change, so by putting it further up the +# Dockerfile we make sure we cache as much as possible + + +COPY setup.py README.rst CHANGES.rst MANIFEST.in /opt/letsencrypt/src/ + +# all above files are necessary for setup.py, however, package source +# code directory has to be copied separately to a subdirectory... +# https://docs.docker.com/reference/builder/#copy: "If is a +# directory, the entire contents of the directory are copied, +# including filesystem metadata. Note: The directory itself is not +# copied, just its contents." Order again matters, three files are far +# more likely to be cached than the whole project directory + +COPY letsencrypt /opt/letsencrypt/src/letsencrypt/ +COPY acme /opt/letsencrypt/src/acme/ +COPY letsencrypt_apache /opt/letsencrypt/src/letsencrypt_apache/ +COPY letsencrypt_nginx /opt/letsencrypt/src/letsencrypt_nginx/ + + +RUN virtualenv --no-site-packages -p python2 /opt/letsencrypt/venv && \ + /opt/letsencrypt/venv/bin/pip install -e /opt/letsencrypt/src + +# install in editable mode (-e) to save space: it's not possible to +# "rm -rf /opt/letsencrypt/src" (it's stays in the underlaying image); +# this might also help in debugging: you can "docker run --entrypoint +# bash" and investigate, apply patches, etc. + +ENV PATH /opt/letsencrypt/venv/bin:$PATH +# TODO: is --text really necessary? +ENTRYPOINT [ "letsencrypt", "--text" ] diff --git a/acme/messages2_test.py b/acme/messages2_test.py index 62de0832c..c1521e2c3 100644 --- a/acme/messages2_test.py +++ b/acme/messages2_test.py @@ -33,9 +33,9 @@ class ErrorTest(unittest.TestCase): def test_typ_decoder_missing_prefix(self): from acme.messages2 import Error - self.jobj['type'] = 'malfomed' + self.jobj['type'] = 'malformed' self.assertRaises(jose.DeserializationError, Error.from_json, self.jobj) - self.jobj['type'] = 'not balid bare type' + self.jobj['type'] = 'not valid bare type' self.assertRaises(jose.DeserializationError, Error.from_json, self.jobj) def test_typ_decoder_not_recognized(self): diff --git a/bootstrap/_deb_common.sh b/bootstrap/_deb_common.sh index b09130d77..4e4c75b33 100755 --- a/bootstrap/_deb_common.sh +++ b/bootstrap/_deb_common.sh @@ -10,21 +10,35 @@ # - 7.8 "wheezy" (x64) # - 8.0 "jessie" (x64) + # virtualenv binary can be found in different packages depending on # distro version (#346) -distro=$(lsb_release -si) -# 6.0.10 => 60, 14.04 => 1404 -version=$(lsb_release -sr | awk -F '.' '{print $1 $2}') -if [ "$distro" = "Ubuntu" -a "$version" -ge 1410 ] -then - virtualenv="virtualenv" -elif [ "$distro" = "Debian" -a "$version" -ge 80 ] +newer () { + distro=$(lsb_release -si) + # 6.0.10 => 60, 14.04 => 1404 + # TODO: in sid version==unstable + version=$(lsb_release -sr | awk -F '.' '{print $1 $2}') + if [ "$distro" = "Ubuntu" -a "$version" -ge 1410 ] + then + return 0; + elif [ "$distro" = "Debian" -a "$version" -ge 80 ] + then + return 0; + else + return 1; + fi +} + +# you can force newer if lsb_release is not available (e.g. Docker +# debian:jessie base image) +if [ "$1" = "newer" ] || newer then virtualenv="virtualenv" else virtualenv="python-virtualenv" fi + # dpkg-dev: dpkg-architecture binary necessary to compile M2Crypto, c.f. # #276, https://github.com/martinpaljak/M2Crypto/issues/62, # M2Crypto setup.py:add_multiarch_paths diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..dbe6e4f01 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +production: + build: . + ports: + - "443:443" + +# For development, mount git root to /opt/letsencrypt/src in order to +# make the dev workflow more vagrant-like. +development: + build: . + ports: + - "443:443" + volumes: + - .:/opt/letsencrypt/src + - /opt/letsencrypt/venv diff --git a/docs/using.rst b/docs/using.rst index f2f758814..89cbc48f6 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -2,6 +2,24 @@ Using the Let's Encrypt client ============================== +Quick start +=========== + +Using docker you can quickly get yourself a testing cert. From the +server that the domain your requesting a cert for resolves to, +download docker, and issue the following command + +.. code-block:: shell + + sudo docker run -it --rm -p 443:443 --name letsencrypt \ + -v "/etc/letsencrypt:/etc/letsencrypt" \ + -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ + quay.io/letsencrypt/lets-encrypt-preview:latest + +And follow the instructions. Your new cert will be available in +``/etc/letsencrypt/certs``. + + Prerequisites =============