私のサーバーにもうSSHで接続できません(それでも問題ありません)

2026/01/07 18:37

私のサーバーにもうSSHで接続できません(それでも問題ありません)

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

著者は高価な「moana」VPSと月額100ドル超のホスティングサービスを廃止し、費用対効果に優れた自己管理型スタック「Tinkerbell」に切り替えました。Moana は自前でサービスをホストするために使用されていましたが、その高い月額コストが縮小のきっかけとなりました。

Tinkerbell には SSH でログインできず、更新は新しいコンテナイメージをレジストリへプッシュし、Tinkerbell がそれを自動的に取得・デプロイすることで行われます。スタックは Fedora CoreOS(FCOS)上で稼働し、Ignition を用いて一度だけのプロビジョニング、Podman Quadlets で宣言型コンテナオーケストレーション、Terraform で Vultr 上のインフラをコード化します。

著者のウェブサイトは Nginx/TLS 経由で配信される静的バイナリです。新しい構成では、Caddy(TLS 用)とスクラッチイメージに包まれたウェブサイトバイナリという 2 つのコンテナが稼働します。Ignition の設定は Butane を使って YAML から生成され、JSON(.ign)ファイルとして FCOS に最初の起動時に適用されます。Terraform は Ignition ファイルへのユーザーデータを指す Vultr インスタンスを定義し、計画を適用または破棄することで VM を再作成します。

当初は systemd のユニットファイルで Podman コンテナを起動していましたが、これが面倒だったため Quadlets(.container と .pod ファイル)へ切り替えました。コンテナに

io.containers.autoupdate=registry
ラベルを付与し、タイマーを日次から毎時に変更することで自動更新を有効化しました。

著者は SSH アクセスを完全に削除し、デプロイはイメージプッシュのみで行う予定です。今後の作業としては観測スタックの構築、TLS 証明書をブロックストレージへ移動する可能性、および OpenTelemetry を使った監視検討が挙げられます。イミュータビリティモデルでは変更時に VM を再作成する必要がありますが、ウェブサイトの更新頻度が低いことから受け入れ可能です。

本文

I would like to thank Yann Régis‑Gianas, Sylvain Ribstein and Paul Laforgue for their feedback and careful review.


2026年のスタートに向けて

私は moana(信頼できる100ドル超/月のVPS)を退役させ、代わりに tinkerbell を導入するという明確な目標を持っていました。
moana は新しいサービスを試すには便利でしたが、1か月に100ドルは当然高額で、2025年の利用実績を振り返るとあまり有効活用できていませんでした。縮小する時期だと感じました。

tinkerbell が稼働している現在、SSH で接続さえもできません――それが必要なのはもうありません。
ホストされているサービスを更新したい場合は、該当レジストリに新しいコンテナイメージを正しいタグでプッシュすれば、tinkerbell が自動的に取得してデプロイします。

この記事では、Fedora CoreOSIgnitionPodman Quadlets を主役に据え、Terraform を不可欠なサポートキャラクターとして活用した「煙と鏡」の旅路を解説します。
このスタックは私が重視する全ての要件を満たしています。

興味がある方は、GitHub に tinkerbell の完全セットアップを公開しています。
本記事は実験ログとして書かれていますので、最終結果だけに興味がある場合はぜひご覧ください。


コンテナ中心・宣言型・低メンテナンス

moana の完全手動構成を再現したくはありませんでした。
結局のところ、すべては

nspawn
コンテナをその場で相互接続できる小さなスクリプトに依存していました。サーバー内部を細かく操作する時間とモチベーションがなくなっていたのです。

最初のアイデアは、moana で唯一保持したいサービスであるこのウェブサイトから始めることでした。
既にそのウェブサイト用コンテナイメージを作成していたので、将来的に他プロジェクトも展開できるような最も単純かつ長期的に安全な本番デプロイ方法が必要でした。

静的ウェブサイトのホスティングだけなら、このセットアップは過剰設計で逆効果になる可能性があります。
tinkerbell は「インターネット上の小さなハンドラボ」―クラウド型ホームラボを実現するための足場です。

  • Docker Compose 単体では適合しませんでした。Compose ファイルは好きですが、VM をプロビジョニングして管理する必要があります。
  • Ansible で VM をプロビジョンできますが、プレイブック作成は思ったより難しく、既存デプロイを信頼性高く更新することも同時に求められます。
  • Kubernetes は紙上では魅力的ですが、我々が直面しない課題の妥協から生まれる非常に複雑なスタックです。マネージドクラスタは便利かもしれませんが、費用対効果が低く moana の退役という動機を損ねます。

コンテナ実行専用 OS として設計された CoreOS が際立ちました。Ignition から調査を始めたのです。Ignition は初回起動時に VM を一度だけプロビジョンし、以後変更が必要な場合は VM を捨て新しく作るというモデルです。
直感的には逆らいそうですが、Ansible の代替を探していた主な理由を排除します。

systemd ユニットファイルで podman CLI コマンドを使ってコンテナを起動する方法は面倒だったため、Docker Compose 風のオーケストレーション――Podman Quadlets と自動更新に進みました。

これで全てが繋がり、何をすべきかが明確になりました。非常にワクワクしました。


tinkerbell の構築

1年余りにわたり、私のウェブサイトは OCaml でビルドされたスタンドアロン静的バイナリを RAM 上で提供し、Nginx が TLS 終端、certbot が証明書更新を担当していました。
moana のセットアップが手動だったと正直に言っているのは事実です。デプロイを自動化したいだけでした。

tinkerbell で運用するコンテナは二つ想定しました:

  1. リバースプロキシ – 長年 Nginx を愛用してきましたが、Caddy が自動的に TLS 証明書を取得・更新できると聞いて購入決定。
  2. ウェブサイト本体 – 静的バイナリは Scratch ベースイメージでほぼオーバーヘッドゼロのコンテナ化が可能です。

ウェブサイトを Vultr がホストする無料プラン公開レジストリに公開しました。
オフラインコピー取得も次のコマンド一つで完了します:

docker pull ams.vultrcr.com/lthms/www/soap.coffee:live

宣言型 …

この時点でアーキテクチャは明確になりました。次に機械が実行できる形へ変換するステップとして、Ignition 設定を作成し、CoreOS VM を起動します。

Ignition / Butane

Ignition 設定(

.ign
)は主にマシン向けに消費される JSON ファイルです。YAML から Butane を使って生成します。例:

variant: fcos
version: 1.5.0
passwd:
  users:
    - name: lthms
      ssh_authorized_keys:
        - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKajIx3VWRjhqIrza4ZnVnnI1g2q6NfMfMOcnSciP1Ws lthms@vanellope

重要: Ignition は初回起動時に一度だけ実行されます。意味のある変更はマシンを置き換える必要があります。

butane main.bu > main.ign
.ign
を生成し、Terraform で Vultr VM を定義します:

resource "vultr_instance" "tinkerbell" {
  region   = "cdg"
  plan     = "vc2-1c-1gb"
  os_id    = "391"

  label      = "tinkerbell"
  hostname   = "tinkerbell"
  user_data  = file("main.ign")
}

terraform apply
を実行し、新ユーザーで SSH してすべてが機能することを確認しました。

MVP

Terraform が完了したら、Butane 設定でコンテナを起動します。最初は podman を呼び出す systemd サービスを使いました:

systemd:
  units:
    - name: soap.coffee.service
      enabled: true
      contents: |
        [Unit]
        Description=Web Service
        After=network-online.target
        Wants=network-online.target

        [Service]
        ExecStart=/usr/bin/podman run \
          --name soap.coffee \
          -p 8901:8901 \
          --restart=always \
          ams.vultrcr.com/lthms/www/soap.coffee:latest
        ExecStop=/usr/bin/podman stop soap.coffee

        [Install]
        WantedBy=multi-user.target

これはシェルスクリプト風の手法でした。Podman Compose(Quadlet)が存在し、上流で統合されていることを思い出しました。

Quadlets

Quadlet では systemd 設定に似たフォーマットでコンテナを記述します;実際の systemd ユニットファイルは

systemd
ジェネレーターによって自動生成されます。ウェブサイト用
.container
ファイル例:

[Container]
ContainerName=soap.coffee
Image=ams.vultrcr.com/lthms/www/soap.coffee:live

[Service]
Restart=always

[Install]
WantedBy=multi-user.target

Caddy の設定も同様に

.container
ファイル化。二つのコンテナが通信できるよう pod を導入:

# soap.pod
[Pod]
Name=webapp

そして各コンテナで

PodName=webapp
を参照。

tinkerbell の再デプロイで全て正常に動作しました。

自動更新

最後の仕上げは Podman の自動更新です。
コンテナを

io.containers.autoupdate=registry
でラベル付けし、
podman-auto-update.timer
を有効化すると、VM が定期的にレジストリをチェックして新しいイメージがあれば必要なコンテナを更新します。

デフォルトのタイマー(1日1回)を 1 時間ごとに変更:

sudo systemctl enable podman-auto-update.timer
sudo systemctl start podman-auto-update.timer

これで新しいタグ(例:

www/soap.coffee:live
)をプッシュすれば、サイトは最大 1 時間以内に更新されます。SSH はデプロイに不要です。


今後の展望

tinkerbell は数日間稼働しており、システムには満足しています。
業界標準への近似を目指した結果であり、何か新しいものを発明したわけではありません。

ただし SSH で可視化できないため、システムはブラックボックスになりがちです。
将来的にメトリクス・ログ・トレーシングの観測スタックを構築し、TLS 証明書をブロックストレージへ移行して耐久性を高める計画です。

結局 tinkerbell は「イミュータブルインフラ」の実験であり、1 回デプロイすれば VM が更新を処理し、シンプルさを保ちます。

同じ日のほかのニュース

一覧に戻る →

2026/01/12 5:47

**macOS Tahoe におけるウィンドウサイズ変更の苦労** macOS Tahoe では、アプリケーションウィンドウをリサイズすることが思ったより難しい場合があります。ユーザーは次のような点に悩むことが多いです: - 標準のドラッグ&ドロップ方式が安定しない。 - リサイズ用キーボードショートカットが十分に文書化されていない。 - 特定のアプリではウィンドウサイズ制限を無視してしまう。 これらの問題は、デスクトップ上で効率的に作業することを困難にします。

## Japanese Translation: --- ## 要約 macOS Tahoe の極端に大きなウィンドウの角丸半径は、通常のリサイズ動作を妨げます。丸みが付いた角は、必要な 19×19 ピクセルのクリックターゲットの約 75% を可視ウィンドウ枠外へ押し出します。その結果、ユーザーが緑色領域(通常使う部分)内で角を掴もうとすると、クリックが許容領域外に落ちてリサイズが失敗します。見える角のすぐ外側、同じ 19×19 ピクセル帯内でのみクリックが成功し、リサイズが起動します。以前の macOS バージョンでは、このターゲットの約 62% がウィンドウ内部に配置されており、ユーザーの期待に合っていました。筆者はほぼ四十年にわたるコンピュータ使用経験の中でこのような問題を一度も遭遇したことがありません。この不一致はフラストレーションと生産性低下を招きます。開発者は対策を設計するか、Apple にバグ報告を提出する必要があります。 ---

2026/01/12 6:29

2026 年はセルフホスティング(自前で運用すること)の年です。

## 日本語訳: > 本記事は、Claude Code CLI エージェントを利用することで、誰でも低価格のミニPCで完全に機能的なホームサーバーを構築できることを示しており、深いシステム管理スキルが不要になる点を強調しています。Beelink Mini N150($379)に8 TB NVMe SSDを搭載し、著者はUbuntu 22.04 LTS をインストールし、セキュアネットワーク用に Tailscale を追加、その後 SSH で Claude Code をインストールします。シンプルな英語のプロンプトを発行するだけで、Claude Code は自動的に Docker を設定し、Compose ファイルを作成し、サービス(Vaultwarden, Plex, Immich, Uptime Kuma, Caddy, Home Assistant, ReadDeck)をデプロイし、リバースプロキシを構築し、永続性を確保し、更新とセキュリティパッケージを管理し、ブート時の再起動も可能にします。 > > Vaultwarden は軽量な Bitwarden 互換パスワードマネージャーとして機能し、Immich は Google Photos の代わりにモバイルアプリ、ローカル顔認識、タイムライン/マップビューを提供します。ReadDeck は Mozilla Pocket を補完するクリーンな UI と読み続行機能を備えています。Lazydocker(Docker コンテナ UI)や Glances(システムモニタリング)などの追加ユーティリティもスタックを完成させます。著者は低い消費電力(CPU 約6 %、メモリ約32 %)を指摘し、保守作業がサーバーを所有する感覚に近く、問題は SSH と Claude Code への英語プロンプトで解決できると強調しています。 > > 対象読者はターミナル操作に慣れたユーザーで、既に SaaS サービスの料金を支払っているが、フルインフラ専門家になることなく基盤システムを理解したい人々です。本記事は、ミニPC 上で Claude Code を利用したセルフホスティングが今や実現可能で楽しく、今年おすすめできると結論付けています。

2026/01/12 7:14

このゲームは、Windows・Linux・ブラウザ上で動作する単一の13 KiBファイルです。

<|channel|>final <|constrain|>## Japanese Translation: 記事では、1つのソースファイルが「ポリグロット」バイナリを生成する方法を示しています。このバイナリには、Windows、Linux/BSD、およびブラウザ用にコンパイルされた3つの小さなプログラム(スネークゲーム)がすべて含まれており、合計13 312バイトです。コードはJustine Tunneyのcosmopolitan libcアイデアを使用し、各プラットフォームでネイティブに実行できる<16 KiBの実行ファイルを生成します。 3つのビルドが作成されます: • WinAPI用C(i686 Visual C)– 画面スクリプトとしても機能する非従来型PEヘッダーを使用。スタブはゲームを解凍して起動し、最初に再実行まで0xc0000005エラーが表示されます。 • Linux/X11用C(x86_64 clang)– lzmaデコンプレッションとシェルドロッパーを使用してファイルからELF64バイナリを抽出します。 • ブラウザ用JavaScript – ブラウザは先頭の無害なゴミを無視し、CSSで隠し、HTML/Canvasゲームがこの余白後に開始されます。 各コンパイル済み/ミニファイド版は約3–5 KiBです。3つのバイナリは順序通りに連結され、各オペレーティングシステムまたはブラウザが自分のセクションを実行します。元のゲームソースは13 772バイトでしたが、パッキングと連結後、正確に13 312バイトになります。 ゲームプレイの詳細(パッケージング物語の一部ではなく、キーポイントで言及されている)は次の通りです: - スネークは食べ物を食べることで成長し、壁を避けます。 - 操作:矢印キー/WASDキー、ESCで終了、Rでリセット、Pで一時停止、Spacebarで開始。 - スコア:フルーツごとに+10、黄色のフルーツは+20。フルーツは一定レートで生成され、スネーク速度/長さに比例した時間が経過すると消えます。 - 10個のフルーツ後、ランダム壁を含むレベル変更が行われ、ヘッドから任意の食べ物へのパスが保証されます。初期スネーク位置はランダムですが、向いている方向に少なくとも5つの空きタイルがあります。 このプロジェクトは、複数のオペレーティングシステムとウェブブラウザ用の実行コードを1ファイルにまとめることができることを示し、小規模プログラムの軽量でプラットフォーム非依存的な展開の可能性を開きます。

私のサーバーにもうSSHで接続できません(それでも問題ありません) | そっか~ニュース