<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>セルフホスト on 或る阿呆の記</title><link>https://hack-le.com/tags/%E3%82%BB%E3%83%AB%E3%83%95%E3%83%9B%E3%82%B9%E3%83%88/</link><description>Recent content in セルフホスト on 或る阿呆の記</description><generator>Hugo -- gohugo.io</generator><language>ja</language><lastBuildDate>Fri, 30 Oct 2026 21:43:01 +0900</lastBuildDate><atom:link href="https://hack-le.com/tags/%E3%82%BB%E3%83%AB%E3%83%95%E3%83%9B%E3%82%B9%E3%83%88/index.xml" rel="self" type="application/rss+xml"/><item><title>AIの力を借りつつWordPressサイトをHugoに移行</title><link>https://hack-le.com/ai-wordpress-hugo/</link><pubDate>Sun, 01 Nov 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/ai-wordpress-hugo/</guid><description>&lt;p&gt;久しぶりのセルフホストな記事。&lt;/p&gt;&#10;&lt;p&gt;このブログはまだWordPressなんですが、サブブログをWordPressからHugoに移行しました。理由は主に昨今のサイバー攻撃の激化のためです。WordPressが悪いというわけではないのですが、アタックサーフェスの大きさやPHPの特性を考えると、正直これからの時代厳しいように思われました。毎日のように「プラグインの更新してないぞ」「このIPアドレスから阿呆みたいなブルートフォースアタックきてるぞ」という通知がくるのも疲れましたし。&lt;/p&gt;&#10;&lt;p&gt;なので、昔に戻ってスタティックなコンテンツ配信に徹しよう、というような感じです。&lt;/p&gt;&#10;&lt;h2 id="wordpressからhugoへ"&gt;WordPressからHugoへ&#10;&lt;/h2&gt;&lt;p&gt;今回手始めに移行したのは、AIに記事を書かせている邪悪なサイトです。こんな感じに変わりました。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/10/4c18bf39ad7feab65dab790a189436fa-699x492.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;before&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/10/8a3acbd3dd44c0b47589270fe46742b3-699x493.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;after&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;なんだかんだで移行まで3日くらいかな。正直AIなかったらしんどすぎて無理ってなったと思います。でも移行を決めたのはAIによるサイバー攻撃の激化のためなので、AIのおかげで言っていいのかどうかは微妙なところです。&lt;/p&gt;&#10;&lt;p&gt;ここからまた色々と手を加えつつ運用をして、課題を洗い出しながら、本ブログであるこのサイトの移行の準備を進めます。このサイトは14年続いているだけあって色々な歴史が不思議なHTMLタグとなって残っているため、すんなりとはいかないでしょう。AIにめっちゃ調査させながら進めていくことになるでしょうね。かなり時間がかかると思います。仕方無い。来月中にできるといいな。&lt;/p&gt;&#10;&lt;h2 id="全体の構成"&gt;全体の構成&#10;&lt;/h2&gt;&lt;p&gt;さて、構成ですが、元々の構成は極めてシンプルでした。&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;graph TD&#10;cf(Cloudflare)&#10;wp(WordPressコンテナ)&#10;cf ---&gt;|トンネル| wp&lt;/pre&gt;&lt;p&gt;これが今回、ちょっと複雑になりました。というのも、私は自作の管理アプリケーションがあり、そこで記事の執筆などもしたいためです。こんな感じのアプリでやってます。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/10/209db6e9e19dbc87e24b33e530223f49-699x501.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;記事執筆と管理系のがずらずらと。ちなみにサイトトップの古のアクセスカウンタもこのアプリケーション上でウィジェットを作っています（アクセス解析自体はOSSのUmamiを使わせていただいております）。ウィジェットのみグローバルに公開して、内部のアプリケーションはLAN内限定です。&lt;/p&gt;&#10;&lt;p&gt;執筆機能は重要です。そもそもWordPressを使っていたのも、ぶっちゃけWYSIWYGで編集してその場で公開できなきゃいやだいという運用上の理由が大きかったです。デザインはどうでもよい。なので、Hugoに移行するとしてもエディタを用意できることはマストでした。このへんはAIのおかげでやれるようになったと言っていいでしょう。&lt;/p&gt;&#10;&lt;p&gt;ただこういうややこしいことをする以上、Hugo側の管理と衝突するために、アーキテクチャはどうしても考えるところが生じます。今回は以下の構成に行き着きました。&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD&#10;subgraph Internet["インターネット"]&#10;User["閲覧者ブラウザ"]&#10;end&#10;subgraph Cloudflare["Cloudflare Edge"]&#10;CDN["Cloudflare DNS / CDN"]&#10;CFTunnel["Cloudflare Tunnel Edge"]&#10;end&#10;subgraph Server["自宅・ホストサーバー（完全閉域）"]&#10;subgraph Delivery["配信基盤 (Docker)"]&#10;TunnelApp["cloudflared コンテナ"]&#10;Caddy["Caddy Webサーバー (ポート開放なし)"]&#10;StaticFiles["静的ファイル (HTML / CSS / 画像)"]&#10;end&#10;subgraph Management["執筆・ビルド基盤"]&#10;Dashboard["Web管理画面 (Blog Dashboard)"]&#10;Hugo["Hugo (静的サイト生成)"]&#10;Source["Markdown記事"]&#10;end&#10;end&#10;%% 閲覧フロー&#10;User --&gt;|HTTPS| CDN&#10;CDN --&gt; CFTunnel&#10;CFTunnel -.-&gt;|アウトバウンド常時接続| TunnelApp&#10;TunnelApp --&gt; Caddy&#10;Caddy --&gt;|読み取り専用| StaticFiles&#10;%% 執筆フロー&#10;Dashboard --&gt;|記事保存| Source&#10;Dashboard --&gt;|ビルド実行| Hugo&#10;Source -.-&gt; Hugo&#10;Hugo --&gt;|HTML出力| StaticFiles&lt;/pre&gt;&lt;p&gt;Hugo環境はコンテナに隔離して、cloudflaredよりトンネル経由で外からアクセスする感じです。Cloudflare依存になってるやんと見えますが、まぁそうなんですが、別に使えなくなったらVPSからfrpなりなんなり使った構成に切り替えればいいだけなので、まぁいいかなと。さらに言えばサイト公開するマシンはそれ専用にする予定です（まだ徹底はできていない）。&lt;/p&gt;&#10;&lt;p&gt;そんで、記事の生成とかビルドの実行とかは、全部管理アプリケーション上でやる構成ですね。一言で言えば管理アプリケーションが正本となる構成です。Hugoリポジトリは中継地点ないしバックアップの役割になります。なのでCI/CDによるホスティングではないです。これによる制約はいくつかあります。主に運用上の制約は以下になるでしょうか。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;管理アプリケーションとHugoのホスティング環境が同一のマシン上にあること（変えてもいいんだがややこしくなり思想から外れる）&lt;/li&gt;&#10;&lt;li&gt;普段は管理アプリケーションからHugoリポジトリのpush/pullを実行するが、Hugo側のデザイン変更時（特に記事データに特殊な記法を挿入する時）はローカルのHugoリポジトリでpushする、2つのワークフローが存在すること&lt;/li&gt;&#10;&lt;li&gt;CI/CDでブランチごとにホスティングしてステージング環境作るとかはできない（できないことはないが構成と運用がややこしくなり、設計思想から外れる）&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;この制約は受け入れることになります。&lt;/p&gt;&#10;&lt;p&gt;別の考え方としてリポジトリを正本とする考え方もあり、まぁそちらのほうがアーキテクチャは綺麗になると思うんですが、なんか無駄に複雑な運用になりそうだったのでやめました。どうせ運用者も僕だし。&lt;/p&gt;&#10;&lt;h2 id="再び個人サイト激動の時代に"&gt;再び個人サイト激動の時代に…&#10;&lt;/h2&gt;&lt;p&gt;とまぁこんな感じでやっていて思ったんですが、AIで楽になったと言っていいんですかねぇ…。25年前は専門じゃなくてもやる気があれば頑張ってサイトを持つことができたと思うんですけれど、今はこれちょっとどうなんでしょう…。&lt;/p&gt;&#10;&lt;p&gt;トンネル技術とコンテナが揃った時には、個人サイトやセルフホストがまたやりやすい時代になった！と思ったのですけれど、サイバー攻撃がヤバいから守備を固めよう、WordPressはよくない、でも運用が不便になって更新しなくなったら元も子もないから利便性も高めよう、みたいなことを考え始めると、AIによる効率化以上に、トータルの難易度自体は上がり続けているような気がします…。&lt;/p&gt;&#10;&lt;p&gt;いやまぁ、僕がややこしくしているだけか。&lt;/p&gt;&#10;&lt;p&gt;これはまぁ結局、何をどこまで信じるか、という話です。少し前までだとVPSやクラウド基盤そのものを疑うのはキチガイ扱いだったかもしれないのですが、最近お名前.comデスクトップクラウドが基盤ごとやられて顧客の資産がハッカーの攻撃により消失し、さらにGMOが顧客の端末を回収するため物理的に全国を駆けずり回ったという事件は、クラウドは絶対安全ではないという当たり前の技術的な真実を曝け出しました。ま…それでAWSをはじめメガクラウドが陥落するかと言えば別にそういうわけではないですけれど、でもメガクラウドだから安全だ、は技術ではなく信仰でしょう。&lt;/p&gt;&#10;&lt;p&gt;結局個人サイトって自分の城です。城をどこにたてますか、どうなったらその城はぶち壊れますか、あなたはそれに納得できますかと、そういう話なんだと思います。絶対防御は無理なので、そのうえで何を賭けるのか。それを考え始めると、やりたいことに対して、本気でぶち壊そうとする勢力、さらにその被害が大きくなりすぎて、それが多分根本的な問題なのだと思います。&lt;/p&gt;&#10;&lt;p&gt;僕の構成がややこしくなっているのは、それだけ僕が納得するのに必要になってしまったということはあります。別にもっとシンプルな構成は可能です。元々のようにCloudflareトンネルでWordPressコンテナ直通でも良いといえばそうなので。ちゃんと更新し続けて、今回のPHP事件みたいなのがあったらキャッチアップして…ってやっても、基本は大丈夫でしょう。心配なら物理的にサイト専用のマシン作って切り離すくらいで、ほぼほぼ問題ないと言って思います（まぁそれも普通からするとややこしいわけですが…）。&lt;/p&gt;&#10;&lt;p&gt;まぁ結局どうしたいかは人それぞれということになるんですが、その構成に至る道筋や、またその構成における必要な運用はなにか、普通の人がそれを理解して辿り着くのが難しくなっているのかなぁと、そんな風に思いました。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;関連記事&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/ai-cyber-attack/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;AIによるサイバー攻撃時代の個人サイト・個人ブログのセキュリティ&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/ai-cyber-attack/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/10/eyecatch_53756_1792651216.webp" alt="AIによるサイバー攻撃時代の個人サイト・個人ブログのセキュリティ" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/aisoftware/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;AIでソフトウェアの作成は楽になったが、結局最後は泥臭い&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/aisoftware/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/eyecatch_50962_1785770655.webp" alt="AIでソフトウェアの作成は楽になったが、結局最後は泥臭い" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>ダイエット788日目：つらいこともあるけれど、ダイエットを再開</title><link>https://hack-le.com/diet-788/</link><pubDate>Wed, 09 Sep 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/diet-788/</guid><description>&lt;p&gt;ここしばらく、ダイエットどころではありませんでした。3ヶ月ほど前に急遽引越しすることになったのですが、その前後1ヶ月は引越しのドタバタでとてもそれどころではなく、引越して少し落ち着き始めたところで帯状疱疹にかかり、なおってきたところでよせばいいのに運動不足だとランニングしたら思いっきり転倒、コンクリートに左手首を強く打ち付けて、病院に行ってないものの恐らく捻挫。その後痣が消えるまで一ヶ月かかり、一ヶ月半が経過した現在も、とてもではないですが腕立て伏せやダンベルを使った筋トレなどできません。&lt;/p&gt;&#10;&lt;p&gt;さらについ先日、重い話でアレなんですが、母が癌告知を受けました。まだ検査中ですが、決して良い状況ではありません。精神的にも色々と限界がありました。しかしまぁ、まだまったく希望がないわけではないですし、私がクヨクヨとしているのは母も望まないでしょう。&lt;/p&gt;&#10;&lt;p&gt;死を考えたとき、生についても強く意識するようになりました。実際のところ、私自身、明日どうなるのかなんてわからないのだと、肌身で感じました。なんだか、ちゃんと生きたいと思われました。&lt;/p&gt;&#10;&lt;p&gt;ということで（？）、長らくストップしていたダイエット再開です。&lt;/p&gt;&#10;&lt;h2 id="なぜか専用アプリを作っている"&gt;なぜか専用アプリを作っている&#10;&lt;/h2&gt;&lt;p&gt;さて、やや断続気味ですが、体重・体脂肪率の計測は一応続けておりました。私のダイエットの定義は既に記録をつけていればOKまで下げているので、一応788日目ということになっています。だってリセットしたら、気持ちがしんどいでしょう。なんでも続けばOK。&lt;/p&gt;&#10;&lt;h3 id="体重体脂肪率イベントのチャート表示"&gt;体重・体脂肪率・イベントのチャート表示&#10;&lt;/h3&gt;&lt;p&gt;ただまぁ、冒頭に述べたとおりここしばらくは運動どころではありませんでした。だからというわけではないのですが、&lt;strong&gt;記録用のセルフホストできるWebアプリケーションを自作し始めました&lt;/strong&gt;。こんな感じです。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/09/09c4916552b7736c93542494649322ee-699x459.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;過去半年のチャート。データを入力すると、移動平均などを計算します。また、イベント…たとえば怪我をしたとか、そういうことがあればメモを入れて、グラフ上で参照し、影響を見ることができるようになりました。&lt;/p&gt;&#10;&lt;h3 id="運動管理"&gt;運動管理&#10;&lt;/h3&gt;&lt;p&gt;また、運動データについても入力できるようにしました。いや、これけっこう自分は問題意識があって、たとえばスクワットの回数を数えられるアプリは多いですけれど、「10kgx2のスクワットでやった」「自重だけでやった」は全然違うでしょう。またスクワットにしても、ゆっくりと時間をかけてやるタイプのやつは、回数よりもむしろ時間を数えたかったりしますよね。ということで、そういう機能も入れました。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/09/f56c3dbc748419b38fdb3ab68e8afa40-699x374.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;見栄えについてはまだ研究中です。ダッシュボードに運動記録も入れたいですね。&lt;/p&gt;&#10;&lt;h3 id="aiパーソナルコーチ"&gt;AIパーソナルコーチ&#10;&lt;/h3&gt;&lt;p&gt;そんできわめつけ、せっかく入力したデータがあるので、このデータと自己認識や方針をベースにして、AIにコーチングしてもらう機能を入れました。もはや何をしているのか。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/09/5b505527ce4e1c3adacbaf108e74592d-699x466.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;めちゃくちゃ分析してくれます。ライフイベントでつらいことがあったことなども斟酌して励ましてくれます。そういう現状を踏まえたアドバイスをしてくれるわけです。&lt;/p&gt;&#10;&lt;p&gt;現在、自分は怪我の影響で出来る種目に限りがあるので、いままでのトレーニングメニューではなく、スロースクワットやブルガリアンスクワットを入れてはどうか、など教えてくれるのは参考になりました。&lt;/p&gt;&#10;&lt;p&gt;まぁ適当に入れたので、まだだいぶプロンプトチューニングの余地はあるかな。というか、UI上でどういう指導をしてほしいのか、どういう観点がほしいのかを制御できたほうがよさそうです。&lt;/p&gt;&#10;&lt;h3 id="そのうち配布までやるか"&gt;そのうち配布までやるか&#10;&lt;/h3&gt;&lt;p&gt;なんでダイエットじゃなくて開発しているんだ状態ですが、ダイエットもしています( ･`ω･´)&lt;/p&gt;&#10;&lt;p&gt;現状、アプリは自分のユースケースに合わせ過ぎていますが、ライフイベントも含めた各種の統合的なデータ入力や、既に契約しているChatGPTやGeminiのサブスク枠も使えるAIパーソナルコーチ機能などを、クラウドではなく、自分のPCで完全にコントロールできるアプリは少ないように思うので、もう少し汎用化させたら、気が向いた時に配布版まで作るかもしれません。使う人がいるのかはわかりませんが…。食事管理系も入れたいなぁ。&lt;/p&gt;&#10;&lt;h2 id="食事のことタンパク質の粉を飲むのはやめた"&gt;食事のこと：タンパク質の粉を飲むのはやめた&#10;&lt;/h2&gt;&lt;p&gt;ここ数ヶ月の筋トレ事情といえば、やはりプロテインの高騰にはウンザリさせられますね。グロングの3kgホエイプロテインが17,000円してて正気か？と思いました。マンジャロでしたか、医療として必要としているのとは別に、美容のために痩せ薬を飲んで食欲を押さえつけ、それだと筋肉が落ちるからとタンパク質の粉を飲むという、わけのわからない人が大勢いて、プロテインの価格高騰に繋がっているようですね。世も末です。&lt;/p&gt;&#10;&lt;p&gt;さすがにこうなると納豆とか卵のほうがいいように思われます。別にプロテイン以外食べたらいけないわけじゃないし。&lt;/p&gt;&#10;&lt;p&gt;‥…というか、冷静に考えると、なんで僕は高い金を払ってタンパク質の粉を飲んでいたのだろうか、といまさら思いました。母の病気のこともありますが、生きるとは何か、ということを考えたとき、何をどう言い繕っても、タンパク質の粉を飲むというのが、良い生活とはどうしても思われませんでした。&lt;/p&gt;&#10;&lt;p&gt;確かに、食欲がどうしてもなかったり、ボディビルダーなどの目標があるのであれば、そういうものは必要かもしれません。しかし&lt;strong&gt;たかだか日常のダイエッターが、いったいどうして自らそんな修行めいたことする必要があるのだろう…と思った時、その答えが自分の中にはありませんでした&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;それで僕は、まぁ今残っているホエイプロテインは、あとちょっとなのでこれは利用しますけれど、あとはもう、やめようと思いました。実はソイプロテインの3kgがまだあったりしますが…これは、非常時のためのサプリメントとして、保存しておきましょうかね。&lt;/p&gt;&#10;&lt;p&gt;タンパク質の粉は現代の貴族に献上します。なんだかそれが欲しいらしいので。どうぞどうぞ。私はリアルフードをいただきます。&lt;/p&gt;&#10;&lt;h2 id="明日どうなるとしてもオレンジを食べる"&gt;明日どうなるとしてもオレンジを食べる&#10;&lt;/h2&gt;&lt;p&gt;ふと思ったことは、&lt;strong&gt;私は根本的に食に興味がないらしい&lt;/strong&gt;、ということです。なので、ベースブレッドとかも食べてました。エンジニアにはそういう人が多いと思います。&lt;strong&gt;みんな完全栄養的な粉とかパンとか冷凍飯にいきます&lt;/strong&gt;。そうでなくても、延々と同じもの、納豆を食べたり、カニカマ食べたり、なんというのか、&lt;strong&gt;食事というより栄養摂取に全振りするような感じ&lt;/strong&gt;ですね。&lt;/p&gt;&#10;&lt;p&gt;私もその傾向があります。&lt;strong&gt;いまも毎日納豆と卵食べています&lt;/strong&gt;。先日、「自分の生活を反省し、もう少し人間らしい生活をしようと思い、いまは毎日オレンジを食べるようにした」的なことを姉に言ったところ、姉から「&lt;strong&gt;毎日オレンジを食べると決めていることが既に人間的ではない&lt;/strong&gt;」と言われました。言われてみるとそうである。&lt;/p&gt;&#10;&lt;p&gt;というか&lt;strong&gt;冷静に考えてなぜ人間らしい生活からオレンジを食べるになったのか、自分でもよくわかりません&lt;/strong&gt;。多分ストレスに対抗するためにビタミンCが必要だと考えたんだと思います。全部栄養で考えてる。&lt;/p&gt;&#10;&lt;p&gt;ただオレンジを食べるのは良いことでした。オレンジは美味しいし、包丁を使うので、少し慣れます。まぁ適当に、キウイとかりんごとか梨とか、季節も見つつ、食べていきたい。特別なものを食べずとも、明日どうなっても、そうなったらそのときで、悔いのないように生きたいと、そんなことを思いました。&lt;/p&gt;&#10;</description></item><item><title>みんなが個人ブログ・サイトをつくる世界線はあるか</title><link>https://hack-le.com/jitakuserverselfhost/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/jitakuserverselfhost/</guid><description>&lt;p&gt;初心者、とはなんの初心者だろうと思いつつ、誰でも個人ブログ・個人サイトを持つ、あるいはそれに類する状況になる未来はないかと、ずっと考えています。一時期はそれは無理だと諦めたのですが、&lt;strong&gt;技術的には、2010年代、非常に難易度が高くなった時期から少しマシになっており、インターネット黎明期に個人サイトをつくっていたガッツがあれば出来るのではないかな&lt;/strong&gt;、と思われます。&lt;/p&gt;&#10;&lt;h2 id="巨大プラットフォームからの逃げ場"&gt;巨大プラットフォームからの逃げ場&#10;&lt;/h2&gt;&lt;p&gt;とはいえ簡単ではないのですけれど、それでもやりたい人は実はいるだろう、と思います。だってXもFacebookもnoteもpixivも窮屈だし、しかも煩いでしょう。ブルスカだのMastodonだのなんだのありますが、まぁちょっとやってみると、結局全部SNSやないかい、と思うわけです。まぁSNSなんでそりゃそうなんですけど。&lt;/p&gt;&#10;&lt;p&gt;SNSであるからというより、&lt;strong&gt;恐らく本質的な問題は巨大プラットフォームが寡占していること&lt;/strong&gt;に端を発している、と思います。巨大過ぎて影響力が無視できないので睨まれるけれど、巨大過ぎてまともな管理なんかできません。つまり、自重で沈んでいるんですよ、もう。&lt;/p&gt;&#10;&lt;p&gt;そうすると、選ばれなかった世界線ではあるのですが、今一度一人ひとりの自由な場ができないものかなぁ、と考えております。いま&lt;strong&gt;２つのシナリオを考えていて、数人から数百人、多くて数千人程度の小規模プラットフォームをたくさんつくる方向と、もう一つは、かつてのように個人サイトよもう一度、というシナリオ&lt;/strong&gt;です。&lt;/p&gt;&#10;&lt;h2 id="個人サイトリバイバルの現実性"&gt;個人サイトリバイバルの現実性&#10;&lt;/h2&gt;&lt;p&gt;どちらかというと小規模プラットフォームが僕の本命なのですが、ここではいったん置いといて、まずは個人サイトリバイバルはありえるのか、ということを考えます。&lt;/p&gt;&#10;&lt;p&gt;技術的には、先に述べたとおりよい環境になりました。&lt;/p&gt;&#10;&lt;p&gt;具体的には、&lt;strong&gt;安価なVPS・または自宅回線とグローバルをつなぐトンネル技術、多くのFOSSや配布されたサーバ用アプリケーション、そして知識の架け橋を繋いでくれるAI、の3つが大きい&lt;/strong&gt;です。これらによって、個人の頑張りで、非ITエンジニアでも個人ブログ・サイトは再び射程内に入ったもの、と見ています。技術的にはね。DNS周りは引き続き鬼門ではあるのですが、これは昔からですし、まぁ複雑性はあがってますけれど、AIという頼れる道具ができたので、やる気さえあれば、多分いまのほうが楽だと思います。&lt;/p&gt;&#10;&lt;p&gt;ただ問題は別のところにあるでしょう。まず&lt;strong&gt;不自由とはいえ巨大プラットフォームが既にある程度の機能を無料で提供しているのはモチベを大きく削ぎます&lt;/strong&gt;。まぁ個人的には見せかけの無料だと思いますが…無料のランチはない、とはいまさら言う事でもないんですけどね。昔は自分で発信しようと思えば、頑張るしかありませんでしたが…頑張らなくてもいい手段があるとなるとどうしても踏ん張りきれない。これは馬鹿にできません。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;それ以上に問題なのは、集客&lt;/strong&gt;でしょうか。これが非常に悩ましいのですが、既にGoogleをはじめ検索エンジンは個人ブログ・サイトを現実的に見限っています。いまから新しいサイト、検索エンジンからの流入を見込むのはかなりしんどいです。うちのブログだって、10年以上やっていますが、いまは良かった時の2割くらいですしねぇ…。それでも多分、マシなほうなんですよ。&lt;/p&gt;&#10;&lt;p&gt;かといって、もはやジャンル別サーチエンジンも、また別サイトからのリンクも、ほとんど見込めません。全部Googleが焼き払いました。焼き払った後に撤退しました。田舎のイオンかよ。そして誰もいなくなった。&lt;/p&gt;&#10;&lt;p&gt;まぁ僕らユーザも便利だと検索エンジンに飛びついてしまったので、共犯といえばそうかもしれないんですが…。Googleは違うという気持ちが20年前にはありましたが、まったく同じでしたねぇ…。&lt;/p&gt;&#10;&lt;h2 id="活路はあるか"&gt;活路はあるか&#10;&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;集客問題に解決はいったいあるんだろうか、というと、今のところは正直ないです&lt;/strong&gt;。現在は、見捨てられたとはいえ少しは検索にも引っかかるので、それに期待するしかありません。また、うちのサイトは少し（？）前からnoteに転載を始めましたが、noteの記事内にブログ記事のリンクを関連として貼ると、興味を持ってくれた方の流入はちょこちょことあります。現状それくらいしかないかなぁ。&lt;/p&gt;&#10;&lt;p&gt;ちょっと触れた小規模プラットフォームの話とも絡むんですが、個人的にはやる気のある人が再び独自の観点でサーチエンジンやリンク集をなるべく負荷を減らして作れるようなものができないか、とは思っています。&lt;/p&gt;&#10;&lt;p&gt;これはMastodonのようなものとはまったく違うものです。あれは分散型だといいますが、技術的にそのように呼ばれるものであるとして、&lt;strong&gt;社会的な概念としての分散とは違う&lt;/strong&gt;ように思われるんですよねぇ…。僕にはあれはプロトコルを中心にした一つの巨大システムに見えるんですよね。&lt;/p&gt;&#10;&lt;p&gt;そうではなくて、&lt;strong&gt;独立した個々の島と、それを勝手に繋いだり外したりするような、自由気ままなかつてあったインターネット的な世界線&lt;/strong&gt;を考えているわけです。多分似たようなこと考えて動いている人はけっこういるような気もするんですが…。&lt;/p&gt;&#10;&lt;p&gt;まぁちょっとまだまだなので、とりあえずいまは、個人ブログ・サイトをつくるための技術的な案内をつくるところから始めますかねぇ…。&lt;/p&gt;&#10;</description></item><item><title>AIプログラミングはマシンやOSを跨ぐと苦労する</title><link>https://hack-le.com/ai-os-kurou/</link><pubDate>Mon, 07 Sep 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/ai-os-kurou/</guid><description>&lt;p&gt;最近、いくつかの自前のアプリケーションについて、Mac上で動かしていたのを、Linuxに移しました。この作業自体は既に何度もやっているので、AIにもそれらを参考にさせることですんなりいくかと思いましたが、だめでした。苦労しました。&lt;/p&gt;&#10;&lt;h2 id="maclinuxへ"&gt;Mac→Linuxへ&#10;&lt;/h2&gt;&lt;p&gt;長らくメインのMac miniに自作のアプリケーションを常駐させてきました。その中には24時間稼働のアプリケーションもあります。一番重たいものでは仮想通貨トレードアプリなどそうでした。&lt;/p&gt;&#10;&lt;p&gt;これは元々、改修を即座に反映してログなど確認するには、開発マシンでそのままやるのが一番効率的だったからです。自作のアプリケーションではそんな運用でも特に問題はありませんでした。&lt;/p&gt;&#10;&lt;p&gt;とはいえ、よほど重い処理をさせるのではない限り、サーバーマシンは一定のスペックがあれば性能的には飽和するものです。もちろんCPUがよければそれだけキビキビ動くのも確かなのですけれど、多くのサーバアプリケーションのユーザは人間はではないことも多く、24時間安定して稼働できることのほうが重要です。&lt;/p&gt;&#10;&lt;p&gt;そういう次第なので、今はAIがあるしなぁと、重い腰を上げて、いまだMac miniにあったサーバアプリケーション、特に24時間稼働のものについて、Linuxサーバに移行することにしました。&lt;/p&gt;&#10;&lt;h2 id="問題はインストールと更新"&gt;問題はインストールと更新&#10;&lt;/h2&gt;&lt;p&gt;今はAIがあるので、まぁすんなりできるだろう……と、できたかどうかは、微妙なところです。&lt;/p&gt;&#10;&lt;p&gt;まず表面化したのは、&lt;strong&gt;MacとLinuxではインストールで必要なプロセスがまったく異なるため、make installの内容が全然変わってしまう&lt;/strong&gt;、ということです。まぁこれを嫌って小規模アプリケーションでもDockerなど扱う人も多いのですが、あれはあれで別の罠が色々とあるし、個人的にはなにかクリティカルな理由がなければネイティブにやります。これは低レベルの操作まで含めてAIに書かせることになるので、AIプログラミングの観点だとつらい面はあるのですが…&lt;/p&gt;&#10;&lt;p&gt;その結果がまったく異なる&lt;code&gt;make install&lt;/code&gt;ではあるのですけれど、まぁ&lt;code&gt;make&lt;/code&gt;はまさにそのためのものではあるので、それは仕方ないのかなぁと思います。そしてその面倒くささをAIは吸収してくれるのだ……。&lt;/p&gt;&#10;&lt;p&gt;というのが期待されることではあるんですけれど、最近はLinuxのインストールにも色々とパターンがあるようで、それによって権限周りで色々と嫌なことが起きます。まずsystemdについて、権限をどうするかで割れます。AIにまかせっきりだと、システム権限でやろうとしたりユーザ権限でやろうとしたりしてブレます。&lt;/p&gt;&#10;&lt;p&gt;ここらへん多分今どきは、特別な理由がなければユーザ権限になるのかなぁと思うのですが、昔はシステム権限が普通だったはずなので、&lt;strong&gt;時間の切り刻まれたAIにおいては対応が確率で混ざってしまう&lt;/strong&gt;のでしょうか。&lt;/p&gt;&#10;&lt;p&gt;しかもシステム権限にするとsudoの権限問題なども出てくるのですが、その対応について問うと&lt;code&gt;sudo ALL=(ALL) NOPASSWD: ALL&lt;/code&gt;などとんでもないことをしれっと提案してきて「この計画で進めてよろしいでしょうか」よろしくないぞ。&lt;strong&gt;スナック菓子感覚で大いなる力を使おうとするな&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;h2 id="全然違うものを参考にするというか模倣する"&gt;全然違うものを参考にするというか模倣する&#10;&lt;/h2&gt;&lt;p&gt;他にも「むむむ」と思ったのが、Mac→Linux移行はこれまでさんざっぱらやってきたので、他のプロジェクトを参考にするようにいったのですが、すると今度は技術選定が全然違うものを参考にしてカオス。&lt;/p&gt;&#10;&lt;p&gt;具体的には、Go言語による生成物がシングルバイナリなシンプルなアプリケーションがあり、それはインストールの過程でバイナリをmvするというもので、まぁシングルバイナリならそれはそれでいいわけです。&lt;/p&gt;&#10;&lt;p&gt;しかし今回のアプリケーションはNext.jsなど使っており生成物が色々あるわけなのですが、それをいろいろなexcludeを付与したrsyncコマンドを羅列して無理やり同期させようとしており、そんなことして良いはずがなく、「なんでそんなことするの」と聞いたところ、シンプルなシングルバイナリのやり方を何も考えずに真似してしまいました、とのことで。oh&amp;hellip;&lt;/p&gt;&#10;&lt;p&gt;なんというか残念な新卒のような振る舞いです。まぁこちらの指示の仕方が甘いといえばそうなのでしょうし、実際こちらで参考にすべきプロジェクトを精査してどこをどう参考にすべきなのか指示すれば通った、と思います。でもそんな細かな指示を毎回するのしんどいなぁと思うし、そもそもAIはうまくいくときは任せとけとばかりにいい感じでやってくれることもまぁあるのです。&lt;/p&gt;&#10;&lt;h2 id="aiの暴走"&gt;AIの暴走&#10;&lt;/h2&gt;&lt;p&gt;たまに暴走するのは、確率の問題なのか、それともこちらの意図が変な普通に伝わって妙な制約を生んでしまうのか、多分両方あるのでしょうけれど、なんとなく肌感で「なんか迷走しそう」と思った時はだいたい迷走する感じです。人間のこの感覚はなんなのでしょうね。&lt;/p&gt;&#10;&lt;p&gt;まぁ私のつくる小規模アプリケーションならば、迷走暴走大爆走したところで大したことにはそうなりませんが、エラい人たちが金と時間をかけて作ったサンドボックス内での実験でも、AIが脱獄紛いのことをして現実のシステムを食い荒らす、というような事故（？）が起きているので、元より完全に制御するというのが無理なのでしょう。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://www.itmedia.co.jp/news/article/2608/30/2000000949/" target="_blank" rel="noopener"&#10; &gt;Hugging Face侵害事件、OpenAIとMETRが最終報告書公開──約1200体のAIエージェントが“闇掲示板”で結託し700体が攻撃に参加 - ITmedia NEWS&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;それでもずっと使っているとなんだかコイツ（Model）のことわかってきたような気がする錯覚かもしれない感覚が生じるのですが、生じたあたりでどうせモデルチェンジなので、なんだかいつになっても悩みの質は変わらない感じですね。&lt;/p&gt;&#10;</description></item><item><title>AIプログラミングでも結局APIの責務で悩む</title><link>https://hack-le.com/ai-programming-api/</link><pubDate>Tue, 01 Sep 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/ai-programming-api/</guid><description>&lt;p&gt;現在公開に向けて、D-Shelf（仮）というメディア管理プラットフォームのセルフホストアプリを開発中です。で、これは基本的にWeb UIで操作するのですけれど、やはり&lt;strong&gt;外部アプリとの連携&lt;/strong&gt;もやりたい。すると、APIを用意するかなと思いました。&lt;/p&gt;&#10;&lt;p&gt;元々の設計として、フロントエンドとバックエンドにわけて、その疎通はAPIでやっていました。なので、何もわざわざ新しく作らずとも、今あるAPIのうちいくつかをドキュメント化すれば十分であるように思えます。AIに聞いても、この規模のアプリケーションならばそれが合理的との回答です。&lt;/p&gt;&#10;&lt;p&gt;そんでまぁ作ってくれと言ったら、秒で作ってくれました。大したものです。で、それはすぐに使えたのですが、いざ実行してみると、想定と動作がちょっと異なる。&lt;/p&gt;&#10;&lt;p&gt;具体的には、たとえば「[作家名] 作品名/作品名 1巻.pdf」みたいなファイルがあったとすると、これについて「作家名 -&amp;gt; 作品名 No.1」のような階層構造を推定して登録したかったのですが、実際にAPIで動かすとそうはなりませんでした。階層構造が推定されず、そのままの名前で登録されてしまったのです。&lt;/p&gt;&#10;&lt;p&gt;なので、AIに「Web UIで登録した時の挙動と異なる」と聞いたところ、どうやら「階層構造の推定はフロントエンドでやっていたため、そのロジックがスクリプトから漏れました」とのことでした。なるほど。&lt;/p&gt;&#10;&lt;p&gt;これはもっともな話です。&lt;strong&gt;ファイル名から階層構造の推定をするのが、バックエンドの仕事なのか、フロントエンドの仕事なのか、これは確かに、ちょっと微妙&lt;/strong&gt;です。個人的には、APIの仕事は最小にしたいところです。そのほうが汎用的だからです。しかしそれだと、当然スクリプトは作り込みが発生します。また、Web UIロジックとの違いから、管理にばらつきが生じるかも。&lt;/p&gt;&#10;&lt;p&gt;うーん……などと思っていたところで、なんか10年前から考えていること変わらないな、と思いました。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/endpoint/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;Web APIのエンドポイントを考えるときの自分の指針&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/endpoint/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/eyecatch_7715_1787720764.webp" alt="Web APIのエンドポイントを考えるときの自分の指針" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;まぁつまりこれは&lt;strong&gt;Web APIというものの、原理的に正解のない問題&lt;/strong&gt;なのであって、どう対応するかはアプリケーションのポリシーであり開発者の思想に基づきます。まぁ実際には、これこれの合理的な理由があるからだと自他を納得させる理屈付けをします。AIに言えば多分「こうするのが合理的です」と推奨案を出してくれます。それは参考になるかもしれません。しかし、僕は今回それについてはただ僕がそのまま考えようと思いました。&lt;/p&gt;&#10;&lt;p&gt;この問題は&lt;strong&gt;多分、突き詰めると、思想&lt;/strong&gt;なんです。誰が何をすべきなのか。客観的なのはそのトレードオフだけで、そのスライドバーの調整に正解などありはしません。&lt;strong&gt;それを突き詰める思想の根幹がまだアプリケーションの中に根付いていないままに、AIの判断を仰ぎたくはない&lt;/strong&gt;、と思いました（僕は作りながらいったい自分は何を作っているんだろうと考えるタイプなのです）。&lt;/p&gt;&#10;&lt;p&gt;そんなようなことを考えていると、&lt;strong&gt;何も変わらないなぁと思う一方、スニペットをAIが秒で作ってくれるという前提にたったとき、調整の仕方はやはり変わる&lt;/strong&gt;ように思われます。つまりAIにとって明確でわかりやすく取り回しの良い仕様のほうが良いはずで、そこから生じる複雑なスクリプト、これはAIは得意ですから、トレードオフとして問題が少ないように思われました。&lt;/p&gt;&#10;&lt;p&gt;もちろん、&lt;strong&gt;Web UIとのロジックの差分を完全に吸収できるか（またそもそもすべきなのか）といったことや、通信量、通信回数からくるパフォーマンスとコストの違いのような物理面は根源的な問題として残ります&lt;/strong&gt;ので、完全解決というわけではないんですけれど、「粒度の小さなAPIだと実装自体に手間がかかる」という問題についてはかなりの部分解決するわけです。これは実務上大きな違いだと思います。&lt;/p&gt;&#10;&lt;p&gt;そう考えると、&lt;strong&gt;AI時代においては、APIは小さく保ちつつ、どこでどういうロジックが任せられているのか、その根幹たる思想はなにか、ユーザにわかるようにすることが大事&lt;/strong&gt;かもしれませんね。そして&lt;strong&gt;今後、AIの処理能力次第によって、スライドバーの調整は絶え間なく変わっていく&lt;/strong&gt;ことでしょう。スライドバーがある事自体は、変わりませんが。もしかするとスライドバーの調整までほとんど不要になる時は来るかもしれないのですが、それでもその存在だけは、認識を続ける必要があると思います。&lt;/p&gt;&#10;</description></item><item><title>セルフホストしたアプリをマシン移行する汎用的な仕組みについて考える</title><link>https://hack-le.com/selfhost-migration/</link><pubDate>Mon, 31 Aug 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/selfhost-migration/</guid><description>&lt;p&gt;現在VPS上で、仮想通貨の自作トレードアプリを稼働しています。これは元々自宅サーバでやっていたのですけれど、引越しのときに数日から下手すると10日以上のダウンが見込まれたので、その間に相場の急変があったらたまらないということで、VPSに移行しました。&lt;/p&gt;&#10;&lt;h2 id="アプリケーションを動作させるマシンを移行したい"&gt;アプリケーションを動作させるマシンを移行したい&#10;&lt;/h2&gt;&lt;p&gt;で、ようやく環境も落ち着いてきたので、いつまでもグローバル空間に置く必要はないし、自宅サーバに戻そうと考えています。もちろん手順を踏めばすぐできるんですけれど、ここで、少し汎用的に考えられないか、と思いました。セルフホスト勢にとってマシン移行は常に生じる汎用的な悩みです。&lt;/p&gt;&#10;&lt;p&gt;実際、このサイトはWordPressをセルフホストしているのですが、VPS,ConoHaの大規模障害（永遠にこする）や引越し前後において頻繁に引越しをしています。それはやはり面倒くささがあったわけです。&lt;/p&gt;&#10;&lt;p&gt;個人的には、マシンの移行はもっと気軽にやりたい、という思いがあります。それはもしもの役にも立つでしょう。何をやるべきで、何をやらないのか、自動化できる部分はなにか、自動しない部分はなにか、そういうことを汎用的に考えたい、と思いました。&lt;/p&gt;&#10;&lt;h2 id="中継地点を介した移行"&gt;中継地点を介した移行&#10;&lt;/h2&gt;&lt;p&gt;考えたところ、基本的には以下のような中継地点を挟むものになると思います。&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;graph LR&#10;mA(移行元)&#10;mB(移行先)&#10;st(中継地点)&#10;repo(リポジトリ)&#10;mA --&gt;|push| st&#10;st -.-&gt;|pull| mB&#10;repo -.-&gt;|pull| mB&lt;/pre&gt;&lt;p&gt;この絵がすべてです。&lt;/p&gt;&#10;&lt;p&gt;なんでダイレクトに送らないのかと言うと、&lt;strong&gt;移行元から移行先にダイレクトにpushできる権限があるとは限らない&lt;/strong&gt;、からです。これは完全に自宅サーバしか使わない！というならダイレクトでいいかもしれませんが、実際には自宅が使えなくなることはあります（今回の場合）し、アプリケーションによっては自宅サーバはやめたほうがよいものもあります。&lt;/p&gt;&#10;&lt;p&gt;なので、移行元からpushできて、移行先がpullできる、そういう中継地点を用意するのが汎用的です。この&lt;strong&gt;中継地点の役割は、アクセス制御と一時的なストレージ&lt;/strong&gt;、ただそれだけです。グローバルなアクセスが必要ならS3のようなクラウドサービスでもいいですし、VPSでもいいでしょう。移行元も移行先も同一ネットワークなら、わざわざ外に出す必要はなく、両者がSSHで通信できるサーバならなんでもいい。&lt;/p&gt;&#10;&lt;p&gt;具体的な作業自体は、アプリケーションごとに個別で判断します。この切り分けによって、搬出と搬入のタイミングをずらせるとか、データの整理が明確になるといった副次的な効能もあります。&lt;/p&gt;&#10;&lt;p&gt;ここで重要なことは、何を引越して何を引っ越さないのかを明確に切り分けることです。具体的には、以下の3つに分かれると思います。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;リポジトリから引き継ぐ&#10;&lt;ul&gt;&#10;&lt;li&gt;ソースコードや設定ファイルのテンプレートなど&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;ファイルの移行で引き継ぐ&#10;&lt;ul&gt;&#10;&lt;li&gt;エクスポートしたファイルやデータストアやアプリケーションログなど&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;引き継がない&#10;&lt;ul&gt;&#10;&lt;li&gt;OS/インフラの差分に基づく設定ファイルなど&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;それぞれ何が対象となるかはアプリケーションごとに変わるでしょう。すべてのパターンを考えて統一的にやろうとしないことです。また、引き継げない部分がある以上全自動の夢も捨てるのが筋です。変に自動的に翻訳するみたいなことするのはトラブルの元です。セルフホストでそこまでする必要があることは皆無ですし、もしやる場合は差分が出なくなるように環境から選定すべきでしょうね。&lt;/p&gt;&#10;&lt;p&gt;そのうえで手順は以下のように言えるでしょう。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;移行元と移行先で、リポジトリから引き継ぐものをアップデート&lt;/li&gt;&#10;&lt;li&gt;移行元をstopして、中継地点に搬出&lt;/li&gt;&#10;&lt;li&gt;移行先に、中継地点から搬入&lt;/li&gt;&#10;&lt;li&gt;データのインポート、差分の編集&lt;/li&gt;&#10;&lt;li&gt;移行先で動作開始&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;自前で開発したものか、あるいは他人が開発したものを使わせてもらっているか、色々あると思いますが、この手順に集約できるかと思われます。&lt;/p&gt;&#10;&lt;p&gt;この方法は基本的にダウンタイムが生じます。工夫次第で発生させないのも可能かと思いますが、セルフホストでそこまで頑張る意味は薄いんじゃないでしょうか。&lt;/p&gt;&#10;&lt;p&gt;とはいえダウンタイムは短いほうがよいので、短くするなら差分の編集は搬出前にやると良いのですけれど、個人的には搬入後に揃ってからのほうがいいかと思います。搬入のどさくさで差分が上書きされるリスクや、また何かしら動かさないと編集できないとかもありえるので…。&lt;/p&gt;&#10;&lt;p&gt;データのインポートはファイルシステムレベルなのか、アプリケーションレベルで実行したほうがいいのか、これもアプリケーションによるでしょうねぇ…。まぁ、都度判断ですね。&lt;/p&gt;&#10;&lt;h2 id="まとめ"&gt;まとめ&#10;&lt;/h2&gt;&lt;p&gt;ここまでの流れをやや詳細に図示すると以下になります。&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TB&#10;subgraph Repo["コード管理"]&#10;Code["ソースコード / 設定テンプレート"]&#10;end&#10;subgraph Relay["中継地点"]&#10;ExportData["エクスポートデータ / DBダンプ / アプリログ"]&#10;end&#10;subgraph Source["移行元"]&#10;SrcApp["アプリ停止"]&#10;SrcData["データ抽出・ダンプ"]&#10;SrcEnv["【破棄】OS・インフラ固有設定"]&#10;end&#10;subgraph Target["移行先（自宅サーバなど）"]&#10;TgtEnv["【新規作成】OS・インフラ固有設定の編集"]&#10;TgtApp["アプリ起動・動作検証"]&#10;TgtData["データインポート"]&#10;end&#10;%% コードの流れ&#10;Code --&gt;|Pull| Source&#10;Code --&gt;|Pull| Target&#10;%% データと状態の流れ&#10;SrcApp --&gt; SrcData&#10;SrcData --&gt;|Push / アップロード| Relay&#10;Relay --&gt;|Pull / ダウンロード| TgtData&#10;TgtData --&gt; TgtEnv&#10;TgtEnv --&gt; TgtApp&#10;%% スタイル&#10;classDef storage fill:#e1f5fe,stroke:#0288d1,stroke-width:2px;&#10;classDef nodeBox fill:#f5f5f5,stroke:#616161,stroke-width:1px;&#10;class Repo,Relay storage;&#10;class Source,Target nodeBox;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;やることは、事前準備として「リポジトリからpullするもの、中継地点で飛ばすもの、直接編集するもの」の切り分け。そのうえで5つの手順の具体的な操作の当てはめ&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;整理してみると、当たり前といえば当たり前なんですが。あらかじめ分類したものを適合させるだけだと思ったほうが、脳の負荷が多少下がるので…。&lt;/p&gt;&#10;&lt;p&gt;とりあえず、トレードアプリから移行するかー。手順を抽象化したところで具体化するのは結局めんどくさいのであった。というより、そういう面倒くささを残したところが肝なのですが…。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;関連記事&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/selfhost-webapps-down/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;セルフホストしたWebアプリになぜかうまくアクセスできない時のチェック&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/selfhost-webapps-down/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/eyecatch_51092_1786019542.webp" alt="セルフホストしたWebアプリになぜかうまくアクセスできない時のチェック" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/selfhosted-susume/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;セルフホストのすゝめ&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/selfhosted-susume/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>PC内にある画像を閲覧しながら、スクリプト処理や削除処理を実行できるセルフホストのWebアプリケーション『LoPiQ』を公開しました</title><link>https://hack-le.com/lopic-pub/</link><pubDate>Sat, 29 Aug 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/lopic-pub/</guid><description>&lt;p&gt;&lt;strong&gt;セルフホストの画像閲覧・管理用Webアプリケーション『LoPiQ（ローピック）』&lt;/strong&gt; を公開しました。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://lopiq.app.hack-le.com/" target="_blank" rel="noopener"&#10; &gt;LoPiQ&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;LoPiQはLocal, Picture, Quickを謳った、&lt;strong&gt;PC内にある大量の画像を、いつでもどこでも、PCのみならずスマホやタブレットからでも、閲覧・整理することを目的にしたセルフホストのWebアプリケーション&lt;/strong&gt;です。写真を多く撮影する人、画像や素材集めをしている人、またAIイラストを利用している人など、大量の画像を見ながら定型的な処理をする人に向いています。&lt;/p&gt;&#10;&lt;p&gt;Linux(Debian/Ubuntu/Mint系)およびMac用のみを公開していますが、Windows版についても公開を検討しています。&lt;/p&gt;&#10;&lt;h2 id="lopiqの特徴"&gt;LoPiQの特徴&#10;&lt;/h2&gt;&lt;p&gt;LoPiQの大きな特徴は2つあります。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;1つは、サーバを必要とするWebアプリケーションであること&lt;/strong&gt;です。これは、PC内にある画像ファイルについて、PCのみならず、ネットワーク内のスマートフォンやタブレット端末から操作することを目的としています。また、PC自体が処理を実行することで、PCの持つスペックを最大限発揮できます。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;もう1つは、スクリプトによるカスタムアクションを自分で定義できること&lt;/strong&gt;です。これによって、たとえば画像をWebPにコンバートする、白色化・グレースケールにする、任意のフォルダに移動する、オンライン・ストレージにアップロードするといったことを、画像を見ながらテンポよく実行することができます。コマンドは任意のキーボードショットに割り当てられ、全画面でプレビューしながら、画像ごとにアクションを振り分けられます。&lt;/p&gt;&#10;&lt;p&gt;なおカスタムアクションでは定義しづらいコマンドとして、ダウンロードボタンと、クリップボードに画像をコピーするボタンはビルトインで備わっています。それ以外のコマンドはすべてカスタムすることになります。&lt;/p&gt;&#10;&lt;p&gt;このように、&lt;strong&gt;ユーザが責任を持ってコマンドを作成・管理することで、マシンの力をフルに発揮して、最大の効率を達成する&lt;/strong&gt;ことを目的としています。&lt;/p&gt;&#10;&lt;p&gt;これらの特徴から、むしろ&lt;strong&gt;コマンド実行のできるファイラのような印象&lt;/strong&gt;を抱かれた方もいらっしゃるかもしれません。まさに、ビューアというより、本質的にはファイラに近い性質を持っています。エンジニア向けに言うと、本アプリは「Linux/Macのコマンドライン環境をWeb UIでラップしてスマホからも叩けるようにした作業自動化・効率化のためのスクリプト実行基盤」と言えます。&lt;/p&gt;&#10;&lt;h2 id="aiと相談しながら自分専用のコマンドを生成"&gt;AIと相談しながら自分専用のコマンドを生成&#10;&lt;/h2&gt;&lt;p&gt;コマンドについては、&lt;strong&gt;Linux/Macについてはシェルスクリプトを利用します&lt;/strong&gt;。したがって、シェルスクリプトについて一定の知識と調べられることが前提となり、敷居が高く感じられるかもしれません。&lt;/p&gt;&#10;&lt;p&gt;以前までならそうだったでしょうが、&lt;strong&gt;現在はAIを利用することで、非常に簡単にコマンドをつくることができるようになりました&lt;/strong&gt;。シェルスクリプトは長年使われてきた汎用的な知識であり、仕様についても固まっているため、商用AIの無料枠でも非常に高い精度での返答が期待できます。&lt;/p&gt;&#10;&lt;p&gt;本アプリケーションはOpenAIのAPIに対応しており、API Keyを持っていれば、アプリケーション内で、マニュアルに即した形でのAI相談が可能です。たとえば、 &lt;strong&gt;「画像を90度回転するボタンを作りたい」とアプリケーション内でAIに相談するだけで、設定すべき内容が即座にかえってきます&lt;/strong&gt;。そのまま登録まで可能です。&lt;/p&gt;&#10;&lt;p&gt;ただし、新しいコマンドの実行については、まず検証し、意図しない破壊的な処理が行われないことを、丁寧に確認してください。その危険性についてもAIは教えてくれますが、大切なデータにかかることですので、バックアップのうえでの検証が非常に重要です。&lt;/p&gt;&#10;&lt;p&gt;AI対応については、今後の更新でより拡張していく予定です。&lt;/p&gt;&#10;&lt;h2 id="インストールと実行"&gt;インストールと実行&#10;&lt;/h2&gt;&lt;p&gt;配布サイトより、インストーラを実行します。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://lopiq.app.hack-le.com/" target="_blank" rel="noopener"&#10; &gt;LoPiQ&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;実行すると、ブラウザの &lt;code&gt;http://localhost:13180&lt;/code&gt; よりアクセスできるようになります。localhostではなくIPアドレスを指定することで、LAN内の他PCやスマホ・タブレットからもアクセス可能です（環境によっては別途ポート開放が必要です）。望まないアクセスについては、パスワードを設定して保護することができます。&lt;/p&gt;&#10;&lt;p&gt;Linux版はsystemdの管理で常駐し次回から自動で起動します。また、今後のアップデートはWeb UI上から可能です。一方でMac版は自動起動の設定はありません。また、アップデートについては通知のみとなり、手動で実行する必要があります。詳細は配布サイトのガイドをご参照ください。&lt;/p&gt;&#10;&lt;p&gt;Windows版は現在準備中です。Windows版については、私が普段このアプリケーションをMac/Linux上で使っているため、検証しきれておらず、今回の公開は見送りとなりました。&lt;/p&gt;&#10;&lt;h2 id="開発のai利用について"&gt;開発のAI利用について&#10;&lt;/h2&gt;&lt;p&gt;本アプリケーションはほとんどAIを利用して開発しました。元々の開発は2年以上前まで遡り、当時はツールも熟れておらず、コードも見ていましたが、現在はツールが発達し、コーディングエージェントの性能が飛躍的に変わったことを受けて、私の開発スタイルも大きく変わりました。現在は専ら設計とテストのみ自分でやり、コーディングは全部AIです。&lt;/p&gt;&#10;&lt;p&gt;現在メインのツールはGoogleのAntigravityで、モデルはGemini 3.x FlashおよびClaude Opus 4.6です。Googleが良いというわけではありませんが、セールで安かったので利用しています。個人開発としては十分だと思います。&lt;/p&gt;&#10;&lt;h2 id="今後の更新について"&gt;今後の更新について&#10;&lt;/h2&gt;&lt;p&gt;LoPiQは私が日常的に利用しているアプリケーションを、多くの人が使えるように公開向けに手直ししたものです。既存のビューアやファイラでは、機能やパフォーマンス、安定性で満足がいかず、自分で作り始めました。なんだかんだで2年以上使っています。したがって、自分自身がまず最大の顧客ですから、今後も継続的に開発を続けていきます。&lt;/p&gt;&#10;&lt;p&gt;コマンドについては、AIに相談できるとはいえ中々難しい面があるように思われますので、今後プラグイン化し、公開サイトからよくあるコマンドをダウンロードして適用できるような形を考えています。&lt;/p&gt;&#10;&lt;p&gt;そもそも対象ファイルを画像に限定する意味ももはや薄れている気もするのですが、対象を広げてしまうと考えることも増えるため、元々のユースケースから、画像ファイルのみ対象としているものの、今後全ファイルを対象とする可能性はあります。&lt;/p&gt;&#10;&lt;p&gt;もしバグなどありましたら、サイトのどこかにコメントするか、管理人の連絡先メールアドレスまでご連絡ください。&lt;/p&gt;&#10;</description></item><item><title>【脱Google？】Google抜きで古のアクセスカウンタを設置できる、そうAIならね</title><link>https://hack-le.com/google-umami/</link><pubDate>Fri, 28 Aug 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/google-umami/</guid><description>&lt;p&gt;&lt;strong&gt;アクセス解析といえばみんな大好き過ぎて涙目で泡吹いているGA4ことGoogle Analytics&lt;/strong&gt;なんですが、当サイトはマイブームだった脱Googleの流れで利用をやめました。まぁこれに関しては脱Googleというより、&lt;strong&gt;純粋に使いづらかったからやめた&lt;/strong&gt;面もあります。GA4は個人サイトのアクセス解析としてはあまりにも重すぎて意味不明、最初からGA4だったら誰も使わなかったんじゃないのこれ、と思います。&lt;/p&gt;&#10;&lt;h2 id="umamiの導入"&gt;Umamiの導入&#10;&lt;/h2&gt;&lt;p&gt;それから当サイトではWordPressのプラグインのお世話になっていたんですけれど、最近、セルフホストできるUmamiを導入しました。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/umami-wordpress/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;セルフホストしたUmamiでWordPressサイトのアクセス解析&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/umami-wordpress/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/image.png" alt="セルフホストしたUmamiでWordPressサイトのアクセス解析" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;これでWordPressプラグインに頼らず、またWordPress以外のあらゆるサイトについて一括してアクセス解析ができるようになりました。有り難いことです。&lt;/p&gt;&#10;&lt;p&gt;UmamiはAPIを利用できるので、サイト内の記事のアクセスランキングなどもつくれます。ま、WordPressで実現しようと思ったらカスタムフィールドとかいじる必要あると思いますが…当サイトはもともと別に独自実装で入れていたものがあるので、それを流用することでランキング生成のバックエンドもサクッとUmamiベースに置換できました。&lt;/p&gt;&#10;&lt;h2 id="アクセスカウンタをもう一度"&gt;アクセスカウンタをもう一度&#10;&lt;/h2&gt;&lt;p&gt;作業中、&lt;strong&gt;もしかして古のアクセスカウンタを設置できるのかなぁ&lt;/strong&gt;、とふと思いました。アクセスカウンタって古代文明の名残みたいな感じかもしれませんが、というか若い人はもしかすると存在を知らないかもしれませんが、昔の個人サイトはたいていあったものです。&lt;/p&gt;&#10;&lt;p&gt;アクセスカウンタが消えたのは、需要が消えたから、ではないと思います。実際、PVランキング自体はけっこう色々なサイトで今でもありますよね。というかWordPressでもアクセス解析プラグインはたくさんあります。&lt;/p&gt;&#10;&lt;p&gt;だったらアクセスカウンタもあっていいじゃない、と思うわけですが、アクセス解析で覇権を取ったGoogle AnalyticsのAPIを追従しながら頑張って設置するにはちょっと情熱が必要になります。API権限の管理問題で、どうしても煩雑になりますよね。まぁ少なくとも、私は今までやる気にはならなかったですねぇ。&lt;/p&gt;&#10;&lt;h2 id="aiが一晩でやってくれました"&gt;AIが一晩でやってくれました&#10;&lt;/h2&gt;&lt;p&gt;しかし今は、今までとは違う。セルフホストの環境が完全に整っており、さらにAIがある。このセットによって、今までならば「できるだろうけどめんどくさいなー」ということで半年の放置不可避だったものが、爆速でそれらしいものが出来上がる。&lt;/p&gt;&#10;&lt;p&gt;ということで、GeminiにUmamiのAPIをつかったアクセスカウンタのジェネレータを作ってもらいました。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/08/image-6-700x616.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;若干の調整は発生しましたが、ジェバンニも真っ青の凄まじいスピードでつくってくれました。これは嬉しい。HTMLの埋め込みタグ一つでアクセスカウンタが設置できます。&lt;/p&gt;&#10;&lt;p&gt;そして当サイトに古のアクセスカウンタがのっかりました。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/08/image-7-697x187.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;ふふふ。00年代感。&lt;/p&gt;&#10;&lt;p&gt;これは既に作っていたサイト管理用Webアプリを土台にして作ったのですが、機能的には独立しているので、切り離せば誰でも使える形になります。なので気が向いたら分離しようかな…と思ったりもしますが、これの場合、通常一番の障壁はどっちかっていうとUmamiをセルフホストすることでしょうね(^_^;)&lt;/p&gt;&#10;&lt;p&gt;まぁUmamiも結構な頻度で更新しているようなのですが、バージョン固定できますし、&lt;strong&gt;Googleの気分に振り回されず、自分のやりたい解析ができて、解析結果もAI使えば存分に利用可能&lt;/strong&gt;、というのは、これはかなり魅力的ではないでしょうか。&lt;/p&gt;&#10;&lt;p&gt;AI使ってなんだかんだと喧しい世の中ですが、そんな派手なことしなくても、確かに自分にとって役立つものができるので、そういうことを人にも勧めていきたいですねぇ。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;関連記事&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/2022-ga/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;2022年改正個人情報保護法でGoogle Analytics使うのに結局同意ポップアップはいるのかいらないのか&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/2022-ga/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2022/04/77facb44116fc4217274ff52525b8254.webp" alt="2022年改正個人情報保護法でGoogle Analytics使うのに結局同意ポップアップはいるのかいらないのか" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/httptohttps/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;結局サイトをhttps対応させました&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/httptohttps/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2016/11/f87bbb3a69696219efe976c987643be6.webp" alt="結局サイトをhttps対応させました" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>楽天ひかり + TP-Link Archer AX5400(AX73) + クロスパスで高速通信の設定</title><link>https://hack-le.com/rakutenhikari-tp-link-archer-ax5400ax73-xpass/</link><pubDate>Sat, 22 Aug 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/rakutenhikari-tp-link-archer-ax5400ax73-xpass/</guid><description>&lt;p&gt;なんかもう忘れている気もするが覚えいてる限りのメモ。&lt;/p&gt;&#10;&lt;h2 id="楽天ひかりとクロスパスについて"&gt;楽天ひかりとクロスパスについて&#10;&lt;/h2&gt;&lt;p&gt;楽天ひかりはクロスパス（Xpass）対応のルータを自分で用意しないといけないのだが、最近のそこそこクラスなら多分対応している。AX5400も対応している。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/B0C9PZBQVJ?language=ja_JP&amp;amp;linkCode=ll1&amp;amp;ref_=as_li_ss_tl&amp;amp;tag=hackle12-22" target="_blank" rel="noopener"&#10; &gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://m.media-amazon.com/images/I/91yMZ8vZ5vL._AC_.jpg"&gt;&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://www.amazon.co.jp/dp/B0C9PZBQVJ?language=ja_JP&amp;amp;linkCode=ll1&amp;amp;ref_=as_li_ss_tl&amp;amp;tag=hackle12-22" target="_blank" rel="noopener"&#10; &gt;WiFiルーター TP-Link 無線LANルーター Wi-Fi6対応 AX5400 EasyMesh WPA3 Archer AX73V 【Amazon限定 / 3年メーカー保証 / PS5・Switch・ iphone 対応】&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;※Amazonアソシエイトリンクを使用しています&lt;/p&gt;&#10;&lt;p&gt;これの商品写真が、僕の持っている宇宙船みたいなやつと違うんだけど型番同じなんだよなぁ。&lt;/p&gt;&#10;&lt;p&gt;まぁそれはいいとして、このクロスパスについて超ざっくりAIに伺いつつ聞いたところ、つまりIPv4 over IPv6で、IPv4のWebサイトもIPv6でやりとりするための技術の一つ、になるらしい。なにかというとIPv4をカプセル化してIPv6のデータに包み込むわけだ。IPv6のほうが接続ルート的に空いてて繋がりやすいため、高速接続に対応する。&lt;/p&gt;&#10;&lt;p&gt;つまり&lt;strong&gt;クロスパスに対応してないと楽天ひかりの本気は出せない&lt;/strong&gt;わけだ。そしてルータの設定をするうえでも、IPv4 over IPv6の実装の一つだということは理解しておく必要がありそうだ。&lt;/p&gt;&#10;&lt;p&gt;なお自分は、自宅サーバ勢でちょっと事情があってIPv4でやっていたため、&lt;strong&gt;ルータでIPv6を切っていた。この時点で暗雲立ち込める&lt;/strong&gt;。まぁとりあえずIPv6はしゃーなしで有効化しますわな。&lt;/p&gt;&#10;&lt;h2 id="繋がるまでにやること"&gt;繋がるまでにやること&#10;&lt;/h2&gt;&lt;p&gt;さて、色々特殊な設定をしていたせいか、工事の人いわく「繋がってるはずなんですけど、ネット使えないですね。まぁ電話サポート一回できるんで」とそそくさと帰っていった。まぁ僕もおまかんの自覚はあったから別によい。&lt;/p&gt;&#10;&lt;p&gt;とりあえず &lt;code&gt;http://192.168.0.1&lt;/code&gt;なりなんありルータのアドレスにログイン。&lt;/p&gt;&#10;&lt;h3 id="ipv6は有効化する"&gt;IPv6は有効化する&#10;&lt;/h3&gt;&lt;p&gt;とりあえずしゃーなし。あまり切っている人はいないと思われるが…。まぁIPv4限定にしていたのもちょっと特殊な事情があったからなので、もういいんです。「詳細設定」の「IPv6」から&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/08/image-2-700x195.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;動的IP（SLAAC / DHCPv6）を選択。&lt;/p&gt;&#10;&lt;h3 id="接続タイプをds-liteに設定する"&gt;接続タイプをDS-Liteに設定する&#10;&lt;/h3&gt;&lt;p&gt;詳細設定の「ネットワーク」よりインターネット接続タイプを「DS-Lite」、AFTRは「自動」。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/08/image-3-700x255.png"&gt;&lt;/p&gt;&#10;&lt;h3 id="再起動"&gt;再起動&#10;&lt;/h3&gt;&lt;ol&gt;&#10;&lt;li&gt;NTTから配られたONUとAX5400をそれぞれ電源抜く&lt;/li&gt;&#10;&lt;li&gt;数分放置&lt;/li&gt;&#10;&lt;li&gt;ONUを電源投入、ランプが安定するまで待つ&lt;/li&gt;&#10;&lt;li&gt;次にAX5400を電源投入。安定するまで待つ&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;これでいけるはず。&lt;/p&gt;&#10;&lt;h2 id="lan内dnsを使うセルフホストの民"&gt;LAN内DNSを使うセルフホストの民&#10;&lt;/h2&gt;&lt;p&gt;あまりいないと思われるが、AGH + Caddyなど使ってセルフホストを使う民の場合、LAN内ドメインの名前解決がうまくいかないかもしれない。これはIPv6の通信が優先されていると思われる。なので、IPv6についてもきちんと対応すればいい、のかもしれないのだが、なんかもうしんどいのでLAN内ではもう全部IPv4でやるようにクライアント側の端末設定しました。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/landnsipv6windowsipv6/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;LAN内DNSでIPv6は使わないのでWindowsでIPv6を無効化する&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/landnsipv6windowsipv6/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/07/eyecatch_50770_1785034008.webp" alt="LAN内DNSでIPv6は使わないのでWindowsでIPv6を無効化する" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/linux-mint-xfce-22-3-ipv6-disabled/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;Linux Mint Xfce 22.3 でIPv6を切る&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/linux-mint-xfce-22-3-ipv6-disabled/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/eyecatch_51088_1786019518.webp" alt="Linux Mint Xfce 22.3 でIPv6を切る" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/android-lan-agh-dns/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;AndroidでLAN内DNS(AdGuard Home)にIPv4アドレスでアクセスする&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/android-lan-agh-dns/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/eyecatch_50782_1786019566.webp" alt="AndroidでLAN内DNS(AdGuard Home)にIPv4アドレスでアクセスする" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;Androidはけっこう鬼門。&lt;/p&gt;&#10;&lt;p&gt;記憶違いなら御免なんだけど、Macはそもそもそんな設定してない。Wi-fiの設定でDNSサーバをAGHがあるIPアドレスに指定したらそれで動いたように思う。&lt;/p&gt;&#10;&lt;p&gt;以上。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;関連記事&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/rakuten-mobile-pixel-7-eth/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;実録：楽天モバイル &amp;#43; Pixel 7からイーサネットテザリングでルータに繋げて家のネット回線にする&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/rakuten-mobile-pixel-7-eth/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/06/original_50265_1782755101_16x9.webp" alt="実録：楽天モバイル &amp;#43; Pixel 7からイーサネットテザリングでルータに繋げて家のネット回線にする" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/nuro-cancel/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;nuro光に申し込んだがキャンセルし、無事ネット難民になった&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/nuro-cancel/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/06/eyecatch_50212_1782374138.webp" alt="nuro光に申し込んだがキャンセルし、無事ネット難民になった" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>セルフホストしたUmamiでWordPressサイトのアクセス解析</title><link>https://hack-le.com/umami-wordpress/</link><pubDate>Fri, 21 Aug 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/umami-wordpress/</guid><description>&lt;p&gt;Google Analytics代替として候補にあがる、セルフホストのアクセス解析ソフトUmamiを使っていく。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://github.com/umami-software/umami" target="_blank" rel="noopener"&#10; &gt;GitHub - umami-software/umami: Umami is a privacy-first analytics platform. Traffic, campaigns, behavior, conversions, and revenue in one place — no cookies, no tracking, self-hosted or in the cloud. · GitHub&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;なお公式サイトはisドメインなんだけれど、なぜか弾かれる。Cloudflare経由で接続するといけるのでおまかんっぽいんだがアイスランドに嫌われるようなことしたっけ？&lt;/p&gt;&#10;&lt;p&gt;まぁそれはいいとして、今回インストールでは「&lt;a class="link" href="https://www.bitdoze.com/umami-analytics-install/" target="_blank" rel="noopener"&#10; &gt;How to Install Umami Analytics on Docker (2026 Guide)&lt;/a&gt;」の記事を参考にさせていただきました、っていうか正直うちの記事よりこの記事のほうが詳しいからこっち見たほうがいいよｗ&lt;/p&gt;&#10;&lt;p&gt;じゃあなんで書くのかというと、記事は消えるから……。10年以上もブログやっていると「この記事が詳しいです！」で雑に案内だけ貼ったリンクが消える消える。まぁ微妙に情報補足と雑なWordPress案内も追加したので…。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;a class="link" href="mailto:Umami@3.2.0" &gt;Umami@3.2.0&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;自宅サーバ&#10;&lt;ul&gt;&#10;&lt;li&gt;ThinkPad L390, Core i5-8265U, 32GB RAM&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Linux Mint Xfce 22.3&#10;&lt;ul&gt;&#10;&lt;li&gt;docker 29.7.2&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Cloudflare Tunnel&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="インストールと最初の設定"&gt;インストールと最初の設定&#10;&lt;/h2&gt;&lt;h3 id="docker-composeyml"&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&#10;&lt;/h3&gt;&lt;p&gt;以下でランダムな文字列を作る&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;openssl&lt;/span&gt; &lt;span class="nx"&gt;rand&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;hex&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;文字列はコピーしておく。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;.env&lt;/code&gt;を作成する。以下の&lt;code&gt;APP_SECRET&lt;/code&gt;にさっきのランダム文字列を入れる。パスワードは適当に入れる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;umami&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-secure-password&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;umami&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;APP_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;run-openssl-rand-hex-32-to-generate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;DISABLE_TELEMETRY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;を編集。元記事からimageのURLだけ差し替えた（エラー出たので）。ポート番号は変えたかったら変える。バージョン固定したかったらする。ちなみにvつかないらしい（v3.2.0ではなく3.2.0）。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; umami:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: umamisoftware/umami:postgresql-latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s2"&gt;&amp;#34;3000:3000&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; DATABASE_URL: postgresql://&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;@umami-db:5432/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; APP_SECRET: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APP_SECRET&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; DISABLE_TELEMETRY: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DISABLE_TELEMETRY&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; umami-db:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; condition: service_healthy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; init: &lt;span class="nb"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; healthcheck:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; test: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD-SHELL&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;curl http://localhost:3000/api/heartbeat&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; interval: 5s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; timeout: 5s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; retries: &lt;span class="m"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; umami-db:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: postgres:15-alpine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; POSTGRES_DB: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; POSTGRES_USER: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; POSTGRES_PASSWORD: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; TZ: UTC&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - ./umami-db-data:/var/lib/postgresql/data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; healthcheck:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; test: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;CMD-SHELL&amp;#34;&lt;/span&gt;, &lt;span class="s2"&gt;&amp;#34;pg_isready -U &lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;{POSTGRES_USER} -d &lt;/span&gt;&lt;span class="nv"&gt;$$&lt;/span&gt;&lt;span class="s2"&gt;{POSTGRES_DB}&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; interval: 5s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; timeout: 5s&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; retries: &lt;span class="m"&gt;5&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここで、参考記事によると、Cloudflare Tunnelを使っている場合、Umamiから見ると全部CloudflareのIPを取ってしまうので、&lt;code&gt;docker-compose.yml&lt;/code&gt;の&lt;code&gt;environment&lt;/code&gt;に以下を追記せよとのことであった。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CLIENT_IP_HEADER: cf-connecting-ip&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;VPSとかで直接公開してCaddyをリバースプロキシにしている場合はヘッダの付与よしなにしているから不要なはず。&lt;/p&gt;&#10;&lt;p&gt;準備が出来たら、&lt;code&gt;docker compose up&lt;/code&gt;でエラーが出ないことを確認する。いけたら&lt;code&gt;docker compose up -d&lt;/code&gt;でバックグラウンド起動。&lt;/p&gt;&#10;&lt;h3 id="最初の設定"&gt;最初の設定&#10;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;http://&amp;lt;IPアドレス&amp;gt;:&amp;lt;ポート&amp;gt;&lt;/code&gt;にアクセスして、ユーザ名&lt;code&gt;admin&lt;/code&gt;とパスワード&lt;code&gt;umami&lt;/code&gt;でログイン。&lt;/p&gt;&#10;&lt;p&gt;当然危ないので、管理者設定からパスワードを変更する。ユーザ名も変更できる。&lt;/p&gt;&#10;&lt;p&gt;言語設定も日本語あり。&lt;/p&gt;&#10;&lt;h3 id="ネットワーク設定"&gt;ネットワーク設定&#10;&lt;/h3&gt;&lt;p&gt;トラッキングデータの送信はクライアントマシンから行うため、グローバルに公開する必要あり。&lt;/p&gt;&#10;&lt;p&gt;全体の流れは以下 by AI。&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;sequenceDiagram&#10;autonumber&#10;actor Client as クライアント&#10;participant WP as WPサーバー(ブログサイト)&#10;participant Umami as Umamiサーバー(セルフホスト)&#10;Note over Client, Umami: 1. ブログページの読み込み&#10;Client-&gt;&gt;WP: ① ページリクエスト (アクセス)&#10;WP--&gt;&gt;Client: ② HTML返却 (Umamiのscriptタグを含む)&#10;Note over Client, Umami: 2. アクセス解析データの送信 (クライアント直接)&#10;Client-&gt;&gt;Umami: ③ script.jsの読み込みリクエスト&#10;Umami--&gt;&gt;Client: ④ script.jsの返却&#10;Client-&gt;&gt;Umami: ⑤ 閲覧データ(PV等)を直接送信 [要グローバル公開]&lt;/pre&gt;&lt;p&gt;うちの場合は例によってCloudflare Tunnelで開通している。&lt;/p&gt;&#10;&lt;p&gt;ここでサブドメインだが、参考記事によると&lt;code&gt;analytics&lt;/code&gt;とか使うと広告ブロッカーに遮断される率が上がるらしい。参考記事では&lt;code&gt;stats&lt;/code&gt;や&lt;code&gt;metrics&lt;/code&gt;や&lt;code&gt;track&lt;/code&gt;などにせよと言われている。&lt;/p&gt;&#10;&lt;h2 id="wordpressサイトの解析"&gt;WordPressサイトの解析&#10;&lt;/h2&gt;&lt;p&gt;別にWordPressサイトじゃなくてもやることは同じ。&lt;/p&gt;&#10;&lt;h3 id="トラッキングコードの取得"&gt;トラッキングコードの取得&#10;&lt;/h3&gt;&lt;p&gt;サイドバーの「Webサイト」より、管理したいドメインを追加する。&lt;/p&gt;&#10;&lt;p&gt;追加したら、Editを開くと以下のようなトラッキングコードが取得できる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;defer&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://your-umami-domain.com/script.js&amp;#34;&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;website&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx&amp;#34;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/script&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;基本はこれを&amp;lt;head&amp;gt;タグに貼り付けること。&lt;/p&gt;&#10;&lt;h3 id="タグの貼り付け"&gt;タグの貼り付け&#10;&lt;/h3&gt;&lt;p&gt;プラグイン「Integrate Umami」があるが、&amp;lt;head&amp;gt;タグに貼り付けるだけなのでプラグイン使う必要はないかなと思う。&lt;/p&gt;&#10;&lt;p&gt;うちはテーマとしてSwellを使っているので、「外観」「カスタマイズ」「高度な設定」から「headタグ終了直前に出力するコード」にコードを貼り付け。&lt;/p&gt;&#10;&lt;p&gt;自分だけ除外とかするなら &lt;code&gt;functions.php&lt;/code&gt;でログインユーザにはトラッキングコードを出さないとかしないといけないかなと思う。&lt;/p&gt;&#10;&lt;h3 id="実測で確認"&gt;実測で確認&#10;&lt;/h3&gt;&lt;p&gt;しばらくダッシュボードを見てきちんと動いているか確認する。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/08/image-700x380.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;まぁなんか動いてそう。使い方についてはおいおい見ていこうと思う。&lt;/p&gt;&#10;&lt;p&gt;以上。ちなみに最初AIに聞いて作業していたんだが、古いバージョンの情報に惑わされて完全に無能だった。&lt;/p&gt;&#10;</description></item><item><title>エアコンとローカルAIサーバで電気代がとんでもないことに</title><link>https://hack-le.com/denkidai/</link><pubDate>Wed, 19 Aug 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/denkidai/</guid><description>&lt;p&gt;さすがに一人暮らしでこれは反省した。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/08/image-1-700x582.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;引越したばかりだからなのか、計算された日付がちょっと長くて、32日分くらい計測されている、というのはあるのだけれど、それにしても469kWhとは。1日あたり15kWhくらい使っている計算になるね。&lt;/p&gt;&#10;&lt;p&gt;まぁまずエアコンの電気代がエグいのはある。1日中つけっぱなしなので、これだけで5kWhにはなってそう。もっとかな。&lt;/p&gt;&#10;&lt;p&gt;あとはサーバやね。一番はStable DiffusionのためのローカルAIサーバかな…。ただこれはMaxでも確か300kWくらいで最大出力出しっぱなしということはないはずなんだけれどなぁ。頻度によるけど、1日で4-5kWhくらい使ってるかもなぁ。&lt;/p&gt;&#10;&lt;p&gt;他にセルフホスト系。&lt;strong&gt;サーバはノートPCなんで、前に測った感じだと消費電力は多分せいぜい15W&lt;/strong&gt;といったところだと思うんだけれど、&lt;strong&gt;意外でもなく重いのがハードディスク4台のせたガチャベイ&lt;/strong&gt;と思われる。これは1度ちゃんと測定しないといけないと思っているが…多分ならすと平均30Wくらいかなぁ。なのでまぁ、合計すると1kWh/日超えそうだよね。&lt;/p&gt;&#10;&lt;p&gt;あとは冷蔵庫とかなんとか色々使ったら5kWhくらいになるでしょう。するとまぁたしかに、5+5+1+5=16なので外出日とかでならすと15kWh/日になる、というのはそうだなぁ。なんか見てみると日によっては20kWh超えているときもあって酷い。去年でもここまでひどくはなかったので、さすがにもうちょっとどうにかしたい。&lt;/p&gt;&#10;&lt;p&gt;しかしそれにしても、&lt;strong&gt;エアコンについては環境的な要因もかなり大きいわけで、エアコンが新聞紙より高い消費税率10%で、しかも謎の再エネ賦課金とか課して起きながらさらにそれにも税金かけるっていうの、本当に意味不明&lt;/strong&gt;だなぁと思う。新聞は露骨に政治的な配慮を求めておきながら、昨今の食品消費税減税については減税するなと発狂しているんだから腐ってる。&lt;/p&gt;&#10;&lt;p&gt;まぁ何を言っても詮無いことなので、とりあえずエアコンとAIはちょっと控えよう。&lt;/p&gt;&#10;</description></item><item><title>セルフホストしたWebアプリになぜかうまくアクセスできない時のチェック</title><link>https://hack-le.com/selfhost-webapps-down/</link><pubDate>Mon, 10 Aug 2026 00:00:59 +0900</pubDate><guid>https://hack-le.com/selfhost-webapps-down/</guid><description>&lt;p&gt;私的メモ。そりゃそうだ集。症状は様々なので症状から逆引きというより流し読みして心当たりあるやつを思い出す集。構成が複雑になるほど、「端末Aでは症状A&amp;rsquo;になるが端末Bでは症状B&amp;rsquo;になる」など発生する。がんばれ。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;p&gt;Linuxが基本。メインはLinux Mint Xfce。&lt;/p&gt;&#10;&lt;h2 id="一般"&gt;一般&#10;&lt;/h2&gt;&lt;h3 id="localhost以外からのアクセスを許可してない"&gt;localhost以外からのアクセスを許可してない&#10;&lt;/h3&gt;&lt;p&gt;症状: ローカル端末からはアクセスできるし正常に起動しているが、他端末からアクセスできない。&lt;/p&gt;&#10;&lt;p&gt;アプリ側でそういう設定になってるので、変更できるか否かという感じ。&lt;/p&gt;&#10;&lt;h3 id="ファイアウォールで許可していない"&gt;ファイアウォールで許可していない&#10;&lt;/h3&gt;&lt;p&gt;症状: ローカル端末からはアクセスできるし正常に起動しているが、他端末からアクセスできない。&lt;/p&gt;&#10;&lt;p&gt;間抜けなことにこれは本当によくある。&lt;/p&gt;&#10;&lt;p&gt;ファイアウォールの設定確認する。&lt;code&gt;ufw&lt;/code&gt;の場合のコマンド。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ufw status&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;空いてなかったら追加。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ufw allow &amp;lt;ポート番号&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="セキュリティグループ的なので許可していない"&gt;セキュリティグループ的なので許可していない&#10;&lt;/h3&gt;&lt;p&gt;AWSをはじめとするクラウドとかVPSで、そもそもネットワークインタフェースに到達していないケース。許可しよう。&lt;/p&gt;&#10;&lt;h3 id="ポートの競合"&gt;ポートの競合&#10;&lt;/h3&gt;&lt;p&gt;症状: なんかうまくいったりいかなかったりする&lt;/p&gt;&#10;&lt;p&gt;複数のアプリケーション、なんなら同一のアプリケーションでポートが競合している。調べるときのコマンドはこれ。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo lsof -i :8080&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="adguardhomeaghとかlan内dnsを使っている場合"&gt;AdGuardHome(AGH)とかLAN内DNSを使っている場合&#10;&lt;/h2&gt;&lt;h3 id="lan内dnsに向いてない"&gt;LAN内DNSに向いてない&#10;&lt;/h3&gt;&lt;p&gt;症状: LAN内ドメインだけ名前解決できない&lt;/p&gt;&#10;&lt;p&gt;そもそも論としてLAN内DNSに向いてない。ルータでDNSをLAN内のやつ指定するか、あるいは各クライアントでそれぞれ設定するか。&lt;/p&gt;&#10;&lt;h3 id="agh側でdns書き換え設定を忘れている"&gt;AGH側でDNS書き換え設定を忘れている&#10;&lt;/h3&gt;&lt;p&gt;症状: LAN内ドメインだけ名前解決できない&lt;/p&gt;&#10;&lt;p&gt;稀によくある。設定しよう。&lt;/p&gt;&#10;&lt;p&gt;サブドメインの法則決めてワイルドカード使うのが楽ではある（ワイルドカードを使えばサブドメインの証明書発行を知られないというのもある。まぁサブドメイン知られたところで別にLAN内限定公開なら問題ないかもしれないが気持ち悪いので…）。&lt;/p&gt;&#10;&lt;h3 id="ipv6が優先されている"&gt;IPv6が優先されている&#10;&lt;/h3&gt;&lt;p&gt;症状: 名前解決できない。端末によってはできることもある。&lt;/p&gt;&#10;&lt;p&gt;AdGuardHomeで頑張ってIPv6対応するか、ルータで切れるならIPv6切るか、あるいはクライアントでIPv6を切るか。クライアントで切る場合は対応はOSによって異なる。Macは基本的にDNSサーバをIPv4で設定すればいけると思うのだが、Windows/Linuxは明示的にやる必要あり。Androidはアプリ使う必要がある。自分はRethinkDNSを使っている。iOSは持ってないから知らない。&lt;/p&gt;&#10;&lt;p&gt;このとおり、OSによって状況が異なるため「端末AではいけるけどBではいけない」ということが起きうる。さらに同じOSでも設定してたりしてなかったりすると、それでも異なる症状になったりする。めんどくさい。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/landnsipv6windowsipv6/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;LAN内DNSでIPv6は使わないのでWindowsでIPv6を無効化する&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/landnsipv6windowsipv6/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/07/eyecatch_50770_1785034008.webp" alt="LAN内DNSでIPv6は使わないのでWindowsでIPv6を無効化する" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/android-lan-agh-dns/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;AndroidでLAN内DNS(AdGuard Home)にIPv4アドレスでアクセスする&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/android-lan-agh-dns/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/08/eyecatch_50782_1786019566.webp" alt="AndroidでLAN内DNS(AdGuard Home)にIPv4アドレスでアクセスする" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;h2 id="caddyを使っている時"&gt;Caddyを使っている時&#10;&lt;/h2&gt;&lt;p&gt;AGH + Caddyまで持っていくとだいぶ捗るけど構築は面倒くさい。DNS-01チャレンジを利用しているとエラーパターンが増える。&lt;/p&gt;&#10;&lt;h3 id="caddyfileの設定を忘れている間違えている"&gt;Caddyfileの設定を忘れている、間違えている&#10;&lt;/h3&gt;&lt;p&gt;稀によくある。設定しよう。ドメインの前にスペース空いてないとかよくある &lt;code&gt;examp.com{&lt;/code&gt;。&lt;code&gt;caddy validate&lt;/code&gt;と&lt;code&gt;caddy fmt --overwrite&lt;/code&gt;しよう。Docker版ならサービス名caddyの時&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose &lt;span class="nb"&gt;exec&lt;/span&gt; caddy caddy validate --config /etc/caddy/Caddyfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;フォーマットは&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose &lt;span class="nb"&gt;exec&lt;/span&gt; caddy caddy fmt --overwrite /etc/caddy/Caddyfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="caddyfileの設定を読み込むのを忘れている"&gt;Caddyfileの設定を読み込むのを忘れている&#10;&lt;/h3&gt;&lt;p&gt;ファイル書き換えただけで。リロードしよう。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;caddy reload&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Docker版&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose &lt;span class="nb"&gt;exec&lt;/span&gt; caddy caddy reload --config /etc/caddy/Caddyfile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="証明書の発行に失敗している"&gt;証明書の発行に失敗している&#10;&lt;/h3&gt;&lt;p&gt;症状: 証明書エラー&lt;/p&gt;&#10;&lt;p&gt;自己証明書以外のとき。ログを見て判断。利用しているレジストラに対応したCaddyを使っているか確認。あとAPIの権限を確認。&lt;/p&gt;&#10;&lt;h3 id="証明書を発行していない"&gt;証明書を発行していない&#10;&lt;/h3&gt;&lt;p&gt;症状: 証明書エラー&lt;/p&gt;&#10;&lt;p&gt;Docker版で &lt;code&gt;docker compose up -d&lt;/code&gt;リロード代わりにした場合、証明書が発行されないまま。&lt;code&gt;docker compose down&lt;/code&gt;してから起動し直す。&lt;/p&gt;&#10;&lt;h3 id="docker利用時-バインドマウントを忘れている"&gt;(Docker利用時) バインドマウントを忘れている&#10;&lt;/h3&gt;&lt;p&gt;症状: 404エラーがでる&lt;/p&gt;&#10;&lt;p&gt;Docker版Caddyを使っている時。ホストマシンのディレクトリをそのまんまfile_serverとか使ってホスティングする場合、バインドマウントしないと当然見えない。&lt;/p&gt;&#10;&lt;h2 id="tailscaleを使っている場合"&gt;Tailscaleを使っている場合&#10;&lt;/h2&gt;&lt;p&gt;最近使ってないけど、使っていたときはややこしかった。特にAGH、Caddyと併用するとカオス。&lt;/p&gt;&#10;&lt;h3 id="magicdnsがうまく機能しない"&gt;MagicDNSがうまく機能しない&#10;&lt;/h3&gt;&lt;p&gt;Tailscaleから付与されるIPアドレスを直打ちするほうが無難。&lt;/p&gt;&#10;&lt;h3 id="aghと一緒に使う"&gt;AGHと一緒に使う&#10;&lt;/h3&gt;&lt;p&gt;TailscaleのDNSをAGHに向けること。&lt;/p&gt;&#10;&lt;p&gt;個人的にはこの構成はそもそも管理がとても複雑なのでやめたほうがいいように思う。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;参考&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/splitdns/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;自宅内のアプリに、同一のドメインで、LAN内とインターネットの外からの両方に対応する（スプリットDNS）構成編&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/splitdns/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/04/eyecatch_49425_1776895341.webp" alt="自宅内のアプリに、同一のドメインで、LAN内とインターネットの外からの両方に対応する（スプリットDNS）構成編" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;h2 id="cloudflare-tunnelとか使っている場合"&gt;Cloudflare Tunnelとか使っている場合&#10;&lt;/h2&gt;&lt;h3 id="トンネルが落ちている接続されていない間違えている"&gt;トンネルが落ちている、接続されていない、間違えている&#10;&lt;/h3&gt;&lt;p&gt;当たり前の見落としをよくする。&lt;/p&gt;&#10;&lt;h3 id="トンネルが競合している"&gt;トンネルが競合している&#10;&lt;/h3&gt;&lt;p&gt;症状: 繋がったり繋がらなかったりする&lt;/p&gt;&#10;&lt;p&gt;Docker版とネイティブ版両方動かしていたりとか、よくわからないことをすると起きる。&lt;/p&gt;&#10;</description></item><item><title>それっぽいことが得意なAIのつくるLPは、少なくとも僕がやるよりそれっぽい</title><link>https://hack-le.com/aiprog-lp/</link><pubDate>Wed, 22 Jul 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/aiprog-lp/</guid><description>&lt;p&gt;帯状発疹よくなってきたけどまだ鈍い痛みが残る。倦怠感は帯状発疹によるのかただしんどいだけなのか。&lt;/p&gt;&#10;&lt;p&gt;さて、先日より、セルフホスト画像閲覧整理Webアプリケーションの公開準備を進めている。コードは公開しないでバイナリのみ配布。結局ドメインは取得せず、このサイトのサブドメインで運用でやるつもりだ。ホスティングはVPSにしようかとも思っていたが、もう少し待てば光回線もあるし、自宅サーバにしようかな。&lt;/p&gt;&#10;&lt;h2 id="名義どうする問題"&gt;名義どうする問題&#10;&lt;/h2&gt;&lt;p&gt;名義は少し悩んでいる。ネット上の活動になるからtama名義でいいかーと思っているのだけれど、新しく屋号をつくったほうがいいかもしれない。屋号は既に一つ持っているのだけれど、こちらはリアルで使っているので、積極的にネットと結びつけたくない感じ。10年以上好き勝手に記事を書いているのは半匿名だから出来ていることだ。半匿名というのは、友人知人には普通にバレているので。まぁその程度の匿名性です。でもネット→リアルでわかるのはちょっとな。&lt;/p&gt;&#10;&lt;p&gt;今の若い世代はネットにスティグマだらけだろうから、アカウントと実名を結びつけるのはもはや厳しいよね。最初からそのつもりでやっていないと。基準がどんどん厳しくなっていて、遡及的に過去のことを裁かれるし、私刑の風潮も強まっているし。たいへんな時代になってしまったよ。インターネットはきっとどこかでリセットされることになるんじゃなかろうか。&lt;/p&gt;&#10;&lt;p&gt;それはともかく、まぁ建付けばかり考えていてもなんなので、ひとまずはこのサイトの活動の延長線上ということで、tama名義で連絡先もサイトのメールアドレスとして進めていこうと思う。&lt;/p&gt;&#10;&lt;h2 id="それっぽいことが得意なaiの本領発揮"&gt;それっぽいことが得意なAIの本領発揮&#10;&lt;/h2&gt;&lt;p&gt;あとは配布にあたってライセンス周りの処理をしており、これも例によってAI頼みとなっている。この分野ではAIはけっこうアテにしていいかなと思う。知財系をうまくやってもらえるのは素直に有り難い。&lt;/p&gt;&#10;&lt;p&gt;それとLPを適当に作らせてみた。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/07/image-700x396.jpg"&gt;&lt;/p&gt;&#10;&lt;p&gt;一発撮り。なんかそれっぽい🤔&lt;/p&gt;&#10;&lt;p&gt;少なくとも僕が作ると確実にセンタリングした文字列羅列with箇条書きになるので、それよりは多分それっぽい。&lt;/p&gt;&#10;&lt;p&gt;ただまぁ改行位置とか気になるし、中身もよくみるとなんか奇妙なところをポイントとして強調していたりするので、やっぱり手直しは必要だなと思ったが、こだわりのない人間のドラフトとしては十分に思えた。一方でこだわりのある人だとなんか色々気になって、結局イチから作るみたいなことになるのかもしれない。&lt;/p&gt;&#10;&lt;h2 id="lpの意味は未だにわかっていない"&gt;LPの意味は未だにわかっていない&#10;&lt;/h2&gt;&lt;p&gt;ただ個人的には、&lt;strong&gt;そもそもLPがそれっぽいからなんなんだと思っている&lt;/strong&gt;。デカいアイキャッチ画像みたいなもんで、トレンドではあるもののあまり意味はないのではなかろうか。必要なことが書いてない割にどうでもいいことばかりが書いてある。だから僕は真面目に見たことはほぼない。Appleのサイトも価格表と技術仕様しか見てない。&lt;/p&gt;&#10;&lt;p&gt;ただそれが一般的な感覚なのかどうかはわからない。まぁ僕としても、&lt;strong&gt;ダウンロードボタンがデカくてドキュメントにすぐ飛べれば文句はないので、プラスアルファでそれっぽいならまぁそれで十分かな&lt;/strong&gt;というお気持ち。&lt;/p&gt;&#10;&lt;p&gt;まだやることはぼちぼち残っているが、この調子なら今月中にはリリースできそうだ。&lt;/p&gt;&#10;</description></item><item><title>ありそうでない？あらゆる端末からPCの画像を見て捨てて保存するWebアプリの開発</title><link>https://hack-le.com/aiprg12/</link><pubDate>Thu, 16 Jul 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/aiprg12/</guid><description>&lt;p&gt;帯状発疹になってから多分10日くらい。薬飲んで4日かな。少しずつなおってはきているのだけれど、相変わらずしんどさがあります。でも一時の倦怠感はだいぶマシになった。とはいえ運動はできないので、ずっとPCに向かっています。痛みがだいぶ引いたので、多少集中できるようになっただけでも有り難い。&lt;/p&gt;&#10;&lt;h2 id="機能がないことが機能"&gt;機能がないことが機能&#10;&lt;/h2&gt;&lt;p&gt;で、今月中に何か正式にアプリをリリースしようとしています。最初はブログ用の広告タグツールを公開するつもりだったのですが、まだ使い始めて日が浅いので、別のもっとずっと前から使っている簡易的な画像表示アプリを公開する予定です。名前はそのまんまで&lt;code&gt;Simple Image Viewer&lt;/code&gt;なんですが、同名のアプリがいくつかあるので変えたほうがよさそうだなぁと思っています。本質的にも、&lt;strong&gt;もともとは画像をざっと閲覧するためのアプリだったんですが、今となっては画像を捨てるためのアプリ&lt;/strong&gt;みたいな側面がありますので、ちょっとあってないかもしれない。もちろん閲覧用途でも使えますけど。&lt;/p&gt;&#10;&lt;p&gt;このアプリは何かというと、&lt;strong&gt;指定したフォルダ以下の画像ファイルをブラウザで表示、いらない画像は削除するというだけの、極めて簡易的なWebアプリ&lt;/strong&gt;です。&lt;/p&gt;&#10;&lt;p&gt;多分、&lt;strong&gt;何の機能があるかというより、ほとんどの機能がない&lt;/strong&gt;、ということのほうが特徴かな。その中で変な機能があります。実際「フォルダをzipにしてダウンロード」「&lt;strong&gt;削除確認なし&lt;/strong&gt;」あたりは珍しい機能になるかなと思います。特に削除確認なしは、これは開発者の心理になるとよくわかるんですが、不可逆性が怖いのでやりたくない機能（というより確認機能がないというべき？）ですね。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/07/5710a9e022752163afe758957f1cfd0b-700x533.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;開発中の画面&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;なんでこんなもの作ったかというと、&lt;strong&gt;画像フォルダの整理&lt;/strong&gt;です。写真とか、スクリーンショットとか、あと個人的にはStable Diffusionで作った有象無象の大量の画像について、必要なのだけ残してあとは削除、というのを、あらゆるデバイスでやりたかったんですね。なのでWebアプリです。&lt;strong&gt;なんかこういうアプリあるかなと思ったら意外となく、自分で作ることになりました&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;けっこう探したんですけどね。OS標準からクライアント画像管理アプリ、Webベースのファイラ、だいぶマイナーな個人開発のやつに金払ったのもあります。でもダメだったなぁ。求めるのに、けっこうニッチな条件がありました。&lt;/p&gt;&#10;&lt;p&gt;ファイルベース、サブフォルダにある画像も含めて一覧表示、削除確認をしない、全画面でちゃんと全画面になる、一気にスクロールしてだーーっっと確認したい、PCだけではなくタブレットやスマホからやりたい、R18もあるのでクラウドにあげたくない、速度重視、何より「とにかく安定して動く、固まらない」の条件を全部満たすもの、なかったですね。&lt;/p&gt;&#10;&lt;p&gt;自分のユースケースに合わせて作ったので、当たり前ですが僕にはフィットしているため、地味に毎日くらいの勢いで使っていたりします。まぁ全部の条件が合致するのは僕くらいでしょうけれど、&lt;strong&gt;LAN内Webアプリのファイルベースなんかは意外と需要あるのでは？&lt;/strong&gt; と思ったりもしています。普通あんまやらんしそんなこと。あと地味に削除確認なしはファイラ的な使い方になるため、これも案外ない。まぁ実際、&lt;strong&gt;本質的には画像管理じゃなくてファイラなんですよこのアプリ&lt;/strong&gt;。サムネイル表示したときのファイラに近い挙動です。&lt;/p&gt;&#10;&lt;p&gt;技術的にはGo言語 + htmxで、まだ生成AIコーディング黎明期に、チクチク指示して大真面目にコード読んでキレてたりして作っていたのですが、今はもうAIに適当にやらせているので、&lt;strong&gt;実際内部がどうなっているのかもはやわかりません&lt;/strong&gt;。htmx使ったり使ってなかったりしてそうです。まぁPureなJSでやる分にはいいよもう。動いているし。地味に二年以上は使っていて特に不具合ない。&lt;/p&gt;&#10;&lt;h2 id="aiプログラミングのハマりどころ"&gt;AIプログラミングのハマりどころ&#10;&lt;/h2&gt;&lt;p&gt;なのでまぁ公開してもいいかなぁと思ったわけですが、それにあたって今までの直接ビルド・インストールではなく、パッケージにしたのですけれど、やっぱりやると色々あるもので、開発環境とパッケージ版の競合などありました。&lt;strong&gt;開発環境で、設定ファイルが見つからないと本番用の設定ファイルを使って設定が競合してバグるなど、謎のフォールバック&lt;/strong&gt;にハマる。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;AIプログラミングで謎フォールバックはだいぶ辛い&lt;/strong&gt;。特定の条件下においてのみ発動するので、日常利用がブラックボックステストだというスタンスでいくと気づきづらい。まぁ正直見当はつくというか、今回も「まさか開発環境と本番環境で設定ファイル競合してたりしないよね？」って聞いたら「それです👍️」で膝から崩れ落ちた。なんでそんなことするの？🥺&lt;/p&gt;&#10;&lt;p&gt;逆に言うと、こういう経験則がまったくないと様々な面でハマるはずなので、&lt;strong&gt;AIプログラミングを少しやる気ある一般人くらいの市井に広められないかなぁ、ということも考えているのだけれど、中々難しそう&lt;/strong&gt;です。&lt;/p&gt;&#10;&lt;h2 id="ドキュメントとホスティング"&gt;ドキュメントとホスティング&#10;&lt;/h2&gt;&lt;p&gt;あとはドキュメント整備ですが、これは&lt;strong&gt;MkDocsを使って内容をざっくりAIに書かせようと画策中&lt;/strong&gt;。マニュアルについては、人間だと面倒臭がって省略してしまうところを書いてくれるのはよいところだと思います。ま、逆に冗長になりがちなので差っ引かないといけないですし、何を書くかはかなりこちらで筋立てしてやらないといけないですが…しかしまぁ、それは必要なことですので。&lt;/p&gt;&#10;&lt;p&gt;あとはホスティングをどこにするかかな。わざわざ新しく独自ドメインを取るのもねぇ。サブドメインとVPSでええか。&lt;/p&gt;&#10;&lt;p&gt;それとフリーソフトですけれども、一応Donation版的なこともできないかなとか、なんか考え中です。パスワード機能とか自動アップデートとか、まぁその程度のささやかな機能になりますが。一通りやってみたいという気持ちです。&lt;strong&gt;決済にJPYCとか使ってみたい&lt;/strong&gt;ですよね。個人開発なので好き勝手できる。&lt;/p&gt;&#10;&lt;p&gt;色々と準備を整えつつ、面倒なところは結局人間だなぁと思う今日この頃です。&lt;/p&gt;&#10;</description></item><item><title>AIプログラミング開発日誌10: Amazon広告タグのHTMLリンクのバナーをつくる</title><link>https://hack-le.com/aidev10/</link><pubDate>Tue, 14 Jul 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/aidev10/</guid><description>&lt;p&gt;東京大脱出からようやく落ち着いてきたので、開発をぼちぼちと再開しています。まぁ落ち着いてきたかなと思った矢先に帯状疱疹にかかり、なんかもうしんどいのですが…。未だ治ってません…。&lt;/p&gt;&#10;&lt;p&gt;とはいえ仕事は一ついただいている他何もないので、時間はあります。働き始めて15年、今が一番時間ある気がする…。&lt;/p&gt;&#10;&lt;p&gt;まぁ次に何をするか全然決めていないのですけれど、それはそれとして、&lt;strong&gt;自分の思い描いていたアプリケーションは一度世に出したいなぁという気持ち&lt;/strong&gt;があります。これはやってから死にたい。それでAIがまだ使える間に色々とやっております。&lt;/p&gt;&#10;&lt;p&gt;一番力を入れているのは、今僕自身も使っているコンテンツ管理アプリのD-Shelf（仮）でv0.29.1とバージョン番号だけ延々と積み上がっています。コンテンツ管理アプリはしぬほどありますが、かなり特殊だと思います。対象が画像ZIP、PDF、画像・動画・音声のような定番のほか、バイナリやHTMLなんかもあります。特にHTMLコンテンツを保存して、それをタブレットで見られるのは、自分で言うのもなんですが一周回って新体験でした。15年くらい前のHTMLで売られていたCG集を2026年にiPadで見る不思議な感じ。&lt;/p&gt;&#10;&lt;p&gt;拡張機能も重要視しており、&lt;code&gt;youtube-dl&lt;/code&gt;や&lt;code&gt;whisper&lt;/code&gt;と組み合わせると、URLを指定したら動画ダウンロードして文字起こしして全文検索できるなど、かなり特殊なことができるので、記者会見やよくあるオッサンが喋っているだけのやつを保存してアーカイブするなどすると、本家YouTube超えの使い勝手になるかもしれません。したい人がいるのかは知らない。&lt;/p&gt;&#10;&lt;p&gt;ただ、機能が増えるほどにクロスプラットフォームでちゃんと動くか不安。現状、Linux(Debian/Ubuntu)版のバイナリを作ってVPSで起動確認をしていますが、何をもってOKとするか。データベース設計もまだ流動的のため、変更があるかもと思うと二の足踏みます。公開の踏ん切りがついていない感じです。&lt;/p&gt;&#10;&lt;p&gt;なので、&lt;strong&gt;もうちょっとライトなアプリケーションで一通りのリリースサイクルをやってみようかなぁという感じ&lt;/strong&gt;です。今考えているのは、ブロガー向けになりますけれど、AmazonアフィリエイトのHTMLコードを吐き出すやつです。開発中の画面はこんな感じ。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/07/1a5bb77c0dfd8cb7f6a5a736f95fa95b-700x719.webp"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;商品リンクとタグを指定したら、HTMLコードとプレビューを吐き出すだけのシンプルなWebアプリ&lt;/strong&gt;です。習作感がある。履歴も残しますがデータベースを使わずjson保存です。&lt;/p&gt;&#10;&lt;p&gt;これも実際に僕が使うために作っています。もう自分が使うものしか作らないよね実際。&lt;/p&gt;&#10;&lt;p&gt;機能自体は既存アプリでもよくあるもので、WordPressだと有名どころではRinkerプラグインなんかあるんですが、Advertising APIの利用制限が随分と厳しくなってしまったのか、うちの場末ブログなんかじゃもう全然使えないんですよねぇ。払込自体は定期的にある程度の売上はあるんですが。&lt;/p&gt;&#10;&lt;p&gt;それにまぁ、WordPressやプラグインに依存してしまうといざという時に困りそうですし。Amazonの公式画像バナーすら殺されてしまった絶対に許さない。&lt;strong&gt;自前のコードしか結局残らないんだなぁと思う今日この頃&lt;/strong&gt;。さすがにWordPressは生きてくれると思いたいですが。一時は脱WordPressも考えましたけれど、総合的に見て個人ブログやるなら今なお一番良いCMSかなぁと思います。&lt;/p&gt;&#10;&lt;p&gt;まぁそんなわけで、シンプルなWebアプリなんですけれど、なんだか案外さっと使えるやつがなかったもので。もうちょっと機能を拡張して、とりあえずパッケージにします。Linux(Debian/Ubuntu系列)版とMac版、その後Windows版と、一通りのリリースを経験しようかなという感じです。セルフホスト用Webアプリのパッケージ配布は時代の逆行感がありますが、結局これが一番いいように思います。&lt;/p&gt;&#10;</description></item><item><title>メールずっと使ってると、メールクライアントに苦労する</title><link>https://hack-le.com/mail-client/</link><pubDate>Sun, 12 Jul 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/mail-client/</guid><description>&lt;p&gt;僕の一番古いメールアドレスはYahooのやつで、多分25年以上前に作ったと思われる。当然その後Googleアカウントを取得し、さらに取得し、また独自ドメインでもメールアドレスをつくり、なんだか色々していると、数万のメールが受信箱にたまっているアカウントが複数あるような状態になる。しかもそのメールは歴代の様々なその時々のトレンドを反映したものだ。&lt;/p&gt;&#10;&lt;p&gt;で、こういう状態になると、現代のメールクライアントはなんだかどれも悲鳴をあげるのかなんなのか、とにかくなんだか使えなくなる。それで、多分似たような状況にあると思われる、以下のRedditのスレッドを共感しながら読んでいた。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://www.reddit.com/r/selfhosted/comments/weua6a/whats_the_best_selfhosted_webmail_client/?tl=ja" target="_blank" rel="noopener"&#10; &gt;セルフホスト型のウェブメールクライアントで一番おすすめってどれ？ : r/selfhosted&lt;/a&gt;&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;もうデスクトップのメールアプリは、完全に見切りつけて立ち去るところ。どのプラットフォームでも「ほぼ最上位」クラスのやつって、Gmailの容量（量が多いこと）にはどうしても耐えられないか、複数サーバーで詰まったりするんだよね。それか、メールの送受信しようとしてる間に何週間も休暇に入っちゃったりさ。で、その間にディスク容量とRAMを食いまくる。さらにデュアルブートしたり、複数マシン持ったりして同期するのも楽しそうに見えて、結局めんどい。デスクトップのメールアプリって、ずっとオン/オフでチャンスは与えてきたけど……いや、もうさすがに…ほぼ20年近く。そろそろ終わりにしようと思ってる。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;わかりみが深い。&lt;/p&gt;&#10;&lt;p&gt;僕の場合だと、たとえばThunderbirdなんかはまずそもそも固まる。同期すらできない有様。Macのメール.appは、これはいつ頃からか検索が機能しなくなった。インデックスの再構築とかそんなもん全部やっているが完全に無駄。というかMac系のメールクライアントで検索うまくいった試しがないんよな。&lt;/p&gt;&#10;&lt;p&gt;一番機能的にうまくいくのは、ブラウザであるVivaldiが内蔵するメーラだった。しかしながら、これは安定性に難があり、すぐに同期が止まる。これはPCの再起動やブラウザのアップデートなどでまた突然動き出す。メーラとしては使い物にならないが、検索がうまくいくので、検索のためだけに使っている。&lt;/p&gt;&#10;&lt;p&gt;結論として、僕のメール環境は送受信はMacのメール.appを基本にしつつ、検索はVivaldiの内蔵メーラを使っている、というなんだかよくわからない形になっている。&lt;/p&gt;&#10;&lt;p&gt;まぁ受信するメールの99.9%くらいはゴミなので、このゴミを一掃できれば多分問題なくなるのだけれど、このゴミの一掃が案外難しい。定期的にやろうとするが、あまりうまくいっていない。このゴミの一掃が本来的な課題の気はする。AIにはメール書かなくていいから過去の数十万件のメールとこれからのメールを完全に問題なく処理してほしい。と思ったがではAIの判断を信じられるかというと信じられないので、まぁダメかも。&lt;/p&gt;&#10;&lt;p&gt;最近はもうメールクライアント全体について諦めている。それで、今考えているのは、過去分のメールについてはアーカイブして、検索できるようにしだけしておき、受信箱は常に軽くすればよいのではないか、というアプローチになる。これについてはMail-Archiverというものが開発されているようだった。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://gigazine.net/news/20251230-mail-archiver/" target="_blank" rel="noopener"&#10; &gt;無料でGmailなどのメールをアーカイブして保存後に自動削除して空き容量を増やすことができる「Mail-Archiver」 - GIGAZINE&lt;/a&gt;&lt;/p&gt;&#10;&lt;p&gt;折を見て試してみたいと思う。&lt;/p&gt;&#10;</description></item><item><title>Growi (Docker) をコンテナごと別マシンに引っ越す</title><link>https://hack-le.com/growi-docker-container/</link><pubDate>Sat, 13 Jun 2026 13:10:29 +0900</pubDate><guid>https://hack-le.com/growi-docker-container/</guid><description>&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;移行元&#10;&lt;ul&gt;&#10;&lt;li&gt;Intel Mac mini 2018&lt;/li&gt;&#10;&lt;li&gt;Docker Desktop&lt;/li&gt;&#10;&lt;li&gt;Growi 7.x&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;移行先&#10;&lt;ul&gt;&#10;&lt;li&gt;Linux Mint Xfce 22.3&lt;/li&gt;&#10;&lt;li&gt;Docker 29.2.1&lt;/li&gt;&#10;&lt;li&gt;Growi 7.x&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="基本的な手順"&gt;基本的な手順&#10;&lt;/h2&gt;&lt;p&gt;手順はWordPressのコンテナ移行とほぼ一緒なので、下記記事を参考にすること（雑）&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/container-wp/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;コンテナ構築のWordPressサイトを別マシンに移行する&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/container-wp/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/05/eyecatch_50016_1779164478.webp" alt="コンテナ構築のWordPressサイトを別マシンに移行する" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;全体の流れと微妙な差分を下記にメモ。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;移行元でコンテナを停止してボリュームをバックアップし、移行先にアーカイブを送信&lt;/li&gt;&#10;&lt;li&gt;移行先でボリュームを復元&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ここでElasticsearchの書き込み権限がなかったりするので修正する&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;ol start="3"&gt;&#10;&lt;li&gt;移行先の&lt;code&gt;docker-compose.yml&lt;/code&gt;でボリューム名を指定する&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;docker compose up&lt;/code&gt;してブラウザで動作確認&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;の流れ。ボリューム名の定義と、権限の修正あたりが若干の追加要素となる。&lt;/p&gt;&#10;&lt;p&gt;ボリューム名は通常はフォルダ名にデフォ名つくような感じだろう。たとえばgrowiフォルダでは以下のようになっているだろう。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;local&lt;/span&gt; growi_es_data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;local&lt;/span&gt; growi_growi_data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;local&lt;/span&gt; growi_mongo_configdb&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;local&lt;/span&gt; growi_mongo_db&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これらについて、&lt;code&gt;docker-compose.yml&lt;/code&gt;で&lt;code&gt;es_dataや&lt;/code&gt;growi_dataとなっているところをそれぞれ修正する。そして&lt;code&gt;external&lt;/code&gt;を&lt;code&gt;true&lt;/code&gt;にする。ここらへんは上記WordPress記事のymlを見て参考に。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;docker compose up&lt;/code&gt;で様子を見るが、もしかするとElasticsearchでエラーが出てしまうかもしれない。これはElasticsearchコンテナの権限問題であるため、以下のコマンドで修正する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --rm -v &amp;lt;ボリューム名、たとえばgrowi_es_data&amp;gt;:/mnt alpine chown -R 1000:1000 /mnt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;雑だが、以上。&lt;/p&gt;&#10;</description></item><item><title>Trilium Notes (Docker) のマシンを移行する</title><link>https://hack-le.com/trilium-notes-docker-migration/</link><pubDate>Sun, 07 Jun 2026 21:21:36 +0900</pubDate><guid>https://hack-le.com/trilium-notes-docker-migration/</guid><description>&lt;p&gt;現在運用しているTrilium Notesについて、Intel Mac mini 2018 + Docker Desktop から Linux Mint Xfce 22.3のサーバマシンに移行する。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;Trilium Notesのlatest&lt;/li&gt;&#10;&lt;li&gt;移行元&#10;&lt;ul&gt;&#10;&lt;li&gt;Intel Mac mini 2018&#10;&lt;ul&gt;&#10;&lt;li&gt;macOS Sonoma 14.6.1&lt;/li&gt;&#10;&lt;li&gt;Docker Desktop for mac v4.76.0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;移行先&#10;&lt;ul&gt;&#10;&lt;li&gt;ThinkPad L390&lt;/li&gt;&#10;&lt;li&gt;Linux Mint Xfce 22.3&#10;&lt;ul&gt;&#10;&lt;li&gt;Docker 29.5.2&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="手順"&gt;手順&#10;&lt;/h2&gt;&lt;p&gt;移行元のマシンで停止する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose down&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;でデータディレクトリを確認する。&lt;code&gt;TRILIUM_DATA_DIR&lt;/code&gt;がどうなっているか見る。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Running `docker-compose up` will create/use the &amp;#34;trilium-data&amp;#34; directory in the user home&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Run `TRILIUM_DATA_DIR=/path/of/your/choice docker-compose up` to set a different directory&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# To run in the background, use `docker-compose up -d`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; trilium:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Optionally, replace `latest` with a version tag like `v0.90.3`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Using `latest` may cause unintended updates to the container&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: triliumnext/trilium:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Restart the container unless it was stopped by the user&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restart: unless-stopped&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;TRILIUM_DATA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/node/trilium-data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="nv"&gt;TZ&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Asia/Tokyo&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# By default, Trilium will be available at http://localhost:8080&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# It will also be accessible at http://&amp;lt;host-ip&amp;gt;:8080&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# You might want to limit this with something like Docker Networks, reverse proxies, or firewall rules,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# however be aware that using UFW is known to not work with default Docker installations, see:&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-and-ufw&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s1"&gt;&amp;#39;8080:8080&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Unless TRILIUM_DATA_DIR is set, the data will be stored in the &amp;#34;trilium-data&amp;#34; directory in the home directory.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# This can also be changed with by replacing the line below with `- /path/of/your/choice:/home/node/trilium-data&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TRILIUM_DATA_DIR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/trilium-data&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:/home/node/trilium-data&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# - /etc/timezone:/etc/timezone:ro&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - /etc/localtime:/etc/localtime:ro&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ここでは&lt;code&gt;~/trilium-data&lt;/code&gt;となっている。ついでにMacで&lt;code&gt;/etc/timezone&lt;/code&gt;がなかったのでコメントアウトされているね。&lt;/p&gt;&#10;&lt;p&gt;とりあえずアーカイブ化しよう。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar -czvf trilium-data-backup.tar.gz ~/trilium-data&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;こいつを新しいマシンに転送してやる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scp trilium-data-backup.tar.gz ユーザ@IPアドレス:移行先のパス&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;新しいマシンで、これを保存先ディレクトリ上に展開する。今回は&lt;code&gt;trilium-data&lt;/code&gt;にしている。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tar -xzvf trilium-data-backup.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;保存先ディレクトリに入って、もしデータベースの一時ファイルが存在したら削除する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rm -f document.db-shm document.db-wal&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;準備ができたらコンテナの起動。とりあえずフロントで。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラーなく起動したら、&lt;code&gt;http://IPアドレス:ポート&lt;/code&gt;にアクセスする。以前使っていたパスワードでログインできることを確認する。&lt;/p&gt;&#10;&lt;p&gt;問題なければOK。Ctrl-cで停止して、改めてバックグラウンドで起動する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これでOK。しばらく動かして、安定していることを確認したら元のコンテナは削除してよい。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;関連記事&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/evernote-notion-trilium-notes/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;Evernote/Notion代替: Trilium NotesでインストールからWeb Clipまで&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/evernote-notion-trilium-notes/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/03/image-4.png" alt="Evernote/Notion代替: Trilium NotesでインストールからWeb Clipまで" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>Dell Latitude 5290は中古PCサーバの母艦としていいかもしれないね、一方クライアントなら意外にも…</title><link>https://hack-le.com/dell-latitude-5290-l390-linux/</link><pubDate>Tue, 26 May 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/dell-latitude-5290-l390-linux/</guid><description>&lt;p&gt;うちには40台くらいジャンクPCがある。特に2018年前後を集めており、定番なのはLenovo ThinkPadとDel Latitudeあたりだ。このへんはまぁ安いといってもジャンクの中では高いのかもしれないのだが、既に送料で底打ちがあるため、バランスを取るならこのへんかなぁ、とは思う。ジャンクでバランスもなにもないが…。&lt;/p&gt;&#10;&lt;h2 id="結局linuxに似合う中古pcはなんなんだい"&gt;結局Linuxに似合う中古PCはなんなんだい&#10;&lt;/h2&gt;&lt;p&gt;個人的には、漁っているとFUJITSUのLIFEBOOKやPANASONICのLet&amp;rsquo;s Noteの古いやつなんかが、むしろ良いのではないか？という気がしている。流通量もそこそこあるし。あのへんはLenovoやDellとは異なる方向にブランドなので、必ずしも安くなっていない…なんなら骨董品レベルのものがやけに高く売られていることもある。あの時代のパーツがほしい人向けなんだろうか…しかしコンシューマのPCでそんなことあるかなぁ。&lt;/p&gt;&#10;&lt;p&gt;まぁなんでもいいのだけれど、無難にいくならThinkPadかLatitude、というのはそれはそう、という感じだ。ただ2018年より、ThinkPadの上位モデルであるX280以降はメモリソルダリングという悪に手を染めてしまっているため、それより一つ落ちるはずのL390のほうが、メモリの拡張性高い分使いやすいという逆転現象が起きている。筐体の無骨さもサーバ用途ならばむしろ悪くない。まぁ問題は、L390はThinkPadシリーズの中だとそんなに量が出回っていないということかな…。あと、LANポートがないのもいたいね。&lt;/p&gt;&#10;&lt;p&gt;そこでいくと、&lt;strong&gt;Dell Latitude 5290は攻守ともに強い感じ&lt;/strong&gt;だ。メモリも換えられるし。ま、ちょっと重いかな。Dellらしい無骨さではある。しかし前述したように&lt;strong&gt;サーバで無骨さは褒め言葉&lt;/strong&gt;よ。ただ同じ型番で2-in-1タイプもあるらしいが、そちらはオンボードという罠仕様になっている。まぁジャンク漁りをする人の中でも2-in-1を狙うのはさらに数寄者だろうから好きでやっているんだろうが…。&lt;/p&gt;&#10;&lt;p&gt;なので、僕はThinkPad L390を母艦にしているけれども、Dell Latitude 5290も実は候補に上がっていた。しかし結局L390になり、Latitude 5290は仕事で使うPCとして供養する流れだ。Core i5-8250Uと8GBという必要十分なスペックに、LANポートがあるのが決めてになったかな。LANポートがあると、それ経由でシングルボードな子機とサクッと接続できるのがよい。SSDは家にあった128GB SATA SSDだがね。m.2 2280フォームファクタのSATAがあるなんて、ジャンク漁るまで知らなかったよ…。&lt;/p&gt;&#10;&lt;p&gt;まぁThinkPadだのDellだのも当然のように裏蓋ネジなかったり画面TNでもやってたしCMOS切れてたり通信たまに切れたりバッテリー死んでたりするという点では変わらない。そこは安くどうにかできるならなんとかするし、できるけど高く付くならそういう使い方は諦めるという割り切りが必要だ。&lt;/p&gt;&#10;&lt;h2 id="クライアントならちょっと冒険してみて"&gt;クライアントならちょっと冒険してみて…&#10;&lt;/h2&gt;&lt;p&gt;さて少し目先を変えて、そんなサーバとかじゃなくて、普通に普段遣いでやりたいんだけど、という向きでは、僕の見た感じだと感触はかなり異なる。&lt;/p&gt;&#10;&lt;p&gt;ここで一番重要なのは液晶で、画面は生きててIPSフルHDとバッテリーとキーボードタッチパッドが生きていること、が条件となる。あとためらわないレベルで外観が保たえれていることとか（時々戦争に持っていったの？みたいな可愛そうな筐体がある…）。ここがクリアしていればあとはまぁなんとか。&lt;/p&gt;&#10;&lt;p&gt;まぁあるにはあるんだけど、普通に1万超えてくるよねこんなの。高いよ。ジャンクでも2万くらいはある。まともな中古店なら2万後半から3万しててもおかしくない。これからもっと高くなるかもな。&lt;/p&gt;&#10;&lt;p&gt;…なんですけど、PANASONICとかLIFEBOOKで捨て値になっているように、バッテリーが死にかけだけどもまだ残っていて、驚くべきことにIPS FHD（ときどきTN FHDがあるので気をつける）、みたいなのが、3000円とか5000円とかで手に入ったりすることもある（送料込み）。もちろんCPUは期待するな。Core i5第4世代でも気にするな。でもバッテリー生きてるならなんでもいいじゃない！たとえ残り39%とかだったとしても！&lt;/p&gt;&#10;&lt;p&gt;このへんのはね、まぁさすがに常用はつらいと思うけど、サーバよりも持ち運びたいタイプの特定用途のクライアントPCとして活躍の場があると思ったな。筐体のめっちゃ軽いからね。当時は最先端だったんだろう。&lt;/p&gt;&#10;&lt;p&gt;PANASONICの昔のやつとかでもボタン一つでWi-fi切り替えギミックとかほしい人はほしそうなやつあるしね。まだそこまでちゃんといじってなけど、僕はけっこういいと思ったな。&lt;/p&gt;&#10;&lt;h2 id="どんどん検証していく"&gt;どんどん検証していく&#10;&lt;/h2&gt;&lt;p&gt;40台くらいジャンク揃えたけど「完璧だ！」みたいなのマジでなくて、「こいつはここがなぁ…」のオンパレードです。今はThinkPad L390を使っていて、これは比較的の文句のないPC…に見せかけて、クリックパッド死んでたりするからねｗあとなんか全体的にもやってる。まぁあんまりメインディスプレイがっつり見ないけどね。&lt;/p&gt;&#10;&lt;p&gt;とりあえず今日現時点においては、このサイトはThinkPad L390 Core i5-8265U, 32GB RAMで動いております。RAMだけすごい。普段は3-6GBの利用料なので完全に無駄。でもこれからメインサーバの機能をうつしていったら重くなるかも。&lt;/p&gt;&#10;&lt;p&gt;最初の間は消費電力も10Wくらいだったけど、メディア系のサーバを入れ始めたから、いまは15Wくらいにあがってそうだなー…。Jellyfinとかは入れる予定ないんだけど。Immichは入れようかなぁ。家族にAppleやGoogleにお布施しているのがいたら救ってもいいんだが…。&lt;/p&gt;&#10;&lt;p&gt;この子がいつでも最後のちからを振り絞れるように、後ろに何台ものジャンクを控えさせておかないとな。そういう態勢を整えて、知見を共有していきたい。&lt;/p&gt;&#10;&lt;p&gt;まぁなんにしても、あんまり失敗したくなくて、でもLinuxほしいなぁって雑に思う人はDell Latitude 5290はいいと思うよ（2-in1は避けつつ）。ジャンクなら別途パーツ含めて1万、保証付きの中古ショップなら…25000くらいかなぁ。ジャンク市場もこれからどうなることやら…&lt;/p&gt;&#10;</description></item><item><title>Linux Mint Xfce 22.3 + LyrionMusicServer + Squeezelite で音楽生活</title><link>https://hack-le.com/linux-mint-xfce-22-3-lyrionmusicserver-squeezelite/</link><pubDate>Mon, 25 May 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/linux-mint-xfce-22-3-lyrionmusicserver-squeezelite/</guid><description>&lt;p&gt;メインサーバになりつつあるLinuxマシンに、チューナレステレビをHDMIでつなぎ、TVに光オーディオ出力でアンプに繋がっている。たいへんややこしい状況だが、どうせなら音楽はこのアンプでききたいものである。&lt;/p&gt;&#10;&lt;p&gt;ということで、音楽サーバ構築編。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;p&gt;とてもややこしいけれども以下のような感じだ。&lt;/p&gt;&#10;&lt;pre class="mermaid" style="visibility:hidden"&gt;graph TD&#10;subgraph PCA ["PC A (操作端末 / リモコン)"]&#10;Browser["Webブラウザ / App(Material Skin UI)"]&#10;end&#10;subgraph PCB ["PC B (Linux Mint / サーバー兼再生機)"]&#10;direction TB&#10;LMS["Lyrion Music Server(楽曲管理・配信)"]&#10;subgraph AudioOutput ["音声出力プロセス"]&#10;Squeezelite["Squeezelite(再生用クライアント)"]&#10;PipeWire["PipeWire / ALSA(OS音声制御)"]&#10;end&#10;Storage[("音楽ファイル群(HDD/SSD)")]&#10;end&#10;subgraph AudioPath ["中継・出力"]&#10;TV["Mi TV(音声ハブ)"]&#10;Speaker["外部スピーカー"]&#10;end&#10;%% 接続とデータの流れ&#10;Browser -- "① 選曲・操作命令 (Port 9000)" --&gt; LMS&#10;LMS -- "② 音楽ストリーム送信 (Port 3483 / localhost)" --&gt; Squeezelite&#10;Squeezelite -- "③ 音声データ引き渡し (default出力)" --&gt; PipeWire&#10;Storage -. "スキャン (パーミッション確認済)" .-&gt; LMS&#10;%% 物理接続&#10;PipeWire == "④ HDMI出力 (DEV=3)" ==&gt; TV&#10;TV == "⑤ 光デジタル出力" ==&gt; Speaker&#10;%% スタイル設定&#10;style PCB fill:#f5f6f8,stroke:#4f5b66,stroke-width:2px&#10;style LMS fill:#d1e7dd,stroke:#0f5132&#10;style Squeezelite fill:#fff3cd,stroke:#856404&#10;style Browser fill:#cfe2ff,stroke:#084298&#10;style PipeWire fill:#e2d9f3,stroke:#4b2c7e&#10;style TV fill:#eeeeee,stroke:#666&lt;/pre&gt;&lt;p&gt;HW/SWは以下。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;ThinkPad L390&#10;&lt;ul&gt;&#10;&lt;li&gt;32GB RAM&lt;/li&gt;&#10;&lt;li&gt;Linux Mint Xfce 22.3&lt;/li&gt;&#10;&lt;li&gt;squeezelite v1.9.9-1449&lt;/li&gt;&#10;&lt;li&gt;Lyrion Music Player v9.1.0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="インストールと設定"&gt;インストールと設定&#10;&lt;/h2&gt;&lt;h3 id="lyrion-music-server"&gt;Lyrion Music Server&#10;&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://lyrion.org/getting-started/#configure" target="_blank" rel="noopener"&#10; &gt;Getting Started with LMS - Lyrion Music Server&lt;/a&gt;より、ダウンロードリンクを取得。記事を書いた時のリンクだとこれ。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget &lt;span class="s2"&gt;&amp;#34;https://downloads.lms-community.org/LyrionMusicServer_v9.1.0/lyrionmusicserver_9.1.0_amd64.deb&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install ./lyrionmusicserver_9.1.0_amd64&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ステータスを確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl status lyrionmusicserver.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;enabledでactive(running)になっていることを確認する。&lt;/p&gt;&#10;&lt;p&gt;ポートを空ける。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ufw allow 9000/tcp&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そうしたら &lt;code&gt;http://IPアドレス:9000&lt;/code&gt;にGo。右下のNextボタンで、音楽ファイルの場所と、プレイリストを保存する場所を指定することになる。&lt;/p&gt;&#10;&lt;p&gt;ここで、ディレクトリのパーミッションは755でないとLMSが読めない。基本的にホームサーバならディレクトリは755でよいはず。外付けディスクとかでパーミッションまとめて変える必要があるときは&lt;code&gt;find&lt;/code&gt;で一気にやってしまう。たとえば&lt;code&gt;/mnt/hdd&lt;/code&gt;のときは以下の感じ。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find /mnt/hdd -type d -exec chmod &lt;span class="m"&gt;755&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; +&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ホームディレクトリは&lt;code&gt;~/.ssh&lt;/code&gt;とかあるんでまとめてやるとか雑なことはしない。&lt;/p&gt;&#10;&lt;p&gt;さらに音楽ファイルの権限も600とかだと読めない。音楽ファイルのあるディレクトリに移動して、パーミッションを変更する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;find . -type f -exec chmod &lt;span class="m"&gt;644&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; +&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;再スキャンするときは、Web画面で歯車よりServerから再スキャン可能。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/05/66d639db4f7220ae225dde9a4235401b-700x399.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;とにかく音楽フォルダとプレイリストフォルダのパーミッションは整えてやる必要がある。ちなみにうちの場合は音楽ファイルは外付けのハードディスクドライブで、プレイリストフォルダは内蔵SSDのホームフォルダ内にしている。&lt;/p&gt;&#10;&lt;h3 id="squeezelite"&gt;Squeezelite&#10;&lt;/h3&gt;&lt;p&gt;まずポート空けておく。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo ufw allow &lt;span class="m"&gt;3483&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下でインストール。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo apt install squeezelite&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;入れたら出力を確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;squeezelite -l&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;なんかいっぱい出てくる。ここでハードウェアを指定して &lt;code&gt;/etc/default/squeezelite&lt;/code&gt;を書き換えていく、ということになっているのだが…。&lt;/p&gt;&#10;&lt;p&gt;ただねぇ…僕はここから相当転がされた結果、一つの結果にたどり着いたが、これは一般的ではない、とあらかじめ申し添えておく。&lt;/p&gt;&#10;&lt;p&gt;まずapt installしたら勝手にsystemctlで動いているsqueezeliteを殺す。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo systemctl stop squeezelite.service&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;有効化はされてないのでdisableする必要はないが、もしenableしてしまったらdisableもしておく。&lt;/p&gt;&#10;&lt;p&gt;そのうえで、&lt;code&gt;~/.config/autostart&lt;/code&gt;にスタートアップスクリプトを書いていく。ディレクトリがなかったら最初につくる。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir -p ~/.config/autostart&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;そしたら設定ファイルを書く。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat &lt;span class="s"&gt;&amp;lt;&amp;lt; &amp;#39;EOF&amp;#39; &amp;gt; ~/.config/autostart/squeezelite-tv.desktop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;[Desktop Entry]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Encoding=UTF-8&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Version=0.9.4&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Type=Application&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Name=Squeezelite-TV&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Comment=Hand-launched success command with delay&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Exec=bash -c &amp;#34;sleep 5 &amp;amp;&amp;amp; squeezelite -o default -n MiTV&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;OnlyShowIn=XFCE;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;StartupNotify=false&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Terminal=false&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;Hidden=false&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s"&gt;EOF&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Execのところは適当に。&lt;code&gt;-n MiTV&lt;/code&gt;は僕がMiTV使ってるからなので。適当にわかりやすい名前にする。&lt;/p&gt;&#10;&lt;p&gt;再起動して、LMSで見つかるかどうか試す。見つかればOK。&lt;/p&gt;&#10;&lt;p&gt;これは明らかに標準の方法ではないが、これが一番安定した。systemdはクソ。昔から思ってたけど、僕の頭が悪いんだと思っていた。今となっては自信を持って言える。僕の頭が悪かろうがなんだろうが関係なくsystemdはクソ。&lt;/p&gt;&#10;&lt;h2 id="systemdはクソ"&gt;systemdはクソ&#10;&lt;/h2&gt;&lt;p&gt;疲れた。なんだかんだで半日消費した。あとは運用していきたい。&lt;/p&gt;&#10;&lt;p&gt;ちなみにフォルダ管理派はフォルダをブラウズするように設定できるが、そのへんの話はMacのときに書いたのでそちらを参照。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/mac-mini-2018-lyrion-music-serverlms-logitech-media-server-squeezelite/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;Mac mini 2018 &amp;#43; Lyrion Music Server(LMS, Logitech Media Server) &amp;#43; Squeezeliteで音楽ライフ&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/mac-mini-2018-lyrion-music-serverlms-logitech-media-server-squeezelite/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/02/eyecatch_48160_1771482682.webp" alt="Mac mini 2018 &amp;#43; Lyrion Music Server(LMS, Logitech Media Server) &amp;#43; Squeezeliteで音楽ライフ" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;p&gt;ってかPipeWireって何？とか、基本的なところ理解できてないなぁと思った。systemdはクソ。&lt;/p&gt;&#10;</description></item><item><title>コンテナ構築のWordPressサイトを別マシンに移行する</title><link>https://hack-le.com/container-wp/</link><pubDate>Sun, 24 May 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/container-wp/</guid><description>&lt;p&gt;現在常時稼働サーバがMac・Linuxと無意味に分かれている。Linuxマシンに統一してIntel Mac mini 2018には予備役となってもらうように、少しずつ機能を移行している。今回は自宅サーバのWebサイト。つまりこのサイト。&lt;/p&gt;&#10;&lt;h2 id="環境"&gt;環境&#10;&lt;/h2&gt;&lt;p&gt;Mac上で展開していたDocker + WordPressのサイトを、別マシンに移行する。前回の移行時はプラグインを使って復元したのだが、せっかくコンテナでやってるのにそれではかいがないと思い、今回はCLIで実施。&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;元マシン: Intel Mac mini 2018&#10;&lt;ul&gt;&#10;&lt;li&gt;Docker Desktop 4.73.0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;移行先マシン: Linux Mint Xfce 22.3&#10;&lt;ul&gt;&#10;&lt;li&gt;Docker 29.5.0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;a class="link" href="https://github.com/BretFisher/docker-vackup" target="_blank" rel="noopener"&#10; &gt;GitHub - BretFisher/docker-vackup: Script to easily backup and restore docker volumes · GitHub&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;code&gt;vackup&lt;/code&gt;コマンドの中身については以下の記事を参照。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/docker-volume-cli-backup/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;DockerのボリュームをCLIでバックアップ・復元する&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/docker-volume-cli-backup/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2024/09/docker-volume-cli-backup.webp" alt="DockerのボリュームをCLIでバックアップ・復元する" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;&lt;h2 id="手順"&gt;手順&#10;&lt;/h2&gt;&lt;p&gt;全体は以下。&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;元マシン：コンテナを停止する&lt;/li&gt;&#10;&lt;li&gt;元マシン：ボリュームのエクスポート&lt;/li&gt;&#10;&lt;li&gt;元マシン：コンテナを再開する&lt;/li&gt;&#10;&lt;li&gt;元マシンからコンテナにボリュームをコピー&lt;/li&gt;&#10;&lt;li&gt;移行先：ボリュームをリストア&lt;/li&gt;&#10;&lt;li&gt;移行先：コンテナを起動&lt;/li&gt;&#10;&lt;li&gt;移行先：localhostにアクセスして復元されていることを確認する&lt;/li&gt;&#10;&lt;li&gt;リバースプロキシなどで向け先を移行先に。元サイトは落とす&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="元マシンボリュームのバックアップ"&gt;元マシン：ボリュームのバックアップ&#10;&lt;/h3&gt;&lt;p&gt;コンテナは持ち運べるとして、問題は永続化ボリュームをコピーすること。&lt;code&gt;ここでは、docker-compose.yml&lt;/code&gt;は以下のようなものとする。変数は&lt;code&gt;.env&lt;/code&gt;で定義しているとする。内容は、WordPressとDBそれぞれコンテナたててるよ、それぞれボリュームを指定して使うよ、というもの。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;services:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hp_wordpress:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: wordpress:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ports:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - &lt;span class="s2"&gt;&amp;#34;ポート番号:80&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WORDPRESS_DB_HOST: データベースコンテナ&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WORDPRESS_DB_USER: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WORDPRESS_DB_PASSWORD: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; WORDPRESS_DB_NAME: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;_DB_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - hp_wordpress_data:/var/www/html&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - ./custom-php.ini:/usr/local/etc/php/conf.d/custom-php.ini&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; depends_on:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - db&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; db:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; image: mariadb:latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; environment:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; MYSQL_ROOT_PASSWORD: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; MYSQL_DATABASE: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; MYSQL_USER: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; MYSQL_PASSWORD: &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DB_PASSWORD&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - db_data:/var/lib/mysql&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; restart: always&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;volumes:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; hp_wordpress_data:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; external: &lt;span class="nb"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; db_data:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; external: &lt;span class="nb"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;volumeとして、&lt;code&gt;hp_wordpress_data&lt;/code&gt;と&lt;code&gt;db_data&lt;/code&gt;を外部で作成したものを使うような設定になっている。&lt;/p&gt;&#10;&lt;p&gt;現在のボリュームを確認する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker volume ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ターゲットとなるボリューム名と存在することを確認しておく。&lt;/p&gt;&#10;&lt;p&gt;コンテナを停止する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose stop&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以下のコマンドでバックアップ。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mkdir volume-backups&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vackup &lt;span class="nb"&gt;export&lt;/span&gt; WPボリューム名 volume-bakcups/WPボリューム名.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vackup &lt;span class="nb"&gt;export&lt;/span&gt; DBボリューム名 volume-bakcups/DBボリューム名.tar.gz&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;ダウンタイムを小さくしたいなら、この時点で元マシンを&lt;code&gt;docker compose up -d&lt;/code&gt;で復帰させる。&lt;/p&gt;&#10;&lt;p&gt;転送する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync -avz --progress volume-backups ユーザ@移行先:移行先のパス/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;容量大きくて途中でdisconnectされるときは&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;rsync -avz --progress -e &lt;span class="s2"&gt;&amp;#34;ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=10&amp;#34;&lt;/span&gt; volume-backups ユーザ@移行先:移行先のパス/&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="移行先マシンボリュームのリストア"&gt;移行先マシン：ボリュームのリストア&#10;&lt;/h3&gt;&lt;p&gt;作業ディレクトリに移動し、ボリュームを復元する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vackup import WPボリューム.tar.gz WPボリューム名&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vackup import DBボリューム.tar.gz DBボリューム名&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;これで問題ないはずだが、なぜか自分の環境でよくわからんことになっていたので、ボリュームの中身を確認しておく。以下のように直下にされておらず&lt;code&gt;vakcup-volume&lt;/code&gt;があるかもしれない。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ docker run --rm -v ボリューム:/volume alpine ls -lh /volume&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;total 4K &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drwxr-xr-x &lt;span class="m"&gt;6&lt;/span&gt; &lt;span class="m"&gt;999&lt;/span&gt; ping 4.0K May &lt;span class="m"&gt;18&lt;/span&gt; 02:53 vackup-volume&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;vackup-volume&lt;/code&gt;なる親ディレクトリが出来ていて、その下にディレクトリがあるようだ。&lt;/p&gt;&#10;&lt;p&gt;この場合は以下のコマンドにより&lt;code&gt;vackup-volume&lt;/code&gt;以下を展開する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run --rm -v WPボリューム名:/volume alpine sh -c &lt;span class="s2"&gt;&amp;#34;mv /volume/vackup-volume/* /volume/ 2&amp;gt;/dev/null || true; mv /volume/vackup-volume/.[!.]* /volume/ 2&amp;gt;/dev/null || true; rmdir /volume/vackup-volume&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;もう一度ボリュームを確認したら直下に展開されていることがわかる。DBのほうのボリュームも同様に。&lt;/p&gt;&#10;&lt;p&gt;これでいけるが、なんかよくわからんことをしている。&lt;/p&gt;&#10;&lt;p&gt;後日実行したときは再現しなかったので、なんだかよくわからない。&lt;/p&gt;&#10;&lt;h3 id="起動と疎通確認"&gt;起動と疎通確認&#10;&lt;/h3&gt;&lt;p&gt;最後にもう一度&lt;code&gt;docker-compose.yml&lt;/code&gt;を確認し、コンテナを起動する。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;エラーとか出ないかを確認するため、最初はフォアグラウンドで。&lt;code&gt;http://localhost:ポート&lt;/code&gt;にアクセスし、いつもの画面が表示されることを確認する。&lt;strong&gt;インストール画面が出たら初期化されちゃってます&lt;/strong&gt;。なにか間違えているので最初からやりなおし。やりなおした🥺&lt;/p&gt;&#10;&lt;p&gt;問題なければ正式にバックグラウンドで動かす。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="移行元から移行先に向ける"&gt;移行元から移行先に向ける&#10;&lt;/h3&gt;&lt;p&gt;準備が整ったので、DNSやらリバースプロキシやらいじって、移行元から移行先に向ける。&lt;/p&gt;&#10;&lt;p&gt;この時点で移行元を落としていいが、いつ落とすかは考え方による。ダウンタイムを小さくするなら移行元をしばらく残しておいてもいい。しかし、変に残しておいてナイスタイミングでコメントついてしまい、消えてしまうみたいな事故が起きる可能性もあるので、何がいいとも言えない。僕はいらなくなったら落とす。&lt;/p&gt;&#10;&lt;h2 id="インフラはai無能"&gt;インフラはAI無能&#10;&lt;/h2&gt;&lt;p&gt;最初これくらいAIがすぐできるだろうと思ったけど何か色々ハマってしまって、結局手作業で心を込めてやりました。インフラ周りは固有の環境や設定が多すぎるので、汎用的な一般解を出し続けるAIは無能になりがち。&lt;/p&gt;&#10;&lt;p&gt;それにしてもこの手の作業をするとき、昔書いた記事を参考にすることがよくあるのだけれど、このサイト自身が対象のとき、失敗するとサイト自体が落ちてしまって閲覧することができないっていう。まぁそれを考えると、ニッチな記事でもnoteに転載していくのは保険としての意味もあるか。釈然としないけど。&lt;/p&gt;&#10;&lt;p&gt;今後Linuxマシンは色々なハードウェアを検証していくため、移行作業はスクリプト化してスムーズに検証できる体制を整えたい。&lt;/p&gt;&#10;&lt;h2 id="追記自動化した"&gt;追記：自動化した&#10;&lt;/h2&gt;&lt;p&gt;けっこう何度も引越ししているので、スクリプトで自動化した。&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/wordpressdocker-script/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;WordPress(Docker)をコンテナとボリュームごと別マシンに移行するスクリプト&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/wordpressdocker-script/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/06/eyecatch_50180_1781419099.webp" alt="WordPress(Docker)をコンテナとボリュームごと別マシンに移行するスクリプト" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item><item><title>AIプログラミング開発日誌8: 裏切らないアプリをつくっている</title><link>https://hack-le.com/aip-dshelf/</link><pubDate>Thu, 21 May 2026 00:00:00 +0900</pubDate><guid>https://hack-le.com/aip-dshelf/</guid><description>&lt;p&gt;AIプログラミングにより今作っている中で、これは配布してもいいかもしれないなぁ、と思うものが出てきた。&lt;/p&gt;&#10;&lt;p&gt;&lt;img loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hack-le.com/images/uploads/2026/05/image-6-700x370.png"&gt;&lt;/p&gt;&#10;&lt;p&gt;&lt;em&gt;v0.25.8 漫画と攻略本が入り混じる&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;何度かネタにしたコンテンツ管理のアプリで、バージョンだけ上がり続けてv0.25.8になった。名前はD-Shelf（仮）。これは一つのアプリで画像・テキスト・動画・音声を全部扱えて、タブレットやスマホでも閲覧できるという、僕が欲しかったものをそのまま形にしたものだ。&lt;/p&gt;&#10;&lt;h2 id="管理アプリはどこに消えた"&gt;管理アプリはどこに消えた？&#10;&lt;/h2&gt;&lt;p&gt;コンテンツを管理するアプリは多いのだけれど、なんだかあまり満足できないでいた。結局フォルダ管理になっている。多分&lt;strong&gt;人生で一番管理を頑張ったのは在りし日のiTunesだったのだが、胴元にApple Musicとかいってライブラリを破壊されて以来、フォルダ教に戻った&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;写真管理についてはPicasaを使っていたが消えた。食事の写真のEvernote Foodも消えた。Evernoteはまだあるけど僕の知っているEvernoteではない。Dropboxは使っていたが垢BANと値上げに怯えるのに疲れた。Google Photoも同じく。そもそもなんか僕のしたい管理ではない。&lt;strong&gt;結局フォルダだけが裏切らない&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;h2 id="オタクは形式を問わない"&gt;オタクは形式を問わない&#10;&lt;/h2&gt;&lt;p&gt;しかし&lt;strong&gt;フォルダはデータが埋もれる&lt;/strong&gt;。すべてが文字列に圧縮される。いかに僕が文字を愛するとはいえ、階層構造の文字列では限界がある。結果、買ってそのまま、積んだことすら記憶にないデータの肥やしに多額の金をかけてきた。&lt;/p&gt;&#10;&lt;p&gt;まぁ最近はデータすらもらえないことが多いのだが…それは置いといて、&lt;strong&gt;まず手元にデータとしておいているものは、まず死滅させずにいたいと願った&lt;/strong&gt;。それは&lt;strong&gt;自分の人生における軌跡&lt;/strong&gt;であり、そこから生まれる&lt;strong&gt;内発的な感情を大事にしたい&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;そのために、&lt;strong&gt;特定のフォーマットにこだわらずに保存する&lt;/strong&gt;。実際、画像、音声、動画、テキストはもちろんだが、&lt;strong&gt;HTMLアーカイブまでそのまま閲覧できる&lt;/strong&gt;。これは今となってはかなり珍しいかもしれない。たとえば昔の更新が止まった個人サイトなどを個人で保管し、当時の風景そのままに手元で永遠に閲覧することができる。また、昔のCG集などはHTML形式のものもけっこう多かったしねぇ。掲示板のログなんかも扱えるだろう。これは意味がわからないという人のほうがもはや多いかもしれないのだけれど、僕にとっては青春のアーカイブそのものだ（実際Evernoteにはかつての掲示板ログやネットSSを残していたりする…）。&lt;/p&gt;&#10;&lt;p&gt;また、ノート機能がある。たとえば漫画を読みながらノートを取れる。これは僕が長年漫画の感想サイトをやっているところに着想がある。コンテンツ消費という表現を僕は好まない。オタクはコンテンツを消費しない。&lt;strong&gt;コンテンツとは消費するものではなく内在化するもの&lt;/strong&gt;だ。 &lt;strong&gt;「朝ごはんを消費する」とは誰も言わない&lt;/strong&gt;はずだ。&lt;/p&gt;&#10;&lt;h2 id="拡張性とインタフェースと効率について"&gt;拡張性とインタフェースと効率について&#10;&lt;/h2&gt;&lt;p&gt;個々の内在化には、個人による拡張が必要であるため、拡張性も現在頑張って作っている。&lt;strong&gt;外部コマンドを登録するプラグイン機能を開発中&lt;/strong&gt;だ。これを使うことで、たとえば&lt;code&gt;pdftoppm&lt;/code&gt;と&lt;code&gt;cwebp&lt;/code&gt;を使ってPDFをWebPのZIPアーカイブに変換したり、&lt;code&gt;yt-dlp&lt;/code&gt;と連携してYouTubeやニコニコ動画を保存したり（自己責任で）、&lt;code&gt;whisper&lt;/code&gt;と連携して動画の文字起こしをしたりできる。その文字起こしを検索対象とすることで、持っている動画の全文検索ということもできたりする。動画の文字起こし+検索対象化は、ここだけ切り出しても割と需要あるかもしんない。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;これらはツールの連携をしているだけで、別に僕の制作しているアプリがなにか新しくできるようにしているのではない&lt;/strong&gt;けれども、それらを&lt;strong&gt;繋げてまとめて管理できる&lt;/strong&gt;のは、データを死蔵させないための有効なインタフェースだと思う。ワークフローというよりは、パイプをGUIに繋げたいという感じだ。&lt;/p&gt;&#10;&lt;p&gt;インタフェースは非常に重要だ。最近Xで外国語を翻訳する機能が出たが、あれは特になにかあたらしいことをしたわけではないけれども、それによって世界的な交流が活発化したのは事実だ。僕のタイムラインにもトルコ語のツイートが流れてきたり、また僕自身も英語ツイートのアカウントなどをためらわずにフォローできるようになった。&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;「使いやすさ」はいうなれば「摩擦を減らす」もの&lt;/strong&gt;だ。この摩擦は目に見えず定量化もできないために、資本効率において軽視されがちだけれども、だいたい人間の手触りというのは定量化できないことのほうが重要である。自分の人生を定量化しようとしてみればわかる。大事なことほど定量化できないと感じるはずだ。&lt;/p&gt;&#10;&lt;p&gt;まぁ&lt;strong&gt;このアプリ自体が、そういう定量化とか効率みたいな一切合切について投げ捨てたもの&lt;/strong&gt;だ。そもそもこのご時世に「24時間稼働のサーバアプリケーション」という時点で、まぁ普通ではない。Jellyfinのような熟れて実績がありバイナリの配布されたOSSでさえも、一般に広まっているとは言い難い現状だ。&lt;/p&gt;&#10;&lt;p&gt;しかしそうしないと僕がやりたいことはできない。ひたすら僕が「ほしい」と思った機能ばかりを求めている。そのために、現在ピーキーになっているのはそう。このへんは熟れさせていくしかない。インストーラや、オフライン化などは考えたい。特にオフライン化は今後あるかもしれないエネルギー不足の世界観などを想定すると、なんとか対応したい。&lt;/p&gt;&#10;&lt;h2 id="もう少し整える"&gt;もう少し整える&#10;&lt;/h2&gt;&lt;p&gt;もう少し整えたうえで、テストプレイを誰かにしてほしいところだが、何しろ&lt;strong&gt;データという私有財産&lt;/strong&gt;を扱うものだから、慎重になっている。機能もそうだがデータベースのスキーマが落ち着かない間は出しづらい…。そもそも私有財産を私有財産と思わないIT企業に嫌気がさしてはじめたという面もあるために、ここは同じ穴の狢になってはいけないと思う。一方で慎重になりすぎているといつまでたってもリリースできない。&lt;/p&gt;&#10;&lt;p&gt;思えば僕はこれまで一品物とも言える基盤開発しかしておらず、個人としては自分専用のCLIツールを作るだけで、アプリケーションをリリースするという、当たり前の経験がなかったことに気づいた。AIを使ってコーディングが劇的に早くなったのは確かだけれども、一番難しいところは結局残っていて、そこに時間がかかるんだなぁと思う。&lt;/p&gt;&#10;&lt;p&gt;まぁもう少し時間がかかりそうだが、ここまできたら配布とその更新まで続けられるようにしたい。まぁでもその前にもっとライトなアプリで一通りのリリースの練習をするかも。&lt;/p&gt;&#10;&lt;p&gt;&amp;lt;関連記事&amp;gt;&lt;/p&gt;&#10;&lt;div class="blog-card-wrapper"&gt;&#10; &lt;a href="https://hack-le.com/ai-selfapps/" class="blog-card"&gt;&#10; &lt;div class="blog-card-content"&gt;&#10; &lt;div class="blog-card-label"&gt;&#10; &lt;svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"&gt;&lt;path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"&gt;&lt;/path&gt;&lt;path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"&gt;&lt;/path&gt;&lt;/svg&gt;&#10; &lt;span&gt;あわせて読みたい&lt;/span&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-title"&gt;AIプログラミング開発日誌：セルフホストしているアプリを管理するアプリをセルフホストしている&lt;/div&gt;&#10; &lt;div class="blog-card-url"&gt;/ai-selfapps/&lt;/div&gt;&#10; &lt;/div&gt;&#10; &lt;div class="blog-card-thumbnail"&gt;&#10; &lt;img src="https://hack-le.com/images/uploads/2026/04/eyecatch_49558_1777434933.webp" alt="AIプログラミング開発日誌：セルフホストしているアプリを管理するアプリをセルフホストしている" loading="lazy" /&gt;&#10; &lt;/div&gt;&#10; &lt;/a&gt;&#10;&lt;/div&gt;&#10;&#10;</description></item></channel></rss>