비공개 캘린더 이벤트용 인증된 ICS 피드

공개 ICS 내보내기가 최근 다음과 같은 방식으로 다시 도입되었습니다.

GET /discourse-post-event/events.ics

이는 전체 ICS 내보내기 재추가 작업 이후 훌륭한 개선 사항입니다.

현재 이 엔드포인트는 익명 사용자에게 표시되는 이벤트로 제한되어 있는 것으로 보입니다. 그 결과, 비공개 카테고리나 기본 everyone 그룹에서 제한된 카테고리 내의 이벤트는 외부 캘린더 클라이언트(예: Google 캘린더, Outlook)에서 구독할 수 없습니다.

Discourse가 비공개 RSS/Atom 피드를 처리하는 방식과 유사하게, 이 엔드포인트에 대한 인증된 액세스(예: 사용자별 토큰 또는 읽기 전용 API 키를 통해)를 지원하는 것이 가능한지 궁금합니다.

이것은 권한 규칙을 변경하지 않으며, 단순히 캘린더 클라이언트가 사용자가 이미 액세스 권한을 가진 이벤트에 접근할 수 있도록 하는 것입니다.

이전 제안에 따라, 공개 ICS 피드 재도입 이후에 별도로 범위가 명확한 요청으로 이 문제를 제기합니다.

1개의 좋아요

코드를 꼼꼼히 살펴본 끝에, User API Key를 생성하고 API에 전달하는 데 필요한 여러 장벽을 처리하는 매우 단순한 프록시를 직접 구현했습니다. 또한 사용자가 캘린더 앱에 붙여넣어야 하는 링크도 생성합니다:

언젠가 이 모든 것이 Discourse 코드로 통합되어 더 이상 필요 없기를 바랍니다. 그 때까지는 다른 분들의 삶을 좀 더 쉽게 만들어 드리고자 이 내용을 공유합니다.

저는 이번 주早些에 이 PR에서 해당 기능을 추가했습니다. 하지만 비기술 사용자에게 사용자 API 키 생성의 사용성이 좋지 않습니다. 이를 원활하게 만들기 위해 다음을 후속 조치로 진행 중입니다:

이 PR은 이를 최대한 친숙하게 만들려고 시도하고 있습니다.

1개의 좋아요

방금 이 기능을 병합했는데 @Ethsim2 님, 한번 테스트해 보실 수 있을까요?

1개의 좋아요

감사합니다 - 인증된 피드 자체가 제 쪽에서 이제 제대로 생성되고 있음을 확인했습니다.

남은 문제는 클라이언트 호환성으로 보입니다. Google Calendar이나 Outlook 모두 현재 이 형태의 인증된 ICS 피드에 직접 구독하는 것을 지원하지 않는 것 같아, 당분간 단일 컨테이너 Discourse 설치 앞에 호스트 레벨 Nginx 리버스 프록시를 두고, 대신 거기서 일반 .ics 파일을 서빙하는 방식으로 우회할 계획입니다.

표준 단일 컨테이너 구성을 사용하고 있으므로, 이는 컨테이너에서 포트 80/443을 해제하고, Discourse가 내부 고(高) 포트에서 리스닝하도록 한 뒤, 호스트 Nginx가 포럼을 프록시하고 정적 캘린더 피드 경로를 서빙하도록 하는 것을 의미할 것으로 생각합니다.

예상되는 명령어는 대략 다음과 같습니다:

# 1. 호스트 nginx + certbot 설치
sudo apt update
sudo apt install -y nginx snapd
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -sf /snap/bin/certbot /usr/bin/certbot

# 2. 포트 80/443을 해제할 수 있도록 Discourse 컨테이너 중지
cd /var/discourse
sudo ./launcher stop app

# 3. 컨테이너 설정을 편집하여 Discourse가 더 이상 80/443에 직접 바인딩하지 않도록 함
sudo nano /var/discourse/containers/app.yml

그런 다음 app.yml에서 expose 섹션을 다음에서:

expose:
  - "80:80"
  - "443:443"

다음과 같이 변경합니다:

expose:
  - "127.0.0.1:8080:80"

그리고, 존재한다면 컨테이너 SSL / Let’s Encrypt 템플릿을 제거하여 TLS가 호스트 리버스 프록시에서 종료되도록 합니다.

그리고 재빌드합니다:

cd /var/discourse
sudo ./launcher rebuild app

그리고 다음과 같은 호스트 레벨 Nginx 사이트를 생성합니다:

sudo nano /etc/nginx/sites-available/discourse

다음과 같은 내용으로:

server {
    listen 80;
    listen [::]:80;
    server_name forum.example.com;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /private-calendar/ethan.ics {
        alias /var/www/private-calendar/ethan.ics;
        default_type text/calendar;
        add_header Content-Type "text/calendar; charset=utf-8";
    }
}

활성화하고 재로드합니다:

sudo mkdir -p /var/www/private-calendar
sudo mkdir -p /var/www/certbot
sudo ln -s /etc/nginx/sites-available/discourse /etc/nginx/sites-enabled/discourse
sudo nginx -t
sudo systemctl reload nginx

그리고 Certbot으로 Let’s Encrypt 인증서를 발급받고 Nginx 구성이 업데이트되도록 합니다:

sudo certbot --nginx -d forum.example.com
sudo nginx -t
sudo systemctl reload nginx

그 후, Nginx 구성에는 일반적으로 HTTPS 서버 블록도 포함되게 됩니다. 예:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name forum.example.com;

    ssl_certificate /etc/letsencrypt/live/forum.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/forum.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /private-calendar/ethan.ics {
        alias /var/www/private-calendar/ethan.ics;
        default_type text/calendar;
        add_header Content-Type "text/calendar; charset=utf-8";
    }
}

그 시점에 호스트에서 스크립트/타이머를 사용하여 인증된 Discourse ICS를 가져와서 다음을 작성할 수 있습니다:

/var/www/private-calendar/ethan.ics

Google Calendar / Outlook은 이를 일반 공개 ICS URL로 구독할 수 있습니다.

따라서 제 관점에서 Discourse 쪽은 이제 해결된 것으로 보입니다. 실질적으로 남은 간극은 주로 주요 캘린더 클라이언트가 인증된 ICS 피드를 잘 처리하지 못한다는 점이며, 이것이 제가 당분간 공개 프록시/정적 파일 방식으로 전환하는 이유입니다.

또한 Certbot이 여기서 가장 단순한 경로라고 가정합니다. 왜냐하면 호스트 Nginx에 대해 Let’s Encrypt 발급/갱신을 직접 관리할 수 있기 때문입니다. acme.sh를 사용할 수도 있지만, 제 인상으로는 이 특정 설정에 대해 가장 직관적인 경로보다는 수동 선택에 가까울 것 같습니다.

무슨 말씀이세요?

저는 Google 캘린더와 함께 잘 사용하고 있으며, 제 동료 중 몇 명도 마찬가지입니다.

Google 캘린더와 호환되지 않는 부분이 대체 어디에 있죠!?

아 - 감사합니다. 이렇게 하면 범위를 좁힐 수 있겠네요.

제 쪽에서는 Google 캘린더가 구독 URL을 정상적으로 받아들이고 있습니다(“URL에서” 옵션을 통해). 다만 제가 확인한 동작은 다음과 같습니다:

  • 캘린더는 정상적으로 추가됩니다.
  • 그러나 사건이 전혀 표시되지 않습니다.

즉, URL이 거부되는 문제는 아닙니다. Google의 관점에서 피드가 비어 있는 것처럼 보이는 것입니다.

원본 ICS 파일에 분명히 VEVENT 항목(예: UID, DTSTART, SUMMARY 등)이 포함되어 있으므로, 다음과 같은 문제일 가능성이 있다고 생각합니다:

  • Google이 과거 이벤트를 필터링하고 있는 경우(제 테스트 데이터 대부분이 과거 데이터이기 때문)
  • 또는 피드가 해석되는 방식에 문제가 있는 경우(예: 시간 범위, 캐싱, 헤더 등)

피드 자체에서 특별히 확인해 보셨으면 하는 부분이 있다면 알려 주세요.

2개의 좋아요

/logs에서 오류를 확인해 보시겠어요? 방금 구식 반복 이벤트로 인해 피드가 실패하는 오류를 수정했습니다.

같은 오류였다면 업데이트가 필요합니다.

Discourse AI 토큰 한도와 관련된 경고/오류가 많아서, 오후 7시보다 이전으로 거슬러 올라가서 찾아봐야 할 것 같습니다.

1개의 좋아요
1개의 좋아요