diff --git a/Makefile b/Makefile index a1053ef72..681ebc733 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ php: webdevops/php webdevops/php-apache webdevops/php-nginx php-dev: webdevops/php-dev webdevops/php-apache-dev webdevops/php-nginx-dev hhvm: webdevops/hhvm webdevops/hhvm-apache webdevops/hhvm-nginx -web: webdevops/apache webdevops/apache-dev webdevops/nginx webdevops/nginx-dev webdevops/varnish +web: webdevops/apache webdevops/apache-dev webdevops/nginx webdevops/nginx-dev webdevops/varnish webdevops/certbot applications: webdevops/typo3 webdevops/piwik @@ -165,3 +165,6 @@ webdevops/sphinx: webdevops/varnish: bash bin/build.sh varnish "${DOCKER_REPOSITORY}/varnish" "${DOCKER_TAG_LATEST}" + +webdevops/certbot: + bash bin/build.sh certbot "${DOCKER_REPOSITORY}/certbot" "${DOCKER_TAG_LATEST}" \ No newline at end of file diff --git a/bin/provision.sh b/bin/provision.sh index 398674ff7..db6a1871c 100755 --- a/bin/provision.sh +++ b/bin/provision.sh @@ -426,4 +426,10 @@ function header() { deployConfiguration samson-deployment/general samson-deployment 'latest' } +## Build cerbot +[[ $(checkBuildTarget certbot) ]] && { + header "certbot" +} + + exit 0 diff --git a/docker/certbot/README.md b/docker/certbot/README.md new file mode 100644 index 000000000..3978257ad --- /dev/null +++ b/docker/certbot/README.md @@ -0,0 +1,44 @@ +# Certbot container layout + +Automated build and tested by [WebDevOps Build Server](https://build.webdevops.io/) + +## Environment variables + +Variable | Description +---------------------- | ------------------------------------------------------------------------------ +`CERTBOT_EMAIL` | Email of sysadmin +`CERTBOT_DOMAIN` | Registered dns or public ip + +## USAGE + +To create or renew existing certificate +```bash +docker run -ti --rm \ + -v /etc/letsencrypt:/etc/letsencrypt \ + -v /your/document_root:/var/www \ + webdevops/certbot /usr/bin/certbot certonly \ + --agree-tos \ + --webroot \ + -w /var/www + -d webdevops.io \ + -m "webmaster@webdevops.io" +``` +See [commandline options](https://certbot.eff.org/docs/using.html#command-line-options) + +## Template a cronjob to reissue the certificate + +Create a file **/etc/cron.monthly/reissue** +```bash +#!/bin/sh +set -euo pipefail +# Certificate reissue + +docker run -ti --rm \ + -v /etc/letsencrypt:/etc/letsencrypt \ + -v /your/document_root:/var/www \ + webdevops/certbot /usr/bin/certbot renew + + ``` +make file executable : chmod +x /etc/cron.monthly/reissue + +see [Renewal](https://certbot.eff.org/docs/using.html#renewal) \ No newline at end of file diff --git a/docker/certbot/latest/Dockerfile b/docker/certbot/latest/Dockerfile new file mode 100644 index 000000000..3ffd9f8c6 --- /dev/null +++ b/docker/certbot/latest/Dockerfile @@ -0,0 +1,17 @@ +#+++++++++++++++++++++++++++++++++++++++ +# Dockerfile for webdevops/certbot:latest +# -- automatically generated -- +#+++++++++++++++++++++++++++++++++++++++ + +FROM webdevops/bootstrap:alpine-3 + +MAINTAINER info@webdevops.io +LABEL vendor=WebDevOps.io +LABEL io.webdevops.layout=8 +LABEL io.webdevops.version=0.53.2 + +VOLUME /etc/letsencrypt +VOLUME /var/www + +RUN /usr/local/bin/apk-install \ + certbot diff --git a/docker/certbot/latest/Dockerfile.jinja2 b/docker/certbot/latest/Dockerfile.jinja2 new file mode 100644 index 000000000..91c145f29 --- /dev/null +++ b/docker/certbot/latest/Dockerfile.jinja2 @@ -0,0 +1,8 @@ +{{ docker.from("bootstrap","alpine-3") }} + +{{ docker.version() }} + +{{ docker.volume('/etc/letsencrypt') }} +{{ docker.volume('/var/www') }} + +{{ certbot.alpine() }} diff --git a/template/Dockerfile/images/certbot.jinja2 b/template/Dockerfile/images/certbot.jinja2 new file mode 100644 index 000000000..d2bf81b73 --- /dev/null +++ b/template/Dockerfile/images/certbot.jinja2 @@ -0,0 +1,11 @@ +{% import 'Dockerfile/provision.jinja2' as provision %} + +{% macro env() -%} +ENV CERTBOT_EMAIL "" +ENV CERTBOT_DOMAIN "" +{%- endmacro %} + +{% macro alpine() -%} +RUN /usr/local/bin/apk-install \ + certbot +{%- endmacro %} \ No newline at end of file diff --git a/template/Dockerfile/layout.jinja2 b/template/Dockerfile/layout.jinja2 index f6527e1bf..33322b4e8 100644 --- a/template/Dockerfile/layout.jinja2 +++ b/template/Dockerfile/layout.jinja2 @@ -21,6 +21,7 @@ {% import 'Dockerfile/images/vsftp.jinja2' as vsftp %} {% import 'Dockerfile/images/samson-deployment.jinja2' as samsonDeployment %} {% import 'Dockerfile/images/varnish.jinja2' as varnish %} +{% import 'Dockerfile/images/certbot.jinja2' as certbot %} #+++++++++++++++++++++++++++++++++++++++ # Dockerfile for webdevops/{{ Dockerfile.image }}:{{ Dockerfile.tag }} # -- automatically generated -- diff --git a/test/Makefile b/test/Makefile index d76032c3f..5441df415 100644 --- a/test/Makefile +++ b/test/Makefile @@ -74,3 +74,6 @@ varnish: sphinx: bash ./run.sh sphinx + +certbot: + bash ./run.sh certbot diff --git a/test/run.sh b/test/run.sh index 8dd4ca93b..5452ee14d 100755 --- a/test/run.sh +++ b/test/run.sh @@ -964,6 +964,20 @@ ENV VARNISH_BACKEND_HOST \"google.com\" waitForTestRun } +####################################### +# webdevops/certbot +####################################### + +[[ $(checkTestTarget certbot) ]] && { + setupTestEnvironment "certbot" + + # setSpecTest "base" + setEnvironmentOsFamily "alpine" + + OS_VERSION="3" runTestForTag "latest" + + waitForTestRun +} echo "" echo " >>> finished, all tests PASSED <<<" diff --git a/test/spec/collection/certbot.rb b/test/spec/collection/certbot.rb new file mode 100644 index 000000000..766d45761 --- /dev/null +++ b/test/spec/collection/certbot.rb @@ -0,0 +1,4 @@ +shared_examples 'collection::certbot' do + include_examples 'misc::letsencrypt' + include_examples 'certbot::layout' +end diff --git a/test/spec/docker/certbot_spec.rb b/test/spec/docker/certbot_spec.rb new file mode 100644 index 000000000..d4dae3595 --- /dev/null +++ b/test/spec/docker/certbot_spec.rb @@ -0,0 +1,15 @@ +require 'serverspec' +require 'docker' +require 'spec_helper' + +describe "Dockerfile" do + before(:all) do + @image = Docker::Image.build_from_dir('.', { 'dockerfile' => ENV['DOCKERFILE'] }) + set :docker_image, @image.id + end + + include_examples 'collection::bootstrap' + # include_examples 'collection::base' + include_examples 'collection::certbot' + +end diff --git a/test/spec/shared/certbot/layout.rb b/test/spec/shared/certbot/layout.rb new file mode 100644 index 000000000..bf18e9c47 --- /dev/null +++ b/test/spec/shared/certbot/layout.rb @@ -0,0 +1,34 @@ +shared_examples 'certbot::layout' do + ######################### + ## Directories + ######################### + [ + "/var/www", + "/etc/letsencrypt", + ].each do |file| + describe file("#{file}") do + # Type check + it { should be_directory } + + # Owner test + it { should be_owned_by 'root' } + it { should be_grouped_into 'root' } + + # Read test + it { should be_readable.by('owner') } + it { should be_readable.by('group') } + it { should be_readable.by('others') } + + # Write test + it { should be_writable.by('owner') } + it { should_not be_writable.by('group') } + it { should_not be_writable.by('others') } + + # Exectuable test + it { should be_executable.by('owner') } + it { should be_executable.by('group') } + it { should be_executable.by('others') } + end + end + +end diff --git a/test/spec/shared/misc/tools.rb b/test/spec/shared/misc/tools.rb index 70151e18c..831b85707 100644 --- a/test/spec/shared/misc/tools.rb +++ b/test/spec/shared/misc/tools.rb @@ -10,9 +10,17 @@ end end - shared_examples 'misc::graphviz' do it "should include graphviz" do expect(file("/usr/bin/dot")).to be_executable end +end + +shared_examples 'misc::letsencrypt' do + it "should include letsencrypt" do + expect(file("/usr/bin/letsencrypt")).to be_executable + end + it "should include certbot" do + expect(file("/usr/bin/certbot")).to be_executable + end end \ No newline at end of file