Fui executando um fórum Discourse com uma quantidade considerável de conteúdo e muitas imagens nos últimos anos. Maker Forums tem mais de 100 GB de imagens e mais de 400.000 publicações, das quais uma quantidade substancial foi importada, principalmente do Google+, e o restante foi criado no site. Esta publicação descreve elementos de como configurei o Maker Forums e, mais tarde, algumas outras instâncias do Discourse. É o que eu gostaria de ter sabido quando comecei, e que usei para ajudar outras pessoas a evitar algumas das mesmas armadilhas em suas próprias instâncias do Discourse.
Hora de atingir um público mais amplo.
Aviso: Se você não se sentir confortável trabalhando como administrador de sistemas Linux, este guia provavelmente não é para você. Eu nem mesmo estou ciente de todas as maneiras pelas quais ele pressupõe conhecimento sobre Linux. Se isso parecer esclarecedor para ler, você pode ser o público-alvo. Se parecer confuso para ler, você provavelmente não é o público-alvo. Se isso parecer trabalho, considere pagar para que a CDCK ou @pfaffman executem o Discourse para você; eles sabem o que estão fazendo. Ou comece com um site gratuito discourse.group e depois pague pelo que você for crescendo.
Como se isso não fosse suficiente: tenho mais experiência em Linux do que em Discourse. Minhas opiniões não vêm com garantia. Se tentar seguir meus conselhos fizer algo seu quebrar (seu fórum Discourse, seu sistema host ou seu coração), você fica com as duas peças, com todas as arestas cortantes. Não tenho planos de fornecer qualquer tipo de suporte para o conteúdo desta publicação.
Planejo (mas não prometo) manter este documento atualizado com minhas práticas cobrindo as instâncias do Discourse nas quais participo da manutenção. Isso está escrito na forma de conselho, mas a intenção é principalmente como conselho para mim mesmo e para quaisquer administradores que herdem implantações do Discourse pelas quais fui responsável. Caso contrário, você deve considerá-lo como um ponto de partida para sua própria pesquisa para determinar como deseja implantar o Discourse.
Configuração do Sistema
Use um sistema operacional derivado do CentOS ou Ubuntu LTS. Qualquer coisa que suporte Docker provavelmente pode ser feita para funcionar, mas usei esses dois.
Docker
Sou usuário do Fedora. Fui o primeiro Líder do Projeto Fedora na Red Hat, e eu preferiria muito executar o Discourse por cima do Podman, porque opino que seu modelo de segurança é preferível ao do Docker. No entanto, as implantações do Discourse são suportadas apenas no Docker, e você será um verdadeiro pioneiro se tentar executar por cima de qualquer outra coisa. (Pode, um dia, funcionar com Podman usando podman-compose se o docker-compose for suportado.)
Agora que o Docker suporta cgroups v2, você pode instalar as compilações oficiais do Docker em um sistema derivado do CentOS:
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
dnf install --allowerasing docker-ce docker-ce-cli
(Inclua --allowerasing devido a um conflito com podman, runc e buildah que podem já estar instalados; eles precisam ser removidos para instalar o docker.)
systemctl enable --now docker
Testei isso com AlmaLinux 9.
Segurança
Esta seção realmente não tem nada a ver com o Discourse per se, mas faz parte da minha prática normal de segurança. Não permita acesso ao shell apenas com senha a nenhum sistema na rede, incluindo uma VM executando o Discourse. Configure o acesso baseado em SSH usando uma chave SSH criptografada com frase de passe, e configure o servidor ssh em sua VM para não permitir acesso por senha.
laptop$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/.../.ssh/id_rsa):
Enter passphrase (empty for no passphrase): ALGUMA FRASE LONGA
Enter same passphrase again: ALGUMA FRASE LONGA
Your identification has been saved in .ssh/id_rsa
Your public key has been saved in .ssh/id_rsa.pub
As distribuições Linux normalmente são configuradas para lembrar a frase de passe na memória, então você só precisa digitá-la uma vez por inicialização. O Windows não é tão conveniente; você pode considerar usar o Pageant com o PuTTY para fazer o mesmo.
Primeiro, valide que o SSH entrante funciona sem senha. Só depois disso, no servidor, modifique o arquivo /etc/ssh/sshd_config e encontre a linha PasswordAuthentication. Defina como no para desabilitar o acesso por senha entrante.
PasswordAuthentication no
Firewall
Você precisará deixar as portas 80 e 443 geralmente abertas para o letsencrypt gerar e renovar seus certificados SSL, mesmo antes de seu Discourse estar aberto ao público.
Se você estiver usando firewalld, estes comandos realizarão isso:
firewall-cmd --add-service http --add-service https --zone public
firewall-cmd --runtime-to-permanent
Dispositivo e sistema de arquivos separados
Faça com que /var/discourse/shared seja um dispositivo separado com seu próprio sistema de arquivos, com 20 GB de espaço mais pelo menos o dobro do espaço que você precisa para imagens; adicione mais espaço se for usar prometheus. Se o dispositivo for fácil de expandir depois (como LVM ou qualquer armazenamento em bloco na nuvem como AWS elastic block storage) você pode monitorar e aumentá-lo conforme necessário; caso contrário, seja generoso no início. Se você estiver usando um dispositivo de armazenamento em bloco de rede, não coloque uma tabela de partições nele. Usá-lo sem uma tabela de partições tornará mais fácil expandir; você não precisará modificar uma tabela de partições. Em muitos casos, você poderá expandir sem nenhuma interrupção do sistema.
No Maker Forums, este é um dispositivo de armazenamento em bloco de rede conectado à VM na qual o Maker Forums está sendo executado. Em outro fórum Discourse, é um Volume de Armazenamento em Bloco da Digital Ocean. Na Amazon, seria o AWS Elastic Block Storage. Em meu sistema de teste executando uma VM KVM sob libvirt no Fedora, é um volume LVM no host Fedora exportado para a VM AlmaLinux como um disco virtual. Em cada caso, eu poderia criar uma nova VM, copiar arquivos-chave para ela, parar a VM antiga, anexar o volume /var/discourse/shared à nova VM e estar de volta funcionando em minutos. Isso torna as atualizações do sistema operacional na VM relativamente de baixo risco.
Certifique-se de começar com pelo menos 25 GB no sistema de arquivos raiz para sua VM, não incluindo nenhum espaço para /var/discourse/shared. Isso será usado para todos os contêineres docker, e o lançador do discourse falhará se houver menos de 5 GB livres a qualquer momento. Você também quer bastante espaço disponível para atualizações do sistema. Se você não tiver espaço em disco suficiente, isso é difícil de recuperar.
Na configuração do site, defina force_https, mas leve em conta os avisos. Configure-o em teste, antes de tornar um site Discourse público. Observe que mesmo com force_https você precisa da porta 80 aberta, tanto para redirecionar para SSL na porta 443 quanto para renovar seu certificado SSL do letsencrypt. (No entanto, se você estiver usando cloudflare, use seu recurso em vez disso; relata-se que não é compatível com force_https no Discourse.)
Configuração do Kernel
Redis (um dos componentes-chave nos quais o Discourse é construído) recomenda fortemente desabilitar páginas transparentes gigantes ao usar persistência em disco (o que o Discourse faz), e eu também permito supercomprometimento de memória.
echo 'w /sys/kernel/mm/transparent_hugepage/enabled - - - - never
w /sys/kernel/mm/transparent_hugepage/defrag - - - - never' > /etc/tmpfiles.d/thp.conf
systemd-tmpfiles --create
echo 'vm.overcommit_memory=1' > /etc/sysctl.d/90-vm_overcommit_memory.conf
sysctl --system
Instalação do Discourse
Enquanto a instalação padrão é um único contêiner, isso faz com que cada atualização, recomendada mensalmente, seja tipicamente uma interrupção de 10-15 minutos se feita a partir da linha de comando, o que é necessário para algumas atualizações, incluindo aquelas que atualizam as ferramentas sobre as quais o Discourse é construído, por segurança ou novos recursos, ou quando a atualização ao vivo pela interface do usuário falha por qualquer motivo. Você pode reduzir essa interrupção na prática com a instalação de dois contêineres.
Instalação de dois contêineres
Inicie a configuração com dois contêineres.
./discourse-setup --two-container --skip-rebuild
${EDITOR:-nano} containers/data.yml
./launcher rebuild data
# minha preferência é usar app.yml, mas você pode ficar com web_only.yml, leia o texto
mv containers/web_only.yml containers/app.yml
${EDITOR:-nano} containers/app.yml
./launcher rebuild app
Isso torna a interrupção do sistema necessária a cada poucos meses muito curta, raramente perceptível; muitos usuários não notarão nada se não clicarem ou rolarem o conteúdo durante a interrupção. Isso facilita a aplicação da maioria das atualizações de segurança; é apenas um pico em vez de aproximadamente 15 minutos reconstruindo tudo. O processo a seguir funciona para a maioria das atualizações e tipicamente dá aproximadamente 30-90 segundos de interrupção, dependendo principalmente do desempenho do sistema host e do conjunto de plugins instalados.
cd /var/discourse
git pull
./launcher bootstrap app
./launcher destroy app && ./launcher start app
./launcher cleanup
Não demore entre as invocações de bootstrap e destroy/start. Raramente (talvez uma ou duas vezes por ano na prática), as migrações de banco de dados feitas perto do final da fase de bootstrap causarão erros mais ou menos sérios para os usuários do aplicativo, devido ao código mais antigo acessando o banco de dados atualizado.
Isso significa que quando você atualiza o Discourse, você também precisa verificar se deve atualizar o contêiner de dados, mas isso raramente é necessário (geralmente espere uma ou duas vezes por ano). Dependendo do conteúdo de seus contêineres de dados e aplicativos e da velocidade do sistema, isso resultará tipicamente em uma interrupção entre 5 e 20 minutos.
cd /var/discourse
git pull
./launcher stop app
./launcher rebuild data
./launcher rebuild app
Para mais informações sobre quando atualizar o contêiner de dados, veja:
(Em minhas próprias implantações, escolhi pessoalmente chamar o contêiner web_only de app tanto porque é mais fácil de digitar quanto porque torna a maioria das instruções mais fáceis de seguir. Isso não é padrão, mas continuo apreciando a facilidade de uso. No entanto, foi trabalho extra, e funciona para mim porque sei o que está acontecendo. Se isso soa mal para você, fique com o web_only padrão para uma implantação multi-contêiner.)
Observe que em algum ponto no futuro, o Docker pode forçá-lo a fazer uma migração para uma nova configuração para conectar seus contêineres:
Se você tiver 4 GB ou mais de memória, ou vários CPUs, leia os conselhos em:
Cronograma de Atualização
Acompanhe a tag release-notes (Clique em release-notes e clique no sino no canto superior direito; eu uso “Acompanhando a Primeira Postagem”) e/ou adicione https://meta.discourse.org/tag/release-notes.rss ao seu feed RSS para saber quando há lançamentos. Leia as notas de lançamento antes de atualizar. Se houver uma mudança no banco de dados, as notas de lançamento mencionarão isso. Elas também destacarão lançamentos que contêm atualizações de segurança. Leia todas as notas de lançamento, mesmo que você pule a atualização real para alguma versão; se você não ler as notas de lançamento de um lançamento que atualiza o banco de dados, você pode perder instruções de atualização do banco de dados nas notas de lançamento que não leu.
Correio
O correio ainda é uma das principais maneiras de manter as pessoas conectadas. Configure o correio de saída e entrada para fazer o correio funcionar para você. Se você tiver problemas, veja:
Continue se comunicando
O Maker Forums viu visitantes ocasionais que estão ausentes por longos períodos antes de retornar. Por padrão, o Discourse para de enviar e-mails de resumo após um ano. Considere definir o suppress_digest_email_after_days para algo maior que o padrão de 365 dias se você quiser incentivar visitantes ocasionais a voltar quando virem algo novo e interessante. Eu o fiz substancialmente maior para o Maker Forums para apoiar visitantes ocasionais se mantendo atualizados. Ler e-mails de resumo é uma maneira válida de “lurkar” em um fórum, e você nunca sabe quando algo vai despertar o interesse de alguém em contribuir.
Da mesma forma, por padrão, usuários sem privilégios que não interagiram muito (nível de confiança 0 sem publicações) são eventualmente excluídos após 730 dias sem fazer login. Defina "limpar usuários inativos após diasup/backup-config
restic --cache-dir=/var/restic
backup
/etc
/root
/var/discourse
/opt/backup
–exclude /var/discourse/shared/data/postgres_data
restic --cache-dir=/var/restic forget
–prune --keep-hourly 24 --keep-daily 7 --keep-monthly 3
EOF
chmod +x backup
Esses detalhes variarão dependendo do destino do restic. Nem todos usam variáveis de ambiente da AWS, então leia a documentação do restic.
```shell
# cat > backup-config <<EOF
### Esses detalhes dependem de qual destino do restic você configurar, então altere-os
export AWS_ACCESS_KEY_ID=sua-chave-aqui
export AWS_SECRET_ACCESS_KEY=mesma
export RESTIC_PASSWORD_FILE=/root/restic-password
export RESTIC_REPOSITORY=veja-a-documentação-do-restic
EOF
# {$EDITOR:-nano} /root/restic-password
Você precisará armazenar uma cópia do que colocou em /root/restic-password, caso contrário, não poderá ler os backups! Use seu cofre de senhas.
Por fim, crie alguns serviços, inicialize o repositório do restic e defina um temporizador para que os backups comecem.
# cat > /etc/systemd/system/backup.service <<EOF
[Unit]
Description=Backup para destino remoto
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
StandardOutput=file:/var/log/backup.out
StandardError=file:/var/log/backup.err
WorkingDirectory=/var/discourse
ExecStart=/opt/backup/backup
[Install]
WantedBy=multi-user.target
EOF
# cat > /etc/systemd/system/backup.timer <<EOF
[Unit]
Description=Backups regulares do sistema
[Timer]
Persistent=true
OnCalendar=00/4:30:00
Unit=backup.service
[Install]
WantedBy=timers.target
EOF
# systemctl daemon-reload
# . /opt/backup/backup-config
# restic init
# /opt/backup/backup
# systemctl enable backup.timer
Após esse processo, você deverá conseguir ver que criou seu backup inicial.
# restic snapshots
Usei com sucesso backups do restic feitos dessa maneira para mover um servidor Discourse de um sistema para outro usando o comando restic restore.
Backups de imagens em streaming com minio
Como alternativa ao Restic, embora os backups de banco de dados possam ser armazenados no S3, não há backup de imagens no S3 separado do serviço de imagens do S3. Uma alternativa é usar o minio-client para copiar imagens para qualquer armazenamento semelhante ao S3. Isso pode ser muitos destinos semelhantes ao S3, incluindo S3 e minio, mas não DigitalOcean Spaces porque é construído sobre o sistema de arquivos Ceph, que não implementa a API ListObjectsV2 da mesma maneira que o S3.
No S3, crie um bucket que bloqueie o acesso público (Permissões → Bloquear acesso público é a maneira fácil de fazer isso corretamente na AWS).
Instale o minio-client (mc) de alguma forma. Aqui está uma maneira.
curl https://dl.min.io/client/mc/release/linux-amd64/mc > /usr/local/bin/mc && chmod +x /usr/local/bin/mc
Configure o minio-client com um alias chamado backup usando um comando como este:
# mc alias set backup https://s3.amazonaws.com ACCESSKEY SECRETKEY --api S3v4
# mc mirror /var/discourse/shared/standalone/uploads backup/UPLOADS-BACKUP-BUCKET
Em seguida, crie um serviço /etc/systemd/system/backup-uploads.service como este
[Unit]
Description=Sincronização de backup remoto quase em tempo real de uploads do discourse
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
Restart=always
RestartSec=600
User=root
ExecStart=/usr/local/bin/mc mirror --overwrite -a --watch /var/discourse/shared/app/uploads backup/UPLOADS-BACKUP-BUCKET
[Install]
WantedBy=multi-user.target
Observe que UPLOADS-BACKUP-BUCKET aqui deve ser um bucket diferente do s3_backup_bucket no qual você configura o discourse para fazer upload de backups de banco de dados. Além disso, observe que o caminho será /var/discourse/shared/web_only/uploads se você usar a implantação multi-container padrão.
# systemctl enable backup-uploads
# systemctl start backup-uploads
# journalctl -fu backup-uploads
Faça upload de uma imagem de teste e verifique se você vê linhas indicando o backup bem-sucedido das imagens original e otimizada. Control-C sairá do modo de acompanhamento no journalctl.
Recuperação
Nunca precisei testar esse plano até o momento desta escrita. Este resumo pode estar omitindo algo.
- Restaure todos os arquivos backupados em geral
- Inicie o nginx (agora sua página de manutenção será exibida)
- Faça uma implantação normal do Discourse usando os arquivos restaurados em /var/discourse/containers
- Instale o minio-client em /usr/local/bin/mc se você não o restaurou dos backups
- Se você não fez backup de
/root/mc, configure o alias de backup# mc alias set backup https://s3.amazonaws.com ACCESSKEY SECRETKEY --api S3v4 # mc cp backup/UPLOADS-BACKUP-BUCKET /var/discourse/shared/app/uploads- Restaure o backup de banco de dados mais recente; recomendo que você Restore a backup from the command line
- Apenas após confirmar que o site está operacional, reconfigure o backup de uploads para o S3 conforme documentado acima.
Backups em streaming do postgresql
No futuro, posso criar, testar e fornecer uma configuração para permitir o uso de arquivamento contínuo de WAL para transmitir backups do Postgres quase instantâneos com o minio-client usando o archive-command no postgresql, semelhante aos backups de uploads em streaming.
Monitoramento de desempenho
Existem pelo menos duas abordagens para monitoramento de desempenho.
Container Prometheus
Configure o prometheus, colocando os logs do prometheus em /var/discourse/shared/prometheus se você estiver executando-o no mesmo sistema. Os arquivos do Prometheus podem crescer muito, e você não quer que eles preencham o sistema de arquivos raiz; você também provavelmente quer levá-los consigo se mover para um sistema host mais novo (seja atualizando para uma VM maior ou uma VM com uma instalação de sistema operacional mais recente).
Se você implantar o prometheus no sistema discourse (ou em qualquer outro lugar na internet pública), configure a segurança na frente dele. Instalado dessa forma, uma opção seria a configuração do nginx como esta:
location /prometheus/ {
auth_basic "Prometheus";
auth_basic_user_file /etc/nginx/prometheus-htpasswd;
proxy_pass http://localhost:9090/;
}
Sysstat
Se o Prometheus for demais, considere usar o sysstat em vez disso.
dnf install sysstat(ouapt install sysstatno debian e derivados)systemctl enable --now sysstatsystemctl enable --now sysstat-collect.timersystemctl enable --now sysstat-summary.timersystemctl edit sysstat-collect.timere altereOnCalendar=*:00/10paraOnCalendar=*:00/2- Se /etc/default/sysstat existir, altere
falseparatrue
Após isso, o comando sar poderá informar se você está ficando sem recursos de vez em quando.
Outros Recursos
Aqui está uma discussão complementar (e mais compacta) sobre o uso do Discourse internamente como forma principal de comunicação interna.