Correr o seu próprio Progress Watch
O servidor é de código aberto sob a AGPL, e o serviço alojado corre a mesma imagem que você correria. Alojá-lo por conta própria custa um contentor e um volume, e a base de dados fica pequena para sempre porque o progresso nunca lá é escrito.
Um único ficheiro
docker-compose.yml é toda a instalação. Corre a imagem publicada, por isso não há nada para clonar nem nada para compilar. Copie-o da a página do Docker, que imprime o ficheiro atual, e arranque:
Isso é toda a configuração: a aplicação em http://localhost:7979, com o Redis e o SQLite no mesmo contentor e tudo o que guardam no volume com nome. Abra-a, crie um espaço, e o menu Ligar desse espaço dá-lhe comandos com o UUID já preenchido.
Configurar
O ficheiro é seu a partir do momento em que o guarda, e é o único sítio onde algo é configurado. Cada definição é uma linha num bloco environment: sob o serviço, que o ficheiro omite até precisar de um:
environment: - DATABASE_URL=postgresql://progresswatch:secret@db.internal/progresswatch - VAPID_PUBLIC_KEY=BJ1w… - VAPID_PRIVATE_KEY=xK2p…
Variáveis de ambiente é a lista completa, e tudo o que lá está funciona aqui. Para publicar num porto diferente do 7979, mude o lado esquerdo de 7979:3000 — a aplicação dentro do contentor está sempre no 3000.
curl http://localhost:7979/up
{"status":"ok","database":true,"redis":true,"worker":true}
O que está a correr
Dois processos e um ficheiro, tudo num contentor. A aplicação responde aos pedidos e corre o worker dentro de si, porque o Sidekiq está embutido no Puma, e arranca o Redis ao seu lado e para-o ao sair. O Redis guarda o progresso atual de cada tarefa e a fila de jobs, e grava instantâneos de ambos no volume; o SQLite guarda os espaços e a forma de cada tarefa. Defina REDIS_URL e a aplicação usa esse Redis em vez disso e não arranca nenhum próprio.
Atualizá-lo
Descarregue a imagem nova e arranque de novo:
docker compose pull docker compose up -d
Cada tarefa em curso fica onde estava. Parar o contentor faz o Redis gravar um instantâneo no volume, e o contentor novo carrega-o ao arrancar. Só uma falha ou um corte de energia salta essa gravação, e então volta o último instantâneo periódico, com minutos se os relatórios forem frequentes e até uma hora se não forem: uma tarefa mostra «À espera de dados…» ou um número mais antigo até ao relatório seguinte.
Porquê 7979
Não 3000. Este é um serviço que deixa a correr durante semanas enquanto trabalha, e o 3000 é onde aterram os seus próprios servidores de desenvolvimento — Rails, Vite, Next, Grafana e metade das linhas docker run de outros guias. Um serviço em segundo plano não devia ocupar o porto mais disputado da máquina, muito menos um cujo URL cola num segredo de CI e depois esquece.
Dentro do contentor continua a ser o 3000; só o porto publicado mudou, e isso é a linha 7979:3000.
Perder o volume é recuperável
Estão lá os espaços, a estrutura das tarefas, um instantâneo do Redis e a chave secreta. Se desaparecer, cria um espaço novo e os seus processos repovoam tudo no pedido seguinte, e uma chave secreta nova não custa nada, porque não há contas de onde tirar alguém. Faça cópia de segurança se preferir não redistribuir um UUID de espaço novo a tudo o que lá reporta, mas não há lá nada que não possa ser reconstruído voltando a correr os trabalhos.
SQLite ou PostgreSQL
Ambos, a partir da mesma imagem e das mesmas migrações, escolhidos por DATABASE_URL. O SQLite é o predefinido e é a resposta certa para uma máquina: duas tabelas, leituras por chave primária, quase nunca escritas. Aponte para postgresql://… quando correr vários contentores da aplicação, porque não podem partilhar um ficheiro.
Atrás de um proxy
Ponha FORCE_SSL=true assim que algo à frente da aplicação terminar o TLS. Está desligado por omissão para que uma instalação alcançada por HTTP simples não o reencaminhe para um certificado que não tem.
Notificações
Ponha um par de chaves VAPID e aparece um botão «Avisar-me» em cada espaço; deixe as chaves por definir e a funcionalidade não existe. Não há nada para registar na Apple nem na Google. Veja notificações para a história completa, incluindo o que tem de acontecer num telemóvel.
Varrer os espaços vazios
Abrir o site cria um espaço para si, por isso criam-se muitos que nunca são usados — incluindo por tudo o que percorre a página. Um espaço que alguma vez tenha tido uma tarefa é guardado para sempre, por muito tempo que ninguém olhe para ele. Só são varridos os que nunca tiveram uma única tarefa, e apenas quando têm mais de 30 dias.
Nada o corre por si. Agende-o como já agenda as coisas:
# crontab, diariamente às 04:17 17 4 * * * cd /path/to/progresswatch && docker compose exec -T progresswatch bin/rails sweep_empty_spaces
Como nada corre em temporizador, 30 dias são um mínimo e não um calendário: corra-o diariamente e os espaços vazios saem no dia em que se qualificam, corra-o uma vez por ano e ficam até lá. Saltá-lo é seguro para os seus dados — a varredura só leva linhas que nunca foram usadas — significa apenas que a tabela cresce com espaços que ninguém abriu.
A sua instância não é indexável
Todas as páginas de uma instalação própria são noindex, o robots.txt proíbe tudo, e /sitemap.xml responde 404. A partir da máquina de alguém não há público a alcançar nem nada ali que queira ser encontrado numa pesquisa, e não é preciso configurar nada para isso — é o que se recebe.