Tenho administrado um fórum Discourse com uma quantidade substancial de conteúdo e muitas imagens nos últimos anos. Maker Forums tem mais de 100 GB de imagens e mais de 400.000 posts, dos quais uma quantidade significativa foi importada, principalmente do Google+, e o restante foi criado no site. Este post descreve elementos de como configurei eventualmente o Maker Forums e, mais tarde, algumas outras instâncias do Discourse. É o que eu gostaria de saber 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 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 presume conhecimento sobre Linux. Se parecer esclarecedor de ler, você pode ser o público-alvo. Se parecer confuso de ler, você provavelmente não é o público-alvo. Se parecer trabalho, considere pagar para a CDCK ou @pfaffman administrarem 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 vêm sem garantia. Se tentar seguir meus conselhos fizer algo seu quebrar (seu fórum Discourse, seu sistema host ou seu coração), você fica com os dois pedaços, com todas as arestas cortantes. Não tenho planos de fornecer qualquer forma de suporte para o conteúdo deste post.
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 é escrito na forma de conselho, mas tenho a intenção principalmente como conselho para mim mesmo e para quaisquer administradores que herdem implantações do Discourse das quais fui responsável. Caso contrário, você deve considerá-lo como um ponto de partida para sua própria pesquisa para determinar como gostaria de 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 preferiria muito mais executar o Discourse sobre o 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 sobre qualquer outra coisa. (Talvez, algum dia, funcione com Podman usando podman-compose se 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 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 na 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 Pageant com PuTTY para fazer o mesmo.
Primeiro, valide que o SSH entrante funciona sem senha. Só depois de fazer isso, no servidor, modifique o arquivo /etc/ssh/sshd_config e encontre a linha PasswordAuthentication. Defina como no para desativar 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 farã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 /var/discourse/shared 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 você for usar prometheus. Se o dispositivo for fácil de expandir mais tarde (como LVM ou qualquer armazenamento em bloco de 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 facilitará a expansão; você não terá que modificar uma tabela de partições. Em muitos casos, você poderá expandir sem qualquer tempo de inatividade do sistema.
No Maker Forums, este é um dispositivo de armazenamento em bloco de rede anexado à VM na qual o Maker Forums está executando. 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 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 suficiente em disco, é difícil se recuperar disso.
Na configuração do site, defina force_https mas leve os avisos a sério. Configure em teste, antes de tornar um site Discourse público. Note 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 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 desativar páginas enormes transparentes ao usar persistência em disco (o que o Discourse faz), e eu também permito supercomprometimento de memória.
echo 'sys.kernel.mm.transparent_hugepage.enabled=never' > /etc/sysctl.d/10-huge-pages.conf
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 torna cada atualização, recomendada mensalmente, tipicamente um tempo de inatividade de 10-15 minutos se feita pela 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 da interface falha por qualquer motivo. Você pode reduzir esse tempo de inatividade 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 o tempo de inatividade obrigatório do sistema a cada poucos meses bastante curto, raramente perceptível; muitos usuários não notarão nada se não clicarem ou rolarem além do conteúdo durante a interrupção. Isso facilita a aplicação da maioria das atualizações de segurança; é apenas um piscar de olhos 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 tempo de inatividade, 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 haja atraso 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 também, mas isso raramente é necessário (tipicamente 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 um tempo de inatividade 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:
(Nas 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 soar mal para você, fique com o padrão web_only em vez disso para uma implantação multi-contêiner.)
Note 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 “Watching First Post”) 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 se você pular a atualização para alguma versão; se você não ler as notas de lançamento para 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 você não leu.
O e-mail ainda é uma das principais maneiras de manter as pessoas conectadas. Configure e-mail de saída e de entrada para fazer o e-mail trabalhar 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 encorajar visitantes ocasionais a voltar quando virem algo novo e interessante. Eu o fiz substancialmente mais longo para o Maker Forums para apoiar visitantes ocasionais se mantendo atualizados. Ler e-mails de resumo é uma maneira válida de “lurk” 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 não privilegiados que não interagiram muito (nível de confiança 0 sem posts) são eventualmente excluídos após 730 dias sem fazer login. Defina “limpar usuários inativos após dias” para 0 para desativar a exclusão de usuários, se você quiser que eles possam lurk lendo e-mails de resumo indefinidamente.
Considere adicionar o plugin yearly review que, uma vez por ano, gerará um post como 2020: The Year in Review e eventualmente enviará por e-mail para seus usuários inativos o que pode encorajá-los a renovar a participação.
Contêiner receptor de e-mail
Configure um terceiro contêiner como receptor de e-mail. Ele garante o processamento de bounces, torna seu processamento de bounces independente do provedor de e-mail de saída e dá a você a opção de resposta por e-mail.
Certifique-se de ter SPF configurado para confiar no seu remetente de e-mail; minimamente, uma política como v=spf1 +mx -all se você enviar e receber através do mesmo MX, mas mais específico pode ser mais confiável como proteção contra spam. Considere DKIM também.
Se você usar o mesmo nome de host para receber e-mail, você realmente deve terminar o SSL fora do seu contêiner como para uma “página offline” (veja abaixo) e precisará mapear seus certificados certbot para o contêiner e reiniciar o contêiner após executar o certbot.
Termine conexões SSL de usuário fora do contêiner
Há duas escolhas para terminar SSL fora do contêiner, qualquer uma das quais traz vantagens substanciais sobre terminar dentro do contêiner. Configure uma delas após ter concluído com sucesso discourse-setup e inicializado seu fórum.
nginx externo
Use o nginx executando no sistema host, em vez de apenas em um contêiner, tanto para hospedar uma página de manutenção, quanto para suportar registro de endereços IPv6 se seu host tiver suporte IPv6. (Caso contrário, todas as conexões IPv6 serão registradas como vindas de um endereço RFC1918 interno associado à sua interface de rede virtual docker local.) Esta configuração apresentará uma página de manutenção temporária durante a maioria das operações de manutenção que eventualmente redirecionará de volta para a página que um usuário estava visualizando.
Note que as instruções naquela página (atualmente) sugerem instalar um pacote chamado letsencrypt mas agora é normalmente chamado certbot em vez disso. Se você seguir as instruções naquela página para usar --certonly, você não precisará do plugin nginx para certbot, mas instalar o plugin nginx é outro mecanismo. Em derivados do CentOS, isso é:
dnf config-manager --set-enabled crb
dnf install epel-release
dnf install certbot python3-certbot-nginx
systemctl enable --now certbot-renew.timer
Certifique-se de que o certbot reinicie o nginx e o contêiner receptor de e-mail para que você não termine com navegadores ou e-mail bloqueando tráfego com seu site devido a continuar usando um certificado antigo e expirado.
# systemctl edit certbot-renew
Para um sistema sem receptor de e-mail, adicionei as duas linhas:
[Service]
ExecStartPost=/bin/systemctl reload nginx
Em um sistema onde estou usando um contêiner receptor de e-mail separado que também compartilha o certificado do sistema:
[Service]
ExecStartPost=/bin/systemctl reload nginx
ExecStartPost=/bin/sh -c 'cd /var/discourse && ./launcher restart mail-receiver'
Se você estiver usando SELinux, os contêineres Ubuntu não estão configurados para rotular o arquivo nginx.http.sock com httpd_sys_content_t para o nginx externo poder acessá-lo. Você tem duas escolhas.
A primeira é executar o nginx em modo permissivo, removendo a proteção SELinux para ele: semanage permissive -a httpd_t
No entanto, isso remove a proteção SELinux do que provavelmente é o serviço mais relevante! Para manter o SELinux habilitado, você precisará permitir que o nginx acesse as páginas de erro e mude de proxy por um soquete de domínio unix para uma porta (que é alguns µs mais lento, mas não deve ser perceptível para seus usuários).
Primeiro, execute estes comandos para permitir que o nginx acesse páginas de erro:
semanage fcontext -a -t httpd_sys_content_t /var/www
restorecon -R -v /var/www
Então no seu app.yaml, comente ou remova o - "templates/web.socketed.template.yml", exponha a porta 80 como uma porta diferente na máquina local e reconstrua o contêiner.
expose:
- "8008:80" # http
Não use https aqui — você terminou o SSL no nginx externo, e o cabeçalho X-Forwarded-Proto diz ao Discourse que a requisição veio via https. Certifique-se de que a porta 8008 (ou qualquer outra porta que você escolheu) não esteja exposta publicamente pelas configurações do seu firewall.
Então execute este comando para permitir que o nginx se conecte pela rede ao contêiner:
setsebool -P httpd_can_network_connect 1
Então modifique sua configuração externa do nginx de proxy via nginx.http.sock para http://127.0.0.1:8008 (ou sua porta escolhida) e limpe o cabeçalho padrão Connection: close, para que o nginx externo não precise estabelecer uma nova conexão IP para cada requisição.
...
location / {
proxy_pass http://127.0.0.1:8008;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
# Disable default "Connection: close"
proxy_set_header "Connection" "";
...
Remover web.socketed.template.yml também removeu a invocação real_ip, então adicione isso de volta. Certifique-se de que a faixa de endereços IP que você usa faça sentido; o padrão do Docker é usar o espaço de endereços RFC1918 172.16* que não são roteados na internet pública por política. Adicione ao seu arquivo app.yml algo como isso na seção de execução, selecionando uma ou mais das faixas de endereços RFC1918 ou qualquer outra coisa apropriada para sua implantação:
run:
- file:
path: /etc/nginx/conf.d/outlets/server/real-ip-recursive.conf
chmod: 644
contents: |
real_ip_recursive on;
- file:
path: /etc/nginx/conf.d/outlets/server/real-ip-header.conf
chmod: 644
contents: |
real_ip_header X-Forwarded-For;
- file:
path: /etc/nginx/conf.d/outlets/server/set-real-ip-from.conf
chmod: 644
contents: |
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 10.0.0.0/8;
Isso é necessário para que a limitação de taxa funcione corretamente, bem como para atribuir endereços IP de registro e último uso para usuários.
Para mais informações:
Serviço externo
Eu não configurei Fastly ou Cloudflare na frente do Discourse, mas outros fizeram, e ao contrário do nginx externo executando no host, eles podem permitir que você sirva uma página de manutenção enquanto o sistema host está completamente fora, como ao reiniciar durante uma atualização do sistema no seu host. Se isso for valioso para você, aqui está como fazer:
Não corra para uploads S3
Tenha certeza absoluta de que sempre quer usar S3 (ou equivalente) para imagens carregadas antes de habilitar enable_s3_uploads durante a configuração, ou migrar para isso mais tarde. Esteja ciente de que usar S3 (s3_endpoint) com seu CDN associado (s3_cdn_url) para imagens também resultará em servir javascript via esse CDN. Migrar de S3 de volta para armazenamento local não é suportado e não há planos concretos para implementá-lo neste momento. É uma “porta de mão única” que nem mesmo pode ser desfeita por um backup e restauração completos. Se você usar S3 ou similar, não use Digital Ocean Spaces em vez de S3. Há referências aqui no meta sobre não ser confiável.
Movi meu site para servir imagens através do Digital Ocean Spaces e seu CDN associado no início, e tive que escrever centenas de linhas de código personalizado para migrar de volta para armazenamento local, causando danos menores à minha instância do Discourse no processo, devido à “porta de mão única” não ser bem compreendida.
Para mais informações:
Você não precisa habilitar uploads S3 para usar um CDN para seu Discourse. Considere usar um CDN independente (por exemplo, Cloudflare, CloudFront, Fastly, GCS CDN) na frente de um Discourse que gerencia suas próprias imagens. É minha compreensão de segunda mão que o aviso sobre Cloudflare não ser recomendado é devido ao “Rocket Loader” modificando JavaScript; e que neste momento, desde que você não use “Rocket Loader”, funciona corretamente.
Configurações do Discourse para moderação
Em qualquer site onde a moderação esteja ativa, considere fortemente a configuração enable_whispers que permite que moderadores e administradores conversem sobre um tópico em linha. Além disso, moderadores de categoria receberam mais habilidades em versões recentes do Discourse. Vale a pena estar ciente de enable_category_group_moderation se você tiver especialistas em diferentes tópicos com suas próprias categorias, ou se você tiver categorias funcionalmente separadas como para suporte.
A geolocalização pode ser útil ao tentar entender se uma conta é legítima.
O recurso Discourse Templates é realmente útil para moderadores. Permite que você colabore em respostas comuns. Temos algumas dezenas no Maker Forums. Tem mais recursos do que o plugin anterior “Canned Responses” que ele substitui.
O recurso User Notes ajudará moderadores a compartilhar notas sobre usuários. Você pode usar isso para coisas como:
- “Fique de olho neste usuário, eles podem ser maliciosos porque…”
- “Embora este comportamento pareça suspeito, validei que este é um usuário legítimo por…”
- “Já estou tendo uma conversa com este usuário para abordar preocupações, outros moderadores não precisam se juntar.”
Acessibilidade de Informações
O plugin Discourse Solved não apenas marca problemas resolvidos para que os visitantes do site possam identificá-los mais facilmente, mas entendo que também pode priorizar resultados de pesquisa do google.
Informações públicas são mais acessíveis do que informações privadas. No Maker Forums, nosso FAQ desencoraja fortemente mensagens pessoais e lembra a todos que mensagens pessoais não são realmente privadas. No entanto, por padrão, os usuários podem ver a mensagem:
Você respondeu ao usuário 3 vezes, sabia que poderia enviar uma mensagem pessoal a eles?
Se você realmente quiser encorajar os usuários a irem para mensagens pessoais, sugiro que você vá para Admin → Customize → Text e mude o modelo get_a_room para corrigir o erro de vírgula.
Se, como o Maker Forums, você quiser manter a conversa em público para beneficiar todos, Admin → Settings → Other → get_a_room_threshold pode ser definido mais alto, como 1000000.
Da mesma forma, se você tiver um fórum fornecendo ajuda, o padrão max_replies_in_first_day 10 pode empurrar novos usuários em uma conversa pedindo ajuda para mensagens pessoais quando usarem seu orçamento de respostas. Considere aumentar esta configuração para evitar empurrar conversas para mensagens pessoais.
Conecte usuários, construa uma comunidade
Alguns plugins podem ajudar a conectar usuários entre si.
Se seu fórum não tiver muitos usuários simultâneos, considere o plugin Who’s Online para dar às pessoas mais sensação de conexão. Você pode querer limitar a exibição a usuários logados, possivelmente apenas aqueles que atingiram pelo menos o nível de confiança 1. Você pode usá-lo apenas para adicionar presença flair (whos_online_avatar_indicator) aos avatares definindo whose_online_minimum_display muito alto e whos_online_hide_below_minimum_display true. Isso pode ser útil para fóruns de suporte para apoiar e encorajar perguntas e respostas rápidas enquanto ajuda os usuários a resolver problemas.
No entanto, uma sensação de presença pode cortar em ambas as direções. Um usuário que está online em um horário diferente da maioria dos usuários do fórum pode se sentir sozinho, ou o fórum pode parecer uma “cidade fantasma” para eles.
Se você tiver usuários em muitos países e quiser que eles tenham dicas sobre quando uns aos outros estão mais provavelmente disponíveis, considere o plugin National Flags, e encoraje os usuários a definir uma bandeira nacional em seu perfil.
Um complicado é tradução. Seria conveniente ajudar as pessoas a se comunicarem quando não falam o mesmo idioma, mas atualmente (até a data desta escrita) não há serviços de tradução com níveis gratuitos de serviço. Se você escolher pagar por serviços de tradução, você pode habilitar tradução com o plugin Discourse Translator.
Backup
Para arquivos do sistema, considere fazer backup pelo menos de:
/var/discourse/containers(para detalhes de configuração do discourse)/var/www(para páginas de erro)/etc/ssl(para configuração letsencrypt, para evitar ter que inicializar o certbot como parte de restaurar um backup; caso contrário você tem que comentar a porção SSL da sua configuração nginx enquanto está inicializando; isso funciona apenas se você mantiver os backups recentes porque os certificados têm validade curta)/etc/systemd/system/backup-uploads.service(para fazer backups de imagens para S3)/usr/local/bin/mc(minio-client como ferramenta de backup de imagem, se você escolher usá-lo)/root/.mc(configuração para backup de imagem com minio-client)/root/.ssh(autenticação de sessão SSH entrante)
Alguns desses arquivos você pode fazer backup verificando-os no Git e empurrando para algum lugar fora do site. Se os arquivos que você verificar no Git incluírem segredos (como senhas de banco de dados), definitivamente não os empurre para um repositório público. Alternativamente, você poderia scriptar copiá-los do sistema e verificá-los no Git em um sistema de supervisão que você controle. Scripte isso com frequência suficiente para manter seus backups de /etc/ssl frescos.
O objetivo é ter backups tanto em caso de desastre quanto para ter registro de mudanças em caso de erro.
Uma alternativa melhor para a maioria desses arquivos é manter as cópias canônicas em outro lugar, e usar uma ferramenta como Ansible para manter a configuração no sistema, o que torna tão fácil atualizar após um backup. Mas se você for fazer isso, você provavelmente descobriu sem eu dizer!
Configuração do Discourse para backup
-
Faça backup de miniaturas com
include_thumbnails_in_backups. Uma restauração sem miniaturas leva muito tempo para regenerá-las. Se seu site não tiver muitas imagens, as miniaturas ocupam espaço insignificante. Se seu site for rico em imagens, regenerar miniaturas pode levar dias. Enquanto as miniaturas estão sendo regeneradas, as notificações por e-mail serão desativadas. De qualquer forma, não faz sentido omitir miniaturas dos backups. -
Não inclua imagens nos backups se você tiver muitas imagens. Isso tornará os backups lentos e desajeitados. Faça backup deles separadamente. Se você fizer backup de imagens após o backup do banco de dados, seus backups serão consistentes.
-
Organize para que os backups vão para fora do site de alguma forma.
Esta página mostra como configurar backups de banco de dados para S3 ou algo como S3:
Faça backup com restic
Configure o discourse para fazer backup para o sistema de arquivos, então faça backup do sistema de arquivos para um destino de backup remoto com restic. Aqui está uma receita de exemplo.
# dnf install restic
# mkdir /var/restic
# mkdir /opt/backup
# cd /opt/backup
# cat > backup <<EOF
#!/usr/bin/bash
set -e
. /opt/backup/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, portanto, leia a documentação do restic.
# cat > backup-config <<EOF
### Esses detalhes dependem de qual destino do restic você configura, então altere-os
export AWS_ACCESS_KEY_ID=seu-aqui
export AWS_SECRET_ACCESS_KEY=igual
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 colocar em /root/restic-password, caso contrário, não conseguirá ler os backups! Use seu cofre de senhas.
Por fim, crie alguns serviços, inicialize o repositório restic e defina um timer para que os backups comecem.
# cat > /etc/systemd/system/backup.service <<EOF
[Unit]
Description=Back up to remote target
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=Regular system backups
[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
Eu 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 imagem 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 imagem 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 (Permissions → Block public access é 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 semelhante a 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 assim
[Unit]
Description=Neartime remote backup sync of discourse uploads
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 padrão de vários contêineres.
# 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 para backup bem-sucedido das imagens originais e otimizadas. Control-C sairá do modo de acompanhamento no journalctl.
Recuperação
Eu nunca tive que testar esse plano até o momento desta escrita. Este resumo pode perder algo.
- Restaurar todos os arquivos backupados em geral
- Iniciar 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 mais recente do banco de dados; recomendo que você Restore a backup from the command line
- Somente 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 habilitar o uso de arquivamento WAL contínuo para transmitir backups do Postgres quase instantâneos com minio-client usando o archive-command no postgresql, semelhante aos backups de uploads em streaming.
Monitoramento de desempenho
Há pelo menos duas abordagens para monitoramento de desempenho.
Contêiner 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 maneira, uma opção seria a configuração do nginx assim:
location /prometheus/ {
auth_basic "Prometheus";
auth_basic_user_file /etc/nginx/prometheus-htpasswd;
proxy_pass http://localhost:9090/;
}
Sysstat
Se Prometheus for demais, considere usar 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 pode dizer 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.