3-1. VPS セットアップ - 初期 hardening まで30分
所要時間: 40-60分 ゴール: 新規 VPS を一台借りて、本番運用に耐える初期 hardening を一通り終える コミット内容:
~/learn/infra/vps01/に hardening 手順を書いたsetup.shとREADME.mdを残す
このレッスンのゴール
- VPS とクラウド (IaaS) の違いを語れる
- SSH 鍵認証・パスワード認証無効・root SSH 無効までを設定できる
- ufw + fail2ban の3点セットで最低限の hardening ができる
- swap 設定の意義と書き方を理解した
-
auth.logから攻撃元 IP を判定できる
なぜ学ぶか(実務悩みベース)
- 月 500 円の VPS で本番が立てられると個人開発の幅が広がる
- マネージドが壊れた時に「裏で何が起きているか」が見える人になる
- 面接「Linux に SSH して何ができますか?」に即答できる
- 「サーバー乗っ取り」の事故を最初から防ぐ
前章とのつながり
2-6 までで「動くアプリ Compose」が完成した。Level 3 はそれを インターネットに出す 旅。最初の関門が VPS の初期 hardening。攻撃 bot が秒単位で来る世界で、Compose を起動する前にやることがある。
大前提: なぜ VPS を「自分で」立てるのか
クラウドのマネージドサービス(Heroku, Vercel, Render など)だけ使っていれば「サーバーを直接触る」機会はゼロに近い。ではなぜ VPS を扱えるべきか。
- コスト: マネージドが月 5,000 円のところ、VPS なら月 500 円〜で同じ要件を満たせる
- 自由度: cron、systemd、独自ポート、独自ミドルウェア、何でも入る
- デバッグ力: マネージドが壊れた時に「裏で何が起きているか」が見える人と見えない人で復旧速度が10倍違う
- 面接で問われる: 「Linux に SSH して何ができますか?」は技術面接の頻出質問
そして、VPS を立てた瞬間から インターネット上のすべての攻撃者のターゲット になる。SSH ポート 22 を開けて1時間放置すると、bot による総当たりログイン試行が数百回〜数千回記録されるのが普通。初期 hardening をやらないサーバーは数日で乗っ取られる。これは脅しではなく観測事実。
このレッスンでは、新規 VPS を借りてから「本番ワークロードを乗せていい状態」までを 30 分で持っていく標準手順を身につける。
セッション①: VPS を選んで借りる(15-20分)
1. VPS プロバイダの選び方
国内・海外の主要 VPS プロバイダの比較(2026年時点の感覚値)。
| プロバイダ | 最安プラン | 拠点 | 特徴 |
|---|---|---|---|
| さくらの VPS | 月 600 円〜(1GB) | 東京/大阪/石狩 | 国内、請求が円、初心者向け |
| さくらクラウド | 従量課金 | 東京/石狩 | API 完備、Terraform 対応、本気の本番向け |
| Vultr | 月 $3.5 〜 | 東京/大阪含む32拠点 | API 充実、安い、米ドル決済 |
| Linode (Akamai) | 月 $5 〜 | 東京含む | 老舗、ドキュメントが優秀 |
| DigitalOcean | 月 $4 〜 | シンガポール(東京なし) | チュートリアルが世界一充実 |
| Hetzner | 月 €3.79 〜 | 独/フィンランド/米 | コスパ最強、ただし日本から遠い |
VPS とクラウド (IaaS) の違い
どちらも「インターネット越しに使える Linux マシン」だが、思想が違う。
- VPS (Virtual Private Server): 「物理マシン1台分の権利を、月額固定で売る」モデル。シンプル、定額、最初から決まったスペック
- クラウド (IaaS): 「使った分だけ秒単位課金」モデル。サイズ変更・スナップショット・複数台連携・マネージド DB 等のコンポーネント連携が前提
学習・個人開発・常時起動の小規模サービス = VPS が圧倒的に安い。スパイク対応や本番大規模サービス = クラウド一択。両方触れる人材 = 最強。
料金と性能のトレードオフ
月 500 円クラス(CPU 1 core / RAM 1GB / SSD 20-30GB)でできること:
- 個人ブログ(WordPress / 静的サイト)
- Discord / Slack の bot
- 小規模な Go/Node API + SQLite or PostgreSQL
- 自前 Mastodon / Misskey インスタンス(人数次第)
足りなくなるライン: メモリ食う JVM 系、Elasticsearch、本格的な MySQL レプリカ、コンテナを多数同時起動するケース。RAM が枯渇すると swap で延命できるが I/O が激重になる。最初は RAM 2GB 以上を選ぶと事故が減る。
「無料 VPS」「永久無料」の罠
Oracle Cloud の Always Free や AWS Free Tier の無料枠は確かに存在するが、請求設定を間違えると無料枠を超えた瞬間に従量課金で月数万円の事故が起きる。学習用途なら 絶対上限の見える定額 VPS が安全。
2. OS 選び
ほぼ全プロバイダで以下から選べる。本書では Ubuntu 24.04 LTS を前提に進める。
| OS | おすすめ度 | 理由 |
|---|---|---|
| Ubuntu LTS (24.04) | 鉄板 | 情報量最多、deb 系、サポート5年 |
| Debian | 玄人向け | 安定性最高、Ubuntu より保守的 |
| Rocky Linux / AlmaLinux | RHEL系 | 旧 CentOS の後継。yum/dnf 文化 |
| Alpine | 上級者向け | 軽量だが musl libc で罠多い、コンテナ用途で使う |
なぜ Ubuntu LTS を選ぶか
LTS = Long Term Support。通常 2 年ごとの偶数年に LTS がリリースされ、5 年のセキュリティパッチ提供がある(拡張で10年)。
個人サーバーでも LTS 一択。通常版(interim release)は 9 か月でサポート終了するので、サポート切れ後の脆弱性放置 = 自動的に乗っ取りリスク。
セッション②: 初回 SSH と一般ユーザー作成(15-20分)
3. 初回 SSH ログイン
VPS 契約後、コントロールパネルに「IP アドレス」「root パスワード」または「初回 SSH 鍵」が表示される。
# root でログイン(推奨されないが最初だけ)
ssh root@203.0.113.42
# プロバイダによっては最初から SSH 鍵方式
ssh -i ~/.ssh/vps_initial root@203.0.113.42SSH 鍵認証の本質
SSH 鍵 = 公開鍵暗号によるパスワードレス認証。
- 公開鍵 (
~/.ssh/id_ed25519.pub): サーバーに置く。漏れてもOK- 秘密鍵 (
~/.ssh/id_ed25519): 手元に置く。絶対に漏らさない。GitHub にコミットしたら即終了ログイン時、サーバーが乱数を秘密鍵で署名させ、公開鍵で検証する。秘密鍵を持っている人だけログインできる。
生成コマンド(まだ作っていなければ):
ssh-keygen -t ed25519 -C "your_email@example.com"RSA より ed25519 が新しく短くて強い。2026 年に新規生成するなら ed25519 一択。
root で SSH ログインしてはいけない
root = 何でもできるユーザー。これが万一乗っ取られると 「サーバー初期化以外に復旧手段なし」 になる。
攻撃者は世界中の VPS の IP レンジを舐めて
rootユーザーへの総当たりを仕掛けている。/var/log/auth.logを見れば、契約直後からFailed password for root from 185.x.x.xが秒間数十件並ぶ。対策の順序:
- 一般ユーザーを作る
- 一般ユーザーに sudo 権限を与える
- 一般ユーザーで SSH ログインできるか確認
- root の SSH ログインを禁止する
- パスワード認証も禁止する(鍵認証のみに)
4. パッケージを最新化
# パッケージリスト更新(インストール可能なリストを取りに行く)
apt update
# 実際にアップグレード
apt upgrade -y
# 不要パッケージ削除
apt autoremove -y
apt updateとapt upgradeの違い初心者が混同しがちな最頻出ポイント。
apt update: パッケージリスト(カタログ)を最新に取得するだけ。実際のソフトウェアは何も変わらないapt upgrade: カタログに従って実際のソフトウェアを更新するつまり 必ず
apt update && apt upgradeの順番でセット実行する。updateだけだと何も上がらない、upgradeだけだとカタログが古いままで最新が降ってこない。
aptとapt-getの違い歴史的経緯で 2 つある。
apt-get: 古参。スクリプト向け、出力が安定apt: 2014 年に登場。人間向け、プログレスバーが出る、推奨対話的に使うなら
apt、スクリプト内ならapt-getが無難。本番デプロイスクリプトにaptを書くと将来出力フォーマット変更で壊れる可能性があるため。
5. 一般ユーザー作成と sudo 化
# ユーザー作成(パスワードや氏名を聞かれる。氏名等は空Enter可)
adduser deploy
# sudo グループに追加
usermod -aG sudo deploy
# 確認
groups deploy
# deploy : deploy sudosudo グループとは
Ubuntu/Debian では
sudoグループに属するユーザーがsudoコマンドを使える。RHEL 系ではwheelグループ。sudo の本質: 「一時的に root として実行する」。実行ログが
/var/log/auth.logに残るため、root 直接ログインより監査性が高い。複数人運用なら 誰がいつ何を sudo したか追跡できる。
root ログインで初期 hardening を進める標準手順
# 1. パッケージ最新化 apt update && apt upgrade -y # 2. 一般ユーザー作成 adduser deploy usermod -aG sudo deploy # 3. 公開鍵を一般ユーザーにコピー mkdir -p /home/deploy/.ssh cp /root/.ssh/authorized_keys /home/deploy/.ssh/ chown -R deploy:deploy /home/deploy/.ssh chmod 700 /home/deploy/.ssh chmod 600 /home/deploy/.ssh/authorized_keys # 4. 別ターミナルで deploy ユーザーでログインできることを確認 # (これを確認せずに root を閉じると詰む)
.sshディレクトリの権限SSH は
~/.sshおよびauthorized_keysの権限が緩いと鍵認証を拒否する。仕様。必須権限:
~/.ssh→700(自分のみ rwx)~/.ssh/authorized_keys→600(自分のみ rw)これが守られていないと「鍵を置いたのにログインできない、なぜ?」となる初心者の最頻出トラップ。
6. SSH の hardening
/etc/ssh/sshd_config を編集する(または /etc/ssh/sshd_config.d/99-hardening.conf に追記)。
# 編集
sudo vim /etc/ssh/sshd_config.d/99-hardening.conf# /etc/ssh/sshd_config.d/99-hardening.conf
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
# ポート変更を行う場合(後述)
# Port 22022# 設定構文チェック
sudo sshd -t
# 再起動
sudo systemctl restart ssh設定項目の意味
PermitRootLogin no: root 直接ログイン禁止。最重要PasswordAuthentication no: パスワード認証禁止。総当たり攻撃が物理的に成功しなくなるPubkeyAuthentication yes: 公開鍵認証のみ許可MaxAuthTries 3: 1接続あたりの認証試行回数上限ClientAliveInterval 300: 5分間アイドル接続を確認、応答なければ切断(ゾンビセッション防止)
sshd_config の編集事故
設定ミスで
sshdが再起動失敗 → SSH 接続が切れる → 二度と入れない という事故が定番。必須の手順:
- 既存の SSH 接続は維持したまま、新しいターミナルで設定変更を試す
sudo sshd -tで構文チェック(エラーなければ無出力)sudo systemctl restart ssh- 既存接続を切らずに、別ターミナルから新規ログインできるか確認
- 新規ログインが成功して初めて、元のセッションを閉じる
プロバイダの「コンソールアクセス」(Web 画面から物理キーボード相当の操作)も最後の保険。場所を確認しておく。
SSH ポート番号を変えるべきか
「Port 22 から 22022 などに変更すると攻撃が激減する」という説。
事実: 確かに bot の総当たりは激減する(多くの bot が 22 番にしか来ない) 反論: 真剣な攻撃者には無意味(nmap でポートスキャンすればすぐ見つかる)。security by obscurity に過ぎない 実害: ログがノイズで埋まらないので調査しやすくなる、というメリットは実在
結論: 鍵認証 + パスワード認証無効 + fail2ban があれば 22 番のままでも実害はない。ただし「ログのノイズが気持ち悪い」「組織方針」などの理由で変える選択は正当。変えるならファイアウォール設定と同時に(新ポートを開け、旧ポートを閉じる順)。
セッション③: ネットワーク・swap・監視(15-20分)
7. swap の設定
# 現状確認
free -h
swapon --show
# 2GB の swap ファイルを作成
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永続化(再起動時も有効)
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# swappiness 調整(RAM 優先度)
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --systemswap とは何か、なぜ小さい VPS で重要か
swap = ディスクを「擬似的な RAM」として使う仕組み。RAM が足りなくなった時に、使用頻度の低いメモリ内容を一時的にディスクに退避する。
小さい VPS(RAM 1GB / 2GB)では事実上必須。理由:
- OOM Killer(メモリ不足時に Linux がプロセスを問答無用で kill する機能)の発動を避けられる
- ピーク時に瞬間的にメモリ超過しても落ちない
- 普段使わない常駐プロセス(systemd 系の小さいデーモン)を swap に逃がして RAM を空ける
デフォルトで swap が無い VPS が多い。クラウド系(AWS の EC2 など)は特に。意識的に作る必要がある。
swappiness のデフォルト値
vm.swappinessは「どれくらい積極的に swap を使うか」(0-100)。
- デフォルト 60: デスクトップ Linux 向け。サーバーには積極的すぎる
- 推奨 10: サーバー用途。「本当に RAM が足りない時だけ swap」
- 0 にしない: swap を完全無効化と同義になり、OOM Killer が暴れる
swap を使い始めると I/O 性能が激落ちする(ディスクは RAM の数百倍遅い)ため、「swap がガリガリ使われている = RAM 不足」のシグナルとして監視すべき。
8. ufw(Uncomplicated Firewall)の初期設定
# インストール(Ubuntu には標準で入っているはず)
sudo apt install -y ufw
# デフォルトポリシー: すべて拒否、外向きは許可
sudo ufw default deny incoming
sudo ufw default allow outgoing
# SSH を許可(これを忘れると自分も入れなくなる)
sudo ufw allow 22/tcp
# HTTP/HTTPS(Web サーバーを置くなら)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 有効化(SSH の確認が出る)
sudo ufw enable
# 状態確認
sudo ufw status verboseufw は iptables のラッパー
Linux のパケットフィルタは元々
iptables(最近はnftables)。だが構文が難解で初心者が事故りやすい。ufw = Uncomplicated Firewall。「ポート番号で許可/拒否を書くだけ」のシンプルなフロントエンド。内部で nftables / iptables ルールに変換される。
Debian/Ubuntu の事実上の標準。RHEL 系には
firewalldがある(こちらも nftables のラッパー)。
SSH を許可する前に ufw を有効化する事故
順番を間違えて以下のようにやると即終了。
sudo ufw default deny incoming sudo ufw enable # SSH を allow する前に! # → 既存の SSH も切られる、新規接続も拒否される、コンソールアクセスがないと復旧不可必ず順番: SSH を allow → enable。
ufw enable実行時には「既存の SSH 接続が切れるかも、いいか?」と確認が出る。確認に Yes と答える前に別ターミナルで SSH を許可していることを確認。
9. fail2ban インストール
sudo apt install -y fail2ban
# デフォルト設定をコピーして編集
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local/etc/fail2ban/jail.local を編集。
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
[sshd]
enabled = truesudo systemctl restart fail2ban
sudo fail2ban-client status sshdfail2ban の仕組み
/var/log/auth.logを監視し、失敗ログインを findtime(10分)の間に maxretry(5回)記録した IP を bantime(1時間)だけ ufw / iptables でブロックする。パスワード認証を切っていても、bot の試行で auth.log が膨らみ続けるのは事実。fail2ban が ban すると IP 単位で接続自体が拒否されるため、ログのノイズも減る。
自分も ban される事故
開発中にパスワードを連打 → 自分の IP が ban される。
対処法: コンソールアクセス(プロバイダの Web 画面)から
sudo fail2ban-client unban <自分のIP>で解除。または時間を待つ。予防: 自宅・オフィスの IP を
ignoreipにホワイトリスト登録。[DEFAULT] ignoreip = 127.0.0.1/8 ::1 203.0.113.10ただし動的 IP の自宅では使いにくい。
10. タイムゾーンとロケール
# タイムゾーン確認
timedatectl
# 日本時間に設定
sudo timedatectl set-timezone Asia/Tokyo
# NTP 同期確認(systemd-timesyncd が標準)
timedatectl status
# System clock synchronized: yes であればOK
# ロケール
locale
sudo locale-gen ja_JP.UTF-8
sudo update-locale LANG=ja_JP.UTF-8タイムゾーンを揃える理由
サーバーのタイムゾーンがズレていると ログのタイムスタンプが混乱する。
- アプリログ:
2026-05-14 03:00:00← これは JST? UTC?- クラウド側ログ: UTC
- 顧客の問い合わせ: JST
チーム方針:
- A 案: 全部 UTC(クラウド標準、サーバーは全部 UTC、ログ確認時に JST 変換)
- B 案: 全部 JST(日本国内サービスの実利、ログがそのまま読める)
どちらでも良いが 混在は最悪。社内で統一する。本書では VPS は JST 設定で進める(ログを直接読む機会が多い学習用途のため)。
NTP 同期が外れている事故
サーバー時刻が数分ズレているだけで:
- JWT トークンが「有効期限切れ」または「まだ有効になっていない」エラー
- HTTPS 証明書の有効期限判定がズレる
- cron が想定時刻と違う時間に走る
- DB のレコード作成日時がバラつく(レプリカと比較して整合性破綻)
timedatectl statusでSystem clock synchronized: yesを必ず確認。
11. 自動セキュリティ更新
sudo apt install -y unattended-upgrades
# 設定
sudo dpkg-reconfigure --priority=low unattended-upgradesunattended-upgrades の役割
セキュリティ更新を 自動で適用する仕組み。デフォルトでは security リポジトリの更新だけが対象(通常パッケージは対象外)。
メリット: 脆弱性が公表されてからパッチ適用までの時間(攻撃者にとっての黄金時間)を最小化 デメリット: 自動更新でアプリが壊れる可能性ゼロではない(稀)。再起動が必要な更新は別途対処
needrestart のプロンプトで本番落ちる事故
Ubuntu 22.04 以降、
apt upgrade時に needrestart がサービス再起動のプロンプトを出す。スクリプト内でapt upgrade -yを実行すると、対話プロンプトで止まるか、サービスが勝手に再起動して短時間ダウンする。対処:
/etc/needrestart/needrestart.confで$nrconf{restart} = 'a';(automatic)または'l';(list only)に設定。本番では'l'で「リスト表示のみ、手動再起動」が安全。
アンチパターン総まとめ
よくある初期設定の失敗
# NG: root のままアプリをデプロイする root@vps:~# git clone https://github.com/my/app.git root@vps:~# ./app/run.shなぜNG: アプリの脆弱性(例: ファイル読み込みの SSRF)が即座にサーバー全体侵害につながる。アプリは必ず非 root ユーザーで動かす。
パスワード認証放置
# /etc/ssh/sshd_config(デフォルトのまま) PasswordAuthentication yes24時間で平均 1,000-10,000 回の総当たり試行を受ける。
123456adminなどの弱いパスワードを使っていたら 1 日で抜かれる。
ファイアウォール無効のまま全ポート公開
# ufw を入れていない、または disable # → MySQL の 3306 が外から見える、Redis の 6379 が外から見える # → 認証なしの Redis に書き込まれて暗号通貨マイニングプロセスが仕込まれるRedis の認証なしホストを狙う攻撃は実在し、観測されている。外部に公開する必要のないサービスは全部ファイアウォールで遮断。
自動更新オフでパッチ放置
# apt upgrade を半年やっていない # → OpenSSL の CVE が公開されているのに古いまま # → 公知の脆弱性で侵入される「動いているから触らない」は最悪のセキュリティ戦略。最低限 security update は自動適用しておく。
実例: 新規 VPS を 30 分で hardening するスクリプト
実運用では手順をスクリプト化しておくと、新しい VPS を借りるたびに迷わず適用できる。
#!/usr/bin/env bash
# ~/learn/infra/vps01/setup.sh
# 新規 Ubuntu 24.04 VPS の初期 hardening スクリプト
# 使い方:
# 1. root で SSH ログイン
# 2. このスクリプトをアップロード or 貼り付け
# 3. bash setup.sh deploy 'AAAAC3NzaC1lZD...your_public_key...'
set -euo pipefail
DEPLOY_USER="${1:?usage: setup.sh <username> <public_key>}"
PUBLIC_KEY="${2:?usage: setup.sh <username> <public_key>}"
echo "==> 1. パッケージ更新"
apt update
apt upgrade -y
apt install -y ufw fail2ban unattended-upgrades
echo "==> 2. 一般ユーザー作成"
if ! id "$DEPLOY_USER" &>/dev/null; then
adduser --disabled-password --gecos "" "$DEPLOY_USER"
usermod -aG sudo "$DEPLOY_USER"
fi
echo "==> 3. SSH 鍵設置"
install -d -m 700 -o "$DEPLOY_USER" -g "$DEPLOY_USER" "/home/$DEPLOY_USER/.ssh"
echo "$PUBLIC_KEY" > "/home/$DEPLOY_USER/.ssh/authorized_keys"
chmod 600 "/home/$DEPLOY_USER/.ssh/authorized_keys"
chown "$DEPLOY_USER:$DEPLOY_USER" "/home/$DEPLOY_USER/.ssh/authorized_keys"
echo "==> 4. sudo パスワードなし(任意。秘密鍵の管理が厳格なら)"
echo "$DEPLOY_USER ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/90-$DEPLOY_USER"
chmod 440 "/etc/sudoers.d/90-$DEPLOY_USER"
echo "==> 5. SSH hardening"
cat > /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
EOF
sshd -t
systemctl restart ssh
echo "==> 6. swap 2GB"
if [ ! -f /swapfile ]; then
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
fi
echo 'vm.swappiness=10' > /etc/sysctl.d/99-swappiness.conf
sysctl --system
echo "==> 7. ufw"
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
echo "y" | ufw enable
echo "==> 8. fail2ban"
cp -n /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
systemctl enable --now fail2ban
echo "==> 9. タイムゾーン / NTP"
timedatectl set-timezone Asia/Tokyo
echo "==> 10. unattended-upgrades 有効化"
dpkg-reconfigure -f noninteractive unattended-upgrades
echo ""
echo "完了。別ターミナルで以下を実行してログインできるか確認せよ:"
echo " ssh $DEPLOY_USER@$(curl -s ifconfig.me)"
echo ""
echo "ログイン成功を確認してから root を抜けること。"スクリプト化のメリット
- 手作業の漏れがなくなる
- チームで共有できる(GitHub に置く、ただし公開鍵以外の秘密情報は含めない)
- Ansible / Terraform の cloud-init / user-data に組み込める
Ansible で書き直すと宣言的になり、複数台を同時 hardening できる。が、初学者の段階では bash スクリプトで「何が起きているか」を理解する方が学習効率が高い。
練習課題
実際に VPS を 1 台借りて以下をすべてやる(月数百円なら学習投資として安い)。
- VPS を 1 つ契約し、Ubuntu 24.04 をインストール
- 初回 root ログインを行い、
apt update && apt upgradeを実行 - 一般ユーザー
deployを作成、sudo グループに追加 - 自分の手元の公開鍵 (
~/.ssh/id_ed25519.pub) をdeployのauthorized_keysに登録 - 別ターミナルで
ssh deploy@<IP>で鍵認証ログインできることを確認 sshd_config.d/99-hardening.confを設置して、root 直接ログインとパスワード認証を禁止- swap 2GB を作成し永続化、
free -hで確認 - ufw で SSH/HTTP/HTTPS のみ許可
- fail2ban をインストール、
fail2ban-client status sshdで動作確認 tail -f /var/log/auth.logを 5 分眺めて、bot の侵入試行ログを観察(結構来る)
締め: git で証跡を残す
cd ~/learn/infra/vps01
git init
git add setup.sh README.md
git commit -m "feat(infra): VPS 初期 hardening スクリプト整備"README.md には:
- 借りたプロバイダ名と理由
- IP アドレス(プライベートリポなら)
- 適用した設定の要約
- ハマったポイント
を書いておくと、3か月後の自分が救われる。
チェックリスト
- VPS を 1 台借りた
- 一般ユーザーで SSH 鍵認証ログインできる
- root の SSH ログインを禁止した
- パスワード認証を禁止した
- ufw で必要なポートのみ許可している
- fail2ban が動いている
- swap が設定されている
- タイムゾーンと NTP 同期が正常
-
auth.logで実際の bot 侵入試行を目視した - hardening 手順をスクリプト化して git に残した
詰まった時のチートシート
| やりたいこと | コマンド |
|---|---|
| 自分の IP 確認(VPS から) | curl ifconfig.me |
| 一般ユーザー作成 | adduser <name> |
| sudo 権限付与 | usermod -aG sudo <name> |
| SSH 設定構文チェック | sshd -t |
| SSH 再起動 | systemctl restart ssh |
| ufw 状態確認 | ufw status verbose |
| ufw でポート許可 | ufw allow 80/tcp |
| fail2ban 状態 | fail2ban-client status sshd |
| ban された IP 解除 | fail2ban-client unban <IP> |
| swap 確認 | free -h && swapon --show |
| 時刻同期確認 | timedatectl status |
| 認証ログ追跡 | tail -f /var/log/auth.log |
対比表: VPS vs IaaS(クラウド)
| 観点 | VPS(さくら、Vultr 等) | IaaS(AWS EC2、GCE) |
|---|---|---|
| 料金モデル | 月額固定 | 秒単位従量 |
| サイズ変更 | 限定的 | 自由(ストップ→変更→起動) |
| API | 限定(プロバイダ次第) | 充実 |
| マネージド連携 | なし | DB / Queue / Cache 等と統合 |
| 適性 | 学習、個人開発、常時起動小規模 | 本番大規模、スパイク対応 |
| 学習価値 | 「裏で何が動くか」が見える | 「マネージド組合せ」を学ぶ |
「実務OK」基準
- 新規 VPS を 30 分以内に hardening 完了できる: 手順を覚えるか、スクリプトを持っている
/var/log/auth.logを読んで攻撃を判断できる: どの IP がどんな試行をしているか- ufw / fail2ban / SSH 鍵認証の3点セットを暗唱できる: hardening の最低ライン
- swap と OOM の関係を説明できる: なぜ小さい VPS に swap が必要か
- 「動かない」時に sshd_config の構文チェックを思い出せる: 自分を閉め出した時の復旧手順
自己評価チェックリスト
知識レベル
- VPS と IaaS の使い分け基準を語れる
- SSH 鍵認証の仕組み(公開鍵を server に置く)を説明できる
- ufw / fail2ban の役割分担を即答できる
- swap が「OOM 最後の砦」になる理由を腹落ちした
実行レベル
- 新規 VPS の hardening を手順通りに30分で完了した
-
setup.shを書き、再現可能な形にした -
auth.logから攻撃元 IP を1つ特定した
メタ認知
- 「自分を閉め出した時」の復旧手順をリストアップした
- 次に同じ作業をする時のために改善点を3つメモした
さらに深掘りするなら
- 公式: Ubuntu Server Guide
- 公式: OpenSSH manual (
man sshd_config) - 書籍: 『入門 Linux のしくみ』(武内覚, 技術評論社)
- DigitalOcean Tutorials: “Initial Server Setup with Ubuntu” 系の英語チュートリアル群が世界一参考になる
- Ansible で hardening を宣言的に書き直す:
geerlingguy.securityロール
次のレッスン
3-2_DNS.md で、立てた VPS にドメインを向ける DNS の世界へ。