Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • libre.sh/compose/haproxy
  • timothee/haproxy
2 results
Show changes
Commits on Source (38)
certs/*
haproxy/certs/*
haproxy/haproxy.cfg
acme-challenge/*
# HAProxy
HAProxy for IndieHosters
# Warning: still experimental, use at your own risk
## What is it?
This repository contains one of the most advanced and libre HAproxy for docker setup that we are aware of.
It ships with:
- container discovery though docker API (like [smartstack](http://nerds.airbnb.com/smartstack-service-discovery-cloud/)) based on Env var `HOST` (Based on [docker-gen](https://github.com/jwilder/docker-gen))
- container discovery though docker API (like [smartstack](http://nerds.airbnb.com/smartstack-service-discovery-cloud/)) based on Env var `VIRTUAL_HOST` (Based on [docker-gen](https://github.com/jwilder/docker-gen))
- [ocsp](https://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol)
- [letsencrypt](https://letsencrypt.org/)
Once you managed to make this running, each time you add a container with the environment variable `HOST` it will:
Each time you add a container with the environment variable `VIRTUAL_HOST` it will:
- generate a valid certificate (if the dns is pointing correctly)
- serves the OCSP response
- serves your web container with https
......@@ -21,25 +19,31 @@ Once you managed to make this running, each time you add a container with the en
- docker
- docker-compose
## Get started
## Get started ( for libre.sh )
```
git clone https://github.com/indiehosters/haproxy.git
# docker network create lb_web (already done when you install libre.sh )
cd /system/
git clone https://lab.libreho.st/libre.sh/compose/haproxy
cd haproxy
docker-compose up -d
libre enable
libre start
```
The first time, you might need to run letsencrypt-watch in an interactive way to accept TOS and register your account.
Use the following to do so:
In these commands, we just created one network (lb_web) to isolate HAProxy with the web servers, and then, we started the containers of HAProxy and companions.
```
docker-compose run letsencrypt-watch
docker run --network=lb_web -e VIRTUAL_HOST=example.org nginx
```
And profit!
Here, we just started the most simple web server, and added to the lb_web network.
The only thing that HAProxy needs to see and connect to this container are the following:
- expose a port 80
- have a VIRTUAL_HOST variable setup with the domain name
- be in the lb_web network
And finally for HAProxy to be able to provision the Let's encrypt certificate, you need to configure your DNS for example.org to point to the IP of HAProxy.
```
docker run -e HOST=example.org nginx
```
## Contributing
......@@ -59,4 +63,3 @@ You can help us by:
- renewal :)
- docker-swarm compatibility
- other backend (etcd/consul...)
#!/bin/bash -eux
grep -wvFf <(ls /data/domains/) <(ls certs/*/*.csr | grep -vf <(echo -e "node-exporter\ncadvisor") | cut -d"/" -f2) | xargs -i% rm -rf /system/haproxy/certs/%
discovery:
image: jwilder/docker-gen
volumes:
version: '2'
networks:
lb_web:
external: true
services:
discovery:
image: jwilder/docker-gen
volumes:
- "/var/run/docker.sock:/tmp/docker.sock:ro"
- "./templates:/etc/docker-gen/templates"
- "./haproxy:/etc/haproxy"
command: "-watch /etc/docker-gen/templates/haproxy.cfg.tmpl /etc/haproxy/haproxy.cfg"
haproxy:
image: indiehosters/haproxy
volumes:
command: "-watch /etc/docker-gen/templates/haproxy.cfg.tmpl /etc/haproxy/haproxy.cfg"
haproxy:
image: indiehosters/haproxy
volumes:
- "./haproxy:/etc/haproxy"
- "/dev/log:/dev/log"
links:
links:
- letsencrypt
ports:
ports:
- "80:80"
- "443:443"
letsencrypt:
image: nginx
volumes:
networks:
- lb_web
letsencrypt-web:
image: nginx
volumes:
- "./acme-challenge:/usr/share/nginx/html/.well-known/acme-challenge:ro"
letsencrypt-watch:
image: indiehosters/letsencrypt
volumes:
networks:
- lb_web
letsencrypt:
image: libresh/letsencrypt
volumes:
- "./haproxy:/etc/haproxy"
- "./acme-challenge:/html-root/.well-known/acme-challenge/"
- "./letsencrypt:/etc/letsencrypt"
ocsp:
image: indiehosters/ocsp
volumes:
- "./certs:/var/certs"
ocsp:
image: indiehosters/ocsp
volumes:
- "./haproxy:/etc/haproxy"
-----BEGIN CERTIFICATE-----
MIIEEzCCAvugAwIBAgIJAPJb5aIb+XTnMA0GCSqGSIb3DQEBCwUAMIGfMQswCQYD
VQQGEwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTEOMAwGA1UEBwwFZmxlcnMxITAf
BgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDERMA8GA1UECwwIVGltb3Ro
ZWUxETAPBgNVBAMMCFRpbW90aGVlMSIwIAYJKoZIhvcNAQkBFhN0aW1vdGhlZUB1
bnRlZW0ub3JnMB4XDTE2MDcyMDE1MTMxNVoXDTE3MDcyMDE1MTMxNVowgZ8xCzAJ
BgNVBAYTAkZSMRMwEQYDVQQIDApTb21lLVN0YXRlMQ4wDAYDVQQHDAVmbGVyczEh
MB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMREwDwYDVQQLDAhUaW1v
dGhlZTERMA8GA1UEAwwIVGltb3RoZWUxIjAgBgkqhkiG9w0BCQEWE3RpbW90aGVl
QHVudGVlbS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvG3Ng
Wf/TJ+9gr+WIDZ1MiiR64Hf09oRt+9/Jb7dtGQu5kZsB9XuFv5tUiQwlAobAifwl
CJuOHsB8eTermb8DymhYn7evK3vWuiYarCmi17M9UqFv7ngKW01tZ2mSV0Syb/yT
V1dJ29icRISUCqfxXpySNQu0pLxTbmmoGFYF4LbYXb+hJnx6pP5KXj2u5VTi5g4q
et8vTkwg23uudYus1e4FqzCappEGZ81HXHus4OzPmv1Wrnz+UzqD6V/kpJLu8w6a
AgrDpTpiRlcqaiAN3UzdBNGrbzJ1DBpI2B0SyEt81YbVxW+0982leC8iWge81J2t
WJOFt3bNt1cYHMnzAgMBAAGjUDBOMB0GA1UdDgQWBBSWslWj8fsJuG8eqZ0jmyU6
FSwo+zAfBgNVHSMEGDAWgBSWslWj8fsJuG8eqZ0jmyU6FSwo+zAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAI82Bg4bUd9QQRngj6p1RLHJRRbR32OvJS
/C/L6dGSoAR4wwGjIzM4XzUcFWk/kM7KmbWeF5uwkoLXaKmSylZ9tIJhdYClERq6
RPun2y9L9E1VnR7m8wemqyTzVEOajbOZuuOnTBnrdDyn3G4yIiFV0U6Wovh8w0VK
u99W1dfvLCaRtvDq5lWCGK0mRvvhZigDAwrjn7JymwxehT8XVLlziTws0Kj3Lm8H
a4m7EMlOit9mA8Qmwo3okdsykKLT7AfLDilOat5iF2KBrJzMQ4ssU/CkZpmQu6TV
8vxuv+J2F+XQIQfq1EtZ4pJdbNipLR5Dwp8vDr94cwf57joGe6gI
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCvG3NgWf/TJ+9g
r+WIDZ1MiiR64Hf09oRt+9/Jb7dtGQu5kZsB9XuFv5tUiQwlAobAifwlCJuOHsB8
eTermb8DymhYn7evK3vWuiYarCmi17M9UqFv7ngKW01tZ2mSV0Syb/yTV1dJ29ic
RISUCqfxXpySNQu0pLxTbmmoGFYF4LbYXb+hJnx6pP5KXj2u5VTi5g4qet8vTkwg
23uudYus1e4FqzCappEGZ81HXHus4OzPmv1Wrnz+UzqD6V/kpJLu8w6aAgrDpTpi
RlcqaiAN3UzdBNGrbzJ1DBpI2B0SyEt81YbVxW+0982leC8iWge81J2tWJOFt3bN
t1cYHMnzAgMBAAECggEADK2XH+3EOPyWN1Dk9IHP1r/VvlPMO58xnWj0HfiJtktu
7uOc7npglCF4VJmLmI5jRUN4TxIdeR++3gRExJbgHp0kCu6ddQBX+gcGRT4b0Z9+
ab021QzWAiH0LCyllyPcZHL5PY3AUyeouj+3vaQ73pz0Bx3yGAUpYX0IB1Sjvc8V
pUOpG45tENA270/rJJ6QeFgU/cinLJZZNfMiUuNaa2SP0kZZ5TmLLcQAwbHbu/B4
1e5OToF8VNhS7ux0yjB7yvqlpn4vOXtv3S6cfoc1ZAuPltpm62xWvg1xoJM3MTCd
cbQ9wrn13fNhHUnQrU/hUFBO4dnVa4oNY52oWeiFEQKBgQDT+T4asgShrVqCXvyO
do2eWKEw4YK6E3kl1RuFVPW0EuQJNOiagJ7B2Bu0QoqAKXK3dukftJyY9XSWRZDJ
i0CZFemldv2n++1A+xv9pFRiWIbvXnULTQ8ftSCrViO0+gAroaE4jRrP910h5CQy
5y/dIDpruHT7Nyq7JDp/CICN6QKBgQDTegB+gkiBHx7MAlGi497Nh0WaA8TJDfBa
IJHtSNiFm9WOxYdkb2l+ZhLF5VVU0GiAbN1yHitrKlaWePhoPV/8COwG7/zm3xkR
fGWNT0lE5a430FpEaKqEdVk99YTHrVIZJijzbmTHWIooglEFEoJX66lmHoBBbLyz
J9bx34vjewKBgQCvRqZKzq6zvbNcoAx4BKG/sIvA7of5M0b2uIukKYdt2j0DO+Om
dfpQUVE/MdJyfVNlTwcfd2oRtM0twOIjNWk57HuhnY3LTK53D+yqRCqek5Mn9VQU
/yglUNFtu7GU4TAo4+J673qfQmyZLJueF7plP1PvZLweShSkYCWaiz45mQKBgQDL
LwIAir6MyNC3JFc5UQTFpf16j7pnjevrPDXYrM/T9zjFdwWxutW56uqIluJYnfB5
y58sQM5opYISCuJojOeG6S+VLslnLN0SDtonXhFAkAjGeXnxFjsXDwSSYi2UB/PE
VASudtd/LJN5flPHstPnE3Zrtkx2D7pxy4paU/U8twKBgFd8po4vi7mTLmfb/un8
jmyILpAd3F5BUcSzRB7l+SFv0nVepOFY8xJXVVBwKdAYg+NIley7Ma1GoFfneubf
7sFSlrH4ioeJeYX6bRZIdigep8aV0p7KftwDdksVx2/w6fKujfuT5H7y3pa2th1t
HrbV/GxbHbML7+8CtaFL4MR0
-----END PRIVATE KEY-----
global
log /dev/log local0 info
log /dev/log local0 notice
ca-base /etc/ssl/certs
maxconn 4096
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
......@@ -10,6 +11,7 @@ defaults
mode http
option forwardfor
option httpclose
option http-server-close
option httplog
option dontlognull
retries 3
......@@ -17,7 +19,7 @@ defaults
compression type text/html text/plain text/css application/javascript
timeout connect 5000
timeout client 50000
timeout server 50000
timeout server 500000
frontend http-in
bind *:80
......@@ -28,22 +30,62 @@ frontend http-in
frontend https-in
mode http
bind *:443 ssl no-sslv3 crt /etc/haproxy/certs
reqadd X-Forwarded-Proto:\ https
bind *:443 ssl no-sslv3 crt /etc/haproxy/certs
reqadd X-Forwarded-Proto:\ https
rspadd Strict-Transport-Security:\ max-age=15768000
rspidel X-Powered-By
use_backend letsencrypt if { path_beg /.well-known/acme }
{{ range $host, $container := groupBy $ "Env.HOST" }}
use_backend {{ $host}} if { hdr(host) -i {{ $host }} www.{{ $host }} }
acl acme path_beg /.well-known/acme
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
{{ $reverseProxyFor := (first (groupByKeys $containers "Env.REVERSE_PROXY_FOR")) }}
{{ if $reverseProxyFor }}
use_backend {{ $host }}-acme if acme { hdr(host) -i {{ $host }} }
{{end}}
{{end}}
use_backend letsencrypt-web if acme
{{ range $host, $containers := groupBy $ "Env.LIBRESH_WEBHOOK_HOST" }}
use_backend webhook if { path_beg /XxosJDdRpo7Rww87VkJGzv1QLegnhh-uniq-libresh }
{{end}}
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
use_backend {{ $host}} if { hdr(host) -i {{ $host }} }
use_backend {{ $host}} if { hdr(host) -i {{ $host }}:443 }
{{end}}
{{ $containers := whereExist $ "Env.HOST" }}
{{ range $container := $containers }}
backend {{ $container.Env.HOST }}
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
{{ $reverseProxyFor := (first (groupByKeys $containers "Env.REVERSE_PROXY_FOR")) }}
{{ if $reverseProxyFor }}
backend {{ $host }}-acme
server Server {{ $reverseProxyFor }}:80
{{end}}
backend {{ $host }}
option http-server-close
cookie SERVERID insert nocache indirect
server Server {{ $container.IP }}:80 cookie Server
{{ range $container := $containers }}
{{ $networkLen := len $container.Networks }}
{{ if $reverseProxyFor }}
http-request set-header Host {{ $host }}
server Server {{ $reverseProxyFor }}:443 ssl sni str({{ $host }}) ca-file ca-certificates.crt
{{ else }}
{{ if eq $networkLen 1 }}
{{ $network := index $container.Networks 0 }}
server Server {{ $network.IP }}:80 cookie Server
{{ else }}
{{ range $network := $container.Networks }}
{{ if eq $network.Name "lb_web" }}
server Server {{ $network.IP }}:80 cookie Server
{{end}}
{{end}}
{{end}}
{{end}}
{{end}}
{{end}}
backend letsencrypt
backend letsencrypt-web
cookie SERVERID insert nocache indirect
server Server letsencrypt:80 cookie Server
server Server letsencrypt-web:80 cookie Server
{{ range $host, $containers := groupBy $ "Env.LIBRESH_WEBHOOK_HOST" }}
backend webhook
cookie SERVERID insert nocache indirect
server Server webhook:80 cookie Server
{{end}}