설치 후 포트 443/80이 닫혀 있음으로 표시됨

안녕하세요,
저는 Proxmox VE(가상 환경)의 Ubuntu 22.04.4 서버에서 첫 Discourse 설치를 방금 마쳤습니다.
설정은 오류 없이 잘 진행되었지만, 설치를 마친 후 포럼 사이트가 열리지 않으며 서비스가 접근할 수 없다는 메시지가 표시됩니다.

네트워크에서 확인했을 때 포트가 닫혀 있는 것으로 보입니다:

PS C:\Users\mwojt> nmap 192.168.131.211
Nmap scan report for 192.168.131.211

PORT    STATE  SERVICE
22/tcp  open   ssh
80/tcp  closed http
443/tcp closed https

하지만 Ubuntu 머신 내부에서 localhost에 대해 동일한 명령을 실행하면 포트가 열려 있는 것으로 표시됩니다:

root@ubuntu-discourse:~# nmap localhost
Nmap scan report for localhost (127.0.0.1)

PORT    STATE SERVICE
22/tcp  open  ssh
80/tcp  open  http
443/tcp open  https

그러나 같은 Ubuntu VM에서 IP 주소를 대상으로 확인을 실행하면 다음과 같은 결과가 나옵니다:

root@ubuntu-discourse:~# nmap 192.168.131.211
Nmap scan report for ubuntu-discourse (192.168.131.211)

PORT    STATE    SERVICE
22/tcp  open     ssh
80/tcp  filtered http
443/tcp filtered https

즉, 포트가 필터링된 상태로 표시됩니다.
방화벽에서는 포트가 열려 있습니다:

root@ubuntu-discourse:~# ufw status
Status: active

To                         Action      From
--                         ------      ----
80                         ALLOW       Anywhere
443                        ALLOW       Anywhere
22                         ALLOW       Anywhere
80 (v6)                    ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)
22 (v6)                    ALLOW       Anywhere (v6)

그리고 Docker 포트 포워딩도 올바르게 설정되어 있는 것으로 보입니다:

root@ubuntu-discourse:~# docker port 6922c7802903
80/tcp -> 0.0.0.0:80
80/tcp -> [::]:80
443/tcp -> 0.0.0.0:443
443/tcp -> [::]:443

제가 무엇을 잘못하고 있을까요? 문제가 어디에 있을까요?

다시 90분 동안 Discourse 설치에 시간을 보냈습니다. 이번에는 가상 환경을 배제하기 위해 별도의 물리적 머신에서 시도했는데, GitHub의 지침을 꼼꼼히 따랐음에도 동일한 문제가 발생했습니다.

이걸 제대로 동작시키는 게 정말 불가능한 건가요??

문제가 상대방 쪽에 있는 것일까요? 제 정상 작동 중인 Discourse 인스턴스에서도 질문자님과 매우 유사한 결과를 확인하고 있습니다.

Browserling 같은 프록시를 통해 인스턴스에 접근해 볼 수 있을까요?

수정: 잠깐, 질문자님의 주소 192.168.131.211은 로컬 주소입니다. 외부에서 접근이 가능할 것으로 예상되지 않습니다.

수정: discourse 호스트에서 netstat -rn을 실행하면 어떤 결과가 보이나요?

제 netstat 출력 결과는 다음과 같습니다:

root@ubuntu-forum:/var/discourse# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.131.1   0.0.0.0         UG        0 0          0 enp1s0
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 docker0
192.168.130.0   0.0.0.0         255.255.254.0   U         0 0          0 enp1s0
192.168.131.1   0.0.0.0         255.255.255.255 UH        0 0          0 enp1s0
192.168.131.152 0.0.0.0         255.255.255.255 UH        0 0          0 enp1s0

Ubuntu에서 Discourse를 설치한 것 외에, Debian에는 Talkyard를 설치했습니다. (Talkyard는 Discourse와 약간 유사한 포럼 엔진입니다) 이 역시 Docker로 설치했으며, 아주 잘 작동하고 있습니다. 그래서 Discourse도 Debian에 설치해 보려고 합니다.

제 Debian의 Netstat -rn 출력 결과는 다음과 같습니다:

root@debian-12:~# netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.131.1   0.0.0.0         UG        0 0          0 ens18
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 docker0
172.26.0.0      0.0.0.0         255.255.255.128 U         0 0          0 br-886bebfa13ae
192.168.130.0   0.0.0.0         255.255.254.0   U         0 0          0 ens18

이 정보가 도움이 될지 잘 모르겠습니다.

Discourse는 도메인을 통해 접근할 때만 제대로 작동하는 것 같습니다. 브라우저와 도메인을 사용하여 사이트를 접근할 수 있는 설정이 있으신가요? 완전히 로컬 LAN 내에서만 작업하고 계시다면 hosts 파일을 통해 그렇게 할 수 있을지 모르겠습니다. 서버와 클라이언트(그리고 아마도 docker도)가 모두 이름 조회(name lookup)를 수행할 수 있어야 한다고 생각합니다.

로컬 DNS 서버가 내 네트워크 이름을 해당 호스트로 해석하도록 설정되어 있어서, 외부에서도 작동하는 것과 동일한 방식으로 동작합니다.

방금 DigitalOcean VM에 Discourse를 성공적으로 설치했습니다. 이 설치 환경을 로컬 설정의 참고 자료로 사용할 예정입니다. 바로 눈치챈 한 가지가 있는데, VM의 hosts 파일에 다음 항목이 포함되어 있습니다:

이것이 문제의 원인이기를 바랍니다. 결과를 알려드리겠습니다.

아니, 실패… 3일 동안 씨름한 끝에 완전히 지쳐버렸어요… :slightly_frowning_face:
게스트 호스팅이 아닌 로컬 머신에 Discourse를 설치하는 것이 불가능하지 않을까 하는 생각이 들기 시작하네요 :frowning:

설치하면서 녹화한 이 영상을 확인해 주세요. 제가 어디서 잘못하고 있는지 알려주시면 감사하겠습니다.

서버에서
lsof -i
를 실행해 보는 것이 좋을 수도 있습니다.

Discourse는 실행 중이지만 네트워크 상황 때문에 접근할 수 없는 것 같습니다.

음, 원인을 찾았어요… 도커 로그를 확인해 보니 Let’s Encrypt 인증서를 가져오는 데 실패해서 nginx 서버가 아예 시작되지 않는다는 걸 알게 됐습니다 (첨부된 로그 참조)
docker_logs_not_working.txt (10.0 KB)

이제 어떻게 고칠지 알아봐야 합니다. 사실 저는 자체 SSL 인증서가 있는 리버스 프록시를 사용하고 있어서 SSL이 전혀 필요하지 않습니다. 그래서 포트 80을 통해 Discourse와 쉽게 통신할 수 있습니다. 다만 Discourse 서버가 이를 허용할지는 잘 모르겠습니다.

검색을 해보시면, 폐쇄형 환경(즉, 인트라넷)에서 로컬 설정이 실패하는 가장 흔한 이유가 이 때문임을 알게 될 것입니다. Discourse에는 SSL이 필요합니다.

제 DNS는 Cloudflare에서 호스팅되고 있으므로, 해당 API 키를 제공할 수 있기 때문에 LetsEncrypt 인증서를 쉽게 발급받을 수 있습니다. Discourse에서 ACME를 구성하여 인증서 프로비저닝이 원활하게 작동하도록 설정할 수 있을까요? 매뉴얼에서 관련 내용을 찾지 못했는데, 아마 제가 제대로 검색하지 못한 것 같습니다.

긴 고생 끝에 마침내 문제를 해결했습니다.

다음과 같은 작업을 수행해야 합니다:
SSH 세션에서 다음 명령을 실행하여 컨테이너 ID 또는 이름을 찾으세요:

docker ps

다음 명령을 사용하여 Docker 컨테이너의 셸에 액세스하세요.

docker exec -it [container_id or name] bash

Cloudflare API 키와 이메일을 환경 변수로 내보냅니다. 이렇게 하면 ‘acme.sh’ 스크립트가 DNS 챌린지에 필요한 DNS 레코드를 생성하고 삭제하기 위해 Cloudflare API와 인증할 수 있습니다. 저는 Cloudflare 계정의 실제 이메일 주소와 전역 API 키를 사용했습니다.

export CF_Key="your_cloudflare_global_api_key"
export CF_Email="your_cloudflare_email_address"

다음 디렉터리로 이동하세요:

cd /shared/letsencrypt

--issue 명령과 함께 acme.sh를 실행하고, DNS 챌린지 처리를 위해 dns_cf(DNS Cloudflare) 모드를 사용하도록 지정합니다. yourdomain.com은 인증서를 발급받으려는 도메인으로 교체하세요.

./acme.sh --issue --dns dns_cf -d yourdomain.com -d *.yourdomain.com

인증서가 성공적으로 생성되면 스크립트가 복사된 디렉터리를 표시합니다. 제 경우 다음과 같았습니다:

Your cert is in: /root/.acme.sh/sprawy.info.pl_ecc/sprawy.info.pl.cer
Your cert key is in: /root/.acme.sh/sprawy.info.pl_ecc/sprawy.info.pl.key
The intermediate CA cert is in: /root/.acme.sh/sprawy.info.pl_ecc/ca.cer
And the full chain certs is there: /root/.acme.sh/sprawy.info.pl_ecc/fullchain.cer

discourse.conf 파일을 편집하여 인증서 경로를 업데이트하세요:

nano /etc/nginx/conf.d/discourse.conf

기존의 ssl_certificate 및 ssl_certificate_key 줄은 다음과 같이 교체해야 합니다:

ssl_certificate /root/.acme.sh/sprawy.info.pl_ecc/sprawy.info.pl.cer;
ssl_certificate_key /root/.acme.sh/sprawy.info.pl_ecc/sprawy.info.pl.key;

이제 새 인증서 위치를 가리키도록 설정됩니다.

다음 명령을 실행하여 구성을 테스트하세요:

nginx -t

오류가 없다면 웹 서버를 다시 로드하세요:

nginx -s reload

그리고— 바로 성공입니다!

훌륭한 소식입니다. 문제를 해결해 주셔서 감사합니다. 참고로, Let’s Encrypt를 사용할 때 인증서 발급 요청이 여러 번 실패하면 일정 기간(아마도 7일 정도) 동안 요청이 차단됩니다. 따라서 요청을 올바르게 구성하는 데 주의를 기울이는 것이 좋습니다.