「Pocket終了」に備える!Raindropとkarakeepで「あとで読む」を続ける方法
2025-05-26
Post Image

2025年7月8日、「あとで読む」アプリの定番 Pocket がサービスを終了します。ウェブページの保存や未読管理、オフライン閲覧を可能にしたPocketは、多くのユーザーにとって欠かせないツールでした。しかし、サービス終了に伴い、代替アプリの選択が急務です。
この記事では、セルフホストを避けたい方には Raindrop、プライバシーと自由度を重視する方には karakeep をおすすめします。特に、karakeepはOIDC対応や公式モバイルアプリなど、独自の強みを持つ優れたツールです。以下では、karakeepの利点と、k3sを使った構築手順をわかりやすく解説します。

Pocketの代替アプリ:Raindropとkarakeepの概要

Raindrop:手軽で直感的なクラウド型ソリューション

Raindropは、セルフホストの手間を避けたい方に最適な「あとで読む」アプリです。主な特徴は以下の通り:

  • 美しいUI:直感的な操作で、ストレスなく記事を整理。
  • タグ管理:柔軟なカテゴリ分けで、大量の記事も簡単に管理。
  • クロスプラットフォーム:Web、iOS、Androidでシームレスに利用可能。
  • Pocketからの移行:インポート機能でスムーズに移行。
    無料プランでも十分な機能があり、プレミアムプランでは高度な整理機能が追加されます。手軽さを求める方にぴったりです。

karakeep:セルフホストで完全制御

一方、karakeepはセルフホスト型のリーディングリストアプリです。自分のサーバーで運用することで、以下のようなメリットがあります:

  • データプライバシー:クラウド依存せず、個人情報を完全に管理。
  • カスタマイズ性:自分のニーズに合わせた柔軟な設定。
  • 長期的な自由度:サービス終了のリスクなし。
    他のセルフホスト型アプリ(WallabagやLinkwarden)と比較しても、karakeepは優れた機能で際立っています(詳細は次項)。初期設定の手間はありますが、プライバシーと自由度を重視する方に最適です。
    デモサイトはこちら

karakeepの強み:WallabagやLinkwardenとの違い

karakeepは、以下の点で他のセルフホスト型アプリをリードしています:

  • OIDC対応でセキュアな認証
    Wallabagは基本的な認証方式に限定されますが、karakeepは**OpenID Connect(OIDC)**に対応。KeycloakやAuth0などとのシングルサインオン(SSO)統合が可能で、エンタープライズ用途にも適しています。
  • 公式モバイルアプリでどこでもアクセス
    Linkwardenはコラボレーション機能が強いものの、公式モバイルアプリがありません。一方、karakeepはiOSとAndroid向けの公式アプリを提供し、オフライン閲覧も快適です。
  • アーカイブ機能でコンテンツを永続保存
    karakeepとLinkwardenは、ウェブページをPDFやHTML形式でアーカイブ可能。Wallabagもアーカイブ機能を持ちますが、設定が煩雑で、保存形式の柔軟性やUIの直感性ではkarakeepが優れています。

その他の違い

  • 高速検索
    karakeepはMeilisearchを統合し、大量の記事でも高速に検索可能。WallabagやLinkwardenの検索は速度面で劣ります。
  • モダンな設計
    karakeepは軽量でモダンなUI/UXを採用。WallabagのUIはやや古く、Linkwardenはチーム利用に特化しています。
  • カスタマイズ性
    karakeepはプラグインやAPIが充実し、開発者にとって柔軟な拡張が可能です。
    これらの特徴から、プライバシーと機能性を両立したい方にkarakeepは最適です。

まとめ:自分に合った「あとで読む」環境を

Pocketの終了は残念ですが、Raindropなら手軽に、karakeepならプライバシーと自由度を確保して「あとで読む」を続けられます。特にkarakeepは、OIDC対応、公式アプリ、アーカイブ機能で他をリード。k3sを使った構築で、完全制御の環境を手に入れましょう!
ぜひこの手順を試し、karakeepのコミュニティ (リンクを挿入)で情報交換してみてください。あなたの「あとで読む」ライフを、もっと自由に、もっと快適に!

以下は実際の構築手順

k3sでkarakeepを動かす

karakeepをセルフホストするには、軽量なKubernetesディストリビューションであるk3sがおすすめです。k3sはリソース消費が少なく、ホームサーバーやVPSでも簡単に運用できます。ここでは、k3sを使ったkarakeepのデプロイ手順を紹介します。

ディレクトリ構成

以下のディレクトリ構成で、karakeepと依存コンポーネント(Meilisearch、Chrome)を管理します:

./projects
├── base
│   ├── karakeep
│   │   ├── deployment-chrome.yaml        # Chromeコンテナのデプロイ
│   │   ├── deployment-karakeep.yaml      # karakeep本体のデプロイ
│   │   ├── deployment-meilisearch.yaml   # Meilisearchのデプロイ
│   │   ├── kustomization.yaml           # kustomize設定
│   │   └── namespace.yaml               # 名前空間定義
└── overlays
    ├── dev
    │   ├── 01_configMap                 # 開発環境の設定
    │   └── karakeep
    └── prod
        ├── 01_configMap                 # 本番環境の設定
        ├── 02_settings
        │   └── karakeep
        │       └── secret-karakeep.yaml # シークレット情報
        └── karakeep
            ├── ingress-traefik.yaml      # Traefikイングレス
            ├── kustomization.yaml       # 本番用kustomize
            ├── local-hostpath-pvc.yaml  # ストレージ設定
            ├── patch-deployment-chrome.yaml
            ├── patch-deployment-karakeep.yaml
            ├── patch-deployment-meilisearch.yaml
            └── Readme.md

主要yamlファイルの役割

  • deployment-karakeep.yaml:karakeep本体のデプロイ設定。
  • deployment-meilisearch.yaml:高速検索のためのMeilisearch設定。
  • deployment-chrome.yaml:ウェブページのアーカイブに必要なChromeコンテナ。
  • ingress-traefik.yaml:Traefikを使った外部アクセス設定。
  • secret-karakeep.yaml:NEXTAUTH_SECRETなどの機密情報を管理。
  • local-hostpath-pvc.yaml:ローカルストレージの永続化設定。

基本リソースのデプロイ

baseディレクトリでkustomizeを適用し、karakeep、Meilisearch、Chromeをデプロイ:

kubectl apply -k ./projects/base/karakeep

本番環境の設定

overlays/prodでパッチを適用し、本番環境を構築:

kubectl apply -k ./projects/overlays/prod/karakeep

外部アクセスの設定

Traefikイングレスで外部からアクセス可能にします。

  • deployment-karakeep.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: karakeep-app
spec:
  selector:
    matchLabels:
      app: karakeep-app
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: karakeep-app
    spec:
      volumes:
        - name: karakeep-main
          emptyDir: {}
      containers:
        - name: karakeep-container
          image: karakeep-image
          imagePullPolicy: IfNotPresent
          securityContext:
            runAsNonRoot: false
            runAsUser: 0
            runAsGroup: 0
          resources: {}
          ports:
            - containerPort: 3000
              protocol: TCP
          env:
            - name: TZ
              value: Asia/Tokyo
            - name: MEILI_ADDR
              value: "http://meilisearch-svc.karakeep.svc.cluster.local:7700"
            - name: BROWSER_WEB_URL
              value: "http://chrome-svc.karakeep.svc.cluster.local:9222"
            - name: NEXTAUTH_URL
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: server_external_url
                  optional: true
            - name: DATA_DIR
              value: "/data"
            - name: NEXTAUTH_SECRET
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: nextauth_secret
                  optional: true
            - name: MEILI_MASTER_KEY
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: meili_master_key
                  optional: true
            - name: NEXT_PUBLIC_SECRET
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: next_public_secret
                  optional: true
          volumeMounts:
            - name: karakeep-main
              mountPath: /data
              subPath: data
---
apiVersion: v1
kind: Service
metadata:
  name: karakeep-svc
  labels:
    app: karakeep-app
spec:
  selector:
    app: karakeep-app
  ports:
    - protocol: TCP
      name: "http"
      port: 80
      targetPort: 3000
  type: ClusterIP
  • deployment-chrome.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: chrome-app
spec:
  selector:
    matchLabels:
      app: chrome-app
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: chrome-app
    spec:
      volumes:
        - name: chrome-main
          emptyDir: {}

      containers:
        - name: chrome-container
          image: chrome-image
          imagePullPolicy: IfNotPresent
          securityContext:
            runAsNonRoot: false
            runAsUser: 0
            runAsGroup: 0

          resources: {}
          ports:
          - containerPort: 9222
            protocol: TCP
          command: ["chromium-browser"]
          args:
            - --headless
            - --no-sandbox
            - --disable-gpu
            - --disable-dev-shm-usage
            - --remote-debugging-address=0.0.0.0
            - --remote-debugging-port=9222
            - --hide-scrollbars

---
apiVersion: v1
kind: Service
metadata:
  name: chrome-svc
  labels:
    app: chrome-app
spec:
  selector:
    app: chrome-app
  ports:
    - protocol: TCP
      name: "http"
      port: 9222
      targetPort: 9222
  type: ClusterIP
  • deployment-meilisearch.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: meilisearch-app
spec:
  selector:
    matchLabels:
      app: meilisearch-app
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: meilisearch-app
    spec:
      volumes:
        - name: meilisearch-main
          emptyDir: {}

      containers:
        - name: meilisearch-container
          image: meilisearch-image
          imagePullPolicy: IfNotPresent
          securityContext:
            runAsNonRoot: false
            runAsUser: 0
            runAsGroup: 0

          resources: {}
          ports:
          - containerPort: 7700
            protocol: TCP
          env:
            - name: TZ
              value: Asia/Tokyo
            - name: MEILI_ADDR
              value: "http://meilisearch-svc.karakeep.svc.cluster.local:7700"
            - name: BROWSER_WEB_URL
              value: "http://chrome-svc.karakeep.svc.cluster.local:9222"
            - name: NEXTAUTH_URL
              value: "http://karakeep-svc.karakeep.svc.cluster.local:3000"
              
            - name: MEILI_NO_ANALYTICS
              value: "true"

            - name: NEXTAUTH_SECRET
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: nextauth_secret
                  optional: true
            - name: MEILI_MASTER_KEY
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: meili_master_key
                  optional: true
            - name: NEXT_PUBLIC_SECRET
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: next_public_secret
                  optional: true

          volumeMounts:
            - name: meilisearch-main
              mountPath: /meili_data
              subPath: meilisearch

---
apiVersion: v1
kind: Service
metadata:
  name: meilisearch-svc
  labels:
    app: meilisearch-app
spec:
  selector:
    app: meilisearch-app
  ports:
    - protocol: TCP
      name: "http"
      port: 7700
      targetPort: 7700
  type: ClusterIP
  • ./projects/base/karakeep/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: karakeep
resources:
  - ./namespace.yaml
  - ./deployment-karakeep.yaml
  - ./deployment-chrome.yaml
  - ./deployment-meilisearch.yaml
  
images:
- name: karakeep-image
  newName: ghcr.io/karakeep-app/karakeep
  newTag: "latest"
- name: chrome-image
  newName: gcr.io/zenika-hub/alpine-chrome
  newTag: "latest"
- name: meilisearch-image
  newName: getmeili/meilisearch
  newTag: "latest"
  • ingress-traefik.yaml
# ここにingress-traefik.yamlの内容を記載
  • patch-deployment-karakeep.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: karakeep-app
  namespace: karakeep
spec:
  selector:
    matchLabels:
      app: karakeep-app
  template:
    metadata:
      labels:
        app: karakeep-app
    spec:
      containers:
        - name: karakeep-container
          env:
            - name: DISABLE_SIGNUPS
              value: "true"
            - name: DISABLE_PASSWORD_AUTH
              value: "true"

            - name: OAUTH_ALLOW_DANGEROUS_EMAIL_ACCOUNT_LINKING
              value: "true"
			
            # - namae: OAUTH_PROVIDER_NAME
            #   valueFrom:
            #     secretKeyRef:
            #       name: karakeep-secret
            #       key: oauth_provider_name
            #       optional: true
            - name: OAUTH_SCOPE
              value: "openid email profile"

            - name: OAUTH_WELLKNOWN_URL
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: oauth_oidc_issuer
                  optional: true
            - name: OAUTH_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: oauth_oidc_client_secret
                  optional: true
            - name: OAUTH_CLIENT_ID
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: oauth_oidc_client_id
                  optional: true

            - name: OPENAI_API_KEY
              valueFrom:
                secretKeyRef:
                  name: karakeep-secret
                  key: openai_api_key
                  optional: true    
                  
          securityContext:
            runAsNonRoot: false
            runAsUser: 0
            runAsGroup: 0
              
      volumes:
          - name: karakeep-main
            emptyDir: null  # emptyDirを削除
            persistentVolumeClaim:
              claimName: karakeep-pvc

      securityContext:
        fsGroup: 1000
  • OAUTH_PROVIDER_NAME
    は現状、指定するとエラーになると思います。そのため、コメントアウトにしています。

注意点

  • Meilisearchの設定:01_configMapでAPIキーを適切に設定してください。
  • Chromeコンテナ:アーカイブ機能に必須。リソース消費を抑えるため、スケーリングを調整。
  • Traefik:イングレスコントローラを事前にインストール(Traefik公式参照)。
  • シークレット管理:secret-karakeep.yamlにNEXTAUTH_SECRETやMEILI_MASTER_KEYを安全に設定。
    詳細なyamlファイルは、リポジトリを参照してください。
「Pocket終了」に備える!Raindropとkarakeepで「あとで読む」を続ける方法
https://notes.midnightstops.com/posts/23/
作者
Author
公開日
2025-05-26