-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
مِيزَانُ الْدِّينْ عَبْدُ ذِيْ الْجَلَالِ وَ الْإِكْرَامِ
committed
Aug 9, 2019
1 parent
9ec92ea
commit afb201b
Showing
16 changed files
with
341 additions
and
578 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
.idea | ||
_site |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
- name: Home | ||
link: / | ||
- name: About | ||
link: /about.html | ||
- name: Services | ||
link: /services.html | ||
- name: Contact | ||
link: /contact.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<footer class="footer"> | ||
<div class="container"> | ||
<p>Articles on this website are © <a href="https://vesica.co.uk" target="_blank">Vesica</a> 2019. Docker is a trademark of Docker, Inc.</p> | ||
</div> | ||
</footer> | ||
|
||
<!-- Optional JavaScript --> | ||
<!-- jQuery first, then Popper.js, then Bootstrap JS --> | ||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> | ||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> | ||
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<head> | ||
<!-- Required meta tags --> | ||
<meta charset="utf-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
<meta name="title" content="{{page.title }} - Docker Stack Deploy" /> | ||
<meta name="description" content="{{page.metaDescription}}" /> | ||
<!-- Bootstrap CSS --> | ||
<link rel="stylesheet" href="/css/bootstrap.min.css" crossorigin="anonymous"> | ||
<!-- Custom styles for this template --> | ||
<link rel="stylesheet" href="/css/style.css"> | ||
<title>{{page.title }} - Docker Stack Deploy</title> | ||
</head> | ||
<body> | ||
<header> | ||
<nav class="navbar navbar-expand-lg navbar-dark fixed-top bg-primary"> | ||
<a class="navbar-brand" href="/">Docker Stack Deploy</a> | ||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarX" aria-controls="navbarsX" aria-expanded="false" aria-label="Toggle navigation"> | ||
<span class="navbar-toggler-icon"></span> | ||
</button> | ||
|
||
<div class="collapse navbar-collapse" id="navbarX"> | ||
<ul class="navbar-nav ml-auto"> | ||
{% for item in site.data.navigation %} | ||
<li class="nav-item {% if page.url == item.link %}active{% endif %}"> | ||
<a class ="nav-link" href="{{ item.link }}"> | ||
{{ item.name }} | ||
</a> | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
</div> | ||
</nav> | ||
</header> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
{% include header.html %} | ||
|
||
<main role="main" class="container"> | ||
<div class="container"> | ||
<div class="row"> | ||
<div class="col-md-12 pt-3"> | ||
{{ content }} | ||
</div> | ||
</div> | ||
</div> | ||
|
||
</main> | ||
|
||
{% include footer.html %} | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
layout: default | ||
--- | ||
<h1>{{ page.title }}</h1> | ||
<p>{{ page.date | date_to_string }} - {{ page.author }}</p> | ||
|
||
{{ content }} |
216 changes: 216 additions & 0 deletions
216
_posts/2019-07-09-running-haproxy-in-a-docker-container-with-lets-encrypt.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
--- | ||
layout: post | ||
author: MA Wal-Ikram | ||
--- | ||
|
||
|
||
Running your reverse proxy to serve domain names via HA Proxy on a Docker Swarm or Kubernetes with Let's Encrypt can be a challenge. When we set off to do this, | ||
we had a few goals in mind: | ||
|
||
* Auto-generate the certificates before they expire</li> | ||
* The ability to have virtually unlimited domain names served by the container</li> | ||
* Do not mount any volumes - so we can easily swap out the machines the containers are deployed on</li> | ||
* This should all be integrated into our CI/CD pipeline, so we can just change the HA Proxy config and push up to a git repository and the new config gets deployed</li> | ||
|
||
### The Solution | ||
|
||
In the end, we came up with a simple solution, but it does require 2 private Docker images (to avoid having mounted volumes). Here's what we did: | ||
|
||
|
||
1. Create a base container with HA Proxy, Let's Encrypt Certbot and all the required plugins that allow us to automatically generate certs.</li> | ||
2. Use this base container to build a private container which has the certificates inside it.</li> | ||
3. Use the second container and push your HA Proxy config file into it, deploy it to Docker Hub to Quay.io, and let a webhook deploy your updated configuration (this deployment bit is not covered in this article).</li> | ||
|
||
Because we use Certbot plugins and build the Docker images in Circle CI, our only limitation is that our domains' DNS be served by either Cloudflare, Linode, Route 53, or Google. | ||
|
||
|
||
### Let's Docker Stack Deploy | ||
#### Step 1: The base container with HA Proxy, Certbot and all the required Plugins | ||
|
||
We've already done this, so you can simply pull the container from <a href="https://hub.docker.com/r/vesica/haproxy-certbot" target="_blank">vesica/haproxy-cerbot:latest</a>. You can also see the Dockerfile @ <a href="https://github.com/vesica/haproxy-certbot" target="_blank">https://github.com/vesica/haproxy-certbot</a>. | ||
|
||
|
||
#### Step 2: Build the container that has all the certificates | ||
|
||
Let's say you will be serving DNS for all your domains via Cloudflare. You will first need to create a .ini file with your Cloudflare API credentials, so Certbot can communicate with it. | ||
Create a file called <code>cloudflare.ini</code> with the following: | ||
|
||
<pre class="bg-light"> | ||
# cloudflare.ini | ||
|
||
dns_cloudflare_email = [email protected] | ||
dns_cloudflare_api_key = __API_KEY__ | ||
</pre> | ||
|
||
Please do replace __API_KEY__ with your actual Cloudflare API key. | ||
|
||
|
||
Now let's create the <code>Dockerfile</code> for the container that will have the certificates: | ||
|
||
<pre class="bg-light"> | ||
# Dockerfile | ||
|
||
FROM vesica/haproxy-certbot:latest | ||
|
||
COPY cloudflare.ini /etc/cloudflare/cloudflare.ini | ||
|
||
RUN mkdir -p /etc/letsencrypt/merged-ssl/domain1.com/ | ||
RUN touch /etc/letsencrypt/merged-ssl/domain1.com/domain1.com.pem | ||
|
||
### CERTIFICATES TO ISSUE - ADD ANY NEW ONES AT THE BOTTOM | ||
|
||
RUN certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/cloudflare/cloudflare.ini --dns-cloudflare-propagation-seconds 60 --non-interactive --agree-tos --email [email protected] \ | ||
-d domain1.com \ | ||
-d *.domain1.com \ | ||
-d domain2.net \ | ||
-d domain3.org \ | ||
-d www.domain4.co.uk | ||
|
||
### DO NOT CHANGE ANYTHING ELSE ### | ||
|
||
COPY startup.sh /usr/local/bin/startup | ||
RUN chmod 755 /usr/local/bin/startup | ||
|
||
ENTRYPOINT ["startup"] | ||
|
||
CMD ["haproxy", "-f", "/usr/local/etc/haproxy/haproxy.cfg"] | ||
</pre> | ||
|
||
Let's go through the above Dockerfile and point our some of the finer points: | ||
|
||
* We start by copying our cloudflare credentials file into the container.</li> | ||
* We create the directory and file where we will store the certificates for all the domains. | ||
<b>Note</b> that <code>domain1.com</code> should be replaced with whatever is the first domain in the list of domains you | ||
are generating certificates for. | ||
|
||
* The rest is copying over a startup.sh file to start HA Proxy. We create this file below.</li> | ||
|
||
Let's create the <code>startup.sh</code> file which will put the certificates in the right folder and start HA Proxy when the container runs. | ||
Add the following code to a file called <i>startup.sh</i>. | ||
|
||
<pre class="bg-light"> | ||
# startup.sh | ||
|
||
#!/bin/sh | ||
|
||
## Put certs in usable place. Pay attention to domain1.com, that must always be the first domain. Otherwise change the below accordingly and haproxy.cfg too. | ||
cat /etc/letsencrypt/live/domain1.com/fullchain.pem /etc/letsencrypt/live/domain1.com/privkey.pem > /etc/letsencrypt/merged-ssl/domain1.com/domain1.com.pem | ||
|
||
# Start HA Proxy | ||
set -e | ||
|
||
# first arg is `-f` or `--some-option` | ||
if [ "${1#-}" != "$1" ]; then | ||
set -- haproxy "$@" | ||
fi | ||
|
||
if [ "$1" = 'haproxy' ]; then | ||
shift # "haproxy" | ||
# if the user wants "haproxy", let's add a couple useful flags | ||
# -W -- "master-worker mode" (similar to the old "haproxy-systemd-wrapper"; allows for reload via "SIGUSR2") | ||
# -db -- disables background mode | ||
set -- haproxy -W -db "$@" | ||
fi | ||
|
||
exec "$@" | ||
</pre> | ||
|
||
|
||
With the Dockerfile and startup.sh in place, let's build this container. Run <code>docker build . -t haproxy-certs:latest</code>. | ||
|
||
|
||
#### Step 3: Build the container with the HA Proxy configuration | ||
|
||
To build this container, we need to create a <code>Dockerfile</code> and an <code>haproxy.cfg</code> file. | ||
Let's start with the Dockferfile. | ||
|
||
<pre class="bg-light"> | ||
# Dockerfile | ||
|
||
FROM haproxy-certs:latest | ||
|
||
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg | ||
</pre> | ||
|
||
|
||
Now let's create our <code>haproxy.cfg</code> file. | ||
|
||
<pre class="bg-light"> | ||
# haproxy.cfg | ||
|
||
#### MAKE CHANGES HERE ONLY IF YOU REALLY KNOW WHAT YOU ARE DOING ##### | ||
#--------------------------------------------------------------------- | ||
# Global settings | ||
#--------------------------------------------------------------------- | ||
global | ||
daemon | ||
maxconn 10000 | ||
tune.ssl.default-dh-param 2048 | ||
|
||
#--------------------------------------------------------------------- | ||
# common defaults that all the 'listen' and 'backend' sections will | ||
# use if not designated in their block | ||
#--------------------------------------------------------------------- | ||
|
||
defaults | ||
|
||
mode http | ||
log global | ||
option dontlognull | ||
option http-server-close | ||
option redispatch | ||
retries 3 | ||
timeout http-request 1m | ||
timeout queue 1m | ||
timeout connect 10s | ||
timeout client 1m | ||
timeout server 1m | ||
timeout http-keep-alive 10s | ||
timeout check 10s | ||
maxconn 10000 | ||
|
||
frontend haproxy-manager | ||
bind :::10000 v4v6 | ||
mode http | ||
stats enable | ||
stats auth username:password | ||
stats refresh 15s | ||
stats show-node | ||
stats uri /haproxy-admin | ||
stats admin if TRUE | ||
|
||
frontend http-in | ||
bind :80 v4v6 | ||
bind :::80 v6only | ||
bind :443 v4v6 ssl crt /etc/letsencrypt/merged-ssl/domain1.com/domain1.com.pem | ||
bind :::443 v6only ssl crt /etc/letsencrypt/merged-ssl/domain1.com/domain1.com.pem | ||
option forwardfor | ||
http-request set-header X-Forwarded-Proto https if { ssl_fc } | ||
http-request set-header HTTPS on if { ssl_fc } | ||
http-request set-header Ssl-Offloaded 1 if { ssl_fc } | ||
|
||
## Define hosts | ||
acl host_domain1.com hdr(host) -i domain1.com | ||
|
||
## Figure out which backend they will use | ||
use_backend domain1.com if host_domain1.com | ||
|
||
default_backend default | ||
|
||
backend default | ||
server w1 swarm-worker-1:port cookie S1 check | ||
server w2 swarm-worker-2:port cookie S1 check | ||
server w3 swarm-worker-3:port cookie S1 check | ||
|
||
backend domain1.com | ||
server w1 swarm-worker-1:port cookie S1 check | ||
server w2 swarm-worker-2:port cookie S1 check | ||
server w3 swarm-worker-3:port cookie S1 check | ||
</pre> | ||
|
||
|
||
Let's build our container with the HA Proxy configuration and the certificates. Run <code>docker build . -t haproxy</code>. | ||
|
||
Once the container builds, you can push it up to Docker Hub or another container registry of your choice and deploy it. | ||
|
||
Once deployed, it will have a valid Let's Encrypt Certificate for all the domains. |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
layout: default | ||
title: About Us | ||
metaDescription: About Docker Stack Deploy | ||
--- | ||
|
||
# About Us | ||
<hr /> | ||
|
Oops, something went wrong.