First semiworking iteration

Container can be started with empty data directory.
After using docker exec the commands from the NOTES file can be
used to create a first cert and additional certs after that.
This commit is contained in:
Joachim Lusiardi 2016-04-06 20:26:08 +02:00
parent 574c94b8ac
commit a57fa08340
7 changed files with 204 additions and 9 deletions

View File

@ -1,16 +1,24 @@
FROM debian
FROM debian8_python3
MAINTAINER Joachim Lusiardi
RUN apt-get update; \
apt-get install -y haproxy;
apt-get install -y \
git \
haproxy; \
git clone https://github.com/letsencrypt/letsencrypt ;\
cd /letsencrypt ;\
./letsencrypt-auto --help
ADD haproxy_ssl.conf /haproxy_ssl.conf
ADD haproxy.conf /haproxy.conf
ADD letencrypt.conf /letencrypt.conf
ADD start.sh /start.sh
RUN chmod +x /start.sh
ADD start.py /start.py
RUN chmod +x /start.py
VOLUME ["/data"]
EXPOSE 80
EXPOSE 443
ENTRYPOINT /start.sh
ENTRYPOINT /start.py

12
NOTES Normal file
View File

@ -0,0 +1,12 @@
# Nach start von haproxy ohne ssl:
/letsencrypt/letsencrypt-auto --config letencrypt.conf certonly -d lusiardi.de
cat /data/config/live/lusiardi.de/fullchain.pem /data/config/live/lusiardi.de/privkey.pem > /data/haproxy/cert.pem
# Nach start von haproxy mit ssl:
/letsencrypt/letsencrypt-auto --config letencrypt.conf certonly --standalone-supported-challenges http-01 --http-01-port 54321 --expand -d lusiardi.de -d ps.lusiardi.de
cat /data/config/live/lusiardi.de/fullchain.pem /data/config/live/lusiardi.de/privkey.pem > /data/haproxy/cert.pem
# aufräumen
rm -rf /data/*

View File

@ -21,10 +21,15 @@ defaults
timeout client 50000
timeout server 50000
frontend https
bind *:443 ssl crt /data/cert.pem
reqadd X-Forwarded-Proto:\ https
frontend http
bind *:80
reqadd X-Forwarded-Proto:\ http
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
default_backend www-backend
backend www-backend
server one target:80
backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321

42
haproxy_ssl.conf Normal file
View File

@ -0,0 +1,42 @@
global
chroot /var/lib/haproxy
stats socket /admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /crypt
ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
ssl-default-bind-options no-sslv3
defaults
#log global
mode http
#option httplog
#option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http
bind *:80
reqadd X-Forwarded-Proto:\ http
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
default_backend www-backend
frontend https
bind *:443 ssl crt /data/haproxy/cert.pem
reqadd X-Forwarded-Proto:\ https
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
default_backend www-backend
backend www-backend
server one target:80
backend letsencrypt-backend
server letsencrypt 127.0.0.1:54321

8
letencrypt.conf Normal file
View File

@ -0,0 +1,8 @@
non-interactive=TRUE
standalone
staging
logs-dir=/data/logs
work-dir=/data/work
config-dir=/data/config
email=letsencrypt@lusiardi.de
agree-tos=TRUE

113
start.py Normal file
View File

@ -0,0 +1,113 @@
#!/usr/bin/python3.4
import os
import signal
import logging
import time
import hashlib
cert_path='/data/haproxy'
cert_file='/data/haproxy/cert.pem'
pid_file='/haproxy.pid'
def hash_cert_file():
if not os.path.isfile(cert_file):
return ''
aFile = open(cert_file, 'rb')
hasher = hashlib.sha256()
buf = aFile.read(65536)
while len(buf) > 0:
hasher.update(buf)
buf = aFile.read(65536)
return hasher.digest()
def setup_logging():
"""Sets up logging with a nice format"""
logging.basicConfig(format='%(asctime)s [%(levelname)s]: %(message)s', level=logging.INFO)
def get_pid():
"""This function reads the process id from the given file and returns as int."""
with open(pid_file, 'r') as file:
return int(file.read())
def kill_haproxy():
"""Stops the currently running instance of haproxy by issueing a kill signal to its pid."""
logging.info('killing haproxy')
try:
os.kill(get_pid(), signal.SIGKILL)
except OSError:
pass
def start_haproxy_ssl():
logging.info('starting haproxy SSL')
os.system('/usr/sbin/haproxy -f /haproxy_ssl.conf -p /haproxy.pid')
def start_haproxy():
logging.info('starting haproxy NON SSL')
os.system('/usr/sbin/haproxy -f /haproxy.conf -p /haproxy.pid')
def is_haproxy_running():
try:
os.kill(get_pid(), 0)
return True
except OSError:
return False
def ssl_possible():
"""Check if a certificate is available."""
if not os.path.exists(cert_path):
logging.info('creating cert_path path: %s', cert_path)
os.mkdir(cert_path)
if not os.path.isfile(cert_file):
return False
else:
return True
if __name__ == '__main__':
setup_logging()
logging.info('starting')
cert_file_hash = ''
if ssl_possible():
logging.info('try in SSL mode')
start_haproxy_ssl()
cert_file_hash = hash_cert_file()
if is_haproxy_running():
SSL_RUNNING=True
else:
logging.info('SSL mode failed')
if not is_haproxy_running() or not ssl_possible():
logging.info('try in NON SSL mode')
start_haproxy()
SSL_RUNNING=False
while True:
time.sleep(10)
if ssl_possible() and not SSL_RUNNING:
kill_haproxy()
start_haproxy_ssl()
if is_haproxy_running():
cert_file_hash = hash_cert_file()
logging.info('NON SSL -> SSL')
SSL_RUNNING=True
else:
start_haproxy()
SSL_RUNNING=False
if SSL_RUNNING and cert_file_hash != hash_cert_file():
logging.info('cert has changed')
kill_haproxy()
start_haproxy_ssl()
if is_haproxy_running():
cert_file_hash = hash_cert_file()
logging.info('SSL -> SSL')
SSL_RUNNING=True
else:
start_haproxy()
logging.info('SSL -> NON SSL')
SSL_RUNNING=False
# logging.info('haproxy is running: %s', str(is_haproxy_running()))
# logging.info('haproxy is running with SSL: %s', str(SSL_RUNNING))

View File

@ -1,3 +1,10 @@
#!/bin/bash
/usr/sbin/haproxy -f /haproxy.conf -p /haproxy.pid -db
if [ -s /data/haproxy/cert.pem ]
then
# ssl cert seems to exist, so start with
/usr/sbin/haproxy -f /haproxy_ssl.conf -p /haproxy.pid -db
else
bash
fi