検証環境
- macOS 13 / Ubuntu 24.04
-
curl 8+
,jq 1.6+
,Python 3.11+
,OpenSSH 9+
やること / やらないこと
- やる: APIでVPS作成 → cloud-initで初期設定 → IP取得 → SSH接続 → 削除まで
- やらない: 料金最適化や本番の権限設計、監視/バックアップの詳細
APIを使ったVPSインスタンス作成の流れ
TL;DR(要約)
- Indigo APIで インスタンス作成 → 初期状態は STOP。
- statusupdate APIで start に変更して起動。
- インスタンス一覧から IPを取得 → SSH接続。
- (任意)起動後に NoCloud方式でcloud-initを適用。
- 料金(1GB Linux): 0.70円/時間(税込み)、月額上限449円(税込み)、最低利用料55円(税込み)。IP/ディスク/転送量の追加課金なし。
対象読者
- WebARENA Indigo をこれからAPIで触ってみたい人
- 手動GUIではなく Infrastructure as Code 的にVPSを作成・破棄したい人
- Qiita/社内Confluence/自社ブログ向けに記事を書きたい人
前提条件
- NTTPC WebARENA Indigoサービスを契約済みであること
- IndigoでSSH鍵を作成済みであること
- macOS / Linux / WSL 環境
- インストール済み:
curl
,jq
,ssh
,ssh-keygen
- (任意)DNSのA/AAAAレコードを編集可能
注意: 本記事では
$INDIGO_API_BASE=https://api.customer.jp/webarenaIndigo/v1 を前提
としています。
この記事で作るもの
- OS/インスタンスタイプ/リージョン/SSH鍵 一覧API を呼ぶ
- createinstance でVM作成(初期状態 STOP)
- statusupdate で起動
- getinstancelist でIP確認 → SSH
- (任意)SSH後に NoCloud seed でcloud-init適用
ステップ1:APIトークンの取得(ポータル)
IndigoのAPIを叩くには Bearerトークン が必要です。
まずはIndigoコントロールパネルでAPI鍵を発行します。
- WebARENA Indigoのコントロールパネルにログイン
- 左側メニュー → API鍵の管理、API鍵を選択し、API鍵の管理画面へ
- API鍵の管理画面で画面右上の[+API鍵の作成]ボタンを押して実行、表示されたAPI鍵とAPI秘密鍵を安全な場所に控える(再表示できないので注意!)
- この鍵を使って以下のようにBearer トークンを取得する
curl -X POST \
https://api.customer.jp/oauth/v1/accesstokens\
-H 'Content-Type: application/json' \
-d '{
"grantType": "client_credentials",
"clientId": "[API鍵]",
"clientSecret": "[API秘密鍵]",
"code": ""
}'
以下のようなレスポンスが表示される
{"accessToken": "[トークン]", "tokenType": "BearerToken", "expiresIn": "3599" , "scope": "" , "issuedAt": "*************"}
[API鍵],[API秘密鍵]はあなたの環境の値に置き換えてください。
ここで取得した[トークン]は有効期限が60分未満ですので注意が必要です
ステップ2:環境変数をセット
エンドポイントやトークンは環境変数で扱うと安全・便利です。
# Indigo APIのベースとなるエンドポイントを環境変数化する
export INDIGO_API_BASE="https://api.customer.jp/webarenaIndigo/v1"
# 認証トークン(Bearer)を環境変数に設定
export INDIGO_TOKEN="[取得したトークン]"
#SSH鍵一覧を取得する
# 200 OK が返れば認証成功。401 が返る場合はトークンを確認
curl -i -X GET "$INDIGO_API_BASE/vm/sshkey" \
-H "Authorization: Bearer $INDIGO_TOKEN"
[取得したトークン]はあなたの環境の値に置き換えてください。
SSH鍵一覧取得に成功するとレスポンスに[SSH鍵のID]が表示されるので控えておく
以下のように変数を設定する
# VMインスタンス作成時に使うパラメータ
export INDIGO_REGION=1 # リージョン 東京
export INDIGO_PLAN=1 # VMプラン 1vCPU1GB20GB
export INDIGO_IMAGE=25 # OSイメージ Ubuntu 24.04
export INDIGO_SSH_KEY_ID="[SSH鍵のID]" # 登録済みのSSH鍵から選択
export INDIGO_INSTANCE_NAME="api-demo-ubuntu2404-1C1G20G" # 任意の名前をつけよう
[SSH鍵のID]はあなたの環境の値に置き換えてください。
.env
に保存してsource .env
で読み込むのもおすすめです。Git管理下に置く場合は トークンを含めない よう注意!
ステップ3:VMインスタンス(VPS)を作成(初期状態STOP)
Indigoの createinstance エンドポイントに必要な引数をJSONで渡します。
curl -X POST \
"$INDIGO_API_BASE/vm/createinstance" \
-H "Authorization: Bearer $INDIGO_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"sshKeyId\": $INDIGO_SSH_KEY_ID,
\"regionId\": $INDIGO_REGION_ID,
\"osId\": $INDIGO_OS_ID,
\"instancePlan\": $INDIGO_INSTANCE_PLAN,
\"instanceName\": \"$INDIGO_INSTANCE_NAME\"
}"
レスポンスに含まれるVMのidを控えておきます。
ステップ4:作成済みVMの一覧を取得
curl -X GET \
"$INDIGO_API_BASE/vm/getinstancelist" \
-H "Authorization: Bearer $INDIGO_TOKEN" | jq
ここで新規作成したVMインスタンスのidと現在のステータス(STOPなど)を確認します。
ステップ5:ステータス変更(start)でVMインスタンスを起動
作成直後は STOP なので、statusupdate で start に変更します
curl -X POST \
"$INDIGO_API_BASE/vm/instance/statusupdate" \
-H "Authorization: Bearer $INDIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"instanceId":"[VMインスタンスのid]","status":"start"}'
[VMインスタンスのid]はあなたの環境の値に置き換えてください。
ステップ6:IP確認 → SSH接続 →(任意)cloud-init 適用
①IPアドレスを確認
一覧のレスポンスからPublic IPv4アドレスを取り出します。
#INDIGO_INSTANCE_NAMEを指定
export INDIGO_INSTANCE_NAME="api-demo-ubuntu2404-1C1G20G"
curl -s -X GET "$INDIGO_API_BASE/vm/getinstancelist" -H "Authorization: Bearer $INDIGO_TOKEN" \
| jq -r --arg name "$INDIGO_INSTANCE_NAME" '
.[]
| select((.instance_name|tostring|gsub("\\s+$";"")|ascii_downcase)
== ($name|gsub("\\s+$";"")|ascii_downcase))
| select(.instancestatus=="Running")
| (.ip // .ipaddress) // empty
'
VMインスタンス一覧が表示されるのでIPアドレスを確認する
②SSH接続を行う(ubuntu想定)
SSH接続を確認します
sudo ssh -i [SSH鍵] ubuntu@[IPアドレス]
[SSH鍵],[IPアドレス ]はあなたの環境の値に置き換えてください。
③(任意)NoCloud方式で cloud-init を後付け適用
IndigoのAPIで userdata を渡せないため、起動後に NoCloud でシードする方法です(Ubuntu想定)。
1)NoCloud をローカル seed に固定(CD-ROM を無視させる)※Indigo固有の対策
sudo tee /etc/cloud/cloud.cfg.d/90_nocloud_seed.cfg >/dev/null <<'EOF'
datasource_list: [ NoCloud ]
datasource:
NoCloud:
seedfrom: /var/lib/cloud/seed/nocloud-net/
EOF
2)まず、以下の cloud-init を使います(Ubuntu 24.04 最小構成+セキュリティ強化)
cloud-init.yaml
#cloud-config
package_update: true
package_upgrade: true
manage_etc_hosts: true
ssh_pwauth: false
disable_root: true
timezone: Asia/Tokyo
packages:
- ufw
- fail2ban
- nginx
- jq
- git
- unattended-upgrades
write_files:
- path: /etc/fail2ban/jail.d/sshd.local
owner: root:root
permissions: '0644'
content: |
[sshd]
enabled = true
port = ssh
banaction = iptables-multiport
bantime = 10m
findtime = 10m
maxretry = 5
- path: /etc/apt/apt.conf.d/51unattended-upgrades-local
owner: root:root
permissions: '0644'
content: |
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "03:30";
- path: /var/www/html/index.nginx-debian.html
owner: www-data:www-data
permissions: '0644'
content: |
<!doctype html>
<html lang="ja"><head><meta charset="utf-8"><title>Indigo API Demo</title></head>
<body><h1>It works 🎉</h1><p>Provisioned by cloud-init.</p></body>
</html>
runcmd:
- [ bash, -lc, 'ufw default deny incoming' ]
- [ bash, -lc, 'ufw default allow outgoing' ]
- [ bash, -lc, 'ufw allow 22/tcp' ]
- [ bash, -lc, 'ufw allow 80/tcp' ]
- [ bash, -lc, 'ufw allow 443/tcp' ]
- [ bash, -lc, 'ufw --force enable' ]
- [ systemctl, enable, --now, nginx ]
- [ systemctl, enable, --now, fail2ban ]
- [ systemctl, enable, --now, unattended-upgrades ]
- [ bash, -lc, 'test -f /swapfile || (fallocate -l 1G /swapfile && chmod 600 /swapfile && mkswap /swapfile && echo "/swapfile none swap sw 0 0" | tee -a /etc/fstab && swapon -a)' ]
final_message: "Indigo server configured via cloud-init."
3)NoCloud seed の配置と実行
# seed を用意(instance-id は毎回ユニーク)
sudo mkdir -p /var/lib/cloud/seed/nocloud-net
sudo tee /var/lib/cloud/seed/nocloud-net/meta-data >/dev/null <<EOF
instance-id: iid-$(uuidgen)
local-hostname: $HOSTNAME
EOF
# 上の cloud-init.yaml を user-data として設置
sudo tee /var/lib/cloud/seed/nocloud-net/user-data > /dev/null <<'EOF'
#cloud-config
# (ここに cloud-init.yaml の中身を貼り付け)
EOF
# cloud-init を再実行
sudo cloud-init clean
sudo cloud-init init
sudo cloud-init modules --mode=config
sudo cloud-init modules --mode=final
ステップ7:クリーンアップ
①VMインスタンスの停止
VMインスタンスのステータスをstatusupdateでStopへ変更
curl -X POST \
"$INDIGO_API_BASE/vm/instance/statusupdate" \
-H "Authorization: Bearer $INDIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"instanceId":"[VMインスタンスのid]","status":"stop"}'
[VMインスタンスのid]はあなたの環境の値に置き換えてください。
VMインスタンスをstopしても課金が続きます。
②VMインスタンスの削除
VMインスタンスのステータスをstatusupdateでdestroyへ変更
curl -X POST \
"$INDIGO_API_BASE/vm/instance/statusupdate" \
-H "Authorization: Bearer $INDIGO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"instanceId":"[VMインスタンスのid]","status":"destroy"}'
[VMインスタンスのid]はあなたの環境の値に置き換えてください。
VMインスタンスを削除で課金が止まります。
ディストリにより cloud-init の導入が必要な場合は sudo apt-get update && sudo apt-get install -y cloud-init を先に実行してください。
ディスク・IPの課金体系に応じて 削除前のスナップショット を検討してください。
付録A:Bashワンショット(作成→待機→接続)
create_and_connect.sh
(雛形)
#!/usr/bin/env bash
set -euo pipefail
: "${INDIGO_API_BASE:?}" "${INDIGO_TOKEN:?}" "${INDIGO_REGION_ID:?}" \
"${INDIGO_OS_ID:?}" "${INDIGO_INSTANCE_PLAN:?}" "${INDIGO_SSH_KEY_ID:?}" "${INDIGO_INSTANCE_NAME:?}"
h=( -H "Authorization: Bearer $INDIGO_TOKEN" -H "Content-Type: application/json" )
# 1) createinstance (STOPで作成)
curl -s -X POST "${INDIGO_API_BASE}/vm/createinstance" "${h[@]}" \
-d "{
\"sshKeyId\": ${INDIGO_SSH_KEY_ID},
\"regionId\": ${INDIGO_REGION_ID},
\"osId\": ${INDIGO_OS_ID},
\"instancePlan\": ${INDIGO_INSTANCE_PLAN},
\"instanceName\": \"${INDIGO_INSTANCE_NAME}\"
}" | tee /tmp/indigo_create.json >/dev/null
# 返却から instanceId を取得(キー名は環境に合わせて変更)
INSTANCE_ID=$(jq -r '.instanceId // .id' /tmp/indigo_create.json)
[ -n "$INSTANCE_ID" ] || { echo "instanceId を取得できませんでした"; exit 1; }
# 2) start
curl -s -X POST "${INDIGO_API_BASE}/vm/instance/statusupdate" "${h[@]}" \
-d "{\"instanceId\":\"${INSTANCE_ID}\",\"status\":\"start\"}" >/dev/null
# 3) IP取得(スキーマに合わせてパスを調整)
for i in {1..60}; do
ip=$(curl -s -X GET "${INDIGO_API_BASE}/vm/getinstancelist" -H "Authorization: Bearer $INDIGO_TOKEN" \
| jq -r --arg id "$INSTANCE_ID" '.[] | select((.id|tostring)==$id and .instancestatus=="Running") | (.ip // .ipaddress)')
if [[ -n "$ip" && "$ip" != "null" ]]; then echo "IP=$ip"; break; fi
sleep 5
echo "waiting IP..."
done
# 4) SSH
exec ssh -i ~/.ssh/indigo_demo_ed25519 ubuntu@"$ip"
付録B:Python(requests
)サンプル
provision.py
(雛形)
import os, time, json, requests
API=os.environ['INDIGO_API_BASE']
TOKEN=os.environ['INDIGO_TOKEN']
REGION_ID=int(os.environ['INDIGO_REGION_ID'])
OS_ID=int(os.environ['INDIGO_OS_ID'])
PLAN=int(os.environ['INDIGO_INSTANCE_PLAN'])
SSH_KEY_ID=int(os.environ['INDIGO_SSH_KEY_ID'])
NAME=os.environ['INDIGO_INSTANCE_NAME']
H={"Authorization":f"Bearer {TOKEN}","Content-Type":"application/json"}
# createinstance (STOP)
body={
"sshKeyId": SSH_KEY_ID,
"regionId": REGION_ID,
"osId": OS_ID,
"instancePlan": PLAN,
"instanceName": NAME
}
resp=requests.post(f"{API}/vm/createinstance", headers=H, data=json.dumps(body))
resp.raise_for_status()
crt=resp.json()
instance_id = crt.get("instanceId") or crt.get("id")
assert instance_id, f"createinstance response missing id: {crt}"
# start
requests.post(f"{API}/vm/instance/statusupdate", headers=H,
data=json.dumps({"instanceId": str(instance_id), "status":"start"})
).raise_for_status()
# poll IP
ip=None
for _ in range(60):
li = requests.get(f"{API}/vm/getinstancelist", headers={"Authorization":f"Bearer {TOKEN}"}).json()
assert isinstance(li, list), f"unexpected list API shape: {type(li)}"
for inst in li:
if str(inst.get("id")) == str(instance_id) or inst.get("instance_name") == NAME:
if inst.get("instancestatus") != "Running":
break
ip = inst.get("ip") or inst.get("ipaddress")
ipv6 = inst.get("secondary_ip")
break
break
if ip: break
time.sleep(5)
print("PUBLIC_IP:", ip or "<not-found>")
セキュリティ & 運用のヒント
- 鍵認証+パスワードログイン無効化(上記cloud-initで対応)
- UFW/iptables で最小限のポートのみ開放
- Fail2ban を有効化
- 監査ログ(auth.log, SSHログ)を中央集約(例:Fluent Bit → Loki/Cloud Logging)
- APIトークンのローテーション、リポジトリに置かない
- Terraform/Ansible への移行:API実験→本番運用の自然な次の一歩
トラブルシュート
-
401/403
:トークン不正・権限不足 → 再発行/権限確認 -
429
:APIレート超過 → バックオフ・再試行 -
400
:パラメータ不正(plan/image/regionなどIDのタイプミス) - IP未付与/SSHできない:
cloud-init
の完了待ち、セキュリティグループ/Firewallを確認 - キー形式エラー:
ssh-ed25519
など正しい形式か再確認
参考の置換ポイント(あなたの環境に合わせる)
-
INDIGO_API_BASE
:公式ドキュメントの 実際のベースURL に変更 -
INDIGO_REGION
/INDIGO_PLAN
/INDIGO_IMAGE
:提供中のIDに変更 - レスポンスのJSONパス(
network.public_ipv4
など)は 実際のスキーマ に合わせて修正 -
cloud-init
の内容は要件に応じて拡張(Docker/Podman, WireGuard, Prometheus Node Exporter等)
コストの目安(1GB Linuxプラン・税込み)
価格は 税込み で表記します。実額・最新は公式サイトをご確認ください。
1GB Linuxプランの料金(プランに含まれるもの)
-
時間従量:0.70円/時間(税込み)
-
月額上限:449円/月(税込み)
-
月の最低利用料:55円/月(税込み)(当月に料金が発生した場合のみ適用)
-
含まれるリソース:IPv4/IPv6 各1個(追加料金なし)、SSD 20GB(追加料金なし)、転送量(課金なし)
試験利用の目安(例)
-
2時間だけ試す → 0.70×2 = **1.40円(税込み)**ですが、**最低利用料 55円(税込み)**が適用 → 請求は 55円(税込み)。
-
インスタンスを作成しなかった月 → 最低利用料は適用されない。
1ヶ月フル稼働の目安(例)
*24時間×30日 = 720時間 → 0.70×720 = **504円(税込み)**ですが、**月額上限 449円(税込み)**が適用 → 請求は 449円(税込み)。
オプションで費用がかかるもの(必要時のみ)
-
スナップショット:0.0088円/GB・時間(税込み) / 月額上限 5.5円/GB(税込み)
-
DNS:550円/ゾーン・月(税込み)
-
契約譲渡手数料:2,200円(税込み)
備考:VPSインスタンスが存在するとVPS停止中も課金、計算期間はUTCの当月1日〜末日。転送量は課金なしですが、運用の目安値は別途ドキュメントに記載があります。
まとめ
- APIベースのVPS作成は 再現性・自動化・監査性 が強み。
- 雛形を土台にして、TerraformやCI/CD、監視まで一気通貫で仕上げましょう。
参考リンク
- cloud-init 公式: https://cloud-init.io/
- Ubuntu cloud-init ドキュメント: https://canonical-cloud-init.readthedocs-hosted.com/
- jq マニュアル: https://stedolan.github.io/jq/manual/
- Indigo API 公式ドキュメント: https://indigo.arena.ne.jp/userapi/
- Zennブログ WebARENA IndigoのAPIを試す: https://zenn.dev/mnod/articles/ab039cccf3c975
変更履歴(記事メンテ用)
- 初版:2025-08-12