Déploiement
L’API Apprise est conçue pour fonctionner comme un service conteneurisé.
Cette page explique comment la déployer et l’exploiter, pas comment utiliser les endpoints de l’API.
Si vous cherchez à :
- envoyer des notifications, consultez Utilisation de l’API
- l’intégrer avec la CLI ou la bibliothèque Python, consultez Intégrations
- comprendre les clés, le stockage ou le verrouillage, consultez Configuration
Modèle de Déploiement
Section intitulée « Modèle de Déploiement »L’API Apprise est un service stateless-first avec un état persistant optionnel.
- L’usage stateless envoie les notifications directement sans sauvegarder de configuration.
- L’usage stateful persiste la configuration sous une clé
{KEY}afin de la réutiliser. - L’interface web intégrée est optionnelle et fournie uniquement par commodité.
Le service peut être exécuté en toute sécurité :
- localement ;
- derrière un reverse proxy ;
- dans Docker ou Docker Compose ;
- dans Kubernetes, y compris dans des environnements durcis et rootless.
Démarrage Rapide
Section intitulée « Démarrage Rapide »Choisissez ci-dessous une méthode de déploiement pour démarrer rapidement l’API Apprise.
docker run --name apprise \ -p 8000:8000 \ -v ./config:/config \ -v ./attach:/attach \ -e APPRISE_STATEFUL_MODE=simple \ -e APPRISE_WORKER_COUNT=1 \ -e APPRISE_ADMIN=y \ -d caronc/apprise:latestLa commande suivante configure le même conteneur, mais avec une surveillance par health check :
docker run --name apprise \ -p 8000:8000 \ -v ./config:/config \ -v ./attach:/attach \ -e APPRISE_STATEFUL_MODE=simple \ -e APPRISE_WORKER_COUNT=1 \ -e APPRISE_ADMIN=y \ --health-cmd='curl -fsS http://127.0.0.1:8000/status >/dev/null || exit 1' \ --health-interval=30s \ --health-timeout=5s \ --health-retries=3 \ --health-start-period=20s \ -d caronc/apprise:latestservices: apprise: image: caronc/apprise:latest container_name: apprise ports: - "8000:8000" environment: APPRISE_STATEFUL_MODE: simple APPRISE_WORKER_COUNT: 1 APPRISE_ADMIN: "y" volumes: - ./config:/config - ./attach:/attachLa configuration suivante met en place le même conteneur, mais avec surveillance par health check :
services: apprise: image: caronc/apprise-api:latest container_name: apprise ports: - "8000:8000" environment: APPRISE_STATEFUL_MODE: simple APPRISE_WORKER_COUNT: 1 APPRISE_ADMIN: "y" volumes: - ./config:/config - ./attach:/attach healthcheck: test: [ "CMD-SHELL", "curl -fsS http://127.0.0.1:8000/status >/dev/null || exit 1", ] interval: 30s timeout: 5s retries: 3 start_period: 20sapiVersion: apps/v1kind: Deploymentmetadata: name: apprisespec: replicas: 1 selector: matchLabels: app: apprise template: metadata: labels: app: apprise spec: containers: - name: apprise image: caronc/apprise:latest ports: - containerPort: 8000 env: - name: APPRISE_STATEFUL_MODE value: simple - name: APPRISE_WORKER_COUNT value: 1 - name: APPRISE_ADMIN value: yL’exemple suivant reprend cette base et ajoute des probes de liveness et readiness :
apiVersion: apps/v1kind: Deploymentmetadata: name: apprisespec: replicas: 1 selector: matchLabels: app: apprise template: metadata: labels: app: apprise spec: containers: - name: apprise image: caronc/apprise:latest ports: - containerPort: 8000 env: - name: APPRISE_STATEFUL_MODE value: simple - name: APPRISE_WORKER_COUNT value: 1 - name: APPRISE_ADMIN value: y
# Prêt uniquement lorsque /status renvoie 200 readinessProbe: httpGet: path: /status port: 8000 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3
# Redémarre le conteneur si /status cesse de renvoyer 200 livenessProbe: httpGet: path: /status port: 8000 initialDelaySeconds: 20 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3Voici un exemple Kubernetes plus complet. Notez qu’il utilise encore les variables d’environnement héritées PGID et PUID :
apiVersion: v1kind: Namespacemetadata: labels: name: apprise name: apprise---apiVersion: v1kind: ConfigMapmetadata: labels: name: apprise name: apprise-api-override-conf-config namespace: apprisedata: location-override.conf: | auth_basic "Apprise API Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd;---apiVersion: v1kind: Secretmetadata: labels: name: apprise name: apprise-api-htpasswd-secret namespace: apprisedata: .htpasswd: <base64_encoded> # ajoutez la sortie de : htpasswd -c apprise_api.htpasswd <USERNAME> && cat apprise_api.htpasswd | base64---apiVersion: v1kind: PersistentVolumeClaimmetadata: labels: name: apprise name: apprise-data namespace: apprisespec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi---apiVersion: v1kind: Servicemetadata: labels: name: apprise name: apprise namespace: apprisespec: ports: - name: http port: 80 protocol: TCP targetPort: 8000 selector: name: apprise type: ClusterIP---apiVersion: apps/v1kind: Deploymentmetadata: labels: name: apprise name: apprise namespace: apprisespec: replicas: 1 selector: matchLabels: name: apprise strategy: type: Recreate template: metadata: labels: name: apprise spec: containers: - env: - name: APPRISE_STATEFUL_MODE value: simple - name: PGID value: "1000" - name: PUID value: "1000" image: caronc/apprise:1.1 name: apprise ports: - containerPort: 8000 protocol: TCP resources: limits: cpu: "500m" memory: "512Mi" requests: cpu: "250m" memory: "128Mi" volumeMounts: - mountPath: /config name: apprise-data - mountPath: /plugin name: apprise-data - mountPath: /attach name: apprise-data # Le mountPath suivant peut être supprimé si non souhaité / non utilisé - mountPath: /etc/nginx/.htpasswd name: apprise-api-htpasswd-secret-volume readOnly: true subPath: .htpasswd # Le mountPath suivant peut être supprimé si non souhaité / non utilisé - mountPath: /etc/nginx/location-override.conf name: apprise-api-override-conf-config-volume readOnly: true subPath: location-override.conf restartPolicy: Always volumes: - name: apprise-data persistentVolumeClaim: claimName: apprise-data # Le volume suivant peut être supprimé si non souhaité / non utilisé - name: apprise-api-htpasswd-secret-volume secret: secretName: apprise-api-htpasswd-secret # Le volume suivant peut être supprimé si non souhaité / non utilisé - name: apprise-api-override-conf-config-volume configMap: name: apprise-api-override-conf-configMerci à @steled pour l’exemple ci-dessus. La même configuration peut être étendue avec des probes de liveness et readiness simplement en remplaçant la dernière section par celle-ci :
apiVersion: apps/v1kind: Deploymentmetadata: labels: name: apprise name: apprise namespace: apprisespec: replicas: 1 selector: matchLabels: name: apprise strategy: type: Recreate template: metadata: labels: name: apprise spec: containers: - env: - name: APPRISE_STATEFUL_MODE value: simple - name: PGID value: "1000" - name: PUID value: "1000" image: caronc/apprise:1.1 name: apprise ports: - containerPort: 8000 protocol: TCP
readinessProbe: httpGet: path: /status port: 8000 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3
livenessProbe: httpGet: path: /status port: 8000 initialDelaySeconds: 20 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3
resources: limits: cpu: "500m" memory: "512Mi" requests: cpu: "250m" memory: "128Mi" volumeMounts: - mountPath: /config name: apprise-data - mountPath: /plugin name: apprise-data - mountPath: /attach name: apprise-data - mountPath: /etc/nginx/.htpasswd name: apprise-api-htpasswd-secret-volume readOnly: true subPath: .htpasswd - mountPath: /etc/nginx/location-override.conf name: apprise-api-override-conf-config-volume readOnly: true subPath: location-override.conf restartPolicy: Always volumes: - name: apprise-data persistentVolumeClaim: claimName: apprise-data - name: apprise-api-htpasswd-secret-volume secret: secretName: apprise-api-htpasswd-secret - name: apprise-api-override-conf-config-volume configMap: name: apprise-api-override-conf-configPour une configuration davantage orientée sécurité, vous pouvez exécuter l’API Apprise comme utilisateur non-root avec un système de fichiers racine en lecture seule et des volumes éphémères explicites.
L’exemple suivant suppose que vous avez déjà créé des persistent volume claims pour /config, /plugin et /attach.
apiVersion: apps/v1kind: Deploymentmetadata: labels: app: apprise name: apprise namespace: apprisespec: replicas: 1 selector: matchLabels: app: apprise template: metadata: labels: app: apprise spec: securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 readOnlyRootFilesystem: true containers: - name: apprise image: caronc/apprise:latest imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] env: - name: APPRISE_STATEFUL_MODE value: simple - name: APPRISE_WORKER_COUNT value: "1" - name: APPRISE_ADMIN value: "y" ports: - containerPort: 8000 name: http volumeMounts: # Données persistantes - name: config mountPath: /config - name: plugin mountPath: /plugin - name: attach mountPath: /attach
# Fichiers runtime et temporaires éphémères - name: tmp mountPath: /tmp
volumes: - name: config persistentVolumeClaim: claimName: apprise-config - name: plugin persistentVolumeClaim: claimName: apprise-plugin - name: attach persistentVolumeClaim: claimName: apprise-attach
# Le déploiement monte /tmp en emptyDir en mémoire ; c'est là que nginx, # gunicorn et supervisord stockent leurs pid, sockets et fichiers temporaires. # Ce volume est éphémère et stocké en mémoire. - name: tmp emptyDir: medium: MemoryLa même configuration peut être étendue avec des probes de liveness et readiness en remplaçant la section par celle-ci :
apiVersion: apps/v1kind: Deploymentmetadata: labels: app: apprise name: apprise namespace: apprisespec: replicas: 1 selector: matchLabels: app: apprise template: metadata: labels: app: apprise spec: securityContext: runAsNonRoot: true runAsUser: 1000 fsGroup: 1000 readOnlyRootFilesystem: true containers: - name: apprise image: caronc/apprise:latest imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] env: - name: APPRISE_STATEFUL_MODE value: simple - name: APPRISE_WORKER_COUNT value: "1" - name: APPRISE_ADMIN value: "y" ports: - containerPort: 8000 name: http
# Les health checks exigent que /status renvoie HTTP 200 readinessProbe: httpGet: path: /status port: http initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds: 3 failureThreshold: 3
livenessProbe: httpGet: path: /status port: http initialDelaySeconds: 20 periodSeconds: 30 timeoutSeconds: 5 failureThreshold: 3
volumeMounts: # Données persistantes - name: config mountPath: /config - name: plugin mountPath: /plugin - name: attach mountPath: /attach
# Fichiers runtime et temporaires éphémères - name: tmp mountPath: /tmp
volumes: - name: config persistentVolumeClaim: claimName: apprise-config - name: plugin persistentVolumeClaim: claimName: apprise-plugin - name: attach persistentVolumeClaim: claimName: apprise-attach
# Le déploiement monte /tmp en emptyDir en mémoire ; c'est là que nginx, # gunicorn et supervisord stockent leurs pid, sockets et fichiers temporaires. # Ce volume est éphémère et stocké en mémoire. - name: tmp emptyDir: medium: MemoryUne fois déployés, l’API et l’interface web optionnelle sont disponibles à l’adresse :
http://localhost:8000/Stockage Persistant
Section intitulée « Stockage Persistant »L’API Apprise prend en charge le stockage persistant pour :
- les configurations enregistrées ;
- les métadonnées d’authentification mises en cache ;
- les pièces jointes téléversées.
Le conteneur attend les chemins inscriptibles suivants :
| Chemin | Rôle |
|---|---|
/config | Configurations enregistrées et état interne |
/attach | Pièces jointes téléversées |
/plugin | Plugins personnalisés optionnels |
/tmp | Fichiers runtime (sockets, buffers, temp) |
Pour la plupart des déploiements, monter uniquement /config et /attach suffit.
Déploiements Durcis
Section intitulée « Déploiements Durcis »Pour des environnements publics ou multi-tenant, l’API Apprise prend en charge une exécution durcie.
Exemple de configuration conteneur durci :
services: apprise: image: caronc/apprise:latest container_name: apprise user: "1000:1000" read_only: true
cap_drop: - ALL
security_opt: - no-new-privileges:true
ports: - "8000:8000"
environment: APPRISE_STATEFUL_MODE: simple APPRISE_WORKER_COUNT: 1 APPRISE_ADMIN: "y"
volumes: - ./config:/config - ./attach:/attach
tmpfs: - /tmpPoints importants :
/tmpdoit rester inscriptible ;- aucun fichier n’est écrit sous
/var/log; - tous les logs sont écrits vers stdout et stderr.
Notes de Durcissement pour Kubernetes
Section intitulée « Notes de Durcissement pour Kubernetes »Si vous déployez dans Kubernetes, consultez Démarrage Rapide -> Kubernetes -> Durci (rootless + lecture seule) pour un exemple prêt à l’emploi qui :
- s’exécute avec un utilisateur non-root ;
- supprime toutes les capacités Linux ;
- désactive l’escalade de privilèges ;
- utilise un système de fichiers racine en lecture seule ;
- monte
/tmpcommeemptyDiren mémoire.
Vérifications d’État
Section intitulée « Vérifications d’État »L’API Apprise expose un endpoint de santé :
GET /status- Renvoie HTTP
200lorsque le service est sain - Renvoie HTTP
417si un problème bloquant est détecté
Exemple :
curl http://localhost:8000/statusCet endpoint convient pour :
- les health checks Docker ;
- les probes de liveness Kubernetes ;
- les systèmes de supervision externes.
Reverse Proxies et Chemins de Base
Section intitulée « Reverse Proxies et Chemins de Base »Si l’API Apprise est hébergée derrière un reverse proxy ou servie sous un sous-chemin, définissez APPRISE_BASE_URL en conséquence.
Exemple :
APPRISE_BASE_URL=/appriseCela garantit :
- une génération correcte des URL ;
- un routage correct de l’interface web ;
- des liens OpenAPI corrects.
Authentification et Contrôle d’Accès
Section intitulée « Authentification et Contrôle d’Accès »L’API Apprise n’implémente pas d’authentification en interne.
C’est intentionnel.
Approches recommandées :
- placer l’API derrière un reverse proxy ;
- utiliser une authentification HTTP basic ;
- restreindre l’accès au niveau réseau ou ingress.
Des fichiers de surcharge Nginx peuvent être injectés dans le conteneur pour imposer un contrôle d’accès.
Un exemple Kubernetes utilisant un Secret (basic auth .htpasswd) et une ConfigMap (nginx location-override.conf) est disponible dans Démarrage Rapide -> Kubernetes -> Exemple Complet.
Logging et Observabilité
Section intitulée « Logging et Observabilité »- Tous les logs sont émis vers stdout et stderr
- Aucun fichier log n’est écrit sur disque
- Des métriques Prometheus sont disponibles sur
/metrics
Déploiements de Développement
Section intitulée « Déploiements de Développement »Pour le développement local, le dépôt inclut des surcharges Docker Compose qui :
- montent l’arborescence source locale ;
- rechargent les changements d’UI et de templates sans rebuild ;
- exposent l’API sur le port
8000.
Ce mode est destiné uniquement au développement et n’est pas recommandé en production.
Étapes Suivantes
Section intitulée « Étapes Suivantes »Une fois l’application déployée, vous pouvez :
- enregistrer des clés de configuration via l’interface web ou l’API ;
- envoyer des notifications avec
/notifyou/notify/{KEY}; - intégrer des systèmes externes via HTTP ou la CLI Apprise.
Questions ou commentaires ?
Documentation
Vous avez repéré une faute de frappe ou une erreur ? Signalez-la ou proposez une correction .
Problèmes Techniques
Vous rencontrez un problème avec le code ? Ouvrez un ticket sur GitHub :