diff --git a/acme-copy-certs/.gitignore b/acme-copy-certs/.gitignore deleted file mode 100644 index 38ce4278b6f53ca9c84b17a805fab69689273e86..0000000000000000000000000000000000000000 --- a/acme-copy-certs/.gitignore +++ /dev/null @@ -1,123 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -.python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don’t work, or not -# install all needed dependencies. -#Pipfile.lock - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ diff --git a/acme-copy-certs/Dockerfile b/acme-copy-certs/Dockerfile deleted file mode 100644 index 337bea601f7c452381cd37e7716684c74f521567..0000000000000000000000000000000000000000 --- a/acme-copy-certs/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM alpine:3.9 - -WORKDIR /usr/src/app -COPY requirements.txt ./ - -RUN apk add --no-cache python3 && \ - python3 -m ensurepip && \ - rm -r /usr/lib/python*/ensurepip && \ - pip3 install --upgrade pip setuptools -r requirements.txt && \ - rm -r /root/.cache diff --git a/acme-copy-certs/README.md b/acme-copy-certs/README.md deleted file mode 100644 index fa57959406502189a96761b5395d9aa1c50b3d32..0000000000000000000000000000000000000000 --- a/acme-copy-certs/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# ACME Copy certs - -Ce service permet l'exploitation des certificats TLS générés par Traefik -par d'autres serveurs pour leur propres besoins de chiffrement de connexions. - -Traefik a la capacité d'automatiser la demande et le renouvellement de certificats -TLS auprès de services en ligne tels que [Let's Encrypt](https://letsencrypt.org) -pour assurer le chiffrement des connexions HTTPS aux sites web dont il a la charge. - -L'idée est de déléguer la gestion de certificats utilisés par d'autres services dans -d'autres conteneurs à Traefik, ce qui présente les avantages suivants : - * Les certificats générés sont signés par une autorité de certification publique dont les - certificats sont déjà présents sur la plupart des systèmes, ce qui facilite la - vérification de l'authenticité des certificats par rapport à des certificats auto-signés (pas - de certificats de signature à déployer) - * A leur expiration, les certificats sont automatiquement renouvelés, ce qui élimine au tâche d'administration - et garantit la disponibilité continue des services \ No newline at end of file diff --git a/acme-copy-certs/app/cert_updater.py b/acme-copy-certs/app/cert_updater.py deleted file mode 100644 index da5a24ae43c134d08d4945726a7e72d0e2c430ef..0000000000000000000000000000000000000000 --- a/acme-copy-certs/app/cert_updater.py +++ /dev/null @@ -1,200 +0,0 @@ -""" Traefik Certificate extraction and update module - -Provides tools to extract TLS certificates from Treafik acme.json files. - -Classes -------- - - CertUpdater: - This class handles acme files decoding and stores or updates the resulting - certificates in separate folders. -""" - -import os -import errno -import json -from base64 import b64decode - -class CertUpdater: - """Decodes acme files and extact the resulting certificates if needed. - - This class keeps flat certificates for specified domain names - in sync with the contents of an acme.json file. The certificates are stored in separated - subdirectories named after the main domain name they are valid for. - If the certificates specify x509 SAN records, only the main CN is used (a single - directory is created, regardless of the number of alternate names.) - - Attributes - ---------- - acme_file : str - Name of the acme.json file containing the certificates - names : list - List of domain names to keep updated - certs_root_path : str - Directory where the certificates will be stored. The certificates are - stored in subdirectories of this directory - - Methods - ------- - add(name) - Adds a domain name to the updater - - remove(name) - Removes a domain name from the updater - - update() - Decodes the acme.json file and updates the certicates that need to be updated. - - - - """ - def __init__(self, acme_file, certs_root_path): - """ - Parameters - ---------- - acme_file : str - path of the acme file containing the certificates - certs_root_path : str - root directory where certificates will be extracted. - They are extracted in subdirectories named after the CN stored in - the certificate. - """ - self.acme_file = acme_file - self.names = [] - self.certs_root_path = certs_root_path + '/' - - def add(self, name): - """Adds a domain name to the updater. - - Parameters - ---------- - name : str - domain name to add - """ - - self.names.append(name) - - # Create directories etc if they do not exist - try: - os.makedirs(self.certs_root_path + name + '/') - except OSError as error: - if error.errno != errno.EEXIST: - raise - - def remove(self, name): - """Removes a domain name from the updater. - - Parameters - ---------- - name : str - domain name to remove - """ - - try: - self.names.remove(name) - except ValueError: - pass - - def update(self): - """Decodes the acme.json file and updates the certicates that need to be updated. - - Returns - ------- - list - a list of domain names that have been updated. An empty list if no certificate - has been updated. - """ - - # Open and decode the acme file - try: - with open(self.acme_file) as acme: - data = json.loads(acme.read()) - except FileNotFoundError: - print('ACME file {0} not found when trying to decode.'.format(self.acme_file)) - return [] - except json.JSONDecodeError: - print('File {0} does not look like an ACME file.'.format(self.acme_file)) - return [] - - # Get the acme file version - try: - acme_ver = 2 if 'acme-v02' in data['Account']['Registration']['uri'] else 1 - except TypeError: - if 'DomainsCertificate' in data: - acme_ver = 1 - else: - acme_ver = 2 - - # Get the certificates - if acme_ver == 1: - certs = data['DomainsCertificate']['Certs'] - elif acme_ver == 2: - certs = data['Certificates'] - - # Iterate over certificates. If a certificate has been updated, - # add its name to the updated_names. - updated_names = [] - - for c in certs: - if acme_ver == 1: - name = c['Certificate']['Domain'] - key = c['Certificate']['PrivateKey'] - fullchain = c['Certificate']['Certificate'] - elif acme_ver == 2: - name = c['Domain']['Main'] - key = c['Key'] - fullchain = c['Certificate'] - - if name in self.names: - key = b64decode(key).decode('utf-8') - fullchain = b64decode(fullchain).decode('utf-8') - chain_start = fullchain.find('-----BEGIN CERTIFICATE-----', 1) - cert = fullchain[0:chain_start] - chain = fullchain[chain_start:] - - print('Updating certificates for {0}'.format(name)) - if self._needs_updating(name, fullchain): - path = self.certs_root_path + name + '/' - with open(path + 'privkey.pem', 'w') as f: - f.write(key) - - with open(path + 'cert.pem', 'w') as f: - f.write(cert) - - with open(path + 'chain.pem', 'w') as f: - f.write(chain) - - with open(path + 'fullchain.pem', 'w') as f: - f.write(fullchain) - - print('Certificates updated') - - updated_names.append(name) - else: - print('Cetificates are already up-to-date') - - return updated_names - - def _needs_updating(self, name, fullchain): - """Checks if a certificate has changed - - Parameters - ---------- - name : str - Name of the directory containing the certificates - fullchain : str - Full certificates extracted from the acme.json file - - Returns - ------- - bool - True if the contents of the current certificates are - different from the fullchain. False otherwise. - """ - - path = self.certs_root_path + name + '/fullchain.pem' - try: - with open(path, 'r') as f: - return f.read() != fullchain - except FileNotFoundError: - return True \ No newline at end of file diff --git a/acme-copy-certs/app/docker_actions.py b/acme-copy-certs/app/docker_actions.py deleted file mode 100644 index 06735e64313217ba528c50ac63f2954004ff9a08..0000000000000000000000000000000000000000 --- a/acme-copy-certs/app/docker_actions.py +++ /dev/null @@ -1,39 +0,0 @@ -import docker - -class DockerAction: - def __init__(self, docker_client, container_id): - self.client = docker_client - self.container_id = container_id - pass - - def exec(self, id): - c = self.client.container.get(self.container_id) - - if c.status == 'running': - self.action(c) - - def action(self, container): - pass - -class RestartDockerAction(DockerAction): - def __init__(self, docker_client, container_id): - super().__init__(docker_client, container_id) - - def action(self, container): - try: - container.restart() - except docker.errors.APIError: - print('Unable to restart container {0}({1})'.format(container.name, - container.id)) - -class KillDockerAction(DockerAction): - def __init__(self, docker_client, container_id, signal='SIGKILL'): - super().__init__(docker_client, container_id) - self.signal = signal - - def action(self, container): - try: - container.kill(self.signal) - except docker.errors.APIError: - print('Unable to kill container {0}({1}) with signal {2}' - .format(container.name, self.container_id, self.signal)) \ No newline at end of file diff --git a/acme-copy-certs/app/docker_monitor.py b/acme-copy-certs/app/docker_monitor.py deleted file mode 100644 index 13e41ca600173877ee9c12570b7d4a329584dd62..0000000000000000000000000000000000000000 --- a/acme-copy-certs/app/docker_monitor.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Docker event monitoring - -Provides a monitor for docker events that add/remove services when -they occur according to the configuration provided in the labels of these -services. - -Classes -------- - DockerMonitor - A monitor for docker events. -""" - -import docker -import threading -import requests - -from service_manager import Service -from docker_actions import RestartDockerAction -from docker_actions import KillDockerAction - -class DockerMonitor(threading.Thread): - """Implements a docker events monitoring thread. - - This class implements a thread that listen to the docker socket to intercept - events on specific containers to launch actions on these when start and stop events occur. - Containers that should be monitored are identified by labels. - - """ - def __init__(self, services_mgr): - self.docker_client = docker.from_env() - self.events = None - self.services_mgr = services_mgr - super().__init__() - - def run(self): - print('Starting monitor') - # Identify all running containers and get dependent services - # at startup - try: - containers = self.docker_client.containers.list() - - for c in containers: - if c.status == 'running': - self._add_service(c) - - # Then, wait for docker events and identify new dependent services - # or services that exit the system. Do an update each time a new - # service is added / restarted etc. or a service is changed. - self.events = self.docker_client.events(decode = True) - for event in self.events: - if 'status' not in event: - continue - - try: - c = self.docker_client.containers.get(event['id']) - if event['status'] == 'stop': - self._remove_service(c) - elif event['status'] == 'start': - self._add_service(c) - - except docker.errors.NotFound: - pass - except docker.errors.APIError as error: - print('Docker error while looking up container {0}: {1} '.format(event.id, error.strerror)) - except requests.exceptions.ConnectionError as error: - print('Connection to docker socket refused.') - - print('No more events to handle: stopping monitor') - - def stop(self): - if self.events is not None: - self.events.close() - self.join() - - def _get_host_from_traefik_rule(self, container): - if 'traefik.frontend.rule' in container.labels: - try: - return container.labels['traefik.frontend.rule'].split('Host:')[1].split(',')[0].strip() - except IndexError: - return '' - - def _get_action_from_label(self, container): - if 'acme_copy_certs.action' not in container.labels: - return None - - try: - action = container.label('acme_copy_certs.action') - if action[0].strip() == 'kill': - if len(action) == 1: - return KillDockerAction(self.docker_client, container.id, 'SIGHUP') - else: - return KillDockerAction(self.docker_client, container.id, action[1].strip()) - elif action[0].strip() == 'restart': - return RestartDockerAction(self.docker_client, container.id) - else: - return None - - except IndexError: - print('Invalid action') - return None - - def _add_service(self, container): - if 'acme_copy_certs.enable' in container.labels: - if container.labels['acme_copy_certs.enable'] == 'true': - host = self._get_host_from_traefik_rule(container) - elif container.labels['acme_copy_certs.enable'] == 'false': - pass - else: - print('Invalid acme_copy_certs.enable value for {0}' - .format(container.name)) - - if host: - print('Handling container {0}({1})'.format(container.name, container.id)) - s = Service(container.id, host, self._get_action_from_label(container)) - self.services_mgr.add(s) - else: - print('Not handling container {0}({1})'.format(container.name, container.id)) - - def _remove_service(self, container): - self.services_mgr.remove(container.id) \ No newline at end of file diff --git a/acme-copy-certs/app/file_watcher.py b/acme-copy-certs/app/file_watcher.py deleted file mode 100644 index 580041be3b6193eada13aaf8013e6745c4cfc47f..0000000000000000000000000000000000000000 --- a/acme-copy-certs/app/file_watcher.py +++ /dev/null @@ -1,33 +0,0 @@ -import os -from watchdog.observers import Observer -from watchdog.events import PatternMatchingEventHandler - -class FileWatcher: - def __init__(self, file_path, handler): - self.observer = Observer() - abs_path, file_name = os.path.split(os.path.abspath(file_path)) - self.observed_path = abs_path - self.observed_file = file_name - self.handler = handler - - self.event_handler = PatternMatchingEventHandler( - patterns=['*/' + file_name], - ignore_patterns=[], - ignore_directories=True) - - self.event_handler.on_any_event = self._on_any_event - - self.observer.schedule(self.event_handler, - self.observed_path, - recursive=False) - - def _on_any_event(self, event): - self.handler() - - def start(self): - print('Starting observing file {0} in directory {1}'.format(self.observed_file, self.observed_path)) - self.observer.start() - - def stop(self): - self.observer.stop() - self.observer.join() \ No newline at end of file diff --git a/acme-copy-certs/app/service_manager.py b/acme-copy-certs/app/service_manager.py deleted file mode 100644 index b20e84dcdba18b7d44df4cbe20143c8f4ad60448..0000000000000000000000000000000000000000 --- a/acme-copy-certs/app/service_manager.py +++ /dev/null @@ -1,139 +0,0 @@ -"""Handling of docker services - -This module provides a ServicesManager class implementing a collection of -services whose certificates are to be updated by the ssytem. - -Classes -------- - Service - A class representing a single service - - ServiceManager - A class handling a collection of services -""" - -from threading import Lock - -class Service: - """ - A service wrapper This object represents a docker service - - Attributes - ---------- - - id : int - The id of the container running the service - host : str - The hostname associated with the service used for CN in TLS certs - action : DockerAction - An action to perform on the service when the run_action method is - invoked. - - Methods - ------- - - run_action() - Runs the action bound to this service - """ - - def __init__(self, id, host, action): - """ - Parameters - ---------- - id : int - The id of the container running the service - host : str - The hostname associated with the service used for CN in TLS certs - action : DockerAction - An action to perform on the service when the run_action method is invoked. - """ - - self.id = id - self.host = host - self.action = action - - def run_action(self): - """Executes the action on the container associated to the service.""" - if self.action is not None: - self.action.exec(self.id) - -class ServicesManager: - """ - A ServicesManager handles a collection of services and forwards certicate update - requests to a CertUpdater. If a service certificate is updated (either after adding a - service or after an explicit update request), the docker action associated - with the service is executed. - - Attribures - ---------- - services_by_id : dict - A dictionnary of the managed services identified by their container id. - services_by_host : dict - A dictionnary of the managed services identified by the CN of their - certificates. - updater : CertUpdater object - The certificates updater in charge of handling the certificates for the managed - services - - Methods - ------- - add(service) - Adds a new service to the collection - - remove(id) - Removes a service from the collection based on its container id - - update() - Checks if any certificate for a managed service needs to be updated. If - so, performs the docker action associated with the service on its - container - """ - - def __init__(self, updater): - """ - Parameters - ---------- - updater : CertUpdater - The CertUpdater used to handle certificates for the services - """ - self.services_by_id = {} - self.services_by_host = {} - self.updater = updater - self.lock = Lock() - - def add(self, service): - """ Adds a service to the collection and enables handling of its - certificates - """ - with self.lock: - self.services_by_id[service.id] = service - if service.host not in self.services_by_host: - self.services_by_host[service.host] = [service] - else: - self.services_by_host[service.host].append(service) - - self.updater.add(service.host) - self.update() - - def remove(self, id): - """ Removes a service by its id from the collection and disables handling - of its certificates - """ - with self.lock: - if id in self.services_by_id: - service = self.services_by_id[id] - host = service.host - self.services_by_host[host].remove(service) - del self.services_by_id[id] - if len(self.services_by_host[host]) == 0: - del self.services_by_host[host] - self.updater.remove(host) - - def update(self): - """ Updates the certificates of the services if needed. If a certificate - has changed, exectute the associated docker action on the service container. - """ - with self.lock: - for h in self.updater.update(): - for s in self.services_by_host[h]: - s.run_action() \ No newline at end of file diff --git a/acme-copy-certs/requirements.txt b/acme-copy-certs/requirements.txt deleted file mode 100644 index c546145a62c9e8123dbbe26981510ce150404eea..0000000000000000000000000000000000000000 --- a/acme-copy-certs/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -docker -watchdog diff --git a/acme-copy-certs/tests/test.py b/acme-copy-certs/tests/test.py deleted file mode 100755 index 9772682d64e5dcc9a973f26b76e156d22378581b..0000000000000000000000000000000000000000 --- a/acme-copy-certs/tests/test.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python3 - -import sys, os -sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../app') - -import time -import cert_updater -import file_watcher -import docker_monitor -import service_manager - - -if __name__ == "__main__": - u = cert_updater.CertUpdater('./acme.json', '.') - - - sm = service_manager.ServicesManager(u) - - f = file_watcher.FileWatcher('./acme.json', sm.update) - dm = docker_monitor.DockerMonitor(sm) - - f.start() - dm.start() - - try: - while True: - time.sleep(1) - except KeyboardInterrupt: - dm.stop() - f.stop() diff --git a/doc/guide_bonnes_pratiques.md b/doc/guide_bonnes_pratiques.md index 84c748c835b2afeec9ea5d0f55c2f4595bf566ce..526337f5464d3c9d18d430e16a4711784a489320 100644 --- a/doc/guide_bonnes_pratiques.md +++ b/doc/guide_bonnes_pratiques.md @@ -112,30 +112,37 @@ Il est suggéré d'éviter les volumes déclarés `external` : ## Reverse-proxy -Si le service est un service **HTTP(S)** (*i.e.* Web), on utilisera systématiquement le reverse-proxy [Traefik](https://wiki.picasoft.net/doku.php?id=technique:infrastructure:archi#traefik) et on bindera **pas** son port interne sur un port de l'hôte. +Si le service est un service **HTTP(S)** (*i.e.* Web), on utilisera systématiquement le reverse-proxy Traefik et on bindera **pas** son port interne sur un port de l'hôte. En effet, Traefik permet de gérer tout pour nous : la redirection vers le bon conteneur et le bon port en fonction du nom de domaine, la création et le renouvellement des certificats, etc. -Il suffit pour ce faire d'ajouter les bons labels, et d'ajouter le conteneur au réseau par défaut de Traefik, qui s'appelle `docker_default`, et existe indépendamment de Docker Compose. +Il suffit pour ce faire d'ajouter les bons labels, et d'ajouter le conteneur au réseau par défaut de Traefik, qui s'appelle `proxy`, et existe indépendamment de Docker Compose. Exemple à reprendre : ```yaml networks: - docker_default: + proxy: external: true services: exemple: networks: - - docker_default + - proxy labels: # Traefik va prendre ce conteneur en compte traefik.enable: true + # websecure correspond au port 443 de la machine (config Traefik) + # Remplacer <exemple> par le nom du conteneur + traefik.http.routers.<exemple>.entrypoints: websecure # Il redirigera vers ce port, exposé par le conteneur - traefik.port: <port> + # Remplacer <exemple> par le nom du conteneur + # Remplacer app.picasoft.net par l'URL souhaitée + traefik.http.routers.<exemple>.rule: Host(`app.picasoft.net`) # Lorsque l'utilisateur consulte cette URL - traefik.frontend.rule: <exemple>.picasoft.net + # Remplacer <exemple> par le nom du conteneur + # Remplacer 80 par le port du service + traefik.http.services.<exemple>.loadbalancer.server.port: 80 ``` ## Healthcheck @@ -182,7 +189,7 @@ Ce qui nous donnerait quelque chose comme : networks: # C'est le réseau dans lequel se trouve # Traefik sur toutes les machines. - docker_default: + proxy: external: true # Ce réseau est créé uniquement pour # ce fichier Compose. @@ -190,11 +197,11 @@ networks: services: exemple: - # On voit que le service est dans le réseau docker_default, pour être + # On voit que le service est dans le réseau proxy, pour être # accessible depuis Traefik, mais aussi dans le réseau db, pour # pouvoir parler à la base de données. networks: - - docker_default + - proxy - db # La base de donnée n'est que dans son réseau, et n'est donc # pas accessible depuis Internet. diff --git a/doc/update_and_test.md b/doc/update_and_test.md index 09caf7459677fe21efae571fa6a2de277503d1ca..66cc18e30d3f51f86f0e3ada30f8960202060c5a 100644 --- a/doc/update_and_test.md +++ b/doc/update_and_test.md @@ -114,7 +114,7 @@ Si nécessaire. Certains services ne sont pas accessibles depuis Internet. Remplacez les URL de production (`.picasoft.net`) par des URL de tests (`.test.picasoft.net`), sauf dans le nom de l'image : -* Si le service utilise Traefik, voir du côté de `traefik.frontend.rule` dans le fichier Compose +* Si le service utilise Traefik, voir du côté de `traefik.http.services.<service>.loadbalancer.server.port` dans le fichier Compose * Si le service utilise des fichiers de configuration, remplacez les références aux URL... ### Créer les fichiers d'example diff --git a/pica-db-backup/docker-compose.yml b/pica-db-backup/docker-compose.yml index 12f10294a310078b6bc7d7d61ec32273dd81afef..fa14ae6a2b5e34e991f214e42017014905a5a800 100644 --- a/pica-db-backup/docker-compose.yml +++ b/pica-db-backup/docker-compose.yml @@ -6,12 +6,9 @@ networks: etherpad_week: name: "etherpad_week" plume: - name: plume + name: "plume" wekan: name: "wekan" - docker_default: - external: true - name: "docker_default" services: db-backup: @@ -24,7 +21,6 @@ services: env_file: - ./secrets/db.secrets networks: - - docker_default - etherpad_main - etherpad_week - plume diff --git a/pica-dokuwiki/Dockerfile b/pica-dokuwiki/Dockerfile index 150d3118c50e47f145dd9226d70750fa770ab467..4a8eaadd9fe7864800ff688aa8e06852f56b561c 100644 --- a/pica-dokuwiki/Dockerfile +++ b/pica-dokuwiki/Dockerfile @@ -34,7 +34,6 @@ RUN apt-get update -y && \ chown -R www-data . && \ chmod +x /run.sh && \ sed -i "s/\${MAXSIZE}/100M/g" /etc/nginx/nginx.conf && \ - apt-get remove -y wget && \ apt-get autoremove -y && \ apt-get clean @@ -45,6 +44,6 @@ ENV LANGUAGE fr_FR.UTF-8 EXPOSE 80 VOLUME ["/var/www/html"] -HEALTHCHECK CMD wget -q -O /dev/null http://127.0.0.1:${DOKUWIKI_PORT:=80}/ +HEALTHCHECK CMD curl http://127.0.0.1:${DOKUWIKI_PORT:=80}/ CMD ["/run.sh"] diff --git a/pica-dokuwiki/docker-compose.yml b/pica-dokuwiki/docker-compose.yml index 79cdf89c37d19c065922cc3e41c26de6df11f577..985279da1bb54b72116a21b91dc8fe8e905c4cd2 100644 --- a/pica-dokuwiki/docker-compose.yml +++ b/pica-dokuwiki/docker-compose.yml @@ -1,11 +1,11 @@ -version : "2.4" +version : "3.7" volumes: dokuwiki-app: name: "dokuwiki-app" networks: - docker_default: + proxy: external: true services: @@ -15,15 +15,11 @@ services: container_name: dokuwiki-app volumes: - dokuwiki-app:/var/www/html - security_opt: - - no-new-privileges - mem_limit: "2048m" - cpus: "0.20" - pids_limit: 1024 labels: - - "traefik.frontend.rule=Host:wiki.picasoft.net" - - "traefik.port=80" - - "traefik.enable=true" + traefik.http.routers.dokuwiki-app.entrypoints: websecure + traefik.http.routers.dokuwiki-app.rule: Host(`wiki.picasoft.net`) + traefik.http.services.dokuwiki-app.loadbalancer.server.port: 80 + traefik.enable: true restart: unless-stopped networks: - - docker_default + - proxy diff --git a/pica-etherpad/docker-compose.yml b/pica-etherpad/docker-compose.yml index 44bf014b5adb40a5f83680e2f4b2f2daa65cb2b1..f4983807f0cfe97bab3f8e71d1f8a16f292e5c66 100755 --- a/pica-etherpad/docker-compose.yml +++ b/pica-etherpad/docker-compose.yml @@ -1,4 +1,4 @@ -version : "2.4" +version : "3.7" volumes: etherpad-db: @@ -12,33 +12,26 @@ volumes: networks: standard: - name: "etherpad_main" + name: etherpad_main week: - name: "etherpad_week" - docker_default: + name: etherpad_week + proxy: external: true - name: "docker_default" services: etherpad-app: image: registry.picasoft.net/pica-etherpad:1.8.4 build: . container_name: etherpad-app - depends_on: - - etherpad-db - security_opt: - - no-new-privileges - mem_limit: "2048m" - cpus: 0.6 - pids_limit: 1024 env_file: ./secrets/etherpad-app.secrets volumes: - ./settings.json:/opt/etherpad-lite/settings.json - deleted-pads-standard:/opt/etherpad-lite/deleted_pads labels: + traefik.http.routers.etherpad-app.entrypoints: websecure + traefik.http.routers.etherpad-app.rule: Host(`pad.picasoft.net`) + traefik.http.services.etherpad-app.loadbalancer.server.port: 8080 traefik.enable: true - traefik.frontend.rule: "Host:pad.picasoft.net" - traefik.port: 8080 environment: DB_HOST: "etherpad-db" LOGLEVEL: "INFO" @@ -47,45 +40,36 @@ services: THEME: "colibris" TITLE: "Picapad" TRUST_PROXY: "true" - restart: unless-stopped networks: - - docker_default + - proxy - standard + depends_on: + - etherpad-db + restart: unless-stopped etherpad-db: image: postgres:12 container_name: etherpad-db - security_opt: - - no-new-privileges - mem_limit: "2048m" - cpus: "0.40" - pids_limit: 1024 volumes: - etherpad-db:/var/lib/postgresql/data env_file: ./secrets/etherpad-db.secrets - restart: unless-stopped networks: - standard + restart: unless-stopped etherpad-week-app: image: registry.picasoft.net/pica-etherpad:1.8.4 container_name: etherpad-week-app build: . - depends_on: - - etherpad-week-db - security_opt: - - no-new-privileges - mem_limit: "2048m" - cpus: 0.6 - pids_limit: 1024 env_file: ./secrets/etherpad-week-app.secrets volumes: - ./settings_week.json:/opt/etherpad-lite/settings.json - deleted-pads-week:/opt/etherpad-lite/deleted_pads labels: + traefik.http.routers.etherpad-week-app.entrypoints: websecure + traefik.http.routers.etherpad-week-app.rule: Host(`week.pad.picasoft.net`) + traefik.http.services.etherpad-week-app.loadbalancer.server.port: 8080 traefik.enable: true - traefik.frontend.rule: "Host:week.pad.picasoft.net" - traefik.port: 8080 environment: DB_HOST: "etherpad-week-db" LOGLEVEL: "INFO" @@ -94,19 +78,16 @@ services: THEME: "colibris" TITLE: "Picapad Hebdo" TRUST_PROXY: "true" - restart: unless-stopped + depends_on: + - etherpad-week-db networks: - - docker_default + - proxy - week + restart: unless-stopped etherpad-week-db: image: postgres:12 container_name: etherpad-week-db - security_opt: - - no-new-privileges - mem_limit: "2048m" - cpus: "0.40" - pids_limit: 1024 volumes: - weekpad-db:/var/lib/postgresql/data env_file: ./secrets/etherpad-week-db.secrets diff --git a/pica-grafana-prom/docker-compose.yml b/pica-grafana-prom/docker-compose.yml index 02baa356a63b36e05c783e7ccfc2bcd2783c052e..08c98392b97cb7377604bf4eba1247054158ca61 100644 --- a/pica-grafana-prom/docker-compose.yml +++ b/pica-grafana-prom/docker-compose.yml @@ -2,8 +2,8 @@ version: '3.7' networks: metrics: - docker_default: - name: docker_default + proxy: + external: true volumes: grafana: @@ -27,11 +27,12 @@ services: - GF_AUTH_LDAP_ALLOW_SIGN_UP=false env_file: ./secrets/grafana.secrets labels: - - "traefik.frontend.rule=Host:grafana.picasoft.net" - - "traefik.port=3000" - - "traefik.enable=true" + traefik.http.routers.grafana.entrypoints: websecure + traefik.http.routers.grafana.rule: Host(`grafana.picasoft.net`) + traefik.http.services.grafana.loadbalancer.server.port: 3000 + traefik.enable: true networks: - - docker_default + - proxy - metrics restart: unless-stopped diff --git a/pica-graphbot/config.json b/pica-graphbot/config.json index b45218ae08841cfdb3e0266a73efe582bffe8966..e984a254cae25a0dcb08ed1a323045e84b74f58a 100644 --- a/pica-graphbot/config.json +++ b/pica-graphbot/config.json @@ -7,7 +7,7 @@ "url": "pica01.picasoft.net", "port": 2376, "exclude": [], - "default_network": "docker_default", + "default_network": "proxy", "tls_config": { "ca_cert": "auth/pica01/ca.pem", @@ -20,7 +20,7 @@ "url": "pica02.picasoft.net", "port": 2376, "exclude": [], - "default_network": "docker_default", + "default_network": "proxy", "tls_config": { "ca_cert": "auth/pica02/ca.pem", @@ -33,7 +33,7 @@ "url": "pica01-test.picasoft.net", "port": 2376, "exclude": [], - "default_network": "docker_default", + "default_network": "proxy", "tls_config": { "ca_cert": "auth/pica01-test/ca.pem", @@ -44,7 +44,7 @@ { "name": "monitoring", "url": "localhost", - "default_network": "docker_default" + "default_network": "proxy" } ], "color_scheme": { diff --git a/pica-lufi/docker-compose.yml b/pica-lufi/docker-compose.yml index 6f50d31c6a3a0f931fd39c958dbab795c8b7d9d6..9cfd2878134844762ef20cb85caad81f7f7eb7f5 100644 --- a/pica-lufi/docker-compose.yml +++ b/pica-lufi/docker-compose.yml @@ -6,7 +6,7 @@ volumes: lufi-files: networks: - docker_default: + proxy: external: true lufi: @@ -22,11 +22,12 @@ services: - lufi-files:/lufi/files - ./lufi.conf:/lufi/lufi.conf networks: - - docker_default + - proxy - lufi labels: - traefik.frontend.rule: Host:drop.picasoft.net - traefik.port: 8081 + traefik.http.routers.lufi.entrypoints: websecure + traefik.http.routers.lufi.rule: Host(`drop.picasoft.net`) + traefik.http.services.lufi.loadbalancer.server.port: 8081 traefik.enable: true env_file: - ./secrets/lufi.secrets diff --git a/pica-mail/docker-compose.yml b/pica-mail/docker-compose.yml index 6aed58883b5cf3823eb8fe7b6e1a44345426d923..9949f622d89ffeba860fa0fd1c8e66bc4947b96a 100644 --- a/pica-mail/docker-compose.yml +++ b/pica-mail/docker-compose.yml @@ -3,7 +3,7 @@ version: "3.7" networks: mail: name: pica-mail - docker_default: + proxy: external: true volumes: @@ -44,7 +44,7 @@ services: - "587:587" networks: - mail - - docker_default + - proxy volumes: - mail-mta-log:/var/log #doit contenir selecteur.domaine.rsa @@ -85,8 +85,7 @@ services: #prefixe DKIM, utilise pour identifier la clef DKIM_SELECTOR: janv2019 labels: - traefik.frontend.rule: Host:mail.picasoft.net - traefik.port: 80 + traefik.http.routers.pica-mail-mta.rule: Host(`mail.picasoft.net`) traefik.enable: true tls-certs-monitor.enable: true tls-certs-monitor.action: restart diff --git a/pica-mattermost/docker-compose.yml b/pica-mattermost/docker-compose.yml index 5f66f8f384daa7649f44274765c76eb8ee687de4..58d07ec5b1dab7c02578d5e0cf153c638c301742 100644 --- a/pica-mattermost/docker-compose.yml +++ b/pica-mattermost/docker-compose.yml @@ -1,8 +1,8 @@ -version : "2.4" +version : "3.7" networks: - docker_default: + proxy: external: true - name: "docker_default" + mattermost: volumes: mattermost-config: @@ -30,12 +30,13 @@ services: - MM_SITEURL=https://team.picasoft.net env_file: ./secrets/mattermost-db.secrets labels: - - "traefik.frontend.rule=Host:team.picasoft.net" - - "traefik.port=8000" - - "traefik.frontend.passHostHeader=true" - - "traefik.enable=true" + traefik.http.routers.mattermost-app.entrypoints: websecure + traefik.http.routers.mattermost-app.rule: Host(`team.picasoft.net`) + traefik.http.services.mattermost-app.loadbalancer.server.port: 8000 + traefik.enable: true networks: - - docker_default + - proxy + - mattermost depends_on: - mattermost-db restart: unless-stopped @@ -48,5 +49,5 @@ services: - /etc/localtime:/etc/localtime:ro env_file: ./secrets/mattermost-db.secrets networks: - - docker_default + - mattermost restart: unless-stopped diff --git a/pica-metrics-bot/docker-compose.yml b/pica-metrics-bot/docker-compose.yml index 9755a65c2d295848403d786e2179304e5272d65a..1475f906cf16c4ac4f527c4507db6b2ccfa7fea8 100644 --- a/pica-metrics-bot/docker-compose.yml +++ b/pica-metrics-bot/docker-compose.yml @@ -5,7 +5,7 @@ volumes: name: influxdb-services networks: - docker_default: + proxy: external: true metrics: @@ -36,10 +36,11 @@ services: - INFLUXDB_REPORTING_DISABLED=true env_file: ./secrets/influxdb.secrets labels: - traefik.frontend.rule: "Host:influxdb.picasoft.net" - traefik.port: 8086 - traefik.enable: true + traefik.http.routers.influxdb-services.entrypoints: websecure + traefik.http.routers.influxdb-services.rule: Host(`influxdb.picasoft.net`) + traefik.http.services.influxdb-services.loadbalancer.server.port: 8086 + traefik.enable: true networks: - metrics - - docker_default + - proxy restart: always diff --git a/pica-mumble-web/docker-compose.yml b/pica-mumble-web/docker-compose.yml index 47e266a7a10a1c99a5a8c8f469ea72a1f20f46d6..f035b82239c424ff8e656748c1119a2e86341470 100644 --- a/pica-mumble-web/docker-compose.yml +++ b/pica-mumble-web/docker-compose.yml @@ -1,8 +1,7 @@ -version: "2.4" +version: "3.7" networks: - docker_default: + proxy: external: true - name: "docker_default" services: mumble-web: @@ -12,12 +11,12 @@ services: environment: MUMBLE_SERVER: "voice.picasoft.net:64738" networks: - - docker_default + - proxy volumes: - ./config.json:/home/node/dist/config.local.js labels: - - "traefik.frontend.rule=Host:voice.picasoft.net" - - "traefik.port=8080" - - "traefik.frontend.passHostHeader=true" - - "traefik.enable=true" + traefik.http.routers.mumble-web.entrypoints: websecure + traefik.http.routers.mumble-web.rule: Host(`voice.picasoft.net`) + traefik.http.services.mumble-web.loadbalancer.server.port: 8080 + traefik.enable: true restart: unless-stopped diff --git a/pica-murmur/docker-compose.yml b/pica-murmur/docker-compose.yml index d42e2cf8615d3c7c8e941b5cc11b9a9cb3b3f066..1cbb5cd8049c8785d0408cc95f19eaf000da639e 100644 --- a/pica-murmur/docker-compose.yml +++ b/pica-murmur/docker-compose.yml @@ -1,8 +1,7 @@ -version: "2.4" +version: "3.7" networks: - docker_default: + proxy: external: true - name: "docker_default" volumes: murmur-data: @@ -23,12 +22,13 @@ services: - murmur-data:/data - /DATA/docker/certs/voice.picasoft.net/:/certs networks: - - docker_default + - proxy labels: - - "traefik.enable=true" - - "traefik.port=8000" - - "traefik.frontend.rule=Host:voice.picasoft.net;Path:/metrics" - - "tls-certs-monitor.enable=true" - - "tls-certs-monitor.action=kill:SIGUSR1" - - "tls-certs-monitor.owner=103" + traefik.http.routers.murmur.entrypoints: websecure + traefik.http.routers.murmur.rule: Host(`voice.picasoft.net`) && Path(`/metrics`) + traefik.http.services.murmur.loadbalancer.server.port: 8000 + traefik.enable: true + tls-certs-monitor.enable: true + tls-certs-monitor.action: kill:SIGUSR1 + tls-certs-monitor.owner: 103 restart: unless-stopped diff --git a/pica-nextcloud/cet/docker-compose.yml b/pica-nextcloud/cet/docker-compose.yml index 121853273c12f837612fc5ce562c47682c8a69d9..8ed5502a79ba9f19564b68188678fdda5fe5c8aa 100644 --- a/pica-nextcloud/cet/docker-compose.yml +++ b/pica-nextcloud/cet/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' networks: nextcloud_cet: name: nextcloud_cet - docker_default: + proxy: external: true volumes: @@ -34,11 +34,17 @@ services: - ./nginx.conf:/etc/nginx/nginx.conf:ro env_file: ./secrets/cloudcet.secrets labels: - - "traefik.frontend.rule=Host:cloudcet.picasoft.net" - - "traefik.port=80" - - "traefik.enable=true" + traefik.http.routers.cloudcet.entrypoints: websecure + traefik.http.routers.cloudcet.rule: Host(`cloudcet.picasoft.net`) + traefik.http.services.cloudcet.loadbalancer.server.port: 80 + traefik.enable: true + # https://docs.nextcloud.com/server/16/admin_manual/configuration_server/reverse_proxy_configuration.html + traefik.http.routers.cloudcet.middlewares: cloudcet@docker + traefik.http.middlewares.cloudcet.redirectregex.permanent: true + traefik.http.middlewares.cloudcet.redirectregex.regex: ^/.well-known/(card|cal)dav + traefik.http.middlewares.cloudcet.redirectregex.replacement: /remote.php/dav/ networks: - - docker_default + - proxy - nextcloud_cet depends_on: - cloudcet diff --git a/pica-nextcloud/pica/docker-compose.yml b/pica-nextcloud/pica/docker-compose.yml index 858886b484741a9818940b03b32c50bb8fbdce43..1ed1cc29da8af7e26e927838de248f728bd59c52 100644 --- a/pica-nextcloud/pica/docker-compose.yml +++ b/pica-nextcloud/pica/docker-compose.yml @@ -8,8 +8,8 @@ volumes: networks: nextcloud: - docker_default: - name: docker_default + proxy: + external: true services: nextcloud-app: @@ -38,15 +38,17 @@ services: - nextcloud-app networks: - nextcloud - - docker_default + - proxy labels: - - "traefik.frontend.rule=Host:cloud.picasoft.net" - - "traefik.port=80" - - "traefik.enable=true" + traefik.http.routers.nextcloud-web.entrypoints: websecure + traefik.http.routers.nextcloud-web.rule: Host(`cloud.picasoft.net`) + traefik.http.services.nextcloud-web.loadbalancer.server.port: 80 + traefik.enable: true # https://docs.nextcloud.com/server/16/admin_manual/configuration_server/reverse_proxy_configuration.html - - "traefik.frontend.redirect.permanent=true" - - "traefik.frontend.redirect.regex=https://(.*)/.well-known/(card|cal)dav" - - "traefik.frontend.redirect.replacement=https://$$1/remote.php/dav/" + traefik.http.routers.nextcloud-web.middlewares: nextcloud-web@docker + traefik.http.middlewares.nextcloud-web.redirectregex.permanent: true + traefik.http.middlewares.nextcloud-web.redirectregex.regex: ^/.well-known/(card|cal)dav + traefik.http.middlewares.nextcloud-web.redirectregex.replacement: /remote.php/dav/ restart: unless-stopped nextcloud-db: diff --git a/pica-nginx/README.md b/pica-nginx/README.md index 361ccca71cf8b567e146cc12ffb8b11519cb9fe6..c2b93dd67dd9c3b29934b34b1427053d2fc8b6cc 100644 --- a/pica-nginx/README.md +++ b/pica-nginx/README.md @@ -33,13 +33,14 @@ mon_site: volumes: - mon_site:/var/www/html labels: - traefik.frontend.rule: Host:mon_site.picasoft.net - traefik.port: 80 + traefik.http.routers.mon_site.entrypoints: websecure + traefik.http.routers.mon_site.rule: Host(`mon_site.picasoft.net`) + traefik.http.services.mon_site.loadbalancer.server.port: 80 traefik.enable: true environment: AUTOINDEX: true networks: - - docker_default + - proxy restart: unless-stopped ``` diff --git a/pica-nginx/docker-compose.yml b/pica-nginx/docker-compose.yml index da771c665239e66461315230eaab9cb4d7d98dcb..f56fe1c8bfcc49ded7c57448a07ada24b8507daa 100644 --- a/pica-nginx/docker-compose.yml +++ b/pica-nginx/docker-compose.yml @@ -15,7 +15,7 @@ volumes: name: stiegler networks: - docker_default: + proxy: external: true x-image-name: &NGINX_IMAGE @@ -29,11 +29,12 @@ services: volumes: - website:/var/www/html labels: - traefik.frontend.rule: Host:www.picasoft.net,picasoft.net - traefik.port: 80 + traefik.http.routers.website.entrypoints: websecure + traefik.http.routers.website.rule: Host(`www.picasoft.net`, `picasoft.net`) + traefik.http.services.website.loadbalancer.server.port: 80 traefik.enable: true networks: - - docker_default + - proxy restart: unless-stopped doc: @@ -43,11 +44,12 @@ services: volumes: - doc:/var/www/html labels: - traefik.frontend.rule: Host:doc.picasoft.net - traefik.port: 80 + traefik.http.routers.doc.entrypoints: websecure + traefik.http.routers.doc.rule: Host(`doc.picasoft.net`) + traefik.http.services.doc.loadbalancer.server.port: 80 traefik.enable: true networks: - - docker_default + - proxy restart: unless-stopped school: @@ -57,11 +59,12 @@ services: volumes: - school:/var/www/html labels: - traefik.frontend.rule: Host:school.picasoft.net - traefik.port: 80 + traefik.http.routers.school.entrypoints: websecure + traefik.http.routers.school.rule: Host(`school.picasoft.net`) + traefik.http.services.school.loadbalancer.server.port: 80 traefik.enable: true networks: - - docker_default + - proxy restart: unless-stopped radio: @@ -71,13 +74,14 @@ services: volumes: - radio:/var/www/html labels: - traefik.frontend.rule: Host:radio.picasoft.net - traefik.port: 80 + traefik.http.routers.radio.entrypoints: websecure + traefik.http.routers.radio.rule: Host(`radio.picasoft.net`) + traefik.http.services.radio.loadbalancer.server.port: 80 traefik.enable: true networks: - - docker_default + - proxy restart: unless-stopped - + culture: container_name: culture image: *NGINX_IMAGE @@ -85,13 +89,14 @@ services: volumes: - culture:/var/www/html labels: - traefik.frontend.rule: Host:culture.picasoft.net - traefik.port: 80 + traefik.http.routers.culture.entrypoints: websecure + traefik.http.routers.culture.rule: Host(`culture.picasoft.net`) + traefik.http.services.culture.loadbalancer.server.port: 80 traefik.enable: true environment: AUTOINDEX: "true" networks: - - docker_default + - proxy restart: unless-stopped stiegler: @@ -101,9 +106,10 @@ services: volumes: - stiegler:/var/www/html labels: - traefik.frontend.rule: Host:stiegler.picasoft.net - traefik.port: 80 + traefik.http.routers.stiegler.entrypoints: websecure + traefik.http.routers.stiegler.rule: Host(`stiegler.picasoft.net`) + traefik.http.services.stiegler.loadbalancer.server.port: 80 traefik.enable: true networks: - - docker_default + - proxy restart: unless-stopped diff --git a/pica-openldap/bootstrap/ldif/init.ldif b/pica-openldap/bootstrap/ldif/init.ldif index 23e37b2de745eade0680d464d66edfe6a4539d19..4343c3bd937ceaf5ba2cc688f17e813182bb96a9 100644 --- a/pica-openldap/bootstrap/ldif/init.ldif +++ b/pica-openldap/bootstrap/ldif/init.ldif @@ -35,8 +35,7 @@ gidNumber: 502 objectClass: posixGroup objectClass: top cn: representant -description: Groupe secondaire. Les personnes dans ce groupes peuvent accéder aux services restreints aux membres (exemple : Cloud...) -memberUid: +description: Groupe primaire. Les personnes dans ce groupe ont un accès basique aux machines et peuvent accéder à des services restreints aux membres (Cloud, édition Wiki...) dn: cn=representant,ou=Groups,{{ LDAP_BASE_DN }} gidNumber: 503 diff --git a/pica-openldap/docker-compose.yml b/pica-openldap/docker-compose.yml index 1882ea54aedd24d57b0b8e85eec58ca888293759..ce93ea0a910cf2f08ee531c7a41057fdf36e8eb2 100644 --- a/pica-openldap/docker-compose.yml +++ b/pica-openldap/docker-compose.yml @@ -16,7 +16,7 @@ services: env_file: - ./secrets/pica-openldap.secrets labels: - traefik.frontend.rule: "Host:ldap.picasoft.net" + traefik.http.routers.ldap.rule: Host(`ldap.picasoft.net`) traefik.enable: true tls-certs-monitor.enable: true tls-certs-monitor.action: "restart" diff --git a/pica-plume/docker-compose.yml b/pica-plume/docker-compose.yml index cce72fbf10f44658eeae490517540b0ce43c05be..4f8acc3534e6c07b82400678193dae89e737ac29 100644 --- a/pica-plume/docker-compose.yml +++ b/pica-plume/docker-compose.yml @@ -11,7 +11,7 @@ volumes: name: plume_first_launch networks: - docker_default: + proxy: external: true plume: name: plume @@ -34,12 +34,13 @@ services: - searchidx:/app/search_index - first-launch:/firstlaunch labels: - traefik.frontend.rule: "Host:blog.picasoft.net" + traefik.http.routers.blog.entrypoints: websecure + traefik.http.routers.blog.rule: Host(`blog.picasoft.net`) + traefik.http.services.blog.loadbalancer.server.port: 7878 traefik.enable: true - traefik.port: 7878 networks: - plume - - docker_default + - proxy depends_on: - blog-db restart: unless-stopped diff --git a/pica-registry/docker-compose.yml b/pica-registry/docker-compose.yml index 6ba2be28667dbc03598e81bf008ff34bc3175e94..9609cd9a501e31fee0b0e607b4b474f0373cd56e 100644 --- a/pica-registry/docker-compose.yml +++ b/pica-registry/docker-compose.yml @@ -1,8 +1,8 @@ version: '3.7' networks: - docker_default: - name: docker_default + proxy: + external: true volumes: registry: @@ -18,12 +18,13 @@ services: REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /var/lib/registry networks: - - docker_default + - proxy volumes: - registry:/var/lib/registry - ./auth.secrets:/auth/htpasswd labels: - traefik.frontend.rule: Host:registry.picasoft.net - traefik.port: 5000 + traefik.http.routers.registry.entrypoints: websecure + traefik.http.routers.registry.rule: Host(`registry.picasoft.net`) + traefik.http.services.registry.loadbalancer.server.port: 5000 traefik.enable: true restart: unless-stopped diff --git a/pica-traefik/README.md b/pica-traefik/README.md index 0544aa4a2f67adb20a15621f8056acdc35e103ce..d3c67df35de51f8fd5d246a2032ffedd3e2244ca 100644 --- a/pica-traefik/README.md +++ b/pica-traefik/README.md @@ -7,36 +7,28 @@ Ce service doit être lancé sur l'ensemble des machines de l'infrastructure. ### Configuration -La configuration a lieu dans le fichier [traefik.toml](./traefik.toml). +La configuration a lieu dans les fichiers [traefik.toml](./traefik.toml) et [traefik_dynamic.toml](./traefik_dynamic.toml). Notez que toute modification dans ce fichier impactera l'ensemble des machines, puisque le même fichier est utilisé pour l'ensemble des machines. À des fins de tests, il peut être modifié localement sur les machines, mais doit toujours rester synchronisé avec ce dépôt à long terme. Pour la génération des certificats, Traefik utilise Let's Encrypt. Il n'y a aucune configuration à faire de ce côté. Attention, le nombre de certificats générables est limité à 50 par semaine. -Si on lance plein de conteneurs de tests, on utilisera temporairement [l'environnement de qualification](https://letsencrypt.org/fr/docs/staging-environment/) de Let's Encrypt, en ajoutant la directive `caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"` sous la section `[acme]`. +Si on lance plein de conteneurs de tests, on utilisera temporairement [l'environnement de qualification](https://letsencrypt.org/fr/docs/staging-environment/) de Let's Encrypt, en ajoutant la directive `caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"` sous la section `[certificatesResolvers.letsencrypt.acme]`. ### Lancement -Assurez-vous que le dossier `/DATA/docker/traefik/certs` existe. -C'est dans ce dossier que seront conservés tous les certificats générés par Traefik. +Au premier lancement, assurez-vous que : +* Le dossier `/DATA/docker/traefik/certs` existe +* Créez un fichier `acme.json` à l'intérieur +* Changez son propriétaire à `root` +* Changez ses permissions à `600` + +C'est dans ce fichier que seront conservés tous les certificats générés par Traefik. ### Mise à jour Il suffit de mettre à jour le tag de l'image dans Compose. -Attention, Traefik v2 introduit énormément de changements et [nous ne sommes pas certains](https://wiki.picasoft.net/doku.php?id=technique:adminsys:migration-traefik-v2) de la manière d'effectuer la migration. - -Aussi, Traefik v1.6 est utilisé pour tenterd d'éviter un bug introduit dans la 1.7, qui rend certains services redémarrés inaccessibles (voir [cette discussion](https://team.picasoft.net/picasoft/pl/66aorsxhtffrjytyhnecn436wa)). - -Avant toute mise à jour, il faudra discuter avec l'équipe technique et modifier ce README le cas échéant. - -### Todo - -*Voir si on peut passer Traefik en "host" au niveau du réseau pour qu'il ait accès à tous les réseaux* : -https://kanban.picasoft.net/b/7fCn765LCNGraBhxA/team-technique-picasoft/kjvc3iw2pFvszCTcR - -Actuellement, Traefik est dans le réseau `docker_default` sur toutes les machines, et les conteneurs souhaitant être accessibles via Traefik doivent être explicitement dans ce réseau. - -Ceci induit une complexité supplémentaire au niveau des fichiers Compose. +Lire la documentation [sur les mises à jour mineures](https://docs.traefik.io/v2.2/migration/v2/) pour voir s'il y a des opérations à effectuer ou des options dépréciées. -Il serait peut être bon de permettre à Traefik d'accéder à tous les réseaux et de supprimer énormément de directives "inutiles" dans les Compose. +La mise à jour vers Traefik v2 a été effectuée ; quelques détails sont à consulter [sur le wiki](https://wiki.picasoft.net/doku.php?id=technique:adminsys:migration-traefik-v2). diff --git a/pica-traefik/docker-compose.yml b/pica-traefik/docker-compose.yml index daaf9802d24f03b53766fa67ec286b8a2a18522f..d4a139e9324c18bbb0c9819548542b547facdc6d 100644 --- a/pica-traefik/docker-compose.yml +++ b/pica-traefik/docker-compose.yml @@ -1,18 +1,22 @@ version: '3.7' +networks: + proxy: + name: 'proxy' + services: traefik: - container_name: traefik - # DO NOT UPGRADE - # SEE THIS BEFORE AND DISCUSS : https://team.picasoft.net/picasoft/pl/66aorsxhtffrjytyhnecn436wa - image: traefik:1.6.6 - ports: - - "80:80" - # Uncomment to expose the web interface. Warning : do not use without setting a password in traefik.toml - #- "8080:8080" - - "443:443" - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - ./traefik.toml:/traefik.toml - - /DATA/docker/traefik/certs:/certs - restart: always + image: traefik:2.3 + container_name: traefik + ports: + - 80:80 + - 443:443 + volumes: + - /etc/localtime:/etc/localtime:ro + - /var/run/docker.sock:/var/run/docker.sock + - ./traefik.toml:/traefik.toml + - ./traefik_dynamic.toml:/traefik_dynamic.toml + - /DATA/docker/traefik/certs:/certs + networks: + - proxy + restart: unless-stopped diff --git a/pica-traefik/traefik.toml b/pica-traefik/traefik.toml index 351461989e113a1faf7e831ca614f1a7922cfd56..a154bb578889e9e2b85f2f512cfeb4e80de4e72f 100644 --- a/pica-traefik/traefik.toml +++ b/pica-traefik/traefik.toml @@ -1,35 +1,40 @@ -logLevel = "INFO" -debug = true -defaultEntryPoints = ["http", "https"] +[global] + sendAnonymousUsage = false + checkNewVersion = true -[docker] -endpoint = "unix:///var/run/docker.sock" -watch = true -exposedbydefault = false +[entryPoints] + [entryPoints.web] + address = ":80" + [entryPoints.web.http.redirections.entryPoint] + to = "websecure" + scheme = "https" + [entryPoints.websecure] + address = ":443" + [entryPoints.websecure.http] + middlewares = ["hardening@file", "compression@file"] + [entryPoints.websecure.http.tls] + certResolver = "letsencrypt" + options = "tls12@file" -[api] -[entryPoints] - [entryPoints.http] - address = ":80" - compress = false - [entryPoints.http.redirect] - entryPoint = "https" - [entryPoints.https] - address = ":443" - compress = false - [entryPoints.https.tls] - # Accept only TLS1.1 and 1.2 - MinVersion = "VersionTLS11" - # Accept all ciphers excepting TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA and TLS_RSA_WITH_3DES_EDE_CBC_SHA - # CipherSuites = ["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA","TLS_RSA_WITH_AES_128_GCM_SHA256","TLS_RSA_WITH_AES_256_GCM_SHA384","TLS_RSA_WITH_AES_128_CBC_SHA","TLS_RSA_WITH_AES_256_CBC_SHA" ] - # Keep only ECDHE : - CipherSuites = ["TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA" ] +[providers] + providersThrottleDuration = "2s" + [providers.docker] + watch = true + endpoint = "unix:///var/run/docker.sock" + exposedByDefault = false + network = "proxy" + [providers.file] + filename = "/traefik_dynamic.toml" + watch = true + +[log] + level = "INFO" -[acme] - email = "picasoft@assos.utc.fr" - storage = "/certs/acme.json" - entryPoint = "https" - onHostRule = true - [acme.httpChallenge] - entryPoint = "http" +[certificatesResolvers] + [certificatesResolvers.letsencrypt] + [certificatesResolvers.letsencrypt.acme] + email = "picasoft@assos.utc.fr" + storage = "/certs/acme.json" + [certificatesResolvers.letsencrypt.acme.httpChallenge] + entryPoint = "web" diff --git a/pica-traefik/traefik_dynamic.toml b/pica-traefik/traefik_dynamic.toml new file mode 100644 index 0000000000000000000000000000000000000000..398f83d557cb2ea3f9ac04233502a4d8292181e2 --- /dev/null +++ b/pica-traefik/traefik_dynamic.toml @@ -0,0 +1,28 @@ +[tls.options] + [tls.options.tls12] + minVersion = "VersionTLS12" + cipherSuites = [ + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305", + "TLS_AES_256_GCM_SHA384", + "TLS_CHACHA20_POLY1305_SHA256" + ] + curvePreferences = ["CurveP521","CurveP384"] + +[http] + [http.middlewares.hardening.headers] + addVaryHeader = true + browserXssFilter = true + contentTypeNosniff = true + forceSTSHeader = true + frameDeny = true + stsIncludeSubdomains = true + stsPreload = true + customFrameOptionsValue = "SAMEORIGIN" + referrerPolicy = "same-origin" + featurePolicy = "vibrate 'self'" + stsSeconds = 315360000 + + [http.middlewares.compression.compress] + excludedContentTypes = ["text/event-stream"] diff --git a/pica-uploads/docker-compose.yml b/pica-uploads/docker-compose.yml index ea307aa8ddbe7421b5a64b4359ac5f64ad106569..6c33d43f7f8a6c4a70a23203a6c929e315672004 100644 --- a/pica-uploads/docker-compose.yml +++ b/pica-uploads/docker-compose.yml @@ -2,11 +2,11 @@ version: "3.7" volumes: uploads: - external: true + name: uploads networks: sftp: - docker_default: + proxy: external: true services: @@ -28,9 +28,10 @@ services: volumes: - uploads:/var/www/html labels: - - "traefik.frontend.rule=Host:uploads.picasoft.net" - - "traefik.port=80" - - "traefik.enable=true" - restart: unless-stopped + traefik.http.routers.uploads.entrypoints: websecure + traefik.http.routers.uploads.rule: Host(`uploads.picasoft.net`) + traefik.http.services.uploads.loadbalancer.server.port: 80 + traefik.enable: true networks: - - docker_default + - proxy + restart: unless-stopped diff --git a/pica-wekan/docker-compose.yml b/pica-wekan/docker-compose.yml index 561b520122e819299685a4e54e4300dc34a9d320..ba783ce75dbaaea00cd0d4ac4fad817dc2494147 100644 --- a/pica-wekan/docker-compose.yml +++ b/pica-wekan/docker-compose.yml @@ -4,10 +4,10 @@ volumes: wekan: networks: - docker_default: + proxy: external: true wekan: - name: "wekan" + name: wekan services: wekan-db: @@ -40,11 +40,12 @@ services: depends_on: - wekan-db labels: - traefik.frontend.rule: Host:kanban.picasoft.net - traefik.port: 8080 + traefik.http.routers.wekan-app.entrypoints: websecure + traefik.http.routers.wekan-app.rule: Host(`kanban.picasoft.net`) + traefik.http.services.wekan-app.loadbalancer.server.port: 8080 traefik.enable: true networks: - - docker_default + - proxy - wekan restart: unless-stopped @@ -55,9 +56,10 @@ services: environment: - KANBAN_URL=https://kanban.picasoft.net networks: - - docker_default + - proxy labels: + traefik.http.routers.wekan-filter-hooks.entrypoints: websecure + traefik.http.routers.wekan-filter-hooks.rule: Host(`kanban.picasoft.net`) && Path('/forward_hooks') + traefik.http.services.wekan-filter-hooks.loadbalancer.server.port: 5000 traefik.enable: true - traefik.port: 5000 - traefik.frontend.rule: Host:kanban.picasoft.net;Path:/forward_hooks restart: unless-stopped diff --git a/template/docker-compose.yml b/template/docker-compose.yml index c4fbd859d9959b1881a61385dbdc044915f74db1..a9a1d4b77528d71c740f9a71c34bc6840a5e5fe0 100644 --- a/template/docker-compose.yml +++ b/template/docker-compose.yml @@ -23,7 +23,7 @@ networks: app: # This is the reverse-proxy default network : put all services # that need to be served via Traefik in this network - docker_default: + proxy: external: true services: @@ -48,10 +48,10 @@ services: # entrypoint, for exemple. init: true # If the container has to be reached from - # the Internet, put in docker_default + # the Internet, put in proxy # Otherwise, just in its own network networks: - - docker_default + - proxy - app volumes: # Mount the Docker Volume in the container @@ -72,10 +72,12 @@ services: # redirected to this container. # Change the port to the exposed port of the # container. + # Replace ".app" by the container name. labels: traefik.enable: true - traefik.frontend.rule: "Host:app.picasoft.net" - traefik.port: 80 + traefik.http.routers.app.entrypoints: websecure + traefik.http.routers.app.rule: Host(`app.picasoft.net`) + traefik.http.services.app.loadbalancer.server.port: 80 # If the service has a database, # tell Compose that it depends on it (i.e.) # should be launched if the service is launched