À l'aube du XXIe siècle il fallait des compétences et des outils techniques pour avoir un espace personnel en ligne. Cela s'est rapidement simplifié au milieu de la première décennie où il suffisait de s'inscrire sur divers sites pour publier ses billets en ligne.

Chronologie des outils et services en ligne permettant d'avoir un espace personnel.

Le tout s'est rapidement centralisé autour de quelques services de micro publications tel que Facebook et Twitter ou de publications de billets comme Wordpress.

Depuis les années 2000, je suis passé par l'hébergement de Free pour mon blog et mon équipe de jeu, par la suite je suis passé par divers acteurs comme OVH, Ikoula, Digital Oceans et AWS.

Désormais, je souhaite tenter l'auto hébergement. Le principe est simple, utiliser sa connexion internet et son propre matériel pour rendre disponible des services de son réseau local au monde extérieur. Si il a toujours été possible de le faire, les connexions non pro et sans fibre étaient un peu frêle en débit montant pour se permettre de proposer plusieurs services.

J'avais sur mon ex-serveur une liste de services dont je ne me servais que trop peu... ou qui demandaient tellement de maintenance par rapport à mon utilisation quotidienne que je me suis résolu à les abandonner.

Adieu Matrix, Peertube, Mastodon et NextCloud, je vous retrouverai peut être un jour. J'ai gardé le plus important: mon Blog Ghost, dont vous lisez les lignes, et mon gitlab. Les pages statiques, je les héberge sur Vercel (la gratuité et la simplicité me satisfont).

Traefik routier

Sur le serveur Ikoula, j'avais tout de centralisé sur une unique machine, Docker écoutait aux ports 80 et 443 et laissait le conteneur NGINX de l'image nginx-proxy rediriger vers les conteneurs qui étaient sur le même réseau; seul le port 222 était redirigé vers gitlab sans l'aide de NGINX. Un autre conteneur gérait le SSL avec Let's Encrypt afin d'avoir le chiffrage entre les internautes et les services.

À l'heure actuelle, les internautes toquent à ma Freebox qui redirige tout le trafic 80, 443 et 222 vers un raspberrypi qui route tout ça vers le conteneur Traefik. Ce dernier agit en tant que Load Balancer, tout comme NGINX précédemment, il fait suivre les données à ghost et git suivant ce qui est tapé dans la barre de navigation des internautes.

architecture réseau

J'ai séparé la charge entre deux serveurs physiques (le Raspberry Pi et l'ordinateur portable) afin de ne pas avoir le Pi qui souffre de trop.

Fichier de composition Docker:

services:
  traefik:
    image: "traefik"
    command:
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.gitssh.address=:222
      - --providers.docker
      - --providers.docker.exposedByDefault=false
      - --providers.file.filename=/etc/traefik/services.toml
      - --providers.file.directory=/config
      - --api
      - --certificatesresolvers.le-ssl.acme.email=${TRAEFIK_SSLEMAIL}
      - --certificatesresolvers.le-ssl.acme.storage=/acme.json
      - --certificatesresolvers.le-ssl.acme.tlschallenge=true
      - --log.level=DEBUG
    ports:
      - "80:80"
      - "443:443"
      - "222:222"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./private/acme.json:/acme.json"
      - "./config/:/config/"
    labels:
      - "traefik.enable=true"
      # Dashboard
      - "traefik.http.routers.traefik.rule=Host(`dashboard.${PRIMARY_DOMAIN}`)"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.tls.certresolver=le-ssl"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.middlewares=authtraefik"
      - "traefik.http.middlewares.authtraefik.basicauth.users=${TRAEFIK_PASSWORD}"
      # global redirect to https
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
    restart: unless-stopped
    networks:
      - traefik

networks:
  traefik:
    external: true
Dossiers et fichiers

Le .env vierge de tout mot de passe:

TRAEFIK_PASSWORD=user:$$d23$$DSJKL$$20d9$KEySMaSH920$$2 # à générer avec htpasswd
TRAEFIK_SSLEMAIL=bonjour@gmail.com # email
PRIMARY_DOMAIN=our-domain.com # domaine

  • Let's Encrypt est utilisé pour obtenir les certificats SSL.
  • Un dashboard est disponible.
  • TRAEFIK_PASSWORD doit être généré via htpasswd et il faut doubler les caractères $.
  • Traefik peut détecter les conteneurs mais la fonctionnalité n'est pas activé ici, cela provoquait des problèmes dans certaines situations.

Le fichier de configuration yaml de Traefik pour gitlab:

http:
  routers:
    to-gitlab:
      rule: "Host(`git.rei.ms`)"
      service: gitlab
      entrypoints: websecure
      tls:
        certResolver: "le-ssl"

    to-reglab:
      rule: "Host(`reg.rei.ms`)"
      service: gitlab
      entrypoints: websecure
      tls:
        certResolver: "le-ssl"

  services:
    gitlab:
      loadBalancer:
        servers:
        - url: http://XXX.XXX.XXX.XXX


tcp:
  routers:
    to-gitssh:
      service: gitssh
      entrypoints: gitssh
      rule: HostSNI(`*`)
  services:
    gitssh:
      loadBalancer:
        servers:
          - address: XXX.XXX.XXX.XXX:222

Blog Ghost

Je déteste wordpress. C'est une usine infernale où l'interface est devenue très compliquée pour rien. Je souhaite me concentrer sur le contenu quand j'écris, pas sur des milliers d'options qui pètent. Mon choix s'est porté sur Ghost pour gérer la publication de mes billets, et je suis très satisfait.

Ma configuration ghost est la suivante:

services:
  db:
    image: mysql:8
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    command: --mysql-native-password=ON
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    networks:
      - db

  ghost:
    depends_on:
      - db
    image: ghost:latest
    restart: always
    volumes:
      - ./content:/var/lib/ghost/content
    environment:
      database__client: mysql
      database__connection__host: db
      database__connection__user: ${MYSQL_USER}
      database__connection__password: ${MYSQL_PASSWORD}
      database__connection__database: ${MYSQL_DATABASE}
      url: https://${GHOST_URL}
      mail__transport: $mail__transport
      mail__options__service: $mail__options__service
      mail__options__host: $mail__options__host
      mail__options__port: $mail__options__port
      mail__options__secure: $mail__options__secure
      mail__options__auth__user: $mail__options__auth__user
      mail__options__auth__pass: $mail__options__auth__pass
      mail__from: $mail__from
    labels:
      traefik.enable: "true"
      traefik.http.routers.ghost.rule: "Host(`${GHOST_URL}`)"
      traefik.docker.network: "traefik"
      traefik.http.routers.ghost.entrypoints: "websecure"
      traefik.http.routers.ghost.service: ghost
      #traefik.http.routers.ghost.tls.certresolver: "default"
      traefik.http.routers.ghost.tls.certresolver: "le-ssl"
      traefik.http.services.ghost.loadbalancer.server.port: "2368"
    networks:
      - traefik
      - db

volumes:
    db_data:
    ghost_data:

networks:
  traefik:
    external: true
  db:

un .env se trouve à la racine avec les variables d'environnements. Notez "labels" qui permet de communiquer avec Traefik et de faire rediriger l'url vers ce conteneur.

Gestionnaire de dépôt git Gitlab

Cette partie se trouve sur la machine qui héberge Gitlab. La configuration de traefik diffère légèrement. Cette machine a également Docker avec un conteneur Traefik qui écoute sur les ports 80 et 443.

Le compose de Traefik ressemble à ça:

services:
  traefik:
    image: "traefik"
    command:
      - --entrypoints.web.address=:80
      - --entrypoints.dashboard.address=:8080
      - --entrypoints.websecure.address=:443
      - --api
    ports:
      - "80:80"
      - "8080:8080"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/traefik.yml:ro"
    restart: unless-stopped
    networks:
      - traefik

networks:
  traefik:
    external: true

Le fichier de configuration traefik.yml ainsi:

entrypoints:
  http:
    address: ":80"
  traefik:
    address: ":8080"


api:
  dashboard: true
  insecure: true
  debug: true

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    network: traefik
    watch: true
    allowEmptyServices: true
    exposedByDefault: true

Pour ce qui est du compose gitlab, j'invite à aller sur la documentation officielle, néanmoins je vais partager les étiquettes (labels) du compose qui sont propres à Traefik:

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.gitlab.service=gitlab-service"
      - "traefik.http.routers.gitlab.entrypoints=http"
      - "traefik.http.routers.gitlab.rule=Host(`git.rei.ms`) || Host(`reg.rei.ms`)"
      - "traefik.http.services.gitlab-service.loadbalancer.server.port=80"

On voit que le conteneur récupère deux hosts, l'un pour les dépôts git et l'autre le gestionnaire d'images docker.