Apache virtual hosts, HTTPS, and JIRA Docker Containers
tl;dr
The goal was to easily create and recreate docker instances protected via SSL and accessed by simple URL. Below I explain how to map https://jira.example.com/
and https://git.example.com/
in apache (used as firewall, reverse proxy, content server) to a specified IP:port of Jira and Bitbucket (git) docker container.
Overview
Docker is awesome, can easily create a new web service in minimal time. However, in my case, I want everything to be routed through one machine’s https (port 443). Additionally I wanted to setup Jira and Bitbucket (and possibly more). Previously I had to use github.com to view my private repositories from a web browser. I show how to do this with apache 2.4 and docker on a single Ubuntu Linux machine.
- Security – single apache instance serves as reverse proxy and can force all HTTP requests to use HTTPS.
- HTTPS certificates – use certbot by Let’s Encrypt to easily install certificates for HTTPS to work for free.
- DNS and Virtual hosts – Assuming multiple domains or subdomains all get routed to same apache instance. Will configure apache conf files to map these requests to correct port and path on docker container.
- Creating / Starting JIRA and Bitbucket (git) docker containers to listen on a specific port
Note that you should replace example.com
everywhere used in this doc with your domain name.
longlonglonglong
DNS
Goal is for several domains, example.com
, jira.example.com
, test-jira.example.com,
, and git.example.com
, test-git.example.com
bitbucket.example.com
, to resolve to the machine where apache will run. There are many ways to do this, I have one A record mapping example.com
to an IP, and CNAME records mapping the subdomains to example.com
.
Apache Setup
I use Apache as the reverse proxy because of its popularity and my experience with it. If performance is an issue, nginx is probably better. Below you’ll find the important bits from these apache conf files:
apache2.conf
sites-enabled/example.com.conf
sites-enabled/jira.example.com.conf
sites-enabled/git.example.com.conf
sites-enabled/000-default.conf
conf-available/certbot.example.com.conf
conf-available/vhost.logging.conf
> grep sites-enabled apache2.conf IncludeOptional sites-enabled/*.conf
> cat /etc/apache2/sites-enabled/example.com.conf <IfModule mod_ssl.c> <VirtualHost *:443> ServerName example.com DocumentRoot /var/www/example.com Include conf-available/vhost.logging.conf Include conf-available/certbot.example.com.conf </VirtualHost> </IfModule>
> cat /etc/apache2/sites-enabled/jira.example.com.conf <IfModule mod_ssl.c> <VirtualHost *:443> ServerName jira.example.com <Proxy *> Order allow,deny Allow from all </Proxy> ProxyRequests Off ProxyPreserveHost On # below must map to docker ip:port setup ProxyPass / http://127.0.0.1:8080/ ProxyPassReverse / http://127.0.0.1:8080/ Include conf-available/vhost.logging.conf Include conf-available/certbot.example.com.conf </VirtualHost> </IfModule>
> cat /etc/apache2/sites-enabled/git.example.com.conf <IfModule mod_ssl.c> <VirtualHost *:443> ServerName git.example.com ServerAlias bitbucket.example.com <Proxy *> Order allow,deny Allow from all </Proxy> ProxyRequests Off ProxyPreserveHost On # below must map to docker ip:port setup ProxyPass / http://127.0.0.1:7990/ ProxyPassReverse / http://127.0.0.1:7990/ Include conf-available/vhost.logging.conf Include conf-available/certbot.example.com.conf </VirtualHost> </IfModule>
> cat /etc/apache2/sites-enabled/000-default.conf <VirtualHost *:80> DocumentRoot /var/www/html Include conf-available/vhost.logging.conf # Redirect http (port 80) to https (port 443) RewriteEngine on RewriteCond "%{SERVER_NAME}" ".*\.example.com$" [OR] RewriteCond %{SERVER_NAME} =example.com RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,QSA,R=permanent] </VirtualHost>
> cat /etc/apache2/conf-available/certbot.example.com.conf # added by certbot-auto SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf
> cat /etc/apache2/conf-available/vhost.logging.conf LogFormat "%{Host}i:%p %h %l %u [%{%d/%b/%Y %T}t.%{msec_frac}t %{%z}t] %{us}T \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined2 CustomLog ${APACHE_LOG_DIR}/access.vhosts.log vhost_combined2 ErrorLog ${APACHE_LOG_DIR}/error.log
HTTPS Certificates
With letsencrypt.org, you can get free certificates from a Certificate Authority (CA). I used the cmd-line certbot to install them and update them. Initial setup can take up to 30 minutes, but every 3 months when you renew it should only take a few minutes. I do this on Ubuntu linux, but they have instructions for all the popular flavors of linux. When done, you can verify your installed certificate using https://www.ssllabs.com/ssltest/analyze.html?d=example.com
One thing to note here is that its easiest to have a single certificate to cover domain and subdomains. In January 2018 wildcard certs will be supported, but till then you’ll need to start with something like this:
cd ssl-certs && ./certbot-auto --apache \ -d example.com \ -d jira.example.com -d git.example.com -d bitbucket.example.com
Docker Setup
Docker is the new cool kid on the block, and as such, it is constantly improving. So what I write here may not be exactly what you need to do. In any case, what I did is setup 3 docker containers – one for Jira, one for Bitbucket, and one for Postgres database. If you don’t have experience setting up Jira or Bitbucket, it can be tricky, but Atlassian has pretty good documentation.
I have created a sample docker-compose.yml that covers whats needed on the docker side. As previously mentioned, you will need to replace example.com
with your domain name.