<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Infra on 万屋猫Labs</title><link>https://yn-labs.com/categories/infra/</link><description>Recent content in Infra on 万屋猫Labs</description><generator>Hugo</generator><language>ja</language><lastBuildDate>Sat, 04 Jul 2026 10:00:00 +0900</lastBuildDate><atom:link href="https://yn-labs.com/categories/infra/index.xml" rel="self" type="application/rss+xml"/><item><title>dotfiles にも CI を — 破壊的インストーラの冪等性を Ubuntu と Kali の二役で検証する</title><link>https://yn-labs.com/posts/dotfiles-ci-idempotency/</link><pubDate>Sat, 04 Jul 2026 10:00:00 +0900</pubDate><guid>https://yn-labs.com/posts/dotfiles-ci-idempotency/</guid><description>&lt;h2 id="自分の開発環境がある日再現できなくなる"&gt;自分の開発環境が、ある日再現できなくなる&lt;/h2&gt;
&lt;p&gt;開発環境を1本のスクリプトにまとめている。シェル設定・プロンプト・ターミナルマルチプレクサ・言語ランタイム・クラウドCLIを、&lt;code&gt;./setup_env.sh&lt;/code&gt; 一発で入れる。最終的に 1,358 行になった。新しいマシンでも、OS を入れ直した後でも、同じ環境がすぐ戻ってくる。便利だ。&lt;/p&gt;
&lt;p&gt;便利なのだが、ひとつ不安が残った。今度は &lt;strong&gt;そのスクリプト自体が壊れたときに気づけない&lt;/strong&gt;。うっかり片方の OS でしか通らない書き方をしても、次にそのマシンを触るまで分からない。設定ファイルを追記する処理が既存の &lt;code&gt;.zshrc&lt;/code&gt; を壊しても、実際に事故ってから気づく。手作業をスクリプトにまとめた結果、こんどはその 1 本のスクリプトに、環境の再現を丸ごと預けることになった。&lt;/p&gt;
&lt;p&gt;それで、dotfiles にも CI をつけた。やることは本番インフラの検証と変わらない。&lt;strong&gt;「危険な変更が入ったら、その場で赤くする」&lt;/strong&gt; を、開発環境の構築スクリプトに対してやる。この記事では、その CI（GitHub Actions）を抜粋して紹介する。リポジトリ固有の名前やレイアウト名は伏せるか一般化し、コードは要点を示す抜粋にしてある。&lt;/p&gt;
&lt;h3 id="数字で見た中身"&gt;数字で見た中身&lt;/h3&gt;
&lt;p&gt;実環境の中身は出せないので、代わりに構成の規模で示す。以下はこの dotfiles と CI を実測した値だ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;指標&lt;/th&gt;
 &lt;th&gt;値&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;setup_env.sh&lt;/code&gt; 行数（単一エントリポイント）&lt;/td&gt;
 &lt;td&gt;1,358&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI ジョブ（builder / breaker / aggregate）&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;検証環境（Ubuntu runner / Kali コンテナ）&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;scripts/ci/validate_*&lt;/code&gt; チェッカ&lt;/td&gt;
 &lt;td&gt;14&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;CI で生成検証する Zellij レイアウト（総数9本のうち）&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;インストーラ検証の段階（dry-run → 実行 → &lt;code&gt;--clean&lt;/code&gt; 再構築）&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="全体構成"&gt;全体構成&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; push / PR / dispatch
 │
 ┌────────────────┴────────────────┐
 ▼ ▼
 ┌──────────────────────┐ ┌──────────────────────────┐
 │ builder (Ubuntu) │ │ breaker (Kali container) │
 │ shellcheck / clippy │ │ shellcheck / clippy │
 │ setup --dry-run │ │ setup --dry-run │
 │ 隔離HOMEで実インストール │ │ 隔離HOMEで実インストール │
 │ --clean で再構築 │ │ --clean で再構築 │
 │ layout ×4 を assert │ │ layout ×4 を assert │
 └──────────┬───────────┘ └────────────┬─────────────┘
 │ report (artifact) │ report (artifact)
 └────────────────┬──────────────────┘
 ▼
 ┌──────────────────────┐
 │ aggregate │
 │ 2環境のレポートを統合 │
 │ → CI step summary │
 └──────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;CI は 3 ジョブに分けている。同じインストーラを 2 つの OS で流す &lt;code&gt;builder&lt;/code&gt; と &lt;code&gt;breaker&lt;/code&gt;、そして両者のレポートを 1 枚にまとめる &lt;code&gt;aggregate&lt;/code&gt; だ。&lt;/p&gt;</description></item><item><title>homelab を Ansible でコード化する — fail-closed な多層防御インフラ</title><link>https://yn-labs.com/posts/ansible-homelab-iac/</link><pubDate>Mon, 15 Jun 2026 10:00:00 +0900</pubDate><guid>https://yn-labs.com/posts/ansible-homelab-iac/</guid><description>&lt;h2 id="自宅サーバを丸ごとコードにした話"&gt;自宅サーバを丸ごとコードにした話&lt;/h2&gt;
&lt;p&gt;自宅サーバ（homelab）で AI エージェント基盤を動かすために、コンテナランタイム、ネットワーク分離、暗号化DNS、カーネル緩和、監査ログまで一通り手で組んだ。動くには動いたのだが、ひとつ不安が残った。OS を入れ直したとき、同じものをもう一度作れる自信が無かったのだ。どこをどう直したか、どのセキュリティ設定を入れ忘れているか、結局は頭の中にしか無い。&lt;/p&gt;
&lt;p&gt;それで、構築手順そのものを Ansible に落とした。最終的に9ロール・約3,900行になった。手順をコードにしただけではなくて、「危険な設定なら構築を止める」ところまで踏み込んでいる。空の許可リストや古い Podman で進もうとすると、playbook が走り出す前に &lt;code&gt;assert&lt;/code&gt; が落とす。&lt;/p&gt;
&lt;p&gt;この記事では、その構成（rootless Podman + Quadlet による多層防御 homelab）を抜粋して紹介する。実環境のホスト名・IP・ユーザ名・トークン・コンポーネント名のたぐいは伏せるか一般化し、コードも要点を示す抜粋にしてある。固有名が絡むところは変数名やファイル名を一般化し、汎用的で機微に関わらないところは実物に近い形で残した。&lt;/p&gt;
&lt;h3 id="数字で見た中身"&gt;数字で見た中身&lt;/h3&gt;
&lt;p&gt;実環境の中身は出せないので、代わりにコードの規模で示す。以下はこの Ansible 構成を実測した値だ。&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;指標&lt;/th&gt;
 &lt;th&gt;値&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Ansible ロール数&lt;/td&gt;
 &lt;td&gt;9&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;roles/*/tasks/main.yml&lt;/code&gt; 総行数&lt;/td&gt;
 &lt;td&gt;3,898&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fail-closed な &lt;code&gt;assert&lt;/code&gt; 箇所&lt;/td&gt;
 &lt;td&gt;13&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;分離ネットワーク（内部用 / 外部egress用）&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Quadlet コンテナユニット&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="全体構成"&gt;全体構成&lt;/h2&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;┌─────────────┐ ansible-playbook ┌──────────────────────────────┐
│ 司令ホスト │ ───── over SSH ─────▶ │ 本番ホスト (target) │
│ (operator) │ apply --tags … │ │
└─────────────┘ │ ┌────────────────────────┐ │
 │ │ bootstrap: OS/pkg/UFW │ │
 │ │ /DoT/helpers │ │
 │ ├────────────────────────┤ │
 │ │ podman 5.x rootless │ │
 │ │ + cgroup v2 + Quadlet │ │
 │ ├──────────┬─────────────┤ │
 internal-net ◀─────────────────────┼──│ policy / │ notification │ │
 （サービス間） │ │ LLM 系 │ / relay │ │
 外部 API ◀──────────────────────────┼──│ gateway │ │ │
 │ ├──────────┴─────────────┤ │
 │ │ audit: ログ収集+署名付死活 │ │
 │ └────────────────────────┘ │
 └──────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;役割は9つのロールに分けている（名前は一般化したもの）。&lt;/p&gt;</description></item></channel></rss>