#+SETUPFILE: /home/vaab/dev/el/org-html-themes/setup/theme-readtheorg.setup #+PROPERTY: Effort_ALL 0 0:30 1:00 2:00 0.5d 1d 1.5d 2d 3d 4d 5d #+PROPERTY: Max_effort_ALL 0 0:30 1:00 2:00 0.5d 1d 1.5d 2d 3d 4d 5d #+PROPERTY: header-args:python :var filename=(buffer-file-name) #+PROPERTY: header-args:sh :var filename=(buffer-file-name) #+TODO: TODO WIP BLOCKED POSTPONED | DONE CANCELED #+LATEX_HEADER: \usepackage[margin=0.5in]{geometry} #+LaTeX_CLASS: article #+OPTIONS: H:8 ^:nil prop:("Effort" "Max_effort") tags:not-in-toc #+COLUMNS: %50ITEM %Effort(Min Effort) %Max_effort(Max Effort) #+begin_LaTeX \hypersetup{ linkcolor=blue, pdfborder={0 0 0 0} } #+end_LaTeX #+TITLE: Architecture 0k.io #+LATEX: \pagebreak * Process de déploiement Description du process de déploiement pour une nouvelle installation ** Base myc *** Qu'est ce c'est ? A partir d'une debian 9, on peut installer la machine pour être prête à utiliser un déploiement myc. Une fois executé, la machine aura toute les deps pour lancer une commande compose qui fera peut-être appel à des registry de mycéliandre. Un compose de base est aussi proposé. *** Déploiement **** Hôte linux base debian 9 #+BEGIN_SRC sh wget https://justodooit.myceliandre.fr/r/deploy -qO - | bash #+END_SRC If you want to setup odoo admin password and domain in one go: #+BEGIN_SRC sh export DOMAIN=myhost.com wget https://justodooit.myceliandre.fr/r/deploy -qO - | bash #+END_SRC **** Hôte macosx - install bash, docker - Uncheck "Securely store docker logins in macOS keychain" *** Ce que cela fait **** Mettre la machine en état charm-ready - installation du strict minimu pour lancer les =charms= - téléchargement de la dernière version des =0k-charms= (collection de recettes d'installation et de gestion de docker) **** Mettre la machine en état compose ready (notre docker qui va bien) via le lancement du charm =docker-host= qui installe: - docker, docker-compose, compose avec des versions qui vont bien - paquets maisons (kal-scripts, 0k-manage, 0k-pgm, lxc-scripts, 0k-docker) - accès pour le repository deb de kalysto.org - clé SSH pour repos git.kal.fr - login sur le docker registry docker.0k.io **** Commandes spécifique à myc - login sur le registry myc - téléchargement du compose de base dans =/opt/apps/myc-deploy= ** Modification du compose *** Qu'est-ce que c'est ? Il y a des update client à faire souvent sur le compose. Cette étape doit être externalisée au plus possible, sont consigné ici ce qu'il faut encore faire à la main. *** Commande **** Création de clé OVH pour letsencrypt/lexicon Ceci n'est nécessaire qu'en cas d'utilisation de la méthode DNS pour valider la possession du domaine auprès de letsencrypt. #+BEGIN_SRC shell APPLICATION_KEY=XXXXXXXXXXXXXXXXX REDIR_WEBSITE=https://0k.io req=$(cat <web-proxy-->apache=. Par défaut, =apache= utilisera du ssl pour tout se virtual-host s'il trouve un =cert-provider= à disposition. Aussi la configuration suivante est suffisante pour avoir un site publié en SSL: #+BEGIN_SRC yaml www.mydomain.org: charm: odoo apache: letsencrypt: #+END_SRC Cela équivaut à : #+BEGIN_SRC yaml www.mydomain.org: charm: odoo relations: web-proxy: myapache: domain: www.mydomain.org ssl: myletsencrypt: challenge-type: http myapache: charm: apache myletsencrypt: charm: letsencrypt #+END_SRC ***** Authentification DNS ****** créer un nouveau jeu de clé OVH pour l'authentification DNS When =letsencrypt= is setup and running:: #+BEGIN_SRC sh compose --debug add letsencrypt DOMAIN [DOMAIN...] #+END_SRC Exemple de setup (dans =compose.yml=): #+BEGIN_SRC yaml letsencrypt: options: email: admin@0k.io ovh: entrypoint: ovh-eu application: key: ZZZ secret: XXX consumer_key: YYYYY #+END_SRC Le résultat est dans =/srv/datastore/data/letsencrypt/etc/letsencrypt/live/DOMAIN1= Il apparaît entre 30sec et 1 minute après la demande. ****** Vérifier que le jeu de clé ovh est bon Cette commande prend le compose yml et va vérifier que les accès sont valides: #+BEGIN_SRC shell check-compose-ovh-credentials compose.yml #+END_SRC **** Utilisation manuelle On peut utiliser le service =letsencrypt= manuellement ***** creation d'un certificat http #+BEGIN_SRC shell compose crt letsencrypt create DOMAIN [DOMAIN...] #+END_SRC Cette action crée un certificat (et force le renouvellement si existant). On peut y injecter une configuration via =--add-compose-content= si nécessaire:: #+BEGIN_SRC shell compose --add-compose-content=' letsencrypt: ovh: ## see: https://api.ovh.com/g934.first_step_with_api entrypoint: ovh-eu application: key: XXX secret: YYY consumer_key: ZZZ challenge-type: dns #renew-before-expiry: 30' crt letsencrypt create DOMAIN [DOMAIN...] #+END_SRC ***** Renew de tous les certificats Cela renew uniquement les certificats dont la date de validité est inférieure à 30j #+BEGIN_SRC shell compose crt letsencrypt renew #+END_SRC ***** Liste des certificats gérés et infos connexes #+BEGIN_SRC shell compose run letsencrypt crt list #+END_SRC ***** suppression d'un certificat #+BEGIN_SRC shell compose run letsencrypt certbot delete --cert-name DOMAIN #+END_SRC *** apache **** Utiliser letsencrypt Pour ajouter la fonctionalité de génération automatique de certificat via le service =letsencrypt=, il faut: - déclarer un service =letsencrypt= si cela n'est pas déjà fait - le lier au charm apache via une relation =cert-provider=: #+BEGIN_SRC yaml frontend: charm: apache relations: cert-provider: letsencrypt letsencrypt: ... #+END_SRC Et l'on peut alors utiliser la valeur =letsencrypt= (le nom du service qui implémente qui est en relation =cert-provider= avec apache) dans le champ =ssl=:: #+BEGIN_SRC yaml web-proxy: apache: ... ssl: letsencrypt #+END_SRC **** Changer les clés SSL Voici un exemple de ce qu'on peut mettre dans les options de la relation apache pour déclarer le certificat que l'on souhaite: #+BEGIN_SRC yaml ssl: ca-cert: -----BEGIN CERTIFICATE----- MIIF6TCCA9GgAwIBAgIQBeTcO5Q4qzuFl8umoZhQ4zANBgkqhkiG9w0BAQwFADCB iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl ... m9T8bJUox04FB6b9HbwZ4ui3uRGKLXASUoWNjDNKD/yZkuBjcNqllEdjB+dYxzFf BT02Vf6Dsuimrdfp5gJ0iHRc2jTbkNJtUQoj1iM= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFdzCCBF+gAwIBAgIQE+oocFv07O0MNmMJgGFDNjANBgkqhkiG9w0BAQwFADBv MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk ... Le9Gclc1Bb+7RrtubTeZtv8jkpHGbkD4jylW6l/VXxRTrPBPYer3IsynVgviuDQf Jtl7GQVoP7o81DgGotPmjw7jtHFtQELFhLRAlSv0ZaBIefYdgWOWnU914Ph85I6p 0fKtirOMxyHNwu8= -----END CERTIFICATE----- cert: | -----BEGIN CERTIFICATE----- MIIF/TCCBOWgAwIBAgIRALUydpTpCApfYMuJchDJv5AwDQYJKoZIhvcNAQELBQAw XzELMAkGA1UEBhMCRlIxDjAMBgNVBAgTBVBhcmlzMQ4wDAYDVQQHEwVQYXJpczEO ... lIxY9HJanHrWvjiz7+eToxXpZJtAPXTx5hxzcJrtWROlq7IJCMIhzr/EVA37jTCk Xs5S6mr0T6Dqx6MQkPATSsEEJlLH5wq3DxXQcrMqnM/WHMRYUCkoTl37sXplflHe jw== -----END CERTIFICATE----- key: | -----BEGIN PRIVATE KEY----- MIIJRQIBADANBgkqhkiG9w0BAQEFAASCCS8wggkrAgEAAoICAQDONqqTCS4CiSi/ XeNpp2nUsq1299spGc7mlRs+PDrXNHscB5lUB5/yo2yEetYXrJacQ8n4NV9hkID5 ... 44eHDYsofcnRbidGR+QT8PQgiiDNCkbpi2u4QnLTs0w4oW+53ZTyHYEYF2rcLbIb vRt4kR4KG6ULXrmsRA4WQjBDJ9vZw2aK+w== -----END PRIVATE KEY----- #+END_SRC **** Ajouter des rêgles particulière de apache #+BEGIN_SRC yaml relations: web-proxy: apache: ... apache-custom-rules: | RewriteEngine On RewriteCond %{HTTPS} off RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA] #+END_SRC *** postgres **** utilisation de pgm récupérer l'IP du docker postgres via =docker-ip= #+BEGIN_SRC sh PGHOST=172.19.0.2 PGUSER=postgres pgm ls #+END_SRC ***** Vérification des derniers logs de renouvellement automatique #+BEGIN_SRC shell tail -f /srv/datastore/data/cron/var/log/cron/letsencrypt-renew_script.log -n 200 #+END_SRC *** mysql **** docker sans compose ***** backup régulier depuis l'hôte #+begin_src sh MYSQL_ROOT_PASSWORD=xxx MYSQL_CONTAINER=mailcowdockerized_mysql-mailcow_1 apt-get install -y mysql-client ~/.my.cnf [client] password=${MYSQL_ROOT_PASSWORD} EOF chmod 600 ~/.my.cnf cat <<'EOF' > /usr/local/sbin/mysql-backup #!/bin/bash . /etc/shlib include common include pretty usage="$exname [--host HOST] [DATABASE...]" DBS=() host= while [ "$1" ]; do case "$1" in "--help"|"-h") print_usage exit 0 ;; "--host") host="$2" shift ;; *) DBS+=("$1") ;; esac shift done mysql_opts=() if [ "$host" ]; then mysql_opts+=(-h "$host") fi m() { mysql "${mysql_opts[@]}" -Bs "$@" } md() { mysqldump "${mysql_opts[@]}" "$@" } mysql_databases() { echo "SHOW DATABASES" | m } mysql_tables() { local db="$1" echo "SHOW TABLES" | m "$db" } if [ "${#DBS[@]}" == 0 ]; then DBS=($(mysql_databases)) || exit 1 fi mkdir -p /var/backups/mysql for db in "${DBS[@]}"; do if [[ "$db" == "information_schema" || "$db" == "performance_schema" || "$db" == "mysql" ]]; then continue fi echo "Dumping database $db..." >&2 # omitting all the rotation logic dst=/"var/backups/mysql/$db" [ -d "$dst.old" ] && rm -rf "$dst.old" [ -d "$dst" ] && mv "$dst" "$dst.old" mkdir -p "$dst.inprogress" (( start = SECONDS )) md "$db" --routines --no-data --add-drop-database --database "$db" | gzip --rsyncable > "$dst.inprogress/schema.sql.gz" tables=$(mysql_tables "$db") for table in $tables; do backup_file="$dst.inprogress/${table}.sql.gz" echo " Dumping $table into ${backup_file}" md "$db" "$table" | gzip --rsyncable > "$backup_file" || break done mv "$dst.inprogress" "$dst" [ -d "$dst.old" ] && rm -rf "$dst.old" (( elapsed = SECONDS - start )) echo " ..dumped $db to $dst ($(du -sh "$dst" | cut -f 1) in ${elapsed}s)" >&2 done EOF chmod +x /usr/local/sbin/mysql-backup cat < /etc/cron.d/mysql-backup SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 0 * * * * root /usr/local/sbin/mysql-backup --host \$(docker-ip "$MYSQL_CONTAINER" 2>/dev/null | sed -r 's/ +/ /g' | cut -f 3 -d " ") | logger -t mysql-backup EOF mkdir -p /etc/mirror-dir && cat <> /etc/mirror-dir/mirror-dir.conf /var/backups/mysql: exclude: - "/*.inprogress" EOF #+end_src *** rsync-backup **** Installation du backup via compose A faire depuis le serveur ayant des services à backupper. Il y a une partie à copier-coller sur le serveur de backup. Ne pas oublier de relancer le serveur de backup pour le prendre en compte. #+begin_src sh DOMAIN=xxx.fr BACKUP_SERVER=core-06.0k.io:10023 ssh-keygen -t rsa -N "" -f /root/.ssh/rsync_rsa -C "rsync@$DOMAIN" cat <> /opt/apps/myc-deploy/compose.yml rsync-backup: options: ident: $DOMAIN target: $BACKUP_SERVER private-key: | $(cat /root/.ssh/rsync_rsa | sed -r 's/^/ /g') EOF echo "copier-coller ceci dans le '/etc/compose/compose.yml' de ${BACKUP_SERVER%:*}:" echo cat < /etc/cron.d/mirror-dir SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin $((RANDOM % 60)) * * * * root mirror-dir -d $BACKUP_SERVER -u rsync ${DESTS[@]} 2>&1 | logger -t mirror-dir EOF #+end_src les logs sont dans =/var/log/mirror.log=. Note, il est possible de spécifier des exclusions pour chaque répértoire mirroré de telle façon: #+begin_src sh cat < /etc/mirror-dir/mirror-dir.conf /home: exclude: - /*/.cache/ - /*/.gvfs/ - /*/.local/share/Trash/files/ - /*/.Trash/ - /*/.mozilla/firefox/*/Cache/ - /*/.mozilla/firefox/*/storage/default/*/cache/ /media/data: exclude: - /binary/games/_steam - /incoming - /.Trash* - /lost+found - /backup/device EOF #+end_src * Interventions avancées Description des process avancés d'intervention sur une installation existante. ** Modification du compose Y a un exemple en commentaire dans le =/opt/apps/myc-deploy/compose.yml= Petit exemple: #+BEGIN_SRC yaml odoo: ... docker-compose: ## Important to keep as a list: otherwise it'll overwrite charm's arguments. command: - "--log-level=debug" environment: TOTO: TUTU image: masuperimage #+END_SRC ** Troubleshooting S'il semble qu'il y ait un soucis, tu peux visualiser le =docker-compose.yml= qui est généré à la fin via l'ajout de =--debug= AVANT la commande: #+BEGIN_EXAMPLE compose --debug up odoo frontend #+END_EXAMPLE * Comment ça marche La surcouche =compose= est là pour créer un =docker-compose.yml= et le lancer tout a fait normalement. Le long du chemin, il peut aussi préparer des trucs utiles si c'est nécessaire. Il part du =compose.yml= et accède aux définitions en yaml des charms à déployer et qui sont dans /srv/charms ... (qui en fait sont dans =/opt/apps/0k-charms=). Chaque charm possède une définition générale (le =metadata.yml=) qui peut aussi injecter des trucs dans le =docker-compose.yml= final. Et puis il y a des =hooks=, qui sont juste des scripts bash qui sont lancés avec des infos dans des variables d'environment, qui vont généralement créer des trucs à l'init ou lors de liaison avec d'autres charms.