※本記事のコードや情報は執筆時点の仕様に基づいています。投資は自己責任であり、必ずデモ環境や少額資金でテストした上で運用してください。
VPSを契約してSSHで接続できるようになった直後、多くの人がやりたくなるのは「さっそくPythonを入れて動かすこと」だと思います。気持ちは分かりますが、その前にやるべきことがあります。
インターネットに公開されたサーバーには、起動から数分で不正ログインの試行が来ます。ログを見ると、1日に数百から数千回のアクセスが記録されていることも珍しくありません。放置すれば、いつか突破されます。
この記事では、Ubuntuサーバーを借りた直後に必ずやるべき初期設定を、優先度順にまとめます。株価分析の自動実行を安全に回し続けるための土台づくりです。全部やっても30分程度で終わります。
なぜ初期設定が必要なのか
「個人の小さなサーバーなんて狙われないだろう」と思うかもしれません。しかし攻撃の実態は、特定の誰かを狙うものではなく、IPアドレスを機械的に総当たりするものです。あなたが誰かは関係ありません。
実際にどれくらい来ているかは、ログを見れば分かります。
# ログイン失敗の回数を数える
sudo grep "Failed password" /var/log/auth.log | wc -l
# どのユーザー名が狙われているかを見る
sudo grep "Failed password" /var/log/auth.log \
| awk '{print $(NF-5)}' | sort | uniq -c | sort -rn | head -10
# どの国・IPから来ているか
sudo grep "Failed password" /var/log/auth.log \
| awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10
狙われるユーザー名は決まっていて、root、admin、test、user、ubuntu あたりが上位に来ます。逆に言えば、これらの名前を使わないだけで、大半の攻撃は空振りするということです。
もし突破されると何が起きるのか。個人サーバーの場合、被害はおおむね次のようになります。
- 踏み台にされる: 他者への攻撃に使われ、自分が加害者側になる
- 暗号資産の採掘に使われる: CPUを占有され、本来の処理が止まる
- APIキーを盗まれる: 証券会社の認証情報を置いていたら致命的
- アカウントを停止される: 不正利用としてVPS事業者から契約を切られる
3番目が特に深刻です。自動売買のためにAPIキーをサーバーに置くなら、セキュリティ設定は「やったほうがよい」ではなく必須です。
📘 外部参考:Ubuntu Server Security(公式ドキュメント) / SSH Key Generation(SSH.COM)
優先度順・やることリスト
全体像を先に示します。上から順に効果が大きい順番で並べました。時間がない場合は、上位3つだけでも実施してください。
| 優先 | 作業 | 効果 | 所要 |
|---|---|---|---|
| 1 | パッケージ更新 | 既知の脆弱性を塞ぐ | 5分 |
| 2 | 作業用ユーザー作成 | rootへの直接攻撃を無効化 | 3分 |
| 3 | 公開鍵認証のみに限定 | 総当たり攻撃が成立しなくなる | 5分 |
| 4 | ファイアウォール設定 | 不要なポートを閉じる | 3分 |
| 5 | fail2ban導入 | しつこいIPを自動遮断 | 3分 |
| 6 | タイムゾーン設定 | 実行時刻のずれを防ぐ | 1分 |
| 7 | 自動更新の設定 | 放置しても更新される | 3分 |
効果が最も大きいのは3番目の公開鍵認証です。パスワード認証を無効にすると、どれだけ総当たりされてもそもそも試す入口がなくなります。これだけで攻撃の大半は無効化できます。
逆に、よく紹介されるわりに効果が薄い対策もあります。誤解されがちなので整理しておきます。
- SSHポートの変更: ログのノイズは減るが、公開鍵認証があれば防御力はほぼ変わらない
- 複雑なパスワード設定: そもそもパスワード認証を切れば不要になる
- IPアドレス制限: 効果は高いが、外出先から接続できなくなり運用が破綻しやすい
あれもこれもと手を広げるより、上位3つを確実にやるほうがずっと効果的です。設定項目が増えるほど、どこかで設定漏れが起きる確率も上がります。シンプルに保つことも立派なセキュリティ対策です。
作業を始める前に、1つだけ注意点があります。SSHの設定を変更する作業では、現在つないでいるターミナルを絶対に閉じないでください。設定を間違えて再起動すると、新規の接続ができなくなります。既存の接続が生きていれば、そこから元に戻せます。
この記事では各手順で「別ウィンドウで接続確認する」という指示を入れています。面倒に感じるかもしれませんが、ここを飛ばした人がサーバーに入れなくなる——というのが最もありがちな失敗です。
1〜2:更新と作業用ユーザー
# パッケージ一覧を更新し、インストール済みを最新にする
apt update && apt upgrade -y
# ホスト名を分かりやすくしておく(任意)
hostnamectl set-hostname stock-server
次に作業用ユーザーを作ります。rootで日常作業をするのは避けてください。誤操作でシステムを壊しても、誰も止めてくれません。
# ユーザー名は「よくある名前」を避ける
adduser trader
# sudo(管理者権限)を使えるようにする
usermod -aG sudo trader
# rootに登録されているSSH鍵を引き継ぐ
mkdir -p /home/trader/.ssh
cp /root/.ssh/authorized_keys /home/trader/.ssh/
chown -R trader:trader /home/trader/.ssh
chmod 700 /home/trader/.ssh
chmod 600 /home/trader/.ssh/authorized_keys
ユーザー名はadmin や ubuntu のような定番を避けるのがコツです。攻撃側はユーザー名を推測して総当たりするので、名前を外すだけで難易度が跳ね上がります。
ここで必ず、別のターミナルを開いて接続確認をしてください。確認せずに次のSSH設定へ進むと、失敗したときに二度とログインできなくなります。
# 【重要】現在の接続は閉じずに、別ウィンドウで試す
ssh trader@203.0.113.10 -i ./your-key.pem
# 接続できたら、sudoが使えるかも確認する
sudo whoami
# → root と表示されればOK
3:SSHを公開鍵認証だけにする
最も効果の大きい設定です。パスワードという概念そのものをなくします。
# 必ずバックアップを取る
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
# 設定を書き換える
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PermitEmptyPasswords.*/PermitEmptyPasswords no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*MaxAuthTries.*/MaxAuthTries 3/' /etc/ssh/sshd_config
# 反映前に文法をチェックする(これが通らないと壊れる)
sudo sshd -t && echo "設定に問題ありません"
# 設定内容を目視確認する
sudo grep -E "^(PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|MaxAuthTries)" \
/etc/ssh/sshd_config
# 反映する
sudo systemctl restart ssh
sshd -t による文法チェックを必ず挟んでください。設定ファイルに誤りがあるまま再起動すると、SSHサービスが起動せず、接続手段が完全に失われます。
万一ログインできなくなっても、ConoHaなどのVPSにはコンソール機能があり、コントロールパネルから画面越しに操作できます。完全に詰むわけではないので、慌てずにそちらから復旧してください。
ポート番号を変えるべきか
「SSHのポートを22から変えるべき」という話をよく聞きますが、公開鍵認証だけにしているなら効果は限定的です。
| メリット | デメリット | |
|---|---|---|
| ポート変更 | ログのノイズが減る | 接続時に指定が必要。設定漏れの元 |
| 公開鍵のみ | 攻撃が原理的に成立しない | 鍵の紛失に注意 |
ポート変更は「攻撃を防ぐ」というより「ログを静かにする」効果と考えるのが正確です。やっても構いませんが、公開鍵認証の代わりにはなりません。
# 変更する場合(ufwの許可も忘れずに)
sudo sed -i 's/^#*Port .*/Port 2222/' /etc/ssh/sshd_config
sudo ufw allow 2222/tcp
sudo sshd -t && sudo systemctl restart ssh
# 接続時はポートを指定する
# ssh trader@203.0.113.10 -p 2222 -i ./your-key.pem
4〜5:ファイアウォールと自動遮断
不要な通信をすべて遮断します。株価分析用途なら、受信を許可すべきはSSHだけです。
# 既定の方針を決める
sudo ufw default deny incoming # 受信は原則拒否
sudo ufw default allow outgoing # 送信は許可(データ取得に必要)
# SSHだけ通す
sudo ufw allow 22/tcp
# 有効化して状態を確認する
sudo ufw --force enable
sudo ufw status verbose
送信は許可のままにしてください。ここを閉じると、yfinanceでのデータ取得も通知の送信もできなくなります。
ConoHa VPSの一部バージョンでは、ufwに加えてコントロールパネル側のセキュリティグループ設定も必要です。ufwを設定したのに接続できない場合は、そちらも確認してください。
fail2banでしつこいIPを遮断する
sudo apt install -y fail2ban
# 設定は jail.local に書く(jail.conf は更新で上書きされるため)
sudo tee /etc/fail2ban/jail.local > /dev/null << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3
[sshd]
enabled = true
EOF
sudo systemctl enable --now fail2ban
sudo systemctl restart fail2ban
# 状態を確認する
sudo fail2ban-client status sshd
設定の意味は「10分以内に3回失敗したIPを1時間遮断する」です。しばらく運用してから fail2ban-client status sshd を見ると、遮断済みIPが積み上がっているのが確認できます。
設定を jail.conf ではなく jail.local に書くのがポイントです。jail.conf はパッケージ更新で上書きされるため、直接編集すると設定が消えます。
6〜7:タイムゾーンと自動更新
セキュリティとは別ですが、これを忘れると自動実行が壊滅します。VPSの初期状態はUTCのことが多く、そのままだと日本時間と9時間ずれます。
# 現在の設定を確認
timedatectl
# 日本時間にする
sudo timedatectl set-timezone Asia/Tokyo
# 時刻同期が有効か確認する
timedatectl show --property=NTPSynchronized
date
「大引け後の15時30分に実行」と設定したつもりが、実際には翌日0時30分に動いていた——これは本当によくある事故です。株価データの取得は市場時間に依存するので、最初に必ず直してください。
cronの時刻設定についてはcronでPython株価分析スクリプトを毎日自動実行する方法で詳しく扱っています。
セキュリティ更新を自動化する
sudo apt install -y unattended-upgrades
# セキュリティ更新のみを自動適用する設定
sudo tee /etc/apt/apt.conf.d/20auto-upgrades > /dev/null << 'EOF'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
EOF
# 適用対象を確認する(実際には適用しない)
sudo unattended-upgrade --dry-run --debug 2>&1 | tail -15
ここで自動再起動は有効にしないでください。処理の途中でサーバーが再起動されると、その日のデータ取得や通知が飛びます。再起動が必要な更新は、自分の都合の良いタイミングで手動実行するのが安全です。
# 再起動が必要かを確認する(月1回程度で十分)
[ -f /var/run/reboot-required ] && cat /var/run/reboot-required \
|| echo "再起動は不要です"
設定が効いているか確認する
ひととおり終わったら、本当に設定が効いているかを検証します。設定したつもりで抜けていた、というのが一番怖いパターンです。
cat > ~/check_security.sh << 'EOF'
#!/bin/bash
echo "===== セキュリティ設定チェック ====="
check() {
if eval "$2" >/dev/null 2>&1; then
echo " ✓ $1"
else
echo " ✗ $1 ← 要確認"
fi
}
check "rootログイン禁止" \
"sudo grep -q '^PermitRootLogin no' /etc/ssh/sshd_config"
check "パスワード認証無効" \
"sudo grep -q '^PasswordAuthentication no' /etc/ssh/sshd_config"
check "公開鍵認証有効" \
"sudo grep -q '^PubkeyAuthentication yes' /etc/ssh/sshd_config"
check "ufw稼働中" \
"sudo ufw status | grep -q 'Status: active'"
check "fail2ban稼働中" \
"systemctl is-active --quiet fail2ban"
check "タイムゾーンがJST" \
"timedatectl | grep -q 'Asia/Tokyo'"
check "自動更新が有効" \
"test -f /etc/apt/apt.conf.d/20auto-upgrades"
echo ""
echo "----- 現在の状態 -----"
echo " 遮断中のIP : $(sudo fail2ban-client status sshd 2>/dev/null | grep 'Currently banned' | awk '{print $NF}')"
echo " ログイン失敗: $(sudo grep -c 'Failed password' /var/log/auth.log 2>/dev/null) 回"
echo " 現在時刻 : $(date '+%H:%M:%S %Z')"
EOF
chmod +x ~/check_security.sh
~/check_security.sh
すべてに ✓ が付けば完了です。このスクリプトは残しておいて、月に一度実行する習慣にすると安心できます。設定は意外と、OSの更新などで戻ってしまうことがあります。
APIキーの置き場所に注意する
ここは株価分析サーバーならではの論点です。証券会社のAPIキーや通知用のWebhook URLを、コードに直接書かないでください。
理由は3つあります。どれも実際に事故が起きているパターンです。
- Gitに上げてしまう: 公開リポジトリにキーが載り、自動収集される
- ブログや質問サイトに貼ってしまう: エラー相談でコードを貼る際に一緒に流出する
- バックアップから漏れる: コードを共有した相手にキーまで渡ってしまう
特に2番目は油断しがちです。「動かないので見てください」とコードを貼った瞬間、キーも一緒に公開される——設定ファイルに分離しておけば、この事故は構造的に起こりません。
加えて、APIキー側でも防御しておくと安心度が上がります。証券会社やサービスによっては、次のような制限をかけられます。
- IPアドレス制限: VPSのIPからのみ有効にする。流出しても他所からは使えない
- 権限の限定: 参照のみのキーと発注可能なキーを分ける
- 有効期限の設定: 定期的に再発行する運用にする
特に2番目は効果的です。データ取得しかしないスクリプトに、発注権限のあるキーを渡す必要はありません。万一漏れても、被害を「見られるだけ」に抑えられます。
# ✕ 悪い例: コードに直書き
# API_KEY = "abcd1234..."
# ○ 良い例: 環境変数ファイルに分離し、権限を絞る
cat > ~/stock/.env << 'EOF'
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/xxxx
BROKER_API_KEY=your_key_here
EOF
# 自分だけが読めるようにする
chmod 600 ~/stock/.env
ls -l ~/stock/.env
# → -rw------- になっていればOK
# Pythonから読み込む
cat > ~/stock/config.py << 'EOF'
import os
from pathlib import Path
def load_env(path=None):
""".env を読み込んで環境変数に設定する"""
path = Path(path or Path(__file__).parent / ".env")
if not path.exists():
raise FileNotFoundError(f"{path} が見つかりません")
for line in path.read_text(encoding="utf-8").splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
os.environ.setdefault(key.strip(), value.strip())
load_env()
EOF
あわせて、Gitで管理する場合は必ず .gitignore に追加してください。公開リポジトリにAPIキーを上げてしまう事故は、驚くほど頻繁に起きています。
cat > ~/stock/.gitignore << 'EOF'
.env
*.log
logs/
venv/
__pycache__/
*.db
EOF
APIキーの管理を含めた運用設計はSQLiteで自動売買のログを一元管理する設計でも触れています。
まとめ
VPS契約直後にやるべきUbuntuの初期設定を、優先度順にまとめました。
- 攻撃は個人を狙うのではなく、IPを機械的に総当たりする。誰でも標的になる
- 最優先は公開鍵認証だけにすること。総当たりが原理的に成立しなくなる
- ユーザー名は
adminやubuntuを避ける。それだけで大半が空振りする - SSH設定の変更前に
sshd -tで文法チェック。別ウィンドウで接続確認も忘れずに - fail2banの設定は
jail.localに書く。jail.confは更新で上書きされる - タイムゾーンをAsia/Tokyoに。忘れると自動実行が9時間ずれる
- APIキーは
.envに分離し、権限600と.gitignoreをセットにする
正直なところ、この作業は面白くありません。やっても何も新しいことができるようにならないからです。それでも、ここを飛ばして本番のコードを書き始めると、後から必ず後悔します。
30分で終わる作業で、APIキーの流出や踏み台化という最悪の事態を防げるのなら、十分に割の合う投資だと思います。まずは本記事の check_security.sh を走らせて、自分のサーバーの現状を確認するところから始めてみてください。

