TL;DR
- エックスサーバーの REST API は Bearer トークンの素朴な作り。
.env.xserverに API キーを 1 つ置いてset -a; source; set +aで export、curl -H "Authorization: Bearer ..."をxs_get()でラップすれば、ドメイン / SSL / DNS / Cron / DB / SSH 鍵を全部 1 つのスクリプトから読める。- 生の JSON を人間が読むなら
jq -r '... | "\(.a)\t\(.b)"' | column -t -s $'\t'の組み合わせが鉄板。 - SSL の
common_name、DNS の長い TXT、SSH 公開鍵などは jq の中で前処理してから出すと読みやすい。
モチベーション
エックスサーバーは「サーバーパネル」(Web 管理画面) が主役の老舗だけど、2024 年以降は REST API と CLI と MCP Server まで整備されている。個人開発のドメイン (example.com) を運用するにあたって、以下の事情で全部 API + curl 経由に寄せた:
- 管理画面に毎回ログインするのがだるい
- 「DNS のレコード何だっけ」「cron 何時に動いてる?」みたいな確認は、CLI で 1 行で出した方が早い
- AI エージェント (Claude Code) に運用を任せる場面で、API の方が再現性が高い
公式ドキュメントは https://developer.xserver.ne.jp/api/server/ にある。本稿では「読み取り系 (GET のみ、副作用なし)」のスクリプトを設計する。
ステップ1: API キーと環境ファイル
エックスサーバー管理画面 > API キー管理で発行。発行後はキーが二度と表示されないので忘れずに控える。
deploy/.env.xserver (gitignore 対象) はこんな構造:
# Xserver API
XSERVER_API_KEY="xs_xxxxxxxxxxxxxxxxxxxxxxxx"
# 操作対象サーバ (= /v1/server/<ここ>)
XSERVER_TARGET_SERVER="myserver.xsrv.jp"
# SSH (rsync デプロイで使う)
XSERVER_SSH_HOST="myserver"
# 取り扱うドメイン
LP_DOMAIN="example.com"
API_DOMAIN="api.example.com"
APP_DOMAIN="app.example.com"
スクリプト側はこう読み込む:
set -a; source "${ENV_FILE}"; set +a
: "${XSERVER_API_KEY:?XSERVER_API_KEY が未設定}"
: "${XSERVER_TARGET_SERVER:?XSERVER_TARGET_SERVER が未設定 (例: myserver.xsrv.jp)}"
set -a から set +a までの間に source した変数はすべて export される。後で xs_get() 内で ${AUTH} を組み立てるときに環境変数として参照できる。
: "${VAR:?エラーメッセージ}" は「VAR が未設定なら表示して即終了」のイディオム。最初に書いておくと「キーがないのに走り始めた」事故を防げる。
ステップ2: 共通の xs_get() ラッパー
全エンドポイントで共通する「ベース URL」と「Bearer ヘッダ」を関数化する。
BASE="https://api.xserver.ne.jp/v1/server/${XSERVER_TARGET_SERVER}"
AUTH="Authorization: Bearer ${XSERVER_API_KEY}"
xs_get() {
local path="$1"
curl -fsS -H "${AUTH}" "${BASE}/${path}"
}
curl のオプション:
-f— HTTP エラー (4xx/5xx) で非ゼロ終了。set -eと組み合わせれば、xs_getが失敗した時点でスクリプト全体が止まる。-s— プログレスバー非表示。-S— ただしエラーメッセージは出す (-sで隠れたものを復活)。
これだけで「xs_get domain | jq .」「xs_get ssl | jq .」みたいに端的に書ける。
ステップ3: jq で見やすく整形する
GET の生レスポンスはどれも JSON。jq の -r (raw 出力) でタブ区切りに整形し、column -t -s $'\t' で揃える、というのが汎用パターン。
ドメイン一覧
show_domain() {
print_header "ドメイン一覧"
xs_get "domain" | jq -r '
.domains[] |
"\(.domain)\ttype=\(.type)\tssl=\(.ssl)\tmemo=\(.memo // "-")"
' | column -t -s $'\t'
}
memo // "-" で null/未設定を - に置換。地味だけど一覧の見やすさに効く。
SSL 一覧 (ドメインで絞り込み)
show_ssl() {
print_header "SSL 証明書 (example.com 関連のみハイライト)"
xs_get "ssl" | jq -r --arg dom "$LP_DOMAIN" '
.ssl_list[]
| select(.common_name | endswith($dom) or . == $dom or contains($dom))
| "\(.common_name)\t\(.type)\texpires=\(.expires_at)\t\(.status)"
' | column -t -s $'\t'
}
--arg で外側の変数を jq に渡す。endswith($dom) or . == $dom or contains($dom) の 3 段重ねは「app.example.com」「example.com」「ワイルドカード *.example.com」をすべてヒットさせるため。
DNS (長い TXT を 80 字でトリム)
DKIM の TXT レコードは平気で 300 文字を超えるので、そのまま出すと見づらい。jq で先頭 80 文字 + … に丸める:
xs_get "dns" | jq -r --arg dom "$LP_DOMAIN" '
.records[]
| select(.domain == $dom)
| (.content | if length > 80 then .[0:80] + "…" else . end) as $c
| "\(.host)\t\(.type)\t\($c)\tttl=\(.ttl)"
' | column -t -s $'\t'
文字列を変数 $c に束ねてからフォーマット文字列に埋め込む、という jq の常套句。
SSH 公開鍵 (末尾 12 文字を short id に)
公開鍵を全部出すと画面が崩れるので、ssh-ed25519 AAAA...XYZ user@host の中から「鍵の末尾 12 文字」と「comment」だけ抜く:
echo "$json" | jq -r '
.keys[] |
((.public_key // "") | split(" ")) as $parts |
($parts[2] // "-") as $comment |
(if ($parts[1] // "" | length) > 12 then ($parts[1] | .[-12:]) else "-" end) as $tail |
"id=\(.id)\tstatus=\(.status)\tlabel=\(.label)\tcomment=\($comment)\tkey…\($tail)\tat=\(.created_at)"
' | column -t -s $'\t'
公開鍵自体は管理画面でしか見られなくても、複数鍵を見分けるなら末尾 12 文字 + comment で十分。
ステップ4: サブコマンドで切り替える
「全部一気に見たい時」と「DNS だけ見たい時」が両方ある。Bash の case で素朴に振り分け:
case "${1:-all}" in
domain) show_domain ;;
ssl) show_ssl ;;
dns) show_dns ;;
cron) show_cron ;;
db) show_db ;;
ssh) show_ssh ;;
raw) shift; show_raw "$@" ;;
all) show_domain; show_ssl; show_dns; show_cron; show_db; show_ssh ;;
*)
echo "使い方: $0 [all|domain|ssl|dns|cron|db|ssh|raw <ep>]" >&2
exit 2
;;
esac
raw <endpoint> を残しておくと、まだスクリプトに組み込んでいないエンドポイントも bash xs-info.sh raw mail で叩けるので便利。
完成形: xs-info.sh
最終的なスクリプトの全文は約 140 行。本連載末尾でリポジトリリンクをまとめて案内する。
呼び出し例:
$ bash deploy/scripts/xs-info.sh domain
== ドメイン一覧 ==
example.com type=独自ドメイン ssl=ON memo=-
api.example.com type=サブドメイン ssl=ON memo=-
app.example.com type=サブドメイン ssl=ON memo=-
$ bash deploy/scripts/xs-info.sh ssl
== SSL 証明書 (example.com 関連のみハイライト) ==
example.com LE expires=2026-08-30T00:00:00+09:00 active
api.example.com LE expires=2026-09-02T00:00:00+09:00 active
app.example.com LE expires=2026-09-02T00:00:00+09:00 active
まとめと次回予告
- API キーを
.env.xserverに置いて、set -a; source; set +aで export。 xs_get()関数で共通ヘッダを 1 箇所に集約。jq -r '...\t...' | column -t -s $'\t'が「読みやすい一覧」の鉄板。- 長文 (TXT) や複合フィールド (SSH 公開鍵) は jq の中で前処理してから出す。
ここまでは GET のみで「読むだけ」だった。次回からは POST で 副作用ありの API を安全に叩く ための設計に入る。第 2 回は「DB + ユーザ + 権限付与」を 3 連 POST で自動化する xs-db-create.sh を題材に、DRY-RUN を既定にする運用パターンを扱う。


コメント