Olá, estou tentando instalar o Discourse usando o processo padrão ./discourse-setup, mas estou encontrando um erro durante o bootstrap:
FAILED
--------------------
Errno::ENOENT: No such file or directory @ rb_sysopen - /etc/runit/1.d/letsencrypt
Location of failure: /usr/local/lib/ruby/gems/3.3.0/gems/pups-1.3.0/lib/pups/replace_command.rb:11:in `read'
replace failed with the params {"filename"=>"/etc/runit/1.d/letsencrypt", "from"=>"/--keylength/", "to"=>"-d forum.mysite.org --keylength"}
bootstrap failed with exit code 1
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
Parece que o erro é acionado por um plugin que tenta executar um comando replace no arquivo /etc/runit/1.d/letsencrypt, que não existe dentro do contêiner durante o bootstrap. A linha relevante no plugin se parece com isto:
- replace:
filename: "/etc/runit/1.d/letsencrypt"
from: "/--keylength/"
to: "-d forum.mysite.org --keylength"
Algum conselho sobre como corrigir isso ou regenerar adequadamente o arquivo ausente?
Um plugin? Esse é o código cups do seu app.yml, certo? Você está tentando adicionar outro certificado? Como em Set up Let’s Encrypt with multiple domains / redirects Você pode incluir o código real e ambos os certificados?
Como você apontou, esse runit não existe mais, e agora essa mágica está em /usr/local/bin/letsencrypt (dentro do contêiner)
Eu acho que você pode querer algo como isso se o seu site for www.mysite.org e você também quiser que ele tenha um certificado para forum.mysite.org:
O que eu faria (o que pode não ser útil para você) é entrar no contêiner, apt update;apt install -y vim e então editar /usr/local/bin/letsencrypt de forma que ele solicite os certificados que você deseja.
Adicionei código ao tópico let’s encrypt vinculado acima que deve permitir que você insira seu domínio e obtenha código que você pode copiar/colar em seu app.yml.
Não me lembro de ter colocado esse código lá, embora eu tivesse configurado meu site para usar letsencrypt para os certificados de segurança gratuitos, mas as instruções em Set up HTTPS support with Let's Encrypt não parecem exigir essas linhas, então não faço ideia para que teriam servido.
Alguma outra coisa poderia ter potencialmente gravado essas linhas no app.yml? Por exemplo, poderiam ter sido adicionadas durante uma atualização beta?
Pelo menos por enquanto, com essas linhas removidas, meu site está funcionando novamente e atualizado.
Quando meu certificado SSL atual expirar, acho que descobrirei para que serviam essas linhas extras.
Se você tem essa seção after_ssl no seu arquivo yml, então em algum momento você configurou as coisas de forma que, se alguém colocasse um www na frente do seu domínio, ele iria para o endereço www e seria redirecionado para o endereço não-www sem um erro de certificado.
Minha sugestão foi instalar o vim dentro do container e tentar mexer nos arquivos lá, mas acho que meu código para adicionar ao app.yml deve funcionar.
Você poderia ir ao link acima e obter o novo código que eu acho que deve funcionar, mas não testei, pois não encontrei um site que estou atualizando que precise dele.
Estou correto em pensar que seu código seria algo como as linhas abaixo, se eu quiser que www.nzarchitecture.net.nz seja coberto pelo mesmo certificado letsencrypt que nzarchitecture.net.nz?
Eu tentei adicionar esta seção (ótima terminologia, obrigado!) ao final de app.yml, em vez da seção original ‘after_ssl:’, e agora consigo reconstruir o Discourse sem erros - mas isso não parece me ajudar; meu navegador ainda exibe uma resposta ‘net::ERR_CERT_COMMON_NAME_INVALID’ se eu tentar usar um prefixo ‘www’ antes do meu domínio principal/certificado nzarchitecture.net.nz
Meu app.yml completo abaixo, caso ajude em alguma coisa (senha e endereços de e-mail omitidos)
## este é o template completo e independente do container Docker do Discourse
##
## Após fazer alterações neste arquivo, VOCÊ DEVE reconstruir
## /var/discourse/launcher rebuild app
##
## TENHA MUITO CUIDADO AO EDITAR!
## ARQUIVOS YAML SÃO SUPER SUPER SENSÍVEIS A ERROS DE ESPAÇAMENTO OU ALINHAMENTO!
## visite http://www.yamllint.com/ para validar este arquivo conforme necessário
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
- "templates/web.ratelimited.template.yml"
## Descomente estas duas linhas se desejar adicionar Lets Encrypt (https)
- "templates/web.ssl.template.yml"
- "templates/web.letsencrypt.ssl.template.yml"
- "templates/import/mysql-dep.template.yml"
## quais portas TCP/IP este container deve expor?
## Se você quiser que o Discourse compartilhe uma porta com outro servidor web como Apache ou nginx,
## veja https://meta.discourse.org/t/17247 para detalhes
expose:
- "80:80" # http
- "443:443" # https
params:
db_default_text_search_config: "pg_catalog.english"
## Defina db_shared_buffers para um máximo de 25% da memória total.
## será definido automaticamente pelo bootstrap com base na RAM detectada, ou você pode substituir
db_shared_buffers: "128MB"
## pode melhorar o desempenho da ordenação, mas adiciona uso de memória por conexão
#db_work_mem: "40MB"
## Qual revisão Git este container deve usar? (padrão: tests-passed)
#version: tests-passed
env:
LANG: en_US.UTF-8
# DISCOURSE_DEFAULT_LOCALE: en
## Quantas requisições web concorrentes são suportadas? Depende da memória e dos núcleos da CPU.
## será definido automaticamente pelo bootstrap com base nas CPUs detectadas, ou você pode substituir
UNICORN_WORKERS: 2
## TODO: O nome de domínio que esta instância do Discourse responderá
## Obrigatório. O Discourse não funcionará com um número IP puro.
DISCOURSE_HOSTNAME: nzarchitecture.net.nz
## Descomente se você quiser que o container seja iniciado com o mesmo
## nome de host (-h option) especificado acima (padrão "$hostname-$config")
#DOCKER_USE_HOSTNAME: true
## TODO: Lista de e-mails separados por vírgula que serão feitos administradores e desenvolvedores
## na inscrição inicial exemplo 'user1@example.com,user2@example.com'
DISCOURSE_DEVELOPER_EMAILS: '****************'
## TODO: O servidor de e-mail SMTP usado para validar novas contas e enviar notificações
# ENDEREÇO SMTP, nome de usuário e senha são necessários
# AVISO o caractere '#' na senha SMTP pode causar problemas!
DISCOURSE_SMTP_ADDRESS: smtp.mailgun.org
DISCOURSE_SMTP_PORT: 587
DISCOURSE_SMTP_USER_NAME: ****************
DISCOURSE_SMTP_PASSWORD: "****************"
#DISCOURSE_SMTP_ENABLE_START_TLS: true # (opcional, padrão true)
## Se você adicionou o template Lets Encrypt, descomente abaixo para obter um certificado SSL gratuito
LETSENCRYPT_ACCOUNT_EMAIL: ******************
## O endereço CDN http ou https para esta instância do Discourse (configurado para puxar)
## veja https://meta.discourse.org/t/14857 para detalhes
#DISCOURSE_CDN_URL: https://discourse-cdn.example.com
## O container Docker é sem estado; todos os dados são armazenados em /shared
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
- volume:
host: /var/discourse/shared/standalone/log/var-log
guest: /var/log
## Plugins vão aqui
## veja https://meta.discourse.org/t/19157 para detalhes
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
- git clone https://github.com/discourse/discourse-bbcode.git
## Quaisquer comandos personalizados para executar após a construção
run:
- exec: echo "Início dos comandos personalizados"
## Se você quiser definir o endereço de e-mail 'De' para seu primeiro registro, descomente e altere:
## Após receber o primeiro e-mail de inscrição, comente a linha novamente. Ela só precisa ser executada uma vez.
#- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
- exec: echo "Fim dos comandos personalizados"
after_ssl:
- replace:
filename: /usr/local/bin/letsencrypt
from: /-d nzarchitecture.net.nz /
to: "-d nzarchitecture.net.nz -d www.nzarchitecture.net.nz "
global: true
O fato de não haver arquivos em /usr/local/bin/ é parte do problema?
Onde encontro o arquivo letsencrypt correto para colocar lá, se é isso que é necessário?
E, se ‘letsencrypt’ for o nome do arquivo no final desse caminho, é normal que não haja extensão de arquivo como parte deste nome de arquivo?
Adicionar isto à seção run na parte inferior do seu app.yml resolverá o problema de fazer com que /usr/local/bin/letsencrypt solicite certificados para DISCOURSE_HOSTNAME e www.DISCOURSE_HOSTNAME.
- exec: sed -i "s|-d \\${DISCOURSE_HOSTNAME}|-d \\${DISCOURSE_HOSTNAME} -d www.\\${DISCOURSE_HOSTNAME}|g" /usr/local/bin/letsencrypt
Isto (de alguma forma?) costumava ser suficiente, mas agora, quando o pedido chega para http://www.HOSTNAME/.well-known…, ele é redirecionado para o site não-www em vez de enviar o desafio que deveria enviar. Eu tentei fazer algo como isto:
server {
listen 80;
listen [::]:80;
server_name nzarchitecture.net.nz www.nzarchitecture.net.nz;
# Serve o desafio ACME (Let's Encrypt)
location ^~ /.well-known/acme-challenge/ {
root /var/www/discourse/public; # Certifique-se de que isto corresponda à sua webroot do Let's Encrypt
allow all;
}
# Redireciona todo o resto para HTTPS
location / {
return 301 https://$host$request_uri;
}
}
mas não descobri completamente.
Se alguém da equipe estiver ouvindo, seria bom se houvesse um hook do letsencrypt para que isso pudesse ser chamado em um after_letsencrypt. Antes de fazer essas alterações em after_ssl funcionava, mas parece que agora, se fizermos isso, ele é executado após o ssl, mas antes do letsencrypt.
Meu DISCOURSE_HOSTNAME é www.textkit.com. Estou fazendo o oposto de nzarchitecture.net.nz e adicionando um hostname sem www ao meu certificado. Isso funcionou para mim:
- exec: sed -i \"s|-d \\${DISCOURSE_HOSTNAME}|-d www.textkit.com -d textkit.com|g\" /usr/local/bin/letsencrypt
Não consigo dizer por que @pfaffman e nzarchitecture.net.nz estariam tendo problemas com a versão dele, embora talvez a ordem do hostname na minha seja relacionada.
Ah! Legal. Talvez a alteração que eles fizeram, que permitiu que as renovações de certificado funcionassem, também resolveu o problema que eu estava enfrentando.
Vou me lembrar disso se encontrar outros sites que precisem disso antes que o PR seja aceito.
Não, não é. Não há muita diferença entre as instâncias (temas/plugins/configurações semelhantes), exceto que uma instância é bem mais antiga que a outra.
Meu certificado LetsEncrypt acabou de expirar ontem sem renovação automática. Não tenho certeza se isso tem algo a ver com as alterações sugeridas no app.yml que fiz de acordo com este tópico acima, ou com atualizações subsequentes do Discourse.
Com assistência de IA (sim, eu sei!) consegui fazê-lo renovar, depois de seguir a IA por vários becos sem saída envolvendo o uso de ngix e certbot (o que acabou funcionando, para ser justo), antes de reverter essas alterações e voltar ao método padrão gerenciado pelo Discourse. No processo, tive que reconstruir algumas vezes, então não tenho certeza se foi isso que acionou a renovação.
Desculpe pelo transtorno - estou curioso, quando foi a última vez que você reconstruiu antes desta?
Acabamos de verificar e testar o processo de renovação novamente, mas não conseguimos reproduzir - nossos testes renovam corretamente, então ou algo não está acontecendo do nosso lado, ou há algo diferente na forma como a renovação do staging versus a produção do Let’s Encrypt funciona.
Também posso confirmar que reconstruir seu site força o processo de renovação a ocorrer, se tudo mais falhar.
Usamos o acme.sh por baixo dos panos (em /opt/acme.sh no contêiner) - se você estiver inclinado, pode entrar no contêiner docker em execução e executar o script para inspecionar/renovar por lá também.