diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2019-03-28 10:26:22 +0000 |
|---|---|---|
| committer | s-ol <s-ol@users.noreply.github.com> | 2019-03-28 10:26:22 +0000 |
| commit | d457233ce8d24b553f9dd163c71025caf8f36bc1 (patch) | |
| tree | 5914752e61d082ac5f6855127130f4874fa39d6a /root | |
| parent | wip blog - self-hosted (diff) | |
| download | mmm-d457233ce8d24b553f9dd163c71025caf8f36bc1.tar.gz mmm-d457233ce8d24b553f9dd163c71025caf8f36bc1.zip | |
finish self-hosted
Diffstat (limited to 'root')
| -rw-r--r-- | root/blog/self-hosted_virtual_home/text$markdown.md | 183 |
1 files changed, 181 insertions, 2 deletions
diff --git a/root/blog/self-hosted_virtual_home/text$markdown.md b/root/blog/self-hosted_virtual_home/text$markdown.md index e218138..6cb6b4c 100644 --- a/root/blog/self-hosted_virtual_home/text$markdown.md +++ b/root/blog/self-hosted_virtual_home/text$markdown.md @@ -5,17 +5,196 @@ First a quick overview of what this guide will cover: - HTTPS server with multiple subdomains and varying backends - [traefik][traefik] reverse-proxy maintains SSL certificates and serves all requests - [docker-compose][docker-compose] manages running sites/microservices - - single DNS wildcard route - a private-public git server - access control, management with [gitolite][gitolite] - [klaus][klaus] web frontend for browsing and cloning public repos - fine-grained permissions and SSH public-key access - micro 'CI' setup rebuilds & redeploys docker images when updates are pushed -# HTTPS server +Most of these projects are very well documented so I won't go into a lot of detail on setting them up. +# HTTPS Server +To run multiple subdomains from a single machine, the HTTP requests need to be matched according to the 'Host' header. +Most HTTP servers have good facilities for doing this, e.g. apache has vhosts, nginx has server directives etc. + +In the past I had used apache as my main server, which worked well for static content and PHP apps, +but not all applications fit into this scheme too well and configuration is a tad tedious. + +With this latest iteration I am using [traefik][traefik] as a "reverse proxy". +This means traefik doesn't serve anything (not even static content) by itself, +it just delegates requests to one of multiple configured services based on a system of rules. + +It also handles letsencrypt certificate generation and updates out-of-the-box and can be tightly integrated with docker, +so that it automatically reacts to new services being added. + +Traefik can be run at system level, but currently I prefer installing the least system-level applications to have my setup +as self-contained as possible. Therefore I went with this [traefik in docker-compose][traefik-in-docker] setup from kilian.io: + + version: '3.4' + + services: + traefik: + image: traefik:1.5-alpine + restart: always + ports: + - 80:80 + - 443:443 + networks: + - web + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - ./traefik.toml:/traefik.toml + - ./acme.json:/acme.json + container_name: traefik + + + networks: + web: + external: true + +with the small addition of the `:ro` at the end of the docker socket volume, +to prevent attacks on traefik from being able to take over the host docker system (too easily). +In the guide you can find more details, including the `traefik.toml` that I am using almost verbatim. + +# Hosting Sites +With traefik set up, dockerized services can be added and exposed trivially. +For example to start `redirectly`, a tiny link redirect service, this addition suffices: + + redirectly: + image: local/redirectly:git + restart: always + networks: + - web + labels: + - "traefik.frontend.rule=Host:s-ol.nu" + - "traefik.enable=true" + +By setting different subdomains in the frontend-rule section, many different services can be provided. + +The image `local/redirectly:git` in this case is built automatically when a repo is pushed (see below). + +note: if a container doesn't have an EXPOSE directive, or EXPOSEs multiple ports, +you will have to add a `traefik.port` label specifying which port to use. + +# private/public Git Server +While I still have a lot of code on Github, where collaboration is easy, +I prefer to own the infrastructure that I store my private projects on. +I also wanted to have a public web index of some of the projects. + +The git infrastructure itself is mananged by [gitolite][gitolite], which I really enjoy using. + + repo gitolite-admin @all + RW+ = s-ol + C = s-ol + + repo public/.* + R = @all daemon + option writer-is-owner = 1 + + repo ... ... + RW+ = ludopium + +In the first block I grant myself full access to all repos, as well as the right to automatically create repos by +attempting to push/pull from them. + +The second block makes all repos prefixed with `public/` readable by anyone in the gitolite system, +as well as the `git-daemon`, which allows cloning via `git://....` access (port 9418). +The `write-is-owner` option lets me set the git `description` field using `ssh git@git.s-ol.nu desc`. + +I chose the `public/` prefix because it results in all public repos being stored in one directory together +(`/var/lib/gitolite/repositories/public`), where klaus can easily pick them up. + +The klaus web frontend is set up using traefik above like so: + + klaus: + image: hiciu/klaus-dockerfile + restart: always + networks: + - web + volumes: + - /var/lib/gitolite/repositories/public:/srv/git:ro + command: /opt/klaus/venv/bin/uwsgi --wsgi-file /opt/klaus/venv/local/lib/python2.7/site-packages/klaus/contrib/wsgi_autoreload.py --http 0.0.0.0:8080 --processes 1 --threads 2 + environment: + KLAUS_REPOS_ROOT: /srv/git + KLAUS_SITE_NAME: git.s-ol.nu + KAUS_CTAGS_POLICY: tags-and-branches + KLAUS_USE_SMARTHTTP: y + labels: + - "traefik.frontend.rule=Host:git.s-ol.nu" + - "traefik.enable=true" + +I am using the ['autoreload' feature][klaus-autoreload] and the `hiciu/klaus-dockerfile` docker image. +Setting `KLAUS_USE_SMARTHTTP` allows cloning repos via HTTP. + +In the future I would like to modify klaus a bit, for example by showing the README in the root of a project per default +and applying a custom theme. + +# Micro-CI +The last piece of the puzzle is automatically deploying projects whenever they are pushed. +This can be realized using git's `post-receive` hooks and is generally pretty well known. + +I followed this gitolite guide for [storing repo-specific hooks in the gitolite-admin repo][gitolite-hooks]. +It requires a change in the gitolite rc file (on the server), but after that you can configure deployment processes in the conf like this: + + @dockerize = public/redirectly ... + @jekyllify = blog + + repo @dockerize + option hook.post-receive = docker-deploy + + # i actually dont have a jekyll blog anymore but its an easy one as well + repo @jekyllify + option hook.post-receive = jekyll-deploy + +The hooks are stored in the same repo under `local/hooks/repo-specific`. +Here is the `docker-deploy` hook I am using: + + #!/bin/bash + read oldrev newrev refname + set -e + + # Get project name + PROJECT=$(basename "$PWD") + PROJECT=${PROJECT%.git} + + # Paths + CHECKOUT_DIR=/tmp/git/${PROJECT} + TARGET_DIR=... # POINT TO docker-compose.yml directory + + if [ ! -d ${TARGET_DIR} ]; then + echo -e "\e[1;32mNo target directory to compile into\e[00m" + fi + + mkdir -p ${CHECKOUT_DIR} + GIT_WORK_TREE=${CHECKOUT_DIR} git checkout -q -f $newrev + echo -e "\e[1;32mChecked out ${PROJECT}.\e[00m" + + cd ${CHECKOUT_DIR} + docker build -t local/${PROJECT}:git . + echo -e "\e[1;32mImage built.\e[00m" + + cd ${TARGET_DIR} + docker-compose up -d ${PROJECT} + echo -e "\e[1;32mContainer restarted.\e[00m" + +It will build a `local/$REPO:git` image whenever you push, then run `docker-compose up -d $REPO` in `$TARGET_DIR`. +Just make sure that your docker-compose service is called the same as the image name (like in the `redirectly` example above). + +This hook definetely needs an addition to filter which pushes trigger a redeploy (e.g. only tags or only master), +but that should be trivial to add (and well documented online). + +--- + +That's basically it! +If you have questions or comments i'll be happy to hear from you on twitter, github or [mastodon][merveilles]. [traefik]: https://traefik.io/ [docker-compose]: https://docs.docker.com/compose/ [gitolite]: http://gitolite.com/gitolite/index.html [klaus]: https://github.com/jonashaag/klaus + +[traefik-in-docker]: https://blog.kilian.io/server-setup/ +[klaus-autoreload]: https://github.com/jonashaag/klaus/wiki/Autoreloader +[gitolite-hooks]: http://gitolite.com/gitolite/cookbook#v36-variation-repo-specific-hooks + +[merveilles]: https://merveilles.town/@s_ol |
