何がおきた?

手元のJenkinsに対して、Google Loginプラグインを使ってSSOを設定しようとしたが
エラーとなってしまいログインできなくなってしまった。
戻し方を調べたのでメモ。

方法1 config.xml を戻す

王道。最も安全。
Jenkinsの設定を大きく変える前は、 $JENKINS_HOME/config.xml をバックアップしておくと良い。
もちろん、私はバックアップしていなかったので次の手段を使った
※厳密にはバックアップはあるが、持ってくるのが面倒だった

方法2 config.xmlを編集する

:::message alert
この手順を行うと、一時的にJenkinsがログイン不要で管理者権限が得られるようになります。
:::

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version='1.1' encoding='UTF-8'?>
<hudson>
<disabledAdministrativeMonitors>
<string>hudson.node_monitors.MonitorMarkedNodeOffline</string>
<string>hudsonHomeIsFull</string>
<string>jenkins.diagnostics.SecurityIsOffMonitor</string>
<string>jenkins.diagnostics.ControllerExecutorsAgents</string>
</disabledAdministrativeMonitors>
<version>2.492.2</version>
<numExecutors>6</numExecutors>
<mode>NORMAL</mode>
<useSecurity>true</useSecurity> ← この true を false にする

たったこれだけ。あとはJenkinsにアクセスすると認証なしで管理者になれる。
Jenkinsにアクセスしたあとは速やかに以下を行う必要がある。
Jenkinsの管理>Security 画面で…

  • ユーザー情報をJenkinsのユーザーデータベース に変更する
  • 権限管理 を認証されたユーザーのみ に変更する
  • Allow anonymous read access のチェックを外す

これをするまでの間、Jenkinsはログイン不要で設定変更ができてしまうので注意。
業務用の場合は、やらないほうが良いでしょう。

前提

  • ターゲットボード ESP32-4827S043N (8048ではないので注意。安い方)
  • ILI9485(ILI6485) を使っている。(資料によって記述が違うが互換性があるらしい)
  • 販売元(Aliexpressで↑の型番を検索するとサンプルコードが入手できる)

参考にしたサイト

サンプルコードで分からないこと

  • ArduinoGFXのバージョンが上がって、色々リファクタリングされたようで初期化パラメタが変わっている。
  • PSRAMの使い方がわからない
  • PSRAMを使わないと、WiFi接続できないくらいにメモリが足りない。(液晶パネルの都合で、すごいメモリを食う)

メモ

PSRAM 有効化

platformio.ini に以下のように記述することでPSRAMを有効にできた。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
platform = espressif32
board = esp32-s3-devkitc-1
framework = arduino
board_build.mcu = esp32s3
monitor_speed = 115200
upload_speed = 921600
board_build.f_cpu = 80000000L # ここは変更OK
board_build.arduino.memory_type = dio_opi
board_upload.flash_size = 16MB
lib_deps =
olikraus/U8g2
moononournation/GFX Library for Arduino@^1.4.1
build_flags =
-Os
-DBOARD_HAS_PSRAM

Arduino_GFX

以下で初期化できる。入手できるサンプルは、 Arduino_GFX 1.2.8 のときの記述であり、これを書いている時点では 1.4.1 にバージョンアップしている。途中、リファクタリングがあったらしくカスタム設定のやりかたがだいぶ変更されていた。
(ただし、以下のサンプルはまだバックライトの制御がON/OFFになってしまっている)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// default backlight pin, you may replace DF_GFX_BL to actual backlight pin
#define GFX_BL DF_GFX_BL
#define TFT_BL 2

Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
40 /* DE */, 41 /* VSYNC */, 39 /* HSYNC */, 42 /* PCLK */,
45 /* R0 */, 48 /* R1 */, 47 /* R2 */, 21 /* R3 */, 14 /* R4 */,
5 /* G0 */, 6 /* G1 */, 7 /* G2 */, 15 /* G3 */, 16 /* G4 */, 4 /* G5 */,
8 /* B0 */, 3 /* B1 */, 46 /* B2 */, 9 /* B3 */, 1 /* B4 */,
0 /* hsync_polarity */, 8 /* hsync_front_porch */, 4 /* hsync_pulse_width */, 43 /* hsync_back_porch */,
0 /* vsync_polarity */, 8 /* vsync_front_porch */, 4 /* vsync_pulse_width */, 12 /* vsync_back_porch */,
1 /* pclk_active_neg */, 9000000 /* prefer_speed */
);

Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
480 /* width */, 272 /* height */, rgbpanel
);

前書き

2年くらいLinuxで暮らしてきたが、あまりにWindowsの使い方を忘れてしまったのでWindowsで環境構築をしようとしてみたメモ。去年と異なり今年はWindows11である。
また、モニタも1枚になったので幾分シンプルなセットアップになった。

アプリ・ツール類のインストール

Microsoft Storeからインストール

  • Windows Subsystem for Linux (WSL)
  • winget

どちらもStore版が最新となっているのでインストールする。

手動インストール

ここでFirefoxを入れたあと、一度起動してデフォルトのブラウザに設定しておく。
後々、ブラウザを使用してログインするアプリをedgeで開かれると面倒なのでここで設定しておく。
Tclockの書式は "UL"NSSK___x"KB/s CPU"CU__x"%" mm/dd ddd\n"DL"NRSK___x"KB/s GPU"GU__x"% " hh:nn:ss

wingetでインストールするもの

この下のコードブロックはそのままPowerShellに貼り付けると途中で止まったりするので
数行ごとにやったほうがいいかもしれない。

1
2
3
4
5
6
7
8
9
10
11
winget install slacktechnologies.slack
winget install git.git
winget install Microsoft.VisualStudioCode
winget install RescueTime.DesktopApp
winget install Dropbox.Dropbox
winget install 7zip.7zip
winget install Greenshot.Greenshot
winget install Adobe.Acrobat.Reader.32-bit
winget install Betterbird.Betterbird
winget install Eugeny.Tabby
winget install Microsoft.WindowsTerminal
1
2
winget install Discord.Discord
winget install SlackTechnologies.Slack

ストアアプリはひとつづつ入れないと毎度インストールしてよいか聞かれるのでコケる

1
winget install XP89DCGQ3K6VLD

言語系はrtxに任せたかったが、rtxはWindows版がなかった。

1
2
3
winget install python.python.3.12
winget install oracle.JDK.17
winget install GoLang.Go.1.21

備考がいりそうなアプリ

  • Betterbird.Betterbird メーラー。thunderbirdにパッチを当てたもの
  • XP89DCGQ3K6VLD PowerToys
  • Eugeny.Tabby Guake LikeにWSLを使うためのターミナル
  • Microsoft.WindowsTerminal Win11なら不要かもしれないが入れても問題にはならないはず

アプリ設定

PowerToys

PowerToysの設定はドキュメント\PowerToysに保存されていそう。

Keyboard Manager

キーの再マップ

1
2
CapsLock    IME Kanji
Apps/Menu Caps Lock (右側Ctrlの左にあるキー。コンテキストメニューキー)

OKボタンを押すと Apps/Menuキーが割当られていないという警告が出るが無視する。

ショートカットの再マップ

1
2
3
4
5
6
7
8
9
10
11
# 音量・再生周りをmac風にする
WIN+F7 Previous Track
WIN+F8 Play/Pause Media
WIN+F9 Next Track
WIN+F10 Volume Mute
WIN+F11 Volume Down
WIN+F12 Volume Up

WIN+Pause Sleep

WIN+Q ALT+F4

PowerToys Run

  • 起動キー ctrl+shift+enter

tabbyの設定

tabby.sh に同期しておけば復元できるっぽい。

  • ショートカットキー toggle window F1
  • デフォルトの環境 Arch
  • Font HackGen35 Console 16
  • Color Scheme -> Dark Pastel
  • Terminal -> Sound -> Terminal bell Audible
  • Terminal -> Mouse -> Right Click Context Menu

Windows terminalの設定

  • スタートアップ→規定のプロファイル Arch
  • 以下の設定を追加。(本当はWIN+Enterに割り当てたいがWIN+`以外だと効かない?模様)
1
2
3
4
5
6
7
8
9
10
"command": 
{
"action": "globalSummon",
"desktop": "toCurrent",
"dropdownDuration": 1,
"monitor": "toMouse",
"name": "_global",
"toggleVisibility": true
},
"keys": "win+`"

Biscuit

  • フォントが指定されていないので指定する
  • メニューは右上アドレスバーの並びの … から
  • 標準、Sans-Serifは VL Pゴシック
  • Serifは適当、固定幅フォントは Hack Console 35

git

改行コードの自動変換を無効に

1
git config --global core.autocrlf false

betterbird (thunderbird)

  • 一度、 "C:\Program Files\Betterbird\betterbird.exe" -p で起動する
  • profileをよしななディレクトリに作成する (私の設定は c:/usr/betterbird

フォント

フォントのインストール時は、アドレスバーに shell:fonts と入れると楽
yuru7氏のフォントは無印、非NerdFont版(ただの好み)

Windows設定変更

環境変数

PythonのデフォルトのエンコーディングをUTF-8にする

これをしないとPlatformIOのコンパイルがコケる。
どのみち、cp-932を指定されて嬉しいことなんて一つもないのでUTF-8にしておくほうが幸せだと思われる。

1
PYTHONUTF8=1

出典
https://qiita.com/methane/items/9a19ddf615089b071e71

個人用設定→色→モードを選ぶ→カスタム
既定のWindowsモード ダーク
既定のアプリモード ライト

WSLを入れる

ネットワーク通信が通ることまで確認したほうがいいかもしれない。

ArchWSLのほうが人気っぽいが、ArchWSL2のほうが初期設定が親切&systemdが動いているので個人的にはおすすめ。key周りでエラーが出たら(GPG Signatureなんたら~)とりあえず
pacman -S archlinux-keyring でキーだけ更新すると良い。(タイミングによっては起きる)

1
2
3
git clone https://aur.archlinux.org/yay-bin
cd yay-bin
makepkg -si

MS-IME

  • 設定→時刻と言語→言語と地域→Microsoft IME→全般→互換性>以前のバージョンのMS-IMEを使う
  • MS-IMEの設定でキーバインドをATOKに変更

キーボードレイアウトが間違えていた時

  • 設定→時刻と言語→言語と地域→優先する言語→日本語をクリック
  • オプションボタンを押す→ハードウェアキーボードレイアウト

ネットワークをプライベート接続に

エクスプローラーのネットワーク をクリックして画面上部にでてくる
ファイル共有が無効です(略
のメッセージからネットワーク探索とファイル共有を有効に を選んで、
いいえ、接続しているネットワークをプライベートネットワークにします。 を選択

ウィンドウスナップの無効化

Windows11のみ

ウィンドウを動かしているときに上から出てくるメニューをオフにする

  • 設定→システム→マルチタスク→ウィンドウを画面の上部にドラッグしたときにスナップレイアウトを表示する 無効

エクスプローラーのコンテキストーメニューを10の頃に戻す

Windows11のみ

  • レジストリ変更→再起動
  • 変更されるといけないので調べて(変更後は再起動が必要)

BitLocker ON

  • Home EditionでもBitLockerは使える。
  • デバイスの暗号化。みたいな名前になっているので探す

はじめに

k3s version v1.28.4+k3s2 (6ba6c1b6)

クラスタ立ち上げ後にIPアドレスを変えると…

自己署名の証明書のCNに新しいIPアドレスが含まれていないのでkubectl等がエラーになります。

1
Unable to connect to the server: tls: failed to verify certificate: x509: certificate is valid for 192.168.1.123, 10.43.0.1, 127.0.0.1, ::1, not 新しいIPアドレス

解決策

https://github.com/k3s-io/k3s/issues/1381#issuecomment-1067141504

上記に書かれている通り…
以下の操作は、すべてk3sのコントロールプレーンのノードで実行する。

secrets/k3s-serving の変更

kubectl -n kube-system edit secrets/k3s-serving

エディタが開く。以下のような行があるので新しいIPアドレスを追加する。
例えば、追加したいIPアドレスが 192.168.123.234 ならば以下のようにする

1
2
3
listener.cattle.io/cn-10.43.0.1: 10.43.0.1
listener.cattle.io/cn-127.0.0.1: 127.0.0.1
listener.cattle.io/cn-192.168.123.234: 192.168.123.234 // この行追加

k3s 停止

証明書を作り直すので一旦k3sを止める

sudo systemctl stop k3s

証明書作り直し

sudo k3s certificate rotate

k3s 開始

sudo systemctl start k3s

リモート接続が必要なPCに証明書をコピーしなおし

sudo cat /etc/rancher/k3s/k3s.yaml の中身を必要なPCにコピーして、IPアドレスを書き換える。 k8sクラスタが一個しかないのであれば、 .kube/config にコピーすればOK。

コピー後、 kubectl get nodes して表示されればOK。

はじめに

地味にハマったのでメモしておく。
環境は、Arch Linux (x86-64) 。他のディストリビューションでも同様だと思われる。

ssh-agent as systemd user service

.config/systemd/user/ssh-agent.service として以下の内容のファイルを作る

1
2
3
4
5
6
7
8
9
10
[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

systemctl --user enable --now ssh-agent.service で有効化しておく。
ps aux | grep ssh-agent で起動しているかチェック。

fish側の設定

ここが一番メモしたかったところ。
ssh-agentを使うためには環境変数 SSH_AUTH_SOCK が export されている必要がある。
.config/fish/conf.d/fish-ssh-agent.fish に以下のように書いた

1
set -gx SSH_AUTH_SOCK "$XDG_RUNTIME_DIR/ssh-agent.socket"

テスト

ssh-add を実行する。実行しているユーザーがSSH鍵を持っていてパスワードがかかっていれば
いつもの、SSH鍵のパスワードを尋ねるプロンプトが出る。

トラブルシューティング

ssh-add がエラー Could not open a connection to your authentication agent. を出力する。

  • ls -l $SSH_AUTH_SOCK したときソケットが表示されますか?
1
2
ls -l $SSH_AUTH_SOCK
srw------- 1 yakumo yakumo 0 12月 10 11:16 /run/user/1000/ssh-agent.socket=

されないなら、多分ssh-agentが起動していません。

  • printenv | grep SSH_AUTH_SOCK で SSH_AUTH_SOCK 環境変数が表示されますか?

されない場合、 set に x が足りていません。 set -g では駄目で、 x がある必要があります。
printenvでは、exportされた変数しか表示しないので、ここに表示されないということは、ssh-agentからも変数が見えていません。

はじめに

Ubiquitiの UAP nanoHDを知人から譲ってもらった。それはいいが、この無線AP、Unifi Network Applicationに接続するか、もしくは同社のルーター的なものを使っていないと簡易な設定しかできない。 (とはいえ、その簡易設定でウチでは十分なんだが…)
ちょっとそのままでは悔しいので、接続を試みたログである。

Unifi Network Applicationの準備

dockerコンテナがあるのでそれを使えば簡単。手元の環境では、docker composeを使用した。
別に起動自体は簡単。起動後、WebUIは 8443番ポートで起動している。ログインとかアカウントの作成とかは省略。

Web UIにアクセスしたら、左側メニューの System > Advanced > inform Host のoverrideにチェックを入れ、その下のテキストボックスに、LAN内からアクセス可能なIPアドレスかホスト名を書いておく。(そして忘れず Apply Change)

docker compose down してから up で再起動してこちらは準備完了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
version: "3"
services:
unifi-network-application:
image: lscr.io/linuxserver/unifi-network-application:latest
container_name: unifi-network-application
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- MONGO_USER=unifi
- MONGO_PASS=unifi-pwd
- MONGO_HOST=unifi-db
- MONGO_PORT=27017
- MONGO_DBNAME=unifi
- MEM_LIMIT=1024 #optional
- MEM_STARTUP=1024 #optional
- MONGO_TLS= #optional
- MONGO_AUTHSOURCE= #optional
volumes:
- ./unifi-data:/config
ports:
- 8443:8443
- 3478:3478/udp
- 10001:10001/udp
- 8080:8080
- 1900:1900/udp #optional
- 8843:8843 #optional
- 8880:8880 #optional
- 6789:6789 #optional
- 5514:5514/udp #optional
networks:
- external
- internal
restart: unless-stopped
unifi-db:
image: docker.io/mongo:4
container_name: unifi-db
volumes:
- ./mongodb:/data/db
- ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
networks:
- internal
restart: unless-stopped
networks:
internal:
internal: true
external:
#driver: host
#external: true

APを Unifi Network Applicationに接続する

まず、工場出荷状態に戻す。これは必須。Standaloneモードでセットアップされたあとでは、Applicationへの接続寸前まで行くが接続できない。

工場出荷状態でとりあえず、LANに接続してDHCPからIPアドレスが取得されるまで待つ。
IPアドレスが取得されたら、そのIPアドレスに対してSSHで接続する。
ユーザー名は ubnt パスワードも ubnt で接続できる。
※ コマンド例 ssh ubnt@192.168.1.123

接続後、 set-inform http://192.168.1.234:8080/inform のようなコマンドを入力する。
IPアドレスは、Unifi Network Applicationが動いているホストのIPアドレス。
このコマンドを入力したあと、Unifi Network Applicationを開いてみると、通知が来ていて Adoption待ちのデバイスがある。とお知らせしてくれるのでそこから承認すればOK。
なお、工場出荷状態にしていない場合、ここでお知らせがでない。スマホのアプリで見ると、Pending Adoption というステータスにはなるが、どうやっても接続できなかった。

接続されると…

端末ごとの帯域使用量だとか、色々と見れて大変楽しい。
別段課金が発生するわけではないのでオススメ。

なにこれ

バックアップ取得時に、tar.gz 形式で取得していたのを tar.zst に変更したらサイズが少し小さくなって、処理時間もそれほど変わらなくて得した。という記事です。

やり方

/work をアーカイブするとします。
tar.gz の場合は tar czvf ~/work-backup.tar.gz /work
tar.zst の場合は tar cvf - /work | zstd -10 > ~/work-backup.tar.zst

蛇足

tar cavf ~/work-backup.tar.zst /work でも作成できますが、zstdの圧縮レベルを指定できないので、zstdにパイプした方がよさそうです。
なお、tarを使った場合も内部でzstdを呼んでいるので、zstdパッケージのインストールが必要です。

注意点

  • Debian 11 では、zstd は標準でインストールされていません。

サイズ比較

5410MB DBダンプのSQLを圧縮

1
2
zstd -3  -> 1148M
zstd -10 -> 951M

他の通常ファイルの圧縮でも7%くらいのサイズ縮小効果が見られました。

前書き

初版の事情で録画サーバーの再構築が必要になったので手順をメモ。
未完で終わっている前の記事の続編でもある。
TVerとかがあるのにまだ録画が必要なのかは割と微妙なところになりつつある。

使用機器

  • DeskMini H110
  • Proxmox 7.3
  • Gemalt カードリーダー
  • MyGica S270

目標

  • LXCコンテナ上に録画環境を作る。
  • Unprivilleged (デフォルト)

ホスト上での作業

LXCコンテナで作ると言っているのに、いきなりホスト上で作業とは…?
となるが、権限周りの理由によりホスト上での作業を行わないとどうにもできないところがある。
とりあえず、LXCコンテナは先に作っておく。(中身の設定はしていなくてよい)

ひとつは、デバイスをLXCコンテナに見せる際に、ホスト上のグループとLXCコンテナ上のグループが一致しない(lxc.idmapでどうにか出来るのかもしれないが試していない)ので、権限を緩める必要があること。
2つ目は、LXCコンテナの設定で、ProxmoxのGUIからはできない設定を入れることの2つ。
順に記述していく。

デバイスのアクセス権限設定

チューナーデバイスは、/dev/dvb/adapterN にマップされている。(ディレクトリであり、配下に demux0,frontend0,dvr0 のようなファイルを持つ)
PCカードリーダーは、/dev/bus/usb/XXX/YYY である。XXXとYYYは lsusb コマンドの出力の先頭にかかれている Bus XXX Device YYY から取得できる。

1
Bus 001 Device 004: ID 08e6:3437 Gemalto (was Gemplus) GemPC Twin SmartCard Reader

udevルールの作成

以下の内容のファイルを /etc/udev/rules.d/99-custom.rules という名前で保存する。
udevは、デバイスが接続されたときにいい感じにデバイスファイルを作成してくれるデーモンである。

1
2
3
4
5
6
7
8
# smartcard reader
# Gemalt
SUBSYSTEM=="usb", ATTRS{idVendor}=="08e6", ATTRS{idProduct}=="3437", GROUP="video", MODE="0666"
# NTT SCR3310
SUBSYSTEM=="usb", ATTRS{idVendor}=="04e6", ATTRS{idProduct}=="511a", GROUP="video", MODE="0666"

# MyGica S270 (siano chip)
SUBSYSTEM=="dvb", ATTRS{idVendor}=="187f", ATTRS{idProduct}=="0600", GROUP="video", MODE="0666"

内容は、idVendro idProductはモノによって異なるので、lsusb で調べてほしい。
兎にも角にも、アクセス権を 666 で作ってくれ。ということをお願いしている。
※ PT3の場合は、lspci を使えばわかるかもしれないが、所有していないので不明

作成後は、以下のコマンドで適用できる。再起動しても良い。

1
2
udevadm control --reload
udevadm trigger

udevルールが適用されたか確認

適用されたか確認する。 先頭部分が crw-rw-rw- であればOK

ls -l /dev/bus/usb/001/004

1
crw-rw-rw- 1 root root 189, 3 Apr 23 17:45 /dev/bus/usb/001/004

ls -l /dev/dvb/adapter0

1
2
3
crw-rw-rw- 1 root video 212, 0 Apr 23 17:43 demux0
crw-rw-rw- 1 root video 212, 1 Apr 23 17:43 dvr0
crw-rw-rw- 1 root video 212, 2 Apr 23 17:43 frontend0

LXCコンテナの設定

あとは、LXCコンテナにデバイスを見せるような設定を追加するだけ。
/etc/pve/lxc/CTID.conf に以下の行を追加する。 CTIDはProxmoxに表示されている 102 みたいな数字。

/etc/pve/lxc/CTID.conf
1
2
3
4
5
lxc.cgroup.devices.allow: c 189:* rwm
lxc.cgroup.devices.allow: c 212:* rwm
lxc.mount.entry: /dev/bus/usb/001 dev/bus/usb/001 none bind,create=dir,mode=0666
lxc.mount.entry: /dev/dvb/adapter0 dev/dvb/adapter0 none bind,create=dir,mode=0666
lxc.mount.entry: /dev/dvb/adapter1 dev/dvb/adapter1 none bind,create=dir,mode=0666

lxc.cgroup.devices.allow はデバイスへのアクセス許可をするもの。先程の確認時に ls -l した際に表示された数値を入れる。
lxc.mount.entry はホスト上のファイルをLXCコンテナ上のどこにマップするかという設定。

蛇足:

  • /dev/dvb 以下を全部マップしても良いかもしれない。
  • mode=0666 は多分不要
  • 動いたら怖くて触りたくないのが本音

LXCコンテナ上の設定

設定は以下の方針とした。

  • コンテナはdebian 11
  • Mirakurun は直接入れる
  • EPGStationはdockerを使う

基本的な色々を入れる

Mirakurunを入れる

チャンネルの設定は省略。チャンネルスキャンがあるのでどうにかなるはず

1
2
3
4
5
6
- name: MYGICA_S270_0
types:
- GR
command: "dvbv5-zap -a 0 -c /work/epgstation/mirakurun/dvbv5_channels_isdbt.conf -r -P <channel> -o -"
decoder: "arib-b25-stream-test"
isDisabled: false

EPGStation

docker-composeで動かすので省略。docker-compose.ymlは以下の通り。
https://gist.github.com/yakumo-saki/07156c4f6a9b9f7f4c22e0f2bbabfdd4

config等はよしなに行ってほしい。

蛇足

Mirakurunがdockerコンテナではない理由

pullした際に以下のように怒られる為。これが解決できるならMirakurunもコンテナで動かせる。

1
failed to register layer: ApplyLayer exit status 1 stdout:  stderr: failed to Lchown "/app/node_modules/statuses/HISTORY.md" for UID 1516583083, GID 0 (try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid): lchown /app/node_modules/statuses/HISTORY.md: invalid argument

前提

  • Dropbox APIを使用するためにはAPIトークンが必要
  • APIトークンはそれほど長くない(14400秒?)有効期限がある。無期限のAPIトークンは存在しない
  • 無期限のAPIトークンは存在しないが、リフレッシュトークン(有効期限付きAPIトークンを取得するためのトークン)は無期限である。

手順

アプリケーションを作る

自分だけが使う場合であってもこの手順は必要。
別に公開されたりするわけではないので気楽にやってOK。

https://www.dropbox.com/developers

権限はよしなに設定してください。

表示される App KeyApp Secret は後で使用するので控えておいてください。
(再表示できるのでその都度見てもOK)

リフレッシュトークンを取得する

ここはWebブラウザが必要。というよりお手元のPC等で行ってください。
この手順は、制限時間があります。一度この手順の最後まで読んでから始めた方がよいでしょう。

AppとDropboxアカウントの接続を許可する

Webブラウザから以下のURLにアクセスします。$APP_KEY は先程表示された、App Keyの値に置き換えてください。

https://www.dropbox.com/oauth2/authorize?client_id=$APP_KEY&response_type=code&token_access_type=offline

すると以下のような画面が表示されるので、続行する。をクリック

その後、アクセスコードが表示されるので表示された値を控えておきます。
多分、これは再表示できないので確実に控えておいてください。(なくしたらもう一度この手順をやれば大丈夫なはずですが)

アクセストークン等を取得する

以下のcurlコマンドを使用する。ちなみに、アクセスコードは一回しか使えないので帰ってきたJSONは確実に保存してください。(失敗したら一つ上からやり直しでOK)

  • $ACC_CODE は先程取得したアクセスコード
  • $APP_KEY はApp key
  • $APP_SEC はApp Secret

と置換してください。

1
2
3
4
curl https://api.dropbox.com/oauth2/token \
-d code=$ACC_CODE \
-d grant_type=authorization_code \
-u $APP_KEY:$APP_SEC

蛇足:公式ドキュメントではredirect_uriを指定するようになっているが、指定しなくても良い。

リフレッシュトークンを使用する

以下のcurlコマンドで新しいAPIトークンを含むJSONを取得できる。

1
2
3
4
curl https://api.dropbox.com/oauth2/token \
-d grant_type=refresh_token \
-d refresh_token=$REFRESH_TOKEN \
-u $APP_KEY:$APP_SECRET$

jq -r ".access_token" とすればAPIトークンを抜き出せる。

変わっていないこと

  • 日記はMarkdown
  • hugo (extended)
  • Cloudflare Pagesに(で)デプロイ

変更前

デプロイ方法

  • 日記を書く
  • git commit & push でGitHubにpush
  • Cloudflare Pagesでhugoビルド&デプロイ
  • 日記が更新される 🏁

問題点

  • そもそも、git commit & push するのが面倒くさい。
  • ローカルで編集するためにエディタを開くのが億劫
  • そもそも、日記をObisidianに取り込みたかった

試したこと

  • github.devを使ってWeb上で編集する→ちょっとは楽になった
  • ローカルにVSCodiumを入れて日記専用にする→ナシではなかった

変更後

DropboxのAPIトークンには有効期限があるので、テスト中は以下の手順でよいが、本番のジョブを組む時はAPIトークンを再取得するようにする必要がある。
具体的には、次の記事を参照
https://zenn.dev/yakumo/articles/75d3df651d0609

前提

  • Obsidian上の日記は一つのフォルダ以下に入っている
  • ObisidianのデータはDropboxに同期されている。

デプロイ方法

  • 日記をObisidan上で書く。Obisidanは常時起動しているのですぐ書ける
  • AM3:00にご家庭内Jenkinsにより、ジョブが起動される。(Github Actionsでも何でも普通にLinux上のなにかであれば可能。もっと言えばおそらくCloudflare Pagesだけでも可能そう)
  • ジョブ内で、Dropboxから日記ディレクトリをZIPでダウンロードしてきて、githubに上げてあるhugoのテンプレート等と合体させてhugoコマンドでビルドする。
  • ビルドの出力(publicディレクトリ)を、WranglerコマンドでCloudflare Pagesに送る
  • Cloudflare Pagesが更新される 🏁

問題点

  • 更新が即時反映されない。が、今までの経験上日記を書いてcommitした瞬間にミスとか不足に気がつく傾向にあったので逆にメリットだと考えている。
  • Dropboxに特定ディレクトリが更新された時のwebhookがあるので、それを使えば更新までの時間を縮めることは出来るはず。

おまけ

これだけだと単純にやったことになるので、使用しているエンドポイントを記述する

Dropboxから特定ディレクトリをダウンロードするときのエンドポイント

以下のエンドポイントから特定のディレクトリをZIPファイルとして取得できる。
DBX_TOKENはDropboxユーザーの設定から取得可能
DBX_BLOG_PATHは、Dropboxのルートから /my_dir のように指定する
このZIPは、日本語ファイル名はShiftJISでエンコードされているので展開時注意[^1]

1
2
3
4
curl -Ss -X POST https://content.dropboxapi.com/2/files/download_zip \
--header "Authorization: Bearer ${DBX_TOKEN}" \
--header "Dropbox-API-Arg: {\"path\":\"${DBX_BLOG_PATH}\"}" \
--output article.zip

Cloudflare Wranglerで転送

転送する時は以下のコマンドで転送できる。--commit-dirty=true は、つけておかないと転送対象のディレクトリがgitリポジトリ、かつコミットされていない変更がある状態の時にファイルが転送されない。
--project-name= の部分は、Cloudflare Pagesのプロジェクト名を指定する。

1
2
CLOUDFLARE_ACCOUNT_ID=abcdefg CLOUDFLARE_API_TOKEN=wranglertoken
npx wrangler pages publish target_dir --project-name=blog --commit-dirty=true

[^1]: こちら参照(宣伝) https://zenn.dev/yakumo/articles/d85738737018f8