Héberger Castopod soi-même pour publier un balado
Suivez ça sur votre propre serveur. Commencer gratuitement, sans carte
La plupart des hébergeurs de balados vous louent un flux RSS : arrêtez de payer et vos épisodes, vos analyses et l’URL même de votre flux peuvent tous disparaître avec le compte. Castopod est un hébergeur de balados open source, construit sur CodeIgniter, qui vous offre le même flux de publication, de vraies analyses d’auditeurs, et des fonctionnalités Podcasting 2.0 comme les transcriptions et les chapitres, avec le flux qui vit sur votre propre domaine au lieu de celui d’un fournisseur. À la fin de ce guide, vous l’aurez en fonctionnement avec MariaDB et Redis derrière HTTPS, votre première émission publiée, et une sauvegarde qui couvre réellement les fichiers audio, pas seulement la base de données.
Ce qu’il vous faut
- Un serveur avec Docker et le plugin Compose. Un Hetzner CX23 (2 vCPU, 4 Go de RAM, 40 Go NVMe, 5,99 €/mois hors TVA) fait tourner Castopod confortablement ; prévoyez du vrai disque au-delà des 40 Go par défaut une fois que vous hébergez plus qu’une poignée d’épisodes, les fichiers audio s’accumulent plus vite que la plupart des applications auto-hébergées.
- Un nom de domaine vers lequel vous pouvez pointer un enregistrement A. Castopod exige le HTTPS pour fédérer correctement avec le fédivers (abonnements et commentaires de balados), donc ce n’est pas optionnel comme ça pourrait l’être pour un outil interne.
- Un accès SSH au serveur.
Étape 1 : pointer le DNS et ouvrir le pare-feu
ufw allow OpenSSH
ufw allow 80
ufw allow 443
ufw --force enable
Créez un enregistrement A pour votre domaine pointant vers l’IP publique du serveur, et laissez-lui quelques minutes avant l’étape 5.
Étape 2 : générer les secrets
openssl rand -hex 24 # MYSQL_ROOT_PASSWORD
openssl rand -hex 24 # MYSQL_PASSWORD
openssl rand -hex 24 # REDIS_PASSWORD
openssl rand -hex 16 # CP_ANALYTICS_SALT
mkdir -p /opt/castopod
cat > /opt/castopod/.env <<'EOF'
MYSQL_ROOT_PASSWORD=paste-the-first-value-here
MYSQL_PASSWORD=paste-the-second-value-here
REDIS_PASSWORD=paste-the-third-value-here
CP_ANALYTICS_SALT=paste-the-fourth-value-here
EOF
chmod 600 /opt/castopod/.env
CP_ANALYTICS_SALT est ce avec quoi Castopod hache les adresses IP des auditeurs avant de compter un téléchargement, ce qui vous donne de vraies analyses agrégées sans stocker les IP brutes ; ça doit rester la même valeur pendant toute la vie de l’instance, en changer réinitialise la façon dont les auditeurs récurrents sont dédupliqués.
Étape 3 : écrire le fichier Compose
services:
castopod:
image: castopod/castopod:1.15.5
restart: unless-stopped
env_file: .env
security_opt:
- no-new-privileges:false
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
environment:
CP_BASEURL: https://podcast.yourdomain.com
CP_DATABASE_HOSTNAME: db
CP_DATABASE_NAME: castopod
CP_DATABASE_USERNAME: castopod
CP_DATABASE_PASSWORD: ${MYSQL_PASSWORD}
CP_REDIS_HOST: redis
CP_REDIS_PASSWORD: ${REDIS_PASSWORD}
volumes:
- castopod_media:/app/public/media
expose:
- "8080"
db:
image: mariadb:12.1
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: castopod
MYSQL_USER: castopod
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- castopod_db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
redis:
image: redis:7.2.5-alpine
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- castopod_redis_data:/data
caddy:
image: caddy:2
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
depends_on:
- castopod
volumes:
castopod_media:
castopod_db_data:
castopod_redis_data:
caddy_data:
caddy_config:
Ce guide fixe 1.15.5, la version stable actuelle au moment de l’écriture, et mariadb:12.1, le moteur de base de données que la propre documentation de Castopod documente plutôt que Postgres. security_opt: no-new-privileges:false est requis, pas optionnel : l’image de Castopod tourne comme utilisateur non root www-data et a besoin de faire un chown sur /run lors de son propre démarrage, ce que la protection par défaut no-new-privileges du noyau bloque, faisant échouer fatalement le conteneur avec s6-overlay-suexec: child failed with exit code 100 si cette protection reste activée. Le propre script d’entrée de Castopod, pas un fichier de configuration que vous écrivez, génère son vrai .env en interne à partir des variables CP_* que ce guide définit, à chaque démarrage.
Vérifiez que le fichier s’analyse :
docker compose config
Étape 4 : ajouter Caddy et démarrer la pile
podcast.yourdomain.com {
reverse_proxy castopod:8080
}
docker compose up -d
docker compose ps
curl -I https://podcast.yourdomain.com
Vous devriez voir chaque service à l’état Up (db à l’état healthy) et le curl retourner HTTP/2 200.
Étape 5 : créer votre compte et votre premier balado
Visitez https://podcast.yourdomain.com/cp-install et suivez l’assistant de configuration pour créer le premier compte administrateur, rien n’est pré-rempli. Depuis le tableau de bord administrateur, créez un balado, remplissez ses métadonnées, et publiez votre premier épisode en téléversant un fichier audio ; Castopod transcode et génère l’entrée RSS automatiquement. Votre flux est publié à https://podcast.yourdomain.com/@<your-podcast-handle>/feed.xml, l’URL à soumettre à Apple Podcasts, Spotify et tout autre répertoire.
Étape 6 : sauvegarder la base de données et le volume de médias
Les fichiers audio et une base de données MariaDB qui grandit comptent tous les deux ici, et le volume de médias est habituellement le plus gros :
cat > /opt/castopod/backup.sh <<'EOF'
#!/bin/sh
cd /opt/castopod
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
docker compose exec -T db mariadb-dump -u root -p"${MYSQL_ROOT_PASSWORD}" castopod | gzip > backups/db-$TIMESTAMP.sql.gz
find backups -mtime +14 -delete
EOF
mkdir -p /opt/castopod/backups
chmod +x /opt/castopod/backup.sh
(crontab -l 2>/dev/null; echo "0 3 * * * /opt/castopod/backup.sh") | crontab -
Lancez-le une fois à la main et vérifiez que ls -lh backups montre un fichier daté. L’export de la base de données seul ne couvre pas l’audio téléversé sur castopod_media ; sauvegardez-le avec l’outillage de capture de disque complet qu’offre votre fournisseur de serveur, ou un rsync périodique vers une autre machine, puisqu’un tar sur des médias activement servis pendant que des épisodes sont en direct est le genre de chose qui vaut la peine d’être planifié pour les heures de faible trafic.
Étape 7 : mettre à niveau
docker compose pull castopod
docker compose up -d castopod
Castopod exécute automatiquement ses propres migrations de base de données au démarrage quand la version de l’image change. Vérifiez les notes de version pour la version vers laquelle vous allez, et confirmez que docker compose logs castopod montre un démarrage propre sans erreur de migration avant de considérer la mise à niveau comme terminée.
Le raccourci : avec Railyard
Tout ce qui précède, MariaDB et Redis branchés automatiquement, le correctif no-new-privileges dont la propre image de Castopod a besoin pour démarrer proprement, un volume dédié pour l’audio téléversé, est aussi ce que le modèle de pile Castopod de Railyard configure pour vous. Connectez un serveur, puis choisissez Castopod dans le catalogue de modèles : app.railyard.run/deploy?stack=castopod. Le HTTPS est géré de la même façon que l’étape 4 le fait à la main, ce qui satisfait aussi la propre exigence de fédération fédivers de Castopod.
Voyez déployer avec un bouton et bases de données et sauvegardes pour savoir comment les modèles et les données persistantes fonctionnent sur la plateforme de façon plus générale.
Dépannage
Le conteneur se ferme avec s6-overlay-suexec: child failed with exit code 100. no-new-privileges est encore activé, vérifiez que security_opt à l’étape 3 est bien défini à no-new-privileges:false sur le service castopod spécifiquement, c’est le seul renforcement par défaut qui doit être relâché pour cette image.
MariaDB journalise « Host X is not allowed to connect » uniquement au tout premier démarrage. Ça se produit si le CPU du serveur est fortement chargé pile au moment où MariaDB crée ses utilisateurs et droits initiaux, interrompant ce processus. Arrêtez la pile, retirez le volume castopod_db_data, et relancez docker compose up -d à un moment plus calme ; il n’y a pas de vraies données à perdre si ça arrive sur une installation vraiment neuve.
Le téléversement audio échoue avec une erreur de permission. Vérifiez la propriété à l’intérieur du conteneur avec docker compose exec castopod ls -la /app/public/media ; ça se produit le plus souvent après avoir restauré une sauvegarde en tant que root alors que le conteneur tourne comme www-data.
Le HTTPS ne s’émet pas. docker compose logs caddy montrant des erreurs ACME répétées signifie presque toujours que le DNS de l’étape 1 ne s’est pas propagé ou pointe vers la mauvaise IP.
Le disque se remplit plus vite que prévu. Les fichiers audio s’accumulent rapidement à travers les épisodes ; du -sh castopod_media (ou le chemin équivalent via docker volume inspect) montre ce qui consomme réellement l’espace, et redimensionner le disque du serveur avant d’en manquer est plus simple que de migrer un volume complet sous pression.
FAQ
Castopod exige-t-il un fournisseur SMTP comme d’autres applications auto-hébergées ? Pas pour publier un balado ou pour que la modération de base fonctionne ; le SMTP n’est nécessaire que si vous activez les notifications de courriel optionnelles, ce qui est une exigence bien plus légère que les applications où la confirmation de compte elle-même en dépend.
Puis-je migrer le flux RSS d’un balado existant vers Castopod ? Oui, Castopod prend en charge l’importation d’épisodes depuis une URL de flux existante pendant la création du balado, ce qui préserve l’historique des épisodes plutôt que de repartir de zéro.
L’intégration au fédivers est-elle obligatoire ? Non, les balados fonctionnent comme un flux RSS et un lecteur web normaux sans elle ; la fédération (abonnements et commentaires depuis des applications façon Mastodon) est une fonctionnalité additionnelle par-dessus, pas une exigence pour publier.
Comment fonctionnent les vraies analyses sans suivre les auditeurs individuellement ? Castopod implémente la spécification d’analyses Podcasting 2.0, hachant les données identifiantes comme les adresses IP avec le sel de l’étape 2 avant de compter un téléchargement, donc vous obtenez de vrais chiffres de téléchargement et de géographie sans stocker quoi que ce soit qui identifie un auditeur individuel.
Quelle est la croissance de disque réaliste pour une émission active ? Un épisode hebdomadaire d’une heure à un débit binaire raisonnable représente des dizaines de mégaoctets par épisode ; ça s’accumule lentement pour la plupart des émissions, mais la vidéo ou l’audio à très haut débit change cette équation rapidement, vérifiez les tailles de fichiers réelles contre le serveur de « Ce qu’il vous faut » avant de présumer que les 40 Go par défaut suffisent pour une année.
Une fois MariaDB, Redis et le HTTPS en place, publier un épisode, c’est les mêmes quelques clics que ce serait sur une plateforme hébergée, le vrai travail continu, c’est l’habitude de sauvegarde de l’étape 6 et garder un œil sur l’espace disque à mesure que l’émission grandit.
Pourquoi les gens choisissent Railyard pour ça
- Votre propre compte infonuagique. Déployez sur DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou n'importe quel serveur Linux par SSH, facturé directement par votre fournisseur, sans majoration.
- Un prix fixe par équipe. L'offre gratuite est gratuite pour toujours : un serveur plus un serveur de base de données, trois applications, sans carte. Pro coûte 19 $ par mois pour jusqu'à cinq serveurs et un nombre illimité d'applications. Team coûte 49 $ par mois avec des serveurs illimités. Aucuns frais par application, par déploiement, par siège ou par gigaoctet.
- Des gabarits en un clic. Déployez des applications open source, comme des bases de données, des outils d'analyse et des outils de développement, sur votre propre serveur en un clic.
- Des bases de données gérées. Postgres, MySQL et Redis, avec des sauvegardes planifiées, vérifiées par restauration, et la récupération à un point dans le temps.
- Déploiement par push. Déployez depuis GitHub, GitLab ou la CLI, avec HTTPS automatique et des mises en production sans interruption.