2026/07/06(月)ConoHa VPSからIPv4のアクセスを自宅サーバーにIPv6でリバースプロキシするときにやったこと

更新日:
投稿日:

ログを取っていないので記憶で書いているし、順序は効率よくなるように変えているため、上手くいかない可能性がある。

前提

  • IPv4接続だけをConoHa VPSに移し、IPv4はConoHa VPSに立てたリバプロから受ける
  • ConoHa VPSスペックとしてOSはDebian GNU/Linux 13、メモリは512MB、CPU 1コアの最安インスタンス
  • ConoHa VPSから自宅サーバーへはIPv6でリバースプロキシする
  • ConoHa VPSから自宅サーバーへはHTTP通信で接続する
    • つまりIPv4側のTLS終端はConoHa VPS、IPv6側は自宅サーバーという構成
  • ConoHa VPSのIPv6アドレスは2400:8500:2002:3175:160:251:206:248

1. ConoHa VPS側でSSH接続できるようにする

この時点ではSSHで繋げないためWeb画面からすべて行う。

  1. SSHとICMPが繋がるようにする
  2. SSHDの設定方法
  3. 秘密鍵を作成し、公開鍵を取り出し.ssh/authorized_keysに追加
    • rootユーザーに追加した

2. ConoHa VPS側でnginxの設定

ここからはSSHで快適操作!

  1. nginxをインストールして証明書置き場を作る

    apt update
    apt upgrade -y
    apt install -y nginx
    
    mkdir -p /etc/nginx/cert/lycolia.info
    
  2. 証明書をSFTPで移す

  3. 自宅サーバーへのリバプロ設定の作成。メンテナンスを最小限にするためにワイルドカードで飛ばす

    cat <<'EOF' | tee /etc/nginx/conf.d/lycolia-info.conf
    map $http_upgrade $connection_upgrade {
      default upgrade;
      ''    close;
    }
    
    upstream backend {
      server [2400:4153:8f01:c800:c14b:3f7a:2b54:353a];
    }
    
    server {
      http2 on;
      listen 443 ssl;
      server_name lycolia.info *.lycolia.info;
    
      ssl_certificate   /etc/nginx/cert/lycolia.info/fullchain1.pem;
      ssl_certificate_key /etc/nginx/cert/lycolia.info/privkey1.pem;
    
      client_max_body_size 500m;
    
      location / {
        proxy_pass http://backend;
    
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    
        proxy_http_version 1.1;
        proxy_set_header Upgrade  $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
      }
    }
    EOF
    
    # enbaleは勝手にやってくれた気がする
    systemctl enable nginx
    systemctl restart nginx
    

3. 自宅サーバー側で疎通可能にする

  1. OpenWrtで80番ポートを開く
    1. LuCIを開き、Network→Firewall→Traffic Rulesで443を開けてるところに80を追加
  2. ufwにある既存の設定からIPv4で443に繋ぐ設定を消す
  3. ufwに新しい設定を足す

    # IPv6のみ許可する
    sudo ufw allow to ::/0 port 443
    # ConoHa VPSからの接続のみ80で受けられるようにする
    sudo ufw allow from 2400:8500:2002:3175:160:251:206:248 to any port 80
    
  4. nginx側でConoHa VPSを信頼するようにする
    set_real_ip_from 2400:8500:2002:3175:160:251:206:248;
    real_ip_header X-Real-IP;
    
  5. ConoHa VPSから来たX-Forwarded-Protoがhttpsならhttps、それ以外なら$schemeと解釈できるようなmapを書く
    これはConoHa→自宅サーバーがhttpで結ばれており、標準ではスキーマがhttpになってしまうが、それを回避しつつ、IPv6からの自作場への直アクセスがhttpないしhttpsだった場合は、そちらを取れるように変換するためである
    map "$realip_remote_addr:$http_x_forwarded_proto" $real_scheme {
      default $scheme;
      "2400:8500:2002:3175:160:251:206:248:https" "https";
    }
    
  6. 対応するスキーマのバインドを全部変更する。以下はMastodonの例(4.5.4では二箇所ある)
    CGIであればCGIヘッダを書き換えるとよいと思うが、今回は該当がなかった
    +    proxy_set_header X-Forwarded-Proto $real_scheme;
    -    proxy_set_header X-Forwarded-Proto $scheme;
    

4. DNSの切り替えをする

  1. AレコードをすべてConoHa VPSのIPv4に変更

5. nginxの設定を再読み込みする

DNSレコードが伝播するまでの間に粉うことでダウンタイムを最小化できる!

  1. nginxの設定を再読み込みする
    sudo systemctl reload nginx
    

6. 疎通確認

  1. 現時点で一般公開しているサイトに対し疎通するかどうか確認する
    curl -4 https://lycolia.info
    curl -4 https://blog.lycolia.info
    curl -4 https://mstdn.lycolia.info
    curl -4 https://eco.lycolia.info/wiki/
    
  2. 落ちてたら設定を見直し再試行

7. 掃除

  1. OpenWrtでIPv4向けの443を閉じる
    1. LuCIを開き、Network→Firewall→Traffic Rulesで443を開けてるところを消す
  2. OpenWrtのDDNSスクリプトを無効化
  3. nginxの設定でIPv4で443をlistenしてるところを全部消す

あとがき

やるだけやったが、結果的に現時点では全部撤回したので実証実験みたいになってしまった。

元々はフレッツ光クロスに切り替えてIPv4が失われることを想定して行ったが、よくよく考えたら切り替えたところで、今使っているルーターであるR86S U1のSFP+ポートが片方不安定で現状活用できないことや、IPv4のポート枯渇のためレスポンスが返せなくなる恐れを考えると、今やることではないなと思い、全撤回することにした。

ただまぁせっかくだしログを残していれば将来役に立つこともあるだろうというので残したが、色々あり構築時のログが消え去っていたので記憶を頼りに書くことになってしまったのは反省点である。

しかしR86S U1のSFP+が片側死んでいるのはどうしたものか。最近は何もかもすべてが高いのでおいそれと買い替えなどできないし…。まぁ現状困ってないし、IPv4は無料で手に入るし、別にクロスに変えなくてもいい気はした。

ところで全然関係ないけどWiFi 7を入れようと思ったもののSFP+の口が付いてるWiFiルーターは価格が高く、そうでなくとも、まともに速度が出る奴はどれもこれもデカく場所も取るので難しいね…。ひとまずやるとしたら1WくらいのトランシーバーでRJ45に変換するのが無難そうだと思った。その場合、10GtekのASF-10G-T80辺りはいい選択肢になりそうだ。

ルーターも最低でもトライバンドないと速度が出ないっぽいのでWXR18000BE10P辺りが5万円程度で、比較的小さいので無難だろう。この製品は過去に設置したことがあるのでサイズ的には問題ないことは確認済みである。今は手放しているので持っていない。経緯としてはかつてクロスを入れようとして導入したが、結局入れなかったし、デカくて邪魔だったので売った。

とはいえWiFiの速度には大きな不満があるので再導入を検討するのはありかもしれない。トランシーバーとセットで6万とかになるので眩暈がしそうだが…w

2026/07/06(月)nginxのリバースプロキシが上手くいかない問題を解消した

ConoHa VPSをフロントエンドにし、自宅サーバーにリバースプロキシする構成を組んだ時のトラブルメモ。

起きていた条件

nginxからnginxへリバースプロキシする構成で前段がTLS終端で、後段へはHTTPで接続していた。前段はVPS、後段は物理サーバーで別の環境。

起きていた事象

lycolia.info*.lycolia.info全体で前段が後段に接続できない状態になっていた。

curl -iSsl4 https://blog.lycolia.info/
HTTP/2 000 
server: nginx
date: Fri, 03 Jul 2026 15:24:44 GMT

前段のnginxにcurlを投げるとステータスコード000が返ってきて、curlが終了コード23で異常終了していた。

2026/07/04 00:11:33 [error] 2537#2537: *12468 upstream sent no valid HTTP/1.0 header while reading response header from upstream, client: xxx.xxx.xxx.xxx, server: lycolia.info, request: "GET /pub/lycolia/rss.xml HTTP/2.0", upstream: "http://[2400:4153:8f01:c800:c14b:3f7a:2b54:353a]:80/pub/lycolia/rss.xml", host: "blog.lycolia.info", referrer: "https://blog.lycolia.info/pub/lycolia/rss.xml"

nginxのエラーログには「アップストリームからのレスポンスヘッダーの読み取り中に、アップストリームが有効な HTTP/1.0 ヘッダーを送信しませんでした。」という意味のエラーを出力していた。

後段のnginxには何もログが出ていなかった。

curl -v --http1.1 -H 'Host: blog.lycolia.info' "http://[2400:4153:8f01:c800:c14b:3f7a:2b54:353a]:80/"
*   Trying [2400:4153:8f01:c800:c14b:3f7a:2b54:353a]:80...
* Connected to 2400:4153:8f01:c800:c14b:3f7a:2b54:353a (2400:4153:8f01:c800:c14b:3f7a:2b54:353a) port 80
* using HTTP/1.x
> GET / HTTP/1.1
> Host: blog.lycolia.info
> User-Agent: curl/8.14.1
> Accept: */*
> 
* Request completely sent off
* Received HTTP/0.9 when not allowed
* closing connection #0
curl: (1) Received HTTP/0.9 when not allowed

前段のnginxのあるVPSから、後段のnginxに対してhttpバージョン1.1を明示して叩くと「HTTP/0.9 when not allowed」というエラーが出てきた。HTTP/0.9…?初めて聞く概念だ…。

curl -s --http0.9 'http://[2400:4153:8f01:c800:c14b:3f7a:2b54:353a]/' | xxd           
00000000: 0000 1204 0000 0000 0000 0300 0000 8000  ................
00000010: 0400 0100 0000 0500 ffff ff00 0004 0800  ................
00000020: 0000 0000 7fff 0000 0000 0807 0000 0000  ................
00000030: 0000 0000 0000 0000 01                   .........

httpバージョン0.9を明示して叩き、帰ってきたレスポンスのバイナリ。端的に言うとプロトコルエラーで帰れと言われているが、理由は後述する。

解決した方法

+listen [::]:80;
-listen [::]:80 http2;

後段のmstdn.lycolia.infoの設定を上記に変更することで、他のドメインでも問題が解決した。

何故解決したかはわからないが、恐らく80 http2と書くと、他の80番ポートのリッスンにも影響が波及するのだと思う。

http2通信にしなくても問題ないのかでいうと、Mastodonは問題なさそうに見えたのでたぶん大丈夫なんだと思う。知らんけど。

何故解決したのか

使用しているnginxのバージョンがproxy_passするときにhttp 2.0をサポートしてなかったからだ。

nginx 1.29.4になるとproxy_passでhttp 2.0がサポートされるようで、2025年12月9日のリリースには以下の一文があった。

*) Feature: the ngx_http_proxy_module supports HTTP/2.

この時ばかりは今までnginxのバージョンに興味が微塵になかった私もバージョンを上げたくなった瞬間だった。

ただ後続のバージョンのバグフィックスを見るに結構バグが出てそうなので、今あげるのは時期尚早かもしれない。まぁ現状困ってないので上げなくてもいいのは幸いだ。

ところでv1.25.1になるとlisten単位のhttp2が非推奨になり、代わりにhttp2 onという全体単位?が推奨設定になるため、将来的に現状のポート単位にhttpバージョンを分ける技は使えなくなりそうである。

あとがき

バイナリ読解

前述したHTTP 2.0のバイナリレスポンスを読んでみようのコーナー。

curl -s --http0.9 'http://[2400:4153:8f01:c800:c14b:3f7a:2b54:353a]/' | xxd           
00000000: 0000 1204 0000 0000 0000 0300 0000 8000  ................
00000010: 0400 0100 0000 0500 ffff ff00 0004 0800  ................
00000020: 0000 0000 7fff 0000 0000 0807 0000 0000  ................
00000030: 0000 0000 0000 0000 01                   .........

そのバイナリを見るといいという情報をやってみたので試してみた結果。

まず16進数なので1桁に0-Fが入る。これは0000~1111ということだ。つまり1桁が4bitであることが分かる。

さて、HTTP/0.9は一旦忘れて、先ほどやってきたHTTP/2.0として解釈してRFC 9113 - HTTP/2を読んでみる。

「4. HTTPフレーム」によればHTTPフレームの先頭24bitがLength、8bitがType、8bitがFlag、1bitがReserved、31bitがStream Identifierらしい。

つまり先頭を分解するとこうなる。

Length: 00 00 12
Type: 04
Flag: 00
Reserved+Stream Identifier: 00 00 00 00

Lengthだ。0x000012なので18個の8bitフィールドがある。

次の8bitがTypeで0x04となっている。0x046.5.1. 設定フォーマットだ。

Reserved+Streamは全て0なので無価値だろう。

設定フォーマットではそこから48bit単位が設定フィールドとなる。先頭16bitがIdentifier、後ろ32bitがValueだ。

18個の8bitフィールドが設定になるため18 * 8 = 144, 144 / 48 = 3で3つの設定が存在すると読める。

00 03 00 00 00 80

つまりこの部分になる。

Identifierは00 03なのでSETTINGS_MAX_CONCURRENT_STREAMS。最大同時ストリーム数だ。

Valueは00 00 00 80なので128

次は00 00 00 00 10なのでSETTINGS_HEADER_TABLE_SIZE。ヘッダ圧縮テーブルの最大サイズ。

04 00 01 00なので67,109,120。オクテット単位なので単位はバイトと思われる。オクテットのオクはオクトパスのOctと同じなのでタコの脚は八本と考えると覚えやすい。Octoberも旧暦の8月だからOct。

次は00 00 05なので、SETTINGS_MAX_FRAME_SIZE

00 ff ff ff 00なので4,294,967,040。これも単位なので単位はバイトと思われる。

これで設定が終わり、またフレームに戻る。

00 0004 0800
0000 0000 7fff 0000 0000 0807 0000 0000
0000 0000 0000 0000 01

これが残り。

Length: 00 00 04 → 4 * 8 = 32bit
Type: 08WINDOW_UPDATE
Unused Flags: 00
Reserved+Stream: 00 00 00 00
Reserved+Window Size Increment: 7f ff 00 002,147,418,112

次の残り

0000 0807 0000 0000
0000 0000 0000 0000 01

Length: 00 00 08 → 64bit
Type: 07帰れ
ここまでくれば尻だけ読めばいいので中間は読み飛ばす。
最後の32bitがエラーコードらしいので00 00 00 01が恐らくエラーコード。意味合い的にはPROTOCOL_ERROR

要するにHTTP 2に対してHTTP 1.1で接続していたのでプロトコルエラーが返却され、しかしnginxは理解できなかったのでHTTP 0.9として解釈していたのだろう。

今回組んだ構成

今回nginxからnginxにリバースプロキシをしたわけだが、結果として上図のような構成にした。前段にはConoHa VPSを利用している。

これをした理由としては、以前フレッツ光クロスでフルポート使えるIPv4が取れないことが判明したため、クロスに移行出来るようにするためというのと、IPv4のためにDDNSし続けるのが地味に面倒なのと、宅内からIPv4を排除したかったところによる。

ただこれはこれでVPS側にもTLS証明書が必要になるため、DDNSが消えてもIPv4保守のための呪いはまだ残る。DDNSよりはマシだが…。

また、この構成では前後でnginxのバージョンが異なり前段がv1.26.3、後段がv1.24.0となっているため、前段ではhttp2 onにしないと警告が出るなど、バージョン差異による違いが微妙にある。

結果的にできた構成

今回の施策によって自宅サーバーからIPv4が失われても、AレコードをConoHa VPSに向けることでIPv4を受けることが可能な体制の検証をすることができた。これによってフレッツ光クロスに乗り換えたときのIPv4不在問題を解消できる状態となった。

実運用に移すためにはVPS側にもTLS証明が必要になるので自宅サーバーからSCPで送るか、VPS側でも取得する必要が出てくるので、まだまだ対策が必要だ。後者は同一ドメインに二重に証明書が存在する状態になるのでなんか嫌だし、恐らく前者でやるだろう。TCP パススルーなる技術も健闘したが、真のクライアントIP転送問題など、いろいろ厄介そうなのでやめた。

SCPで送る場合はパスフレーズ付きの鍵認証を突破させ、更にnginxをリロードさせないといけないからこちらもやや頭が痛い。パスフレーズ付きのSSH鍵を無人突破させるにはどこかに平文でパスフレーズを持つ必要がある。暗号化もできるがどんどん複雑に…。

或いはDNS-PERSIST-01を使うことで証明書更新を不要にするのも一つの選択肢かもしれないので、こちらも検討していいかもしれない。

しかしVPSがあることで監視対象が増えるなど、なかなか複雑化してしまうので、これを軌道に乗せるかどうかは現時点では不透明だ。ただConoHa VPSは最低スペックで36ヶ月契約であれば月額293円のため、36ヶ月換算でも10,548円にしかならず、IPv4を保持する手段としてはお手頃である。安いISPでもv4を買おうとすると月2~3,000円はするし、まともなところだと一万円以上するので、IPv4にサーバーがついてこの価格は破格と言える。

帯域は100Mbpsだが、100Mbpsあれば十分だろう。

おまけConoHa VPSで帯域実測

自宅サーバーとConoHa VPS間でiperf3をやってみた結果。自宅サーバーへの穴あけが面倒だったので自宅サーバー→ConoHaという逆経路でしか試していない。

Interval Transfer Bitrate Retr Cwnd
0.00-1.00 sec 24.4 MBytes 204 Mbits/sec 0 1.42 MBytes
1.00-2.00 sec 10.9 MBytes 91.2 Mbits/sec 0 1.43 MBytes
2.00-3.00 sec 12.2 MBytes 103 Mbits/sec 0 1.43 MBytes
3.00-4.00 sec 11.0 MBytes 92.3 Mbits/sec 0 1.43 MBytes
4.00-5.00 sec 10.9 MBytes 91.2 Mbits/sec 0 1.43 MBytes
5.00-6.00 sec 12.2 MBytes 103 Mbits/sec 0 1.43 MBytes
6.00-7.00 sec 11.0 MBytes 92.3 Mbits/sec 11 1.26 MBytes
7.00-8.00 sec 11.0 MBytes 92.3 Mbits/sec 169 762 KBytes
8.00-9.00 sec 11.0 MBytes 92.3 Mbits/sec 0 807 KBytes
9.00-10.00 sec 12.2 MBytes 103 Mbits/sec 0 838 KBytes
  • sender: 106 Mbits/sec
  • receiver: 103 Mbits/sec

2026/07/03(金)ConoHaのVPSのポートに穴をあけて外部通信できるようにした

更新日:
投稿日:

任意のポートでSSH接続をしようとしたら全然繋がらず、ググっても出てこなかったので書く。

この記事ではSSH接続に限らず、IP制限なく任意のポートを開放する方法について扱う。

1. セキュリティグループの作成

  1. コントロールパネルにログインする
  2. 左のメニューからセキュリティ→セキュリティグループを開く
  3. 「+セキュリティグループ」ボタンを押し、MySSHとか適当な名前で設定を作る
  4. 作成したセキュリティグループを開き、左下の「+」を押す
  5. 通信方向:IN
    イーサタイプ:IPv4 or IPv6
    プロトコル:TCP or UDP。1つの設定でTCPとUDP両方開けることはできない
    ポート範囲:単体の場合は10092、範囲の場合は10000-11000のように指定すると思うが範囲指定は試していない
    IP/CIDR:IPv4なら0.0.0.0/0、IPv6なら::/0
  6. コンソールに入る
  7. 初期設定

2. NICへセキュリティグループを割り当て

  1. 左のメニューからサーバーを開き、適用するVPSを開く
  2. ネットワーク情報の「セキュリティグループ」を開く
  3. 「+」ボタンを押し、先ほど作成したセキュリティグループを選択
  4. 保存ボタンを押し、セキュリティグループが追加されていることを確認
  5. この時に、プリセットに存在するICMPのルールも割り当てておくと良い。「IPv4v6-ICMP」がそれだ

この設定の反映は即座には反映されないようで、数秒のタイムラグがあった。3秒くらい待つと繋がった。

3. VPSのファイアーウォールに穴をあける

  1. コンソールからVPSのシェルに入る
  2. /etc/nftables.confを開き、先ほどセキュリティグループで開けた穴が開くように設定する

    #!/usr/sbin/nft -f
    
    flush ruleset
    
    table inet filter {
        chain input {
            type filter hook input priority 0;
            policy drop;
    
            iif "lo" accept
    
            ct state established,related accept
    +
    +         meta l4proto { icmp, ipv6-icmp } accept
    +
    +         tcp dport 3000 accept
        }
    
        chain forward {
            type filter hook forward priority 0;
        }
    }
    
  3. nftablesを再起動する
    systemctl restart nftables
    

おまけ:公開鍵認証を使ったSSH接続について

コントロールパネルのセキュリティ→SSH Keyという項目があるが、ここを設定する必要はない。

/etc/ssh/sshd_configを書き換えて、公開鍵を所定の場所に設置すれば普通に設定できるので、わざわざWeb画面から設定する必要はない。

ここから追加したところでパスワード認証が無効になるのかどうかもわからないし、そもそもこれがSSHDに関連するのかもわからないし、謎設定だと思う。ひょっとしたら単に鍵を生成するだけなのかもしれないが、それならssh-keygenなどを使えばいいわけで…。

あとがき

Conoha公式のVPSスタートアップガイドにはSSH接続でVPSにログインするというのがあるが、セキュリティグループに関する記述がないので、そのままでは標準の22番ポートにすら繋がらないのが困りものだ。

VPSスタートアップガイドと言うからにはそのくらい書いてくれてもいいんじゃないだろうか?と思った。

2026/06/19(金)さくらのレンタルサーバーにCachetを設置したログ

ステータス管理画面のCachetをさくらのレンタルサーバーに設置したときのログ。

開発版の3.xを利用しているが、軽く叩いた感じはとりあえず使える気がする。

確認環境

確認時点でのさくらのレンタルサーバーではSQLiteでの動作は出来なかった。これはPHP拡張がJSONをサポートしていないからと思われる。

Env Ver
Cachet 3.x 2b0fc68988309647bdc0ba8e0b40862a3b8ddef4
cachethq/core 87be2387c06264c672dad94c87d00408bf34536d
PHP 8.3.31
MySQL 8.0

Cachetには正確なバージョン番号がなさそうなのでコミットハッシュを書いている。最新のハッシュのコードが入っていることを確認済。

またCachet 3.xの中身は事実上からっぽで、vendor/配下にあるcachethq/coreが本体なので、そちらのバージョンも併記している。

手順

以下のコマンドはすべてzshで実行しているため、さくら標準のcshでは動かない箇所があるかもしれない。

  1. composerがなかったのでcomposerを入れた。ここから先は~/bin/にPATHが通っていることを前提で進める

    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    php -r "if (hash_file('sha384', 'composer-setup.php') === 'c8b085408188070d5f52bcfe4ecfbee5f727afa458b2573b8eaaf77b3419b0bf2768dc67c86944da1544f06fa544fd47') { echo 'Installer verified'.PHP_EOL; } else { echo 'Installer corrupt'.PHP_EOL; unlink('composer-setup.php'); exit(1); }"
    php composer-setup.php
    php -r "unlink('composer-setup.php');"
    
    mkdir ~/bin
    mv composer.phar ~/bin/composer
    
  2. Cacheの取得と設置

    git clone -b 3.x https://github.com/cachethq/cachet.git
    cd cachet
    
    composer install --no-dev -o
    # composerでエラーが出てupdateしろといわれたためupdate、これでインストールまでしてくれる
    composer update
    # 本体のアップデート
    composer update cachethq/core
    # 環境変数の編集
    cp .env.example .env
    
  3. .envの編集
    デフォルトでAPP_DEBUGがtrueなのでfalseにした方が良い。まだ開発版のためかTIMEZONEを設定してもトップ画面には反映されない。管理画面の一部では反映される。

    APP_DEBUG=false
    APP_TIMEZONE="Asia/Tokyo"
    APP_URL=https://status.example.com
    DB_CONNECTION=mysql
    DB_HOST=DBホスト
    DB_PORT=3306
    DB_DATABASE=データベース名
    DB_USERNAME=データベース名
    DB_PASSWORD=パスワード
    
  4. Cachetのセットアップ

    php artisan key:generate
    
    php artisan vendor:publish --tag=cachet
    php artisan migrate
    
    # envを閲覧不能にする
    cat <<'EOF' | tee .htaccess
    <Files .env>
    deny from all
    </Files>
    EOF
    
    # 403になることを確認
    curl https://status.example.com/.env
    
    php artisan cachet:make:user
    
  5. crontの設定。ステータスページ表示する機能しかないのにやる意味があるのかは謎。
    *   *   *   *   *   php /home/<username>/www/path/to/artisan schedule:run >> /dev/null 2>&1
    
  6. さくらのコンパネからドメインを開き、Web公開フォルダーをpath/to/cachet/publicにする。

備考

Cachet v3.x is currently in development and not yet released. The following instructions are intended for development purposes only and are subject to change.

現時点では上記のようにあり、開発版なのでバグはあると思われる。

トラブルシューティング

Illuminate\Database\QueryExceptionが出る

SQLiteを使っていて次のようなエラーが出る場合、MySQLに変えると直る。恐らくさくらのレンサバに入ってるSQLite拡張がjson_eachをサポートしてないのが原因。

!Illuminate\Database\QueryException

Internal Server Error


SQLSTATE[HY000]: General error: 1 no such table: json_each (Connection: sqlite, SQL: select *
from "webhook_subscriptions" where ("send_all_events" = 1 or exists (select 1 from
json_each("selected_events") where "json_each"."value" is component_updated)))

Expand vendor frames

app/Http/Middleware/TrustProxies.php :32

あとがき

ステータスページを作る以上の機能が中区、外形監視はしてくれなかった

外形監視をして、その結果をステータスに表示してくれるツールだと思っていたら、ステータスの設定を行う機能と、それを表示する機能しかなかった。

つまり手動でメンテナンス中とか出したり、外形監視からAPIを蹴って何か表示するのには使えるが、このツールにはそれ以上の機能はないようだ。

これはダッシュボードを作る画面とAPIを提供してくれるツールということだ。

親切だったユーザー作成ウィザード

install.phpにアクセスして設定を書き換えるみたいな、一瞬ではあるものの脆弱な瞬間がないのは便利だと思った。

簡単なものなら自作できそう

Cachetは画面操作によってステータスを変えたり、履歴を出したりできるが、curlを投げて落ちてたら画面に表示くらいならパパっと作れそうだなと思った。

とはいえ、画面のリッチさや、APIからも操作できることなどを考えると、そんなのを作るのも大変なので、Cachetのようなツールを使った方が楽なのは間違いない。

ほぼ自分しか使ってないサーバーのためにこんなリッチなものが必要なのか…?

まぁあった方が豪華だし…みたいな…。

保守やオペのコストの方が高いので結局使わずじまいになる可能性も無きにしも非ずではある。

2026/05/28(木)Value-DomainのDNSを操作するユーティリティを更新した

更新日:
投稿日:

value-domain-dns-utilを更新したので、その記録とか、その感想の怪文章とか。

更新内容

ワイルドカード証明を発行するときに失敗する問題の修正

これまでDNS更新のタイミングの関係で偶々成功していたが、何度もやってると失敗することが多かったので、失敗しないようにした。

変更前

  • vd-dcr.pl
    • APIからDNSレコードを取得→レコードにACME TXTレコードがなければ追加、あれば上書き→編集後のレコードをAPIに送る

変更後

  • vd-dcr-auth.pl
    • APIからDNSレコードを取得→レコードにACME TXTレコードを追加
  • vd-dcr-cleanup.pl
    • cleanup:PIからDNSレコードを取得→レコードから今回登録したACMEレコードを除去→編集後のレコードをAPIに送る

モジュール化

lib/VdDnsUtil.pllib/VdDnsUtil.pmに変更し、shebangを削除。

並びに今回の変更で追加したユーティリティも.pmとして実装。

バージョニングの追加

スクリプトを叩いたときに依存モジュールと本体のバージョンが出るようにした。

対処が必要なこと

vd-dcr.plの改修に関わる影響のため、vd-dcr.plを使っている人だけに影響がある。

Net::DNS::Digの追加

rootユーザーで以下を流し、Net::DNS::Digを入れる。既にある場合は不要。

cpan Net::DNS::Dig

Certbotの走行コマンドの変更

certbotを以下の書式で再走行させる。具体的には--manual-cleanup-hookが増えてるので、そこを足す。これによってrenewが上書きされ、次回以降、正しく動作するようになる。

 sudo certbot certonly --manual -n \
   --preferred-challenges dns \
   --agree-tos -m <your-email> \
   --manual-auth-hook "/path/to/vd-dcr-auth.pl <value-domain-api-key> <root-domain> <optional:ttl>" \
+  --manual-cleanup-hook "/path/to/vd-dcr-cleanup.pl <value-domain-api-key> <root-domain> <optional:ttl>" \
   -d <FQDN>

また、従来であればValue-DomainのAPIに更新リクエストを投げてから3秒しか待っていなかったところ、今回はDNSの伝播を待ち、更に5秒待つように直しているため、以前より実行時間が伸びているため、もし何かしらのタイミング処理がある場合は見直しが必要。

今回の対応をした理由

切欠としてはモジュール化の作業中に不具合が発覚したところに始まる。

これまで共通部品として.plを使っていたが、Perlの再利用性について考えていた時に.pmの概念を知ったので改修することにした。その動作確認をしていたところ、ワイルドカードドメインの更新がやたらと失敗することに気付き、本格的に調査を始めたのが発端だ。

そして以前は次の順序で処理していた。

  1. 初回走行時にルートドメインのTXTレコードを追加する
  2. 二回目走行時にこのレコードをワイルドカード用のTXTレコードで上書きする

しかし、本来これは正しくなかった。ワイルドカードドメインを指定する場合、プライマリとセカンダリのTXTレコードが両方とも登録されている必要があるようだった。

ではなぜ今まで動いていたのか。これはDNS更新のタイミングの関係で偶々成功していただけと思われる。そして、私がそのことに気付いていなかったわけだ。動作確認で何度も実行しているとやけに失敗するので、今回この不具合に対応することに決めた。

そして前述の更新内容に繋がるわけだが、これまでは--manual-auth-hook向けのスクリプトしか用意しておらず、その中で「既存ACMEレコードがあれば上書きする」という擬似的なクリーンアップ処理を行っていた。これが前述の不具合を引き起こす要因となっていたため、次の改修を施した。

  • auth側からクリーンアップ処理(既存ACMEレコードの上書き)を除去し、純粋に「TXTレコードを追加する」だけの処理に変更
  • 新たに--manual-cleanup-hook用のスクリプトを追加し、authで登録したレコードをDNSから削除する処理を、こちらに新設した

これにより、プライマリ・セカンダリ両方のTXTレコードが正しく揃った状態でLet's Encryptの検証に渡され、検証完了後にきちんと後始末されるようになった。

参考までにコケていたときは次のエラーが出ていた。

Certbot failed to authenticate some domains (authenticator: manual). The Certificate Authority reported these problems:
Domain: hogezzz.lycolia.info
Type: dns
Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.hogezzz.lycolia.info - check that a DNS record exists for this domain

Domain: hogezzz.lycolia.info
Type: unauthorized
Detail: During secondary validation: Incorrect TXT record "tiHFPEdgZ24aejUpmRkkzNvzUoisQn6mDv3d3xqHBNo" found at _acme-challenge.hogezzz.lycolia.info

あとがき

二日で15コミット変更行数は1,397行追加、217行削除という結構大規模な改修を入れたので、どこかにバグが潜んでいる可能性は捨てきれない。

何せ以前開発していたvalue-domain-dns-cert-registerから、このvalue-domain-dns-utilに移行するときにLLMにガっとやらせてから、今回に至るまでコードのメンテはほとんどLLMに任せている。

当然LLMが書いたコードはレビューして明らかに変なところは手直ししているが、精々コード全体の3-4割で、過半数はLLMが書き、LLMが直せる場所は私が直さずLLMに直させている。テストコードに至っては99%くらいLLMに書かせており、正直正しいコードが掛かれているのかまで見切れていない。以前なら血眼になってテストコードを書いていたはずなのに不思議なものである。

まぁでも実コードを手直ししたら落ちたので、たぶん機能していると思う。あとvalue-domain-dns-cert-registerから継承されたテストコードについては一通り見ているので、全く見ていないわけでもない。

LLMにコードを書かせると作るのは楽だがレビューが大変なのが困りものだ。あと私はAnthropicをBANされている関係で地味にお金がかかるのも困りものである。今回の改修には20USDほどかかっており、安くはない。もう少し手でコードを書くべきだとは思う。考える力も徐々に薄れていっている気がしており、人間として危機感を感じることもある。

ボケ防止のためにはAIに頼らず、自分の手を動かすのも大切なことだと思う。こういう話では、よくそろばん論を持ち出して、そろばんを使わなくなったが人類は劣化していない、電卓があるみたいなことを言う人がいるが、実際問題珠算ができる人は非常に速い速度で暗算ができ、頭の回転も速いとされているので、電卓があるから優位と言われれば、それは違うと思う。例えば電卓を取り出す時間で計算が終わっていたり、物事を予測しやすかったりするわけだ。

ある能力が減った分、別の能力が増えるみたいな考えもあるとは思うが、一人の人間としてAIにべったり過ぎるのもやや危険ではないかと思う。第一災害時どうするんだと思うし、登山などでは電波の届かない山の中ではそもそも使えないとかもあるし、ボケるボケないも寿命に影響するみたいな話は聞くので、考える力は大切だと思う。私は管理職とか企画職みたいなところよりは、現場人間でありたい気もしているし…。

なんだかオチが迷走してきたが、とりあえずvalue-domain-dns-utilはワイルドカード証明書も含めて安定して動くようになったはずなので、必要に応じて更新してもらえれば安定性が増すかもしれない。もしバグを踏んだら報告してもらえれば対応するかもしれません。

しかしこのスクリプトは動作確認が非常に面倒なので、できればもう手を入れたくないところではある…。