Sockets (.socket)¶
Les unités .socket permettent l'activation à la demande des services. systemd peut écouter sur un socket (Unix, TCP, UDP...) et démarrer le service associé uniquement lorsqu'une connexion arrive.
Principe de l'activation par socket¶
L'activation par socket offre plusieurs avantages :
- Démarrage plus rapide : Le socket est créé immédiatement, le service démarre à la demande
- Parallélisation : Plusieurs services peuvent démarrer en parallèle même s'ils ont des dépendances
- Économie de ressources : Services inactifs ne consomment pas de mémoire
- Redémarrage transparent : Les connexions sont mises en file pendant le redémarrage
Fonctionnement¶
- systemd crée et écoute sur le socket
- Une connexion arrive
- systemd démarre le service associé
- systemd passe le socket au service
- Le service traite la connexion
Structure d'un fichier socket¶
[Unit]
Description=SSH Socket for Per-Connection Servers
[Socket]
ListenStream=22
Accept=no
[Install]
WantedBy=sockets.target
Section [Socket]¶
Types de sockets¶
- ListenStream
-
Socket TCP ou Unix stream
# TCP
ListenStream=8080
ListenStream=0.0.0.0:8080
ListenStream=[::]:8080
# Unix socket
ListenStream=/run/myapp.sock
- ListenDatagram
-
Socket UDP ou Unix datagram
- ListenSequentialPacket
-
Socket Unix sequential packet
- ListenFIFO
-
Named pipe (FIFO)
- ListenSpecial
-
Fichier spécial (device)
- ListenNetlink
-
Socket Netlink
- ListenMessageQueue
-
File de messages POSIX
Options de socket¶
- Accept
-
Crée une instance de service par connexion
Accept=yes # Une instance par connexion (inetd-style)
Accept=no # Service unique gère toutes les connexions (défaut)
- SocketUser / SocketGroup
-
Propriétaire du socket Unix
- SocketMode
-
Permissions du socket Unix
- Backlog
-
Taille de la file d'attente des connexions
- BindIPv6Only
-
Écouter uniquement IPv6
- Broadcast
-
Activer le broadcast UDP
- PassCredentials
-
Passer les credentials via SCM_CREDENTIALS
- PassSecurity
-
Passer le contexte de sécurité
- RemoveOnStop
-
Supprimer le socket Unix à l'arrêt
- MaxConnections
-
Nombre maximum de connexions simultanées
- Service
-
Nom du service à activer (par défaut : même nom sans .socket)
Exemples¶
Socket HTTP simple¶
# /etc/systemd/system/webapp.socket
[Unit]
Description=Web Application Socket
[Socket]
ListenStream=8080
Accept=no
[Install]
WantedBy=sockets.target
# /etc/systemd/system/webapp.service
[Unit]
Description=Web Application
[Service]
Type=simple
ExecStart=/usr/bin/webapp
StandardInput=socket
Activation :
systemctl enable webapp.socket
systemctl start webapp.socket
# Le service webapp.service démarrera automatiquement à la première connexion
Socket Unix avec permissions¶
# /etc/systemd/system/myapp.socket
[Unit]
Description=My Application Socket
[Socket]
ListenStream=/run/myapp.sock
SocketMode=0660
SocketUser=myapp
SocketGroup=www-data
RemoveOnStop=yes
[Install]
WantedBy=sockets.target
Socket SSH par connexion (Accept=yes)¶
# /etc/systemd/system/sshd.socket
[Unit]
Description=SSH Socket per Connection
[Socket]
ListenStream=22
Accept=yes
[Install]
WantedBy=sockets.target
# /etc/systemd/system/sshd@.service
[Unit]
Description=SSH Per-Connection Server
[Service]
Type=simple
ExecStart=-/usr/sbin/sshd -i
StandardInput=socket
StandardError=journal
Socket UDP syslog¶
# /etc/systemd/system/syslog.socket
[Unit]
Description=Syslog Socket
[Socket]
ListenDatagram=514
Broadcast=yes
[Install]
WantedBy=sockets.target
Socket Docker¶
Exemple réel de Docker :
# /lib/systemd/system/docker.socket
[Unit]
Description=Docker Socket for the API
[Socket]
ListenStream=/var/run/docker.sock
SocketMode=0660
SocketUser=root
SocketGroup=docker
[Install]
WantedBy=sockets.target
Socket avec plusieurs ports¶
# /etc/systemd/system/multiport.socket
[Unit]
Description=Multi-Port Socket
[Socket]
ListenStream=8080
ListenStream=8443
ListenStream=/run/myapp.sock
Accept=no
[Install]
WantedBy=sockets.target
Intégration avec les services¶
Recevoir le socket dans le service¶
Pour qu'un service reçoive le socket, utilisez :
Ou l'API systemd pour récupérer les file descriptors :
En C :
#include <systemd/sd-daemon.h>
int n = sd_listen_fds(0);
if (n > 0) {
int fd = SD_LISTEN_FDS_START + 0; // Premier socket
// Utiliser fd...
}
En Python :
import systemd.daemon
fds = systemd.daemon.listen_fds()
if fds:
sock = socket.fromfd(fds[0], socket.AF_INET, socket.SOCK_STREAM)
En Go :
import "github.com/coreos/go-systemd/activation"
listeners, _ := activation.Listeners()
if len(listeners) > 0 {
ln := listeners[0]
// Utiliser ln...
}
Gestion des sockets¶
Commandes de base¶
# Lister les sockets actifs
systemctl list-sockets
# Démarrer un socket
systemctl start myapp.socket
# Arrêter (arrête aussi le service associé)
systemctl stop myapp.socket
# Activer au boot
systemctl enable myapp.socket
# Voir l'état
systemctl status myapp.socket
# Voir les connexions actives
systemctl show myapp.socket -p NAccepted,NConnections
Dépendances¶
Quand un socket est démarré, systemd crée automatiquement des dépendances :
Requires=myapp.service: Le service est requisBefore=myapp.service: Le socket démarre avantTriggers=myapp.service: Le socket déclenche le service
Cas d'usage avancés¶
Redémarrage sans coupure¶
L'activation par socket permet de redémarrer un service sans perdre de connexions :
# Les nouvelles connexions sont mises en file
systemctl restart myapp.service
# Le socket reste actif et buffer les connexions
Dépendances parallélisées¶
Sans socket :
Avec socket :
service-a.socket (instantané)
service-b.socket (instantané)
→ Les deux services peuvent démarrer en parallèle
Socket pour services gourmands¶
Pour des services qui consomment beaucoup de ressources mais rarement utilisés :
Surveillance et métriques¶
Voir les statistiques¶
Propriétés intéressantes :
NAccepted: Nombre total de connexions acceptéesNConnections: Nombre de connexions actuellesNRefused: Nombre de connexions refusées
Logs¶
Limitations et considérations¶
Quand utiliser l'activation par socket ?¶
Bon pour :
- Services utilisés occasionnellement
- Optimisation du temps de boot
- Services avec dépendances complexes
- Redémarrages sans interruption
Moins bon pour :
- Services à haute fréquence (overhead de démarrage)
- Services qui doivent être toujours actifs
- Services avec initialisation longue
Latence de démarrage¶
La première connexion peut être plus lente (temps de démarrage du service). Pour éviter cela :
Sécurité¶
Limiter les connexions¶
Filtrage par IP¶
Utiliser IPAddressAllow / IPAddressDeny :
Permissions Unix socket¶
[Socket]
SocketMode=0660 # Permissions
SocketUser=myapp # Propriétaire
SocketGroup=www-data # Groupe
Débogage¶
Problème : le service ne démarre pas¶
Vérifier :
# Le socket est-il actif ?
systemctl status myapp.socket
# Le service peut-il se lancer manuellement ?
systemctl start myapp.service
# Erreurs dans les logs
journalctl -u myapp.socket -u myapp.service
Problème : permission denied¶
Vérifier les permissions du socket :
Tester manuellement¶
Tester la connexion au socket :
L'activation par socket est une fonctionnalité puissante de systemd qui permet d'optimiser les performances et la gestion des services. Elle est particulièrement utile pour les services occasionnellement utilisés ou avec des dépendances complexes.