wwwgmo stack
Description
Examples site with nginx, phpfpm, mysql, phpmyadmin, elasticsearch and kibana
Build environment
| folders | description |
|---|---|
| docker.sh | files to build the docker image |
| docker/mariadb | env file |
| docker/nginx | config file |
| docker/php-fpm | files to create docker image |
| src | site source |
Docker
Global environment variables
Copy file ALL .env.dist to .env
Complete or modify the values according to your needs
Build
Install plugin php for elasticsearch
./docker.sh install
Build image
./docker.sh build
or
./docker.sh build-no-cache
Start
./docker.sh start
Check
docker exec wwwgmo-mariadb mysql -uroot -p<MYSQL_ROOT_PASSWORD> mysql -e 'SELECT user,host FROM mysql.user;'
docker exec wwwgmo-elasticsearch curl -u elastic:<ELASTIC_PASSWORD> http://wwwgmo-elasticsearch:9200/_cluster/health?pretty
docker exec wwwgmo-php-fpm curl -s -u elastic:<ELASTIC_PASSWORD> http://wwwgmo-elasticsearch:9200/_cluster/health?pretty
Access
http://<server_name>:<NGINX_PORT>
kubernetes
| folders | description |
|---|---|
| deploy.sh | files to deploy on k8s or k3s (see ./deploy.s -h) |
| helm | Chart root folder |
| Chart.yaml | Charts file |
| values-configs.yml | configs file use for kubernetes manifest |
| values-secrets.yaml | secrets file for kubernetes manifet (Must be encrypted with sops in a production environment) |
| templates/elasticsearch | manifests for elasticsearch |
| templates/kibana | manifests for kibana |
| templates/mariadb | manifests for mariadb |
| templates/phpmyadmin | manifests for phpmyadmin |
| templates/php-fpm | manifest for php-fpm |
Secret registry (regcred)
You need credential to pull an image from private registry.
Create or modify the secret
kubectl create secret docker-registry secret-regcred --dry-run=client \
--docker-server=https://index.docker.io/v1/ \
--docker-username=<username> \
--docker-password=<secret> \
--docker-email=<adress@sample.com> -o yaml > helm/template/secret-regcred.yaml
Certificats
cat certs/gmolab.net.key | base64 -w0
copy the base64 result into file values-secrets.yaml in ssl_key key
cat certs/gmolab.net.crt | base64 -w0
copy the base64 result into file values-config.yaml in ssl_crt key
Docker image version
In the helm/Chart.yaml file, the appVersion value must match the version of the docker image (see DOCKER_IMAGE_VERSION in the .env file and SITE_VERSION in the docker/php-fpm/.env file)
Deployment by script
This is the recommended way
This script builds the docker image based on the Kubernetes VM architecture (AMD64 or ARM64). At each deployment the minor version of the image is incremented by 1.
./deploy.md -n wwwgmo -k k3s
Manual deployment
Set kubesystem config
rm -f $HOME/.kube/config
for k3s
ln -s $HOME/.kube/k3s $HOST/.kube/config
for k8s
ln -s $HOST/.kube/k8s $HOST/.kube/config
Set namespace and kube system
export NS=wwwgmo
export KUBE_SYS=k3s|k8s
Test template
helm template $NS --set kube=$KUBE_SYS ./helm --values=./helm/values-configs.yaml --values=./helm/values-secrets.yaml --namespace $NS
Chart deployment
helm upgrade $NS --set kube=$KUBE_SYS ./helm --install --atomic --cleanup-on-fail --values=./helm/values-configs.yaml --values=./helm/values-secrets.yaml --namespace $NS --create-namespace
Remove
helm uninstall $NS -n $NS
kubectl delete namespaces $NS
NOTES
Cronjob
When we deploy manually (I do not why) you must trig manually the cronjob to make a DB backup to termine correctly the helm command
kubectl create job -n $NS --from=cronjob/cronjob-mariadb-backupdb dbbackup-$(date +%Y-%m-%d-%H-%M-%S)
Database
Not necessary because created during deployment. We leave the procedure below for information
First export NS environment variable
export NS=<your_namespace>
You can use createDBOnKube.sh or create manually with below commands
Create user
kubectl -n $NS exec statefulset-mariadb-0 --container mariadb -- /bin/bash -c "/usr/bin/mysql -u root -p<rootPass> -e \"CREATE USER 'gmo_db'@'%' IDENTIFIED BY '<dbPass>';\""
Check user
kubectl -n $NS exec statefulset-mariadb-0 --container mariadb -- /bin/bash -c "/usr/bin/mysql -u root -p<rootPass> -e 'SELECT user,host FROM mysql.user;'"
Create database
kubectl -n $NS exec statefulset-mariadb-0 --container mariadb -- /bin/bash -c "/usr/bin/mysql -u root -p<rootPass> -e \"CREATE DATABASE gmo_db;\""
Check database
kubectl -n $NS exec statefulset-mariadb-0 --container mariadb -- /bin/bash -c "/usr/bin/mysql -u root -p<rootPass> -e 'SHOW DATABASES;'"
Grants access
kubectl -n $NS exec statefulset-mariadb-0 --container mariadb -- /bin/bash -c "/usr/bin/mysql -u root -p<rootpass> -e \"GRANT ALL PRIVILEGES ON gmo_db.* TO 'gmo_db'@'%';FLUSH PRIVILEGES;\""
Check grants
kubectl -n $NS exec statefulset-mariadb-0 --container mariadb -- /bin/bash -c "/usr/bin/mysql -u root -p<rootPass> -e \"SHOW GRANTS FOR 'gmo_db'@'%';\""
Troubeshooting
How to Fix "Pods stuck in Terminating status" Error
kubectl get pods --all-namespaces | grep Terminating | while read line; do
pod_name=$(echo $line | awk '{print $2}' ) \
name_space=$(echo $line | awk '{print $1}' ); \
kubectl delete pods $pod_name -n $name_space --grace-period=0 --force
done
Sources
Elasticsearch-PHP
Pull an Image from a Private Registry
MariaDB Statefulset
PHP-FPM, nginx, kubernetes and docker
https://www.elastic.co/guide/en/elasticsearch/reference/8.18/docker.html
Changelog
3.25 (2024-04-14)
New features:
- added elasticsearch and kibana
- added option
installto scriptdocker.shto install php elasticserch module - created
deploy.shscript
Fixed bugs:
- problem with display environment var in php site
Updated:
- added new features in README.md
- added Changelog part in README.md
2.5 (2024-03-29)
Fixed bugs:
- fixed somes bugs
New features:
- posibility to deploy on k3s or k8s
Updated:
- updated README.md
1.0 (2024-03-01)
- Created from scratch
Ignorer et passer au contenu Vous avez dit : J'ai l'erreur suivante lorsque j'exécute mon ficher docker-compose.yml: [2025-06-19T16:58:29.674+00:00][ERROR][elasticsearch-service] Unable to retrieve version information from Elasticsearch nodes. security_exception Root causes: security_exception: missing authentication credentials for REST request [/_nodes?filter_path=nodes..version%2Cnodes..http.publish_address%2Cnodes.*.ip]
Mon fichier docker-compose.yml elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.18.2 container_name: elasticsearch environment: - node.name=es01 - cluster.name=es-docker-cluster - discovery.type=single-node - bootstrap.memory_lock=true - xpack.security.enabled=true - ELASTIC_PASSWORD=changeme - xpack.security.http.ssl.enabled=false - ES_JAVA_OPTS=-Xms1g -Xmx1g ulimits: memlock: soft: -1 hard: -1 ports: - "9200:9200" - "9300:9300" volumes: # - esdata:/usr/share/elasticsearch/data - wwwgmo-elasticsearch:/usr/share/elasticsearch/data
kibana: image: docker.elastic.co/kibana/kibana:8.18.2 container_name: kibana depends_on: - elasticsearch environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 - xpack.security.enabled=false ports: - "5601:5601" ChatGPT a dit : L’erreur que vous rencontrez est causée par l’activation de la sécurité dans Elasticsearch (xpack.security.enabled=true) sans fournir d’identifiants d’authentification lors de la tentative d’accès à l'API REST.
🔍 Détail de l'erreur : security_exception: missing authentication credentials for REST request [/_nodes?...] Cela signifie que Kibana ou un autre service tente de communiquer avec Elasticsearch sans credentials, alors que ce dernier requiert une authentification.
✅ Solution 1 : Aligner la sécurité entre Kibana et Elasticsearch
Actuellement :
Elasticsearch a xpack.security.enabled=true Kibana a xpack.security.enabled=false Ce n’est pas compatible. Kibana doit être configuré pour utiliser les identifiants quand Elasticsearch a la sécurité activée.
🛠 Modifier la section kibana comme suit : kibana: image: docker.elastic.co/kibana/kibana:8.18.2 container_name: kibana depends_on: - elasticsearch environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 - ELASTICSEARCH_USERNAME=elastic - ELASTICSEARCH_PASSWORD=changeme ports: - "5601:5601" ⚠️ Important : On utilise ici ELASTICSEARCH_USERNAME=elastic et ELASTICSEARCH_PASSWORD=changeme, car vous avez défini ce mot de passe dans la variable d'environnement ELASTIC_PASSWORD côté Elasticsearch. ✅ Solution 2 : Désactiver complètement la sécurité (pour développement uniquement)
Si vous êtes en environnement de test ou de développement local, vous pouvez désactiver la sécurité côté Elasticsearch.
environment:
- xpack.security.enabled=false
Dans ce cas, gardez aussi Kibana sans sécurité :
- xpack.security.enabled=false
⚠️ Pas recommandé en production : cette approche désactive les protections d’accès aux données. 🧪 Astuce : Tester si tout fonctionne Une fois les containers relancés, testez l’accès à Elasticsearch :
curl -u elastic:changeme http://localhost:9200 Et pour Kibana : ouvrez http://localhost:5601 dans un navigateur.
Souhaitez-vous :
Garder la sécurité activée et intégrer les credentials dans tous les services ? Ou désactiver la sécurité pour un usage local plus simple ? Vous avez dit : Garder la sécurité activée et intégrer les credentials dans tous les services ChatGPT a dit : Parfait ! Si vous souhaitez garder la sécurité activée, alors il faut que tous les services clients (comme Kibana) s’authentifient auprès d’Elasticsearch.
Voici comment ajuster correctement votre docker-compose.yml pour intégrer les identifiants.
✅ Fichier docker-compose.yml corrigé
version: "3.8"
services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.18.2 container_name: elasticsearch environment: - node.name=es01 - cluster.name=es-docker-cluster - discovery.type=single-node - bootstrap.memory_lock=true - xpack.security.enabled=true - xpack.security.http.ssl.enabled=false - ELASTIC_PASSWORD=changeme - ES_JAVA_OPTS=-Xms1g -Xmx1g ulimits: memlock: soft: -1 hard: -1 ports: - "9200:9200" - "9300:9300" volumes: - wwwgmo-elasticsearch:/usr/share/elasticsearch/data
kibana: image: docker.elastic.co/kibana/kibana:8.18.2 container_name: kibana depends_on: - elasticsearch environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 - ELASTICSEARCH_USERNAME=elastic - ELASTICSEARCH_PASSWORD=changeme ports: - "5601:5601"
volumes: wwwgmo-elasticsearch: 🔐 Authentification à l'API Elasticsearch (test via curl)
Une fois vos conteneurs démarrés, testez si l'accès avec mot de passe fonctionne :
curl -u elastic:changeme http://localhost:9200 Réponse attendue :
{ "name": "es01", "cluster_name": "es-docker-cluster", "cluster_uuid": "...", "version": { "number": "8.18.2", ... }, "tagline": "You Know, for Search" } ✅ Accès à Kibana
Ouvrez http://localhost:5601 dans votre navigateur. Kibana devrait démarrer sans vous afficher d'erreur liée à la connexion Elasticsearch.
✅ Recommandation de sécurité (optionnelle)
Pour un environnement plus sûr :
Créez un nouvel utilisateur avec des permissions spécifiques pour Kibana, via l’API ou l’interface d’admin de Kibana. Évitez d'utiliser elastic en production, car c’est un super admin. Souhaitez-vous un exemple de script pour créer un utilisateur avec rôle personnalisé ?
Vous avez dit : Error: [config validation of [elasticsearch].username]: value of "elastic" is forbidden. This is a superuser account that cannot write to system indices that Kibana needs to function. Use a service account token instead. Learn more: https://www.elastic.co/guide/en/elasticsearch/reference/8.0/service-accounts.html at ensureValidConfiguration (/usr/share/kibana/node_modules/@kbn/core-config-server-internal/src/ensure_valid_configuration.js:44:11) at Server.preboot (/usr/share/kibana/node_modules/@kbn/core-root-server-internal/src/server.js:181:7) at Root.preboot (/usr/share/kibana/node_modules/@kbn/core-root-server-internal/src/root/index.js:48:14) at bootstrap (/usr/share/kibana/node_modules/@kbn/core-root-server-internal/src/bootstrap.js:96:29) at Command. (/usr/share/kibana/src/cli/serve/serve.js:235:5) ChatGPT a dit : Merci pour ce message d’erreur très clair — Kibana refuse catégoriquement d'utiliser l'utilisateur elastic à partir d'Elasticsearch 8, car :
❌ elastic est un super-utilisateur. Il ne peut pas être utilisé pour que Kibana écrive dans les indices système, ce qui est nécessaire pour qu'il fonctionne correctement. ✅ Solution recommandée : utiliser un service account token
🔐 Étapes pour créer un Service Account Token pour Kibana :
Lancer Elasticsearch avec sécurité activée
Gardez xpack.security.enabled=true
Assurez-vous que le conteneur Elasticsearch fonctionne
Créer un Service Account Token pour Kibana
Ouvrez un terminal et exécutez :
docker exec -it elasticsearch
bin/elasticsearch-service-tokens create kibana kibana-token
Cela génère un token dans ce format :
AAEAAWVsYXN0aWMvY2liYW5hL2tpYmFuYS10b2tlbjoxR3VOSVZzUjZsb3pk...
Mettre à jour votre docker-compose.yml pour Kibana
Supprimez ELASTICSEARCH_USERNAME et ELASTICSEARCH_PASSWORD, et utilisez ELASTICSEARCH_SERVICEACCOUNTTOKEN à la place :
kibana: image: docker.elastic.co/kibana/kibana:8.18.2 container_name: kibana depends_on: - elasticsearch environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 - ELASTICSEARCH_SERVICEACCOUNTTOKEN=AAEAAWVsYXN0aWMvY2liYW5hL2tpYmFuYS10b2tlbjoxR3VOSVZzUjZsb3pk... ports: - "5601:5601" (remplace le token par celui généré précédemment) 🔄 Ensuite :
Redémarre les services : docker-compose down docker-compose up -d Va sur http://localhost:5601 pour voir Kibana se connecter correctement. 🔎 Besoin d'aller plus loin ?
Si tu préfères créer un utilisateur dédié à Kibana au lieu d’un token de service, je peux aussi te guider pas à pas avec elasticsearch-users ou via l'API REST.
Souhaites-tu cette alternative ?
Vous avez dit : oui ChatGPT a dit : Parfait ! Voici comment créer un utilisateur dédié à Kibana, via l'API REST d'Elasticsearch, avec des rôles appropriés pour permettre à Kibana de fonctionner sans utiliser le super-utilisateur elastic.
🎯 Objectif
Créer un utilisateur, par exemple kibana_system_user, qui a le rôle kibana_system (prérequis minimum pour que Kibana fonctionne).
✅ Étapes détaillées
- 🔐 Authentifiez-vous avec le super-utilisateur elastic Exécute cette commande pour vérifier que tu peux parler à Elasticsearch :
curl -u elastic:changeme http://localhost:9200
2. 👤 Créer un nouvel utilisateur kibana_system_user
curl -X POST http://localhost:9200/_security/user/kibana_system_user
-u elastic:changeme
-H "Content-Type: application/json"
-d '{
"password" : "kibanapassword",
"roles" : [ "kibana_system" ],
"full_name" : "Kibana System User",
"email" : "kibana@example.com"
}'
⚠️ Le mot de passe ici est kibanapassword. Tu peux le changer selon tes préférences.
- 🔧 Modifier docker-compose.yml pour Kibana Mets à jour la section Kibana avec ces variables d’environnement :
kibana: image: docker.elastic.co/kibana/kibana:8.18.2 container_name: kibana depends_on: - elasticsearch environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 - ELASTICSEARCH_USERNAME=kibana_system_user - ELASTICSEARCH_PASSWORD=kibanapassword ports: - "5601:5601" 4. 🔄 Redémarre les services docker-compose down docker-compose up -d 5. ✅ Accès à Kibana Rends-toi sur http://localhost:5601. Kibana devrait démarrer sans erreur de permission, car il utilise désormais un utilisateur restreint, mais autorisé à accéder aux indices système nécessaires.
✅ Résumé
Élément Valeur Utilisateur Elasticsearch kibana_system_user Rôle attribué kibana_system Mot de passe kibanapassword (ou autre) Avantage Bonne pratique, sécurisé Souhaites-tu aussi créer un utilisateur pour ingester des données dans Elasticsearch via une application ?
Vous avez dit : et tout ca dans un fichier docker-compose ChatGPT a dit : Parfait, je vais t’aider à tout intégrer dans un seul docker-compose.yml, avec :
Elasticsearch sécurisé Création automatique de l’utilisateur kibana_system_user avec le rôle kibana_system Kibana configuré pour utiliser cet utilisateur ⚠️ Important : Elasticsearch ne permet pas nativement la création d'utilisateurs via le docker-compose.yml, donc on doit ajouter un script d'initialisation personnalisé monté dans le conteneur, qui s'exécute au démarrage.
✅ Structure du projet recommandée :
project/ ├── docker-compose.yml ├── elasticsearch/ │ └── create_kibana_user.sh 🔧 elasticsearch/create_kibana_user.sh (script d'init)
#!/bin/bash
Attendre qu'Elasticsearch soit démarré
echo "⏳ Attente du démarrage d'Elasticsearch..." until curl -u elastic:changeme -s http://localhost:9200 >/dev/null; do sleep 2 done
echo "✅ Elasticsearch est prêt. Création de l'utilisateur Kibana..."
Créer un utilisateur pour Kibana
curl -X POST http://localhost:9200/_security/user/kibana_system_user
-u elastic:changeme
-H "Content-Type: application/json"
-d '{
"password" : "kibanapassword",
"roles" : [ "kibana_system" ],
"full_name" : "Kibana System User"
}'
echo "✅ Utilisateur Kibana créé avec succès." Donne les permissions au script : chmod +x elasticsearch/create_kibana_user.sh 📦 docker-compose.yml complet
version: "3.8"
services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:8.18.2 container_name: elasticsearch environment: - node.name=es01 - cluster.name=es-docker-cluster - discovery.type=single-node - bootstrap.memory_lock=true - xpack.security.enabled=true - xpack.security.http.ssl.enabled=false - ELASTIC_PASSWORD=changeme - ES_JAVA_OPTS=-Xms1g -Xmx1g ulimits: memlock: soft: -1 hard: -1 ports: - "9200:9200" - "9300:9300" volumes: - wwwgmo-elasticsearch:/usr/share/elasticsearch/data - ./elasticsearch/create_kibana_user.sh:/usr/local/bin/create_kibana_user.sh command: > bash -c " /bin/tini -g -- /usr/local/bin/docker-entrypoint.sh & pid=$!; sleep 20; bash /usr/local/bin/create_kibana_user.sh; wait $pid "
kibana: image: docker.elastic.co/kibana/kibana:8.18.2 container_name: kibana depends_on: - elasticsearch environment: - ELASTICSEARCH_HOSTS=http://elasticsearch:9200 - ELASTICSEARCH_USERNAME=kibana_system_user - ELASTICSEARCH_PASSWORD=kibanapassword ports: - "5601:5601"
volumes: wwwgmo-elasticsearch: ✅ Lancer le tout
Dans ton terminal :
docker-compose down -v docker-compose up --build ✅ Résultat attendu
Elasticsearch démarre avec la sécurité activée Un script crée automatiquement un utilisateur kibana_system_user Kibana l'utilise pour se connecter Tout est prêt et fonctionnel sans intervention manuelle Souhaites-tu que je t’aide à ajouter aussi un utilisateur applicatif (ex: my_app_user) avec accès en lecture/écriture ?
Joindre
Rechercher
Voix
ChatGPT peut faire des erreurs. Envisagez de vérifier les informations importantes.