Obsidian에서 ghost blog로 글 보내기 (이미지까지!)

obsidian에서 ghost blog로 글과 이미지를 보내는 플러그인 제작

Obsidian에서 ghost blog로 글 보내기 (이미지까지!)

Summary

  • Obsidian 글을 Ghost 블로그로 이미지와 함께 전송하는 플러그인 제작.
  • Send-to-ghost 플러그인 수정, Nginx 설정 변경 통한 CORS 에러 해결.
  • 로컬 이미지 위키링크 지원, Feature Image Frontmatter 설정 기능 수정.
  • Ghost 블로그 전송용 ghost-upload-preview.md 생성, 인용구 오류 수정.

최근에 obsidian에 대해 알게 되면서 문서로 정리해야될 일이 있으면 obsidian을 사용하고 있다. 이렇게 작성한 글들을 블로그로 업로드하고 싶었는데 이미지까지 올라가는 플러그인은 존재하지 않았다. 그래서 직접 이미지까지 ghost 블로그로 업로드할 수 있는 플러그인을 제작하게 되었다. 아래의 블로그를 보고 동기부여와 큰 도움을 얻었고, 마찬가지로 send-to-ghost 플러그인을 수정하여 플러그인을 제작하였다.

옵시디언 노트를 고스트로 보내기 위한 빡센 여정
옵시디언의 AI 글쓰기 기능을 활용하여 글을 작성한 후, 고스트 블로그에 게시하기 위해 여러 플러그인을 시도했지만, 원활하게 작동하지 않았습니다. 결국, ‘Send to Ghost’ 플러그인을 직접 수정해서 사용하기로 했습니다. 고스트로 이미지 전송에 실패해서 N8N을 경유하기로 했습니다.

설치방법

첨부파일의 압축을 푼후 obsidian vault 폴더에서 /.obsidian/plugins로 이동후 압축파일의 내용을 복사 붙여넣기 해준다. 그 후 obsidian에서 커뮤니티 플러그인을 새로고침 한 후 실행시켜주면 된다.

Nginx 설정

이 플러그인을 설정하려면 nginx 설정을 바꿔줘야 한다. 따라서 self-hosted된 ghost 블로그에서만 사용이 가능하고 ghost 프로에서는 사용하기 어려울 것이다. 설정하지 않는다면 이미지를 올릴 때 교차 출처 리소스 공유 정책에 걸려서 업로드가 안된다고 나온다. 이는 Obsidian은 electron(웹브라우저) 기반 프로그램이라 발생하는 것으로 이에 대한 구체적인 설명은 다음에 하겠다. 이 글에서는 플러그인 사용방법만 다룬다.

  1. ghost를 호스팅하고 있는 서버에서 nginx 설정파일이 있는 곳으로 이동한다. 보통 /etc/nginx/sites-enabled 에 위치해 있을 것이고, 접속방식이 ssl인지 아닌지에 따라 (블로그 도메인)-ssl.conf을 수정할지, (블로그 도메인).conf를 수정할지가 나뉜다.
  2. 아래 코드 블록들을 복사하여 위 설정파일들에 붙여 넣어야한다. 첫번째 코드 블록은 설정파일 가장 위쪽에 붙여넣는다.
map $http_origin $allow_origin {
        default "";
        "app://obsidian.md" $http_origin;
}

두번째 코드 블록은 server 안, location 밖의 어딘가에 붙인다.

    location ~ ^/ghost/api/admin/images/upload {
        add_header 'Access-Control-Allow-Origin' $allow_origin;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;
        add_header 'Access-Control-Allow-Credentials' 'true';

        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' $allow_origin;
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Max-Age' 86400;
            add_header 'Content-Length' 0;
            return 204;
        }
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass http://127.0.0.1:2368;
    }
  1. nginx를 다시 시작한다.

이렇게 하면 설정이 마무리된다. 고스트 블로그의 admin api key를 발급받는 방법 등은 다른 곳에서도 많이 찾아볼 수 있으므로 생략하겠다.

추가된 기능 및 유의사항

  • obsidian에 로컬로 저장된 이미지를 self-hosted된 ghost 블로그로 보낼 수 있다. 링크는 기존 obsidian의 링크처럼 위키링크를 그대로 사용하면 된다. 현재는 마크다운 링크를 사용하면 안된다.
  • Feature image frontmatter에 로컬 이미지를 삽입할 수 있다. feature image frontmatter에 파일 링크를 그대로 넣으면 된다. 아래 캡쳐는 가능한 frontmatter 설정을 보여준다.
  • 이 플러그인은 파일 상단에 ghost-upload-preview.md를 만들고 이를 ghost 블로그로 보낸다.
  • 플러그인으로 ghost 블로그에 마크다운 인용구(맨 앞에 >) 글을 보내면 블로그 에디터에서 인용구 전체를 지울 수 없는 문제가 있다. 이를 방지하기 위해 이 플러그인은 문장 앞에 ">"가 있으면 이를 지운다. 인용구 추가는 블로그 에디터에서 해야한다.

마무리

typescript로 개발을 하는건 처음이었는데 google Gemini를 이용해서 코드를 작성해 개발시간을 크게 줄일 수 있었다. 남은 일은 원 플러그인에 PR을 올리는 일일 것이다. 왜 obsidian에서 ghost로 이미지를 직접 보내면 CORS 에러가 뜨는지, nginx의 설정이 정확히 무엇을 의미하는지 등 기술적인 내용에 대해서도 한번 다뤄보고 싶다.