Faire tourner votre propre Progress Watch

Le serveur est open source sous licence AGPL, et le service hébergé fait tourner la même image que vous. L'auto-hébergement coûte un conteneur et un Redis, et la base de données reste petite pour toujours parce que la progression n'y est jamais écrite.

Un seul fichier

docker-compose.yml est toute l'installation. Il lance l'image publiée, il n'y a donc rien à cloner et rien à construire — copiez-le depuis la page Docker, qui affiche le fichier courant, remplacez le secret d'exemple par openssl rand -hex 64 et démarrez :

C'est toute l'installation : l'application sur http://localhost:7979, un Redis et un fichier SQLite sur un volume nommé. Ouvrez-la, créez un espace, et le menu Connecter de cet espace vous donne des commandes avec son UUID déjà rempli.

Le configurer

Le fichier est à vous dès l'instant où vous l'enregistrez, et c'est le seul endroit où quoi que ce soit se configure — chaque réglage est une ligne d'un bloc environment:, en ajouter un revient donc à ajouter une ligne :

    environment:
      - SECRET_KEY_BASE=8f3c…
      - DATABASE_URL=postgresql://progresswatch:secret@db.internal/progresswatch
      - VAPID_PUBLIC_KEY=BJ1w…
      - VAPID_PRIVATE_KEY=xK2p…

Variables d'environnement est la liste complète, et tout ce qui s'y trouve fonctionne ici. Pour publier ailleurs que sur 7979, changez la partie gauche de 7979:3000 — l'application dans le conteneur est toujours sur 3000.

curl http://localhost:7979/up

{"status":"ok","database":true,"redis":true,"worker":true}

Ce qui tourne

Deux processus et un fichier. L'application répond aux requêtes et exécute le worker en son sein — Sidekiq est embarqué dans Puma, donc il ne manque à une notification aucun service dédié. Redis conserve la progression actuelle de chaque tâche et la file de jobs ; SQLite conserve les espaces et la forme de chaque tâche.

Le mettre à jour

Nommez le service. Un docker compose pull seul récupère aussi Redis, et si un redis:8-alpine plus récent a été publié, up -d remplace ce conteneur également — ce qui jette la progression de tout ce qui tourne.

docker compose pull progresswatch
docker compose up -d progresswatch

Remplacer seulement le conteneur de l'application laisse chaque tâche en cours exactement où elle était, car la progression est dans Redis et Redis n'a pas été touché. Les titres et la structure sont sur le volume et survivent de toute façon. Rien ne survit à docker compose down ni à un redémarrage de l'hôte : Redis ne garde rien sur disque, délibérément.

Pourquoi 7979

Pas 3000. C'est un service que vous laissez tourner des semaines pendant que vous travaillez, et 3000 est là où atterrissent vos propres serveurs de développement — Rails, Vite, Next, Grafana et la moitié des lignes docker run des autres guides. Un service d'arrière-plan ne devrait pas occuper le port le plus disputé de la machine, encore moins un dont vous collez l'URL dans un secret de CI avant de l'oublier.

À l'intérieur du conteneur c'est toujours 3000 ; seul le port publié a bougé, et c'est la ligne 7979:3000.

Perdre le volume est réparable

Les espaces et la structure des tâches y sont, et rien d'autre. S'il disparaît, vous créez un nouvel espace et vos processus repeuplent tout à leur requête suivante. Sauvegardez-le si vous préférez ne pas redistribuer un nouvel UUID d'espace à tout ce qui rapporte dedans — mais il n'y a rien dessus qui ne puisse être reconstruit en relançant les travaux.

SQLite ou PostgreSQL

Les deux, depuis la même image et les mêmes migrations, choisis par DATABASE_URL. SQLite est la valeur par défaut et la bonne réponse pour une seule machine : deux tables, des accès par clé primaire, presque jamais d'écriture. Pointez vers postgresql://… quand vous faites tourner plusieurs conteneurs de l'application, car ils ne peuvent pas partager un fichier.

Derrière un proxy

Mettez FORCE_SSL=true dès que quelque chose devant l'application termine le TLS. C'est désactivé par défaut pour qu'une installation atteinte en HTTP simple ne vous redirige pas vers un certificat que vous n'avez pas.

Notifications

Posez une paire de clés VAPID et un bouton « Me notifier » apparaît sur chaque espace ; laissez les clés vides et la fonctionnalité n'existe pas. Il n'y a rien à enregistrer chez Apple ou Google. Voyez notifications pour toute l'histoire, y compris ce qui doit se passer sur un téléphone.

Balayer les espaces vides

Ouvrir le site crée un espace pour vous, il s'en crée donc beaucoup qui ne servent jamais — y compris par tout ce qui explore la page. Un espace qui a un jour contenu une tâche est conservé pour de bon, quel que soit le temps que personne n'y regarde. Seuls ceux qui n'ont jamais contenu la moindre tâche sont balayés, et seulement une fois qu'ils ont plus de 30 jours.

Rien ne le lance pour vous. Planifiez-le comme vous planifiez déjà les choses :

# crontab, chaque jour à 04:17
17 4 * * * cd /path/to/progresswatch && docker compose exec -T progresswatch bin/rails sweep_empty_spaces

Comme rien n'est sur une minuterie, 30 jours est un plancher et non un calendrier : lancez-le chaque jour et les espaces vides partent le jour où ils y ont droit, une fois par an et ils restent jusque-là. Le sauter ne risque rien pour vos données — le balayage ne prend que des lignes jamais utilisées — cela signifie simplement que la table grossit d'espaces que personne n'a jamais ouverts.

Votre instance n'est pas indexable

Chaque page d'une installation auto-hébergée est en noindex, robots.txt interdit tout, et /sitemap.xml répond 404. Depuis la machine de quelqu'un il n'y a pas de public à atteindre et rien là-dedans qui souhaite être trouvé dans une recherche, et il n'y a rien à configurer pour cela — c'est ce que vous obtenez.