Docker @ Home, an awesome way for your in-the-closet server.

March 1, 2015 - 5 min read
Old (and unfinished) post for historical reasons

This post is very old and contains next to none relevant info anymore. Today (2021), there are plenty of solutions today. Google it.

It's a common problem among us, how and where should I put my personal running services. Lets say you want to run a dns server, gitlab, splunk, a piratepad, sickbeard, sabnzb, (and the list goes on...), all on 1 server, in your home, accessible from the outside, and use https.. And then you want backup of this, and a personal documentation, so you can replicate it later.. It will take a real some real efford to get all this running.

Personally, I have tried a lot of different self-hosting solutions for my small services, including 1 per vm, all running at the same host (but seperated with SELinux), and spreading it out over several physical servers.

So, here is what we will create;

  • All your stuff behind 1 domain.
  • Authentication using your mail (OAuth/Gmail support).
    • Different people can access different parts of your stuff
    • A solution for public access to some part of your page.
    • SSO for services like Gitlab, ...
  • Accessible from the outside and inside of your network.
  • http redirect to https with a valid ($5 USD) certificate.
    • Multiple domain support (if you want more than 1 domain on your ip)
  • Dynamic ip
  • Something that is easy to expand, take backup of, and rebuild if failed.

We will make this work with the use of Docker and docker-compose, and a lot of custom-created containers. Feel free to use other containers as well, or build your own based on mine. :)

Ok, so before you start, you should have 1 server running Docker.

Structure (some if it)

File and folders

Everything should run inside one folder on your server, lets call it your.domain.com, the structure inside that is as follows:

  • your.domain.com
    • fig.yml - The main configuration for how all the docker-containers is runned.
    • gitlab/data - Datafolder for Gitlab
    • postgresql/data
    • wwwhisper/data - Authentication container
    • nginx-simple/nginx.conf
    • _front/your.domain.com_127.0.0.1:8000

Container layout

FIXME

Authentication

The authentication will be done by wwwhisper, which uses Persona to do the authentication itself. wwwhisper uses some nginx magic to make it possible to give access to example your-mail@your.domain.com to your.domain.com/secret. Even tho the service running with the url /secret doesn't know about authentication.

wwwhisper will also make a http-header available with the users mail-adress when logged in. We will use this for SSO.

It also have a pretty admin-interface :)

Inside and outside access

So, this is not really a big problem. But I had some issues when I depended on only my public ip/dns from inside my LAN. With the firewall configuration I wanted, I usually ended up at my gateway web-side, not my server.

I ended up creating a tiny dnsmasq container that made sure that my inside ip to your.domain.com was pointing to the LAN ip, not my public ip.

Certificate

You could obviously have both a self-signed, or extended validation certificate. But untill letsencrypt (free, automated, open) is here. cheapsslsecurity sells Comodo and RabidSSL certs for around $5usd/year.

I also made a container for taking care of https. It will be the first container that is hit when accessing your server on bort 80 or 443. It supports multiple domains, and redirecting traffic both to the same server, or another server on the same LAN.

Dynamic ip problem

You can solve this many ways. There are plenty of dns update utilities out there. Someone can even be configured on the router. I am a big fan of [DNSSimple], so I made a container to keep my ip up-to-date. I am including the configuration if you also want to use it.

Robustness

As the folder/file structure hints to, you will end up with 1 configuration file for how all your services are stitched together (the fig.yml file), and all your actual data in separate data folders. Fig will make it easy to setup, and the folders will make it easy to backup.

Details

fig.yml (example)

dnsupdater:
  image: xeor/dnsimple-updater
  environment:
    DOMAIN: your.domain.com
    DOMAIN_API_TOKEN: abc123
    RECORD_ID: 300000
    UPDATE_TIMER: 1200

intproxy:
  image: xeor/webproxy
  volumes:
    - /var/run/docker.sock:/docker.sock

wwwhisper:
  image: xeor/wwwhisper
  environment:
    SITE_URL: https://your.domain.com
    ADMIN_MAIL: your-mail@your.domain.com
    VIRTUAL_HOST: your.domain.com
  volumes:
    - wwwhisper/data:/wwwhisper/sites
    - /var/run/docker.sock:/docker.sock

secretUrl:
  image: xeor/nginx-simple
  links:
    - intproxy:your.domain.com
  environment:
    WWWHISPER_USES_RELATIVE_PATH: "true"
    WWWHISPER_PROTECT: s
    HTTP_PROXY_PATH: s
  volumes:
    - nginx-simple/nginx.conf:/nginx.conf

nginxProxyWatcher:
  image: xeor/nginx-proxy-m-watcher-nossl
  volumes:
    - /var/run/docker.sock:/docker.sock

nginxProxyForwarder:
  image: xeor/nginx-proxy-m-forwarder
  ports:
    - "80:80"
  volumes_from:
    - nginxProxyWatcher

postgresql:
  image: postgres
  volumes:
    - postgresql/data:/var/lib/postgresql/data

gitlabRedis:
  image: redis

gitlab:
  image: xeor/gitlab-sso
  ports:
    - "2222:22"
  links:
    - gitlabRedis:redisio
    - postgresql:postgresql
    - intproxy:your.domain.com
  environment:
    WWWHISPER_PROTECT: git
    HTTP_PROXY_PATH: git
    GITLAB_HOST: your.domain.com
    GITLAB_SSH_PORT: 2222
    GITLAB_EMAIL: git@your.domain.com
    GITLAB_BACKUPS: daily
    GITLAB_RELATIVE_URL_ROOT: /git
    DB_TYPE: postgres
    DB_USER: gitlab
    DB_NAME: gitlabhq
    SMTP_USER: git@your.domain.com
    SMTP_PASS: abc123
    OAUTH_GOOGLE_API_KEY: abc123.apps.googleusercontent.com
    OAUTH_GOOGLE_APP_SECRET: abc123

gitstats:
  image: xeor/git-stats
  environment:
    GIT_REPO: http://gitstats:longpw@your.domain.com/git/org/project.git/
    WWWHISPER_PROTECT: gitstats
    WWWHISPER_PORT: 8080
    WWWHISPER_USES_RELATIVE_PATH: "true"
  links:
    - intproxy:your.domain.com