endaaman.com

2024-05-30

更新履歴

個人ブログリニューアル2024

SvelteKit+FastAPIで作り直した

概要

コンテンツをObsidianで作成し、自宅NASおよびすべてのデバイスとSyncthingで同期し、NAS内のVMに置いたアプリから元のディレクトリをnfsでマウントし、それを配信するシステムを作った。

記事の管理

コンテンツはObsidianでmarkdownを書く。書いたものを自宅NAS(QNAP)とSyncthingで同期してすべてのデバイスで閲覧・編集できるようにする。

├── Obsidian
│   ├── Blog
│   │   ├── diary
│   │   │   ├── ....
│   │   │   └── 2021-10-07_XPS9305-review.md
│   │   ├── game
│   │   │   ├── ....
│   │   │   └── 2021-03-12_osu-on-linux.md
│   │   ├── tips
│   │   │   ├── ....
│   │   │   └── 2023-11-11_plasma-dont-open-menu-by-meta-key.md
│   │   ├── update
│   │   │   ├── ...
│   │   │   └── 2024-05-28_renewal.md
│   │   └── meta.toml
│   ├── static
│   │   ├── favicon.png
│   │   └── images
│   │         └── ...

このような形で記事を書く。ObsidianフォルダをVaultとしてSyncthingで共有する。Dropboxと違ってスマホとも同期できるのが大きな強みだ。 またこれは別の観点にはなるが、systemd-unitとしても登録できるのでリモートホストのデスクトップがない環境とも簡単にファイルを同期できるので、そのような環境にデータを送りつける手段として非常に便利である。

この中にさらにBlogというディレクトリを作り、この中の記事を公開する。他のディレクトリは共有のみし、普通のObsidianの使い方で運用する。

ファイルの作成ルールとして、必ず一つのdiaryなどのサブフォルダを挟んだ上で、書式は 2024-01-01_slug.md という形式とする。これにマッチしないファイルは無視する。日付を入れることでフォルダで見たときにソートされた状態で一覧できる。

Obsidianの編集画面。タイトルやタグをfrontmatterで記載できる。

また、Obsidianでは各テキストをfrontmatterで管理できるので、titletagsを記事に応じて設定する。正直これが一番使いたかった機能だ。 もともとブログの記事をfrontmatterで管理することで、DB-lessのCMSとして作っていたが、これに対応するエディタがなかった。Web管理画面なども作っていたが、個人で使うにはValidationやAPIの整備などの労力は割に合わなかった。

画像など静的ファイルの扱い

Obsidianではfuzzyにファイルをリンクさせられるので、この仕組みも利用する。

公開するデータはObsidian/static 以下に画像は集約し、![](/static/favicon.png) みたいに /をつけて参照するようにする(Obsidian/static/favicon.png/static/favicon.png のパスで配信するようにするため)。

記事をパース・配信するAPIバックエンド

バックエンドのソース

QSyncしたディレクトリをNAS内のVMにマウントする。

$ motunt -t nfs 192.168.1.101:/share/Obsidian /mnt/obsidian

これをDocker volumeでアプリに引き渡す。

アプリ内ではvolumeで渡ってきたディレクトリをwatchdogで監視し、読み込んだものをメモリ上にキャッシュしてFastAPIでREST APIを配信する。

---
title: 個人ブログリニューアル2024
tags:
  - Linux
  - Python
---

## 概要
コンテンツをObsidianで作成し、自宅NAS内のQSyncで同期し、NAS内のVMに置いたアプリから元のディレクトリをnfsでマウントし、パースしそれを配信するシステムを作った。

このような構造になっているので、--- に挟まれる部分をyamlでパースし、メタデータとする。

このとき、Obsidian/Blog/<dir><dir>をカテゴリとして扱う。このままだと名前をつけられないので、それを補うために Obsidian/Blog/meta.toml というファイルを使う。ここでは、

[[Category]]
slug = "tips"
label = "Tips"
hidden = false

[[Category]]
slug = "diary"
label = "日記"
hidden = false

みたいにして名前を設定できるようにする。ファイルベースで制御できないものはここに置いていく。 変更があるたびにQSync/Obsidian/Blog/*/*.mdを読み取り、ヘッダと本文のMarkdown(サーバーではHTMLにパースしない)から記事、カテゴリ、タグを読み取りREST APIで配信する。

フロントエンド

フロントエンドのソース

SvelteKitでバックエンドから取得した記事データをルーティング・HTMLへの変換を行う。 デザインは時間がかかるので、とりあえず記事を書いて読めるところまでやってデプロイしている。 Markdownのパースにはmarkdown-itを使っている。TOCやカスタムコンテナなどを柔軟に設定できる。ひとまず簡単にハイライトやGithub Alertsなどを入れてみた。

Note

GitHubスタイルのカスタムアノテーション

app = FastAPI()

@app.get('/')
async def root():
    return { 'message': 'Hello.'}

SSGもできるが404なリンクや記事の頻繁な更新を考えたらSSRにして、キャッシュはCDNに任せることにした。

デザインはdaisyUIを使い、markdownのコンテンツにはtailwindlabs/tailwindcss-typography.proseを雑に使った。

案外悪くない。

インフラ

VM on NAS

NASのVMにdockerを入れて、nginx-proxy nginx-proxy-le-companionを使ってまとめてSSL化している。つまり自宅サーバーである。 コンテナは開発環境でビルドし、VMのdocker compse pull && docker compose up -d で更新するだけ。 Docker HubのAutomationが使えなくなったので、イメージをDocker Hubに投げっぱなし、ということができなくなってしまった。これについてはちょっと考えないといけない。

Cloudflare tunnel

VM内にcloudflaredを導入し、ここにトンネルしている。詳細は別で書くかも。

コメント

デザインは適当にしたけど案内悪くない感じにまとまった気がする。


©2024 endaaman.com