「サーバー」の管理をしてみたくなった
はじめに
プログラミングを何度も学んで挫折してきた。今回気づいたのは「広く浅く」が問題だったということ。Linux・Bash・Rust に特化して深く学ぶ方針に切り替えた。ターミナル・Vim・SSH・サーバーが好きという自分の本質に素直に従った結果です。だってさ、かっこいいじゃん。
この記事は、ローカルの Docker 環境から本物の VPS に移行するまでの全記録である。
1. 環境方針の決定
これまで Docker Desktop を使っていたが重すぎた。いや、いけるんだけど…新しいMacが欲しくなってしまうくらい。そこで CLI に移行し、Colima の上で Ubuntu のコンテナを動かす構成にしていた。
Dockerfile はこのような構成だった。
- OS: Ubuntu 24.04
- エディタ: vim + vim-plug
- 言語: Rust + rust-analyzer
- ターミナルマルチプレクサ: zellij(Rust 製)
- ツール: bat / btop / ripgrep / shellcheck / bash-completion
- man ページの完全復元(unminimize)
しかし気づいた。SSH やサーバーが好きなら、本物のリモートサーバーにいる方が楽しい。 んじゃないのか?
2. Hetzner VPS の契約
月数百円で本物の Linux サーバーが持てると知り、Hetzner を選んだ。ドイツの会社で GDPR の管轄下にあり、コスパが業界最強クラス?っぽい。あまりお金に余裕がないためにこれに即決する。AWS高いっぽいし…
スペック
| 項目 | 内容 |
|---|---|
| プラン | CX23 |
| 月額 | $3.49 + IPv4 $0.60 = $4.09/月 |
| CPU | 2 vCPU |
| RAM | 4 GB |
| ストレージ | 40 GB NVMe SSD |
| 通信量 | 20 TB/月(超過分は $1.20/TB) |
| ロケーション | フィンランド(Helsinki) |
ヘルシンキって昔オリンピックあったっけ?
SSH 鍵の準備
# 既存の鍵を確認
ls ~/.ssh/
# id_ed25519 と id_ed25519.pub があればそのまま使える
# 公開鍵をクリップボードにコピー
cat ~/.ssh/id_ed25519.pub | pbcopy
Hetzner のコンソールで SSH 鍵を登録してからサーバーを作成した。
接続確認
ssh root@<サーバーのIPアドレス>
3. セキュリティ設定
公開サーバーは立てた瞬間から世界中でスキャンされる。最低限の設定を最初に済ませた。これは建てる前にある程度押さえておいた方がいいと思う。
一般ユーザーの作成
root のまま使い続けるのは危険なので、一般ユーザーを作成する。(colimaの時は常にrootだった為に違和感があったけど、ここで解決
adduser XXXX
usermod -aG sudo XXXX
# SSH 鍵を新ユーザーにコピー
rsync --archive --chown=XXXX:XXXX ~/.ssh /home/XXXX
別のターミナルタブで XXXX としてログインできることを確認してから次に進む。
ssh XXXX@<サーバーのIPアドレス>
SSH の強化
sudo vim /etc/ssh/sshd_config
ファイルの末尾に以下を追記する(コメントアウトされた既存の設定より末尾の設定が優先される)。
PermitRootLogin no
PasswordAuthentication no
設定を反映する。
sudo systemctl restart ssh
ファイアウォールの設定
sudo ufw allow OpenSSH
sudo ufw enable
fail2ban の導入
ブルートフォース攻撃を自動ブロックするツール。
sudo apt install -y fail2ban
状態確認コマンド。数日後にブロックされた IP が溜まってくる。
sudo fail2ban-client status sshd
Hetzner クラウドファイアウォール
Hetzner のコンソールから Firewall を作成し、Inbound ルールを SSH(TCP XX番)のみに絞った。「必要なものだけ許可、それ以外は全部拒否」がセキュリティの基本だ。
4. 開発環境の構築
Dockerfile と同等の環境をサーバー上に再現した。
パッケージのインストール
sudo apt update && apt upgrade -y
sudo apt install -y vim git curl shellcheck man-db bat btop \
build-essential ripgrep bash-completion
sudo unminimize # man ページの完全復元
sudo ln -s /usr/bin/batcat /usr/local/bin/bat
Rust のインストール
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
rustup component add rust-analyzer
# 確認
rustc --version
zellij のインストール(x86_64)
curl -L https://github.com/zellij-org/zellij/releases/latest/download/zellij-x86_64-unknown-linux-musl.tar.gz \
| sudo tar -xz -C /usr/local/bin
2026/2/27 追記 zellij削除しました。tmuxで十分です。
vim の設定
# vim-plug のインストール
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
# vimrc をローカルから転送(ローカルのターミナルで実行)
scp /path/to/vimrc enoki@<サーバーのIPアドレス>:~/.vimrc
# プラグインのインストール
vim +PlugInstall +qall
.bashrc の設定
echo 'export MANPAGER="batcat -l man -p"' >> ~/.bashrc
echo 'export MANWIDTH=120' >> ~/.bashrc
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
echo 'alias zellij="TERM=xterm-256color zellij"' >> ~/.bashrc
echo '[ -f /etc/bash_completion ] && . /etc/bash_completion' >> ~/.bashrc
echo 'set keyseq-timeout 50' >> ~/.inputrc
source ~/.bashrc
SSH config の設定(ローカルの Mac で)
毎回 IP アドレスを入力しなくていいよう、~/.ssh/config に設定を追加する。
Host foo
HostName <サーバーのIPアドレス>
User XXXX
これで ssh foo だけで接続できる。
5. Xserver 解約 & Cloudflare へのドメイン移管
Xserver でレンタルサーバーと maigonosekai.com のドメインを管理していたが、サーバーを Hetzner に移行するにあたって整理した。
注意点として、Xserver の「独自ドメイン永久無料特典」はサーバー契約中のみ有効で、解約すると更新費用が発生する。そのため、解約前に Cloudflare へドメインを移管した。
Cloudflare へのネームサーバー移管手順
- Cloudflare にドメインを追加し、DNS レコードを自動スキャン
- A レコード(
*/ apex /www)の IP アドレスを Xserver から Hetzner に変更 - MX レコード・TXT レコード(メール用)を削除(メール不使用のため)
- CNAME レコード(
devサブドメイン)は Vercel 向けのためそのまま維持 - Xserver のネームサーバー設定画面で「その他のサービスで利用する」を選択
- Cloudflare 指定のネームサーバー 2 つを入力して保存
- Cloudflare ダッシュボードで「Active」になったことを確認
6. 現在のインフラ構成
ドメイン管理 → Cloudflare(Free プラン)
ブログ → Vercel(dev.maigonosekai.com / CNAME で接続)
開発・学習環境 → Hetzner VPS(SSH アクセス)
セキュリティ → Cloudflare DNS プロキシ + Hetzner Firewall + fail2ban
7. 攻撃の監視
セキュリティの学習として、実際に来る攻撃をログで確認できる。
# SSH のリアルタイムログ
sudo journalctl -u ssh -f
# 失敗したログイン試行
sudo journalctl -u ssh --since "1 day ago" | grep "Failed"
# fail2ban でブロックされた IP
sudo fail2ban-client status sshd
# リソース監視
btop
数日後には世界中からのブルートフォース試行が記録されており、セキュリティ設定の重要性が実感できる。
8. 今後の予定
- Xserver のドメイン契約 → 更新タイミングで Cloudflare Registrar への完全移管を検討
- WireGuard で自前 VPN の構築
- nginx を立てたタイミングで Cloudflare Tunnel を導入し IP を完全隠蔽
- Rust・Bash・Linux を Hetzner VPS 上でガシガシ学習
まとめ
月 $4 のサーバーで、本物のインフラ環境が手に入った。壊しても再作成すればいい。世界中からアクセスできる。SSH・ファイアウォール・fail2ban・Cloudflare の多層防御を自分で設定した。
「広く浅く」ではなく「深く狭く」。この方針で Linux・Bash・Rust を極めていく。