サーバー移行(Postfix/Samba/WordPressなど)

4年半運用したサーバーマシンを新サーバーマシンに移行しました。価格も性能も倍以上になりました。\(^o^)/

とはいえ、13,000円弱の BMAX の MaxMini B1 Pro という、発売から1年くらい経つ Celeron N4000 のミニPCですので、一般的には非力で使えないPCですね。うちのサーバー用途なら全然問題なしです。前のが貧弱すぎましたので、なおさらですね。

ModelMaxMini B1 Pro
ProcessorIntel® Gemini Lake N4000
FrequencyBase Frequency 1.6 GHz/ Burst Frequency 2.6 GHz
Number of Cores & Number of Threads
2 Cores & 2 Threads
GraphicsIntel® UHD Graphics 600
RAM8GB
Storage128GB
Expandable storageTF (Micro SD) Card Reader x1、 M.2 2280 SSD x1
LAN1000Mbps
WiFi802.11a/b/g/n/ac
BluetoothBluetooth 4.2
USBUSB 3.0 ×2, USB 2.0 ×2
Other portsDC12V/2A, 3.5mm Headset jack, HDMI ×1,VGA ×1, RJ45 ×1
Item Dimensions120mm(L)×120mm(W)×26mm(H)
Item WeightApproximately 220g

M.2 2280 SSD スロットはあるんですが、NVMe ではなく SATA みたいで、そんなの持ってないので SDカードでディスクを増設することにしました。

目次

OSインストール

旧サーバと同じく Ubuntu Server ですが、バージョンは 24.04.1 LTS (Noble Numbat) になりました。

Windows でISOファイルをダウンロードして、Rufas でUSBメモリに書き込んで起動ディスクを作成、インストールです。

起動したらコンソールのフォントを大きくします。Terminus の最大(16×32)を選択しました。

$ sudo dpkg-reconfigure console-setup

日本語ランゲージパックを入れて、ロケールを変更します。

$ sudo apt install language-pack-ja
$ sudo update-locale LANG=ja_JP.UTF8

いろいろインストールします。

$ sudo apt install nvi emacs-nox screen
$ sudo update-alternatives --config vi

vi はデフォルトで vim が入っているんですが、素の vi しか使えないので nvi を入れてデフォルト vi を変更しています。

SDカードのマウント

持っていた200GBのSDカードに ext4 のファイルシステムを作成し、マウントします。

まず、こんな感じでSDのデバイスファイルを確認します。

$ sudo lshw -short -C disk
H/W path                 Device            Class          Description
=====================================================================
/0/100/15/0/4/0.0.0      /dev/sda          disk           196GB Storage Device
/0/100/15/0/4/0.0.0/0    /dev/sda          disk           196GB

次に parted でパーティションを割り当てます。全部の領域を1つのパーティションにします。

$ sudo parted /dev/sda
(parted) print
(parted) mklabel gpt
(parted) mkpart primary ext4 0% 100%
(parted) name 1 microSD200

ファイルシステムを作成します。

$ sudo mkfs.ext4 -F /dev/sda1

/etc/fstab にマ以下のウント情報を記載します。parted でパーティション1にラベルを付けたので LABEL ではなく PARTLABEL です。

PARTLABEL=microSD200    /mnt/sd ext4    defaults        0       0

マウントします。

$ sudo mount /mnt/sd

ネットワーク設定

インストール時に Wi-Fi の設定をしたので、普通に使う分には何もしなくてもいいのですが、IPv4 と IPv6 でデフォルトルーターを分けないと、外部からアクセスしたときのレスポンスが返されないので、変更する必要があります。

前のサーバで作った netplan の設定ファイルをコピーします。前のサーバはレンダラーに NetworkManager を指定したのですが、インストーラーで Wi-Fi の設定をしたら、レンダラーが systemd-networkd だったので、「renderer: NetworkManager」をコメントアウトしました。それ以外は同じです。

$ scp oldserver:/etc/netplan/99-my-config.yaml .
$ vi 99-my-config.yaml
$ sudo cp 99-my-config.yaml /etc/netplan/
$ sudo chmod go-rw /etc/netplan/99-my-config.yaml

Postfix

Postfix は外部からのメールを受け付けるようにし、さくらインターネットのサーバをリレーホストにして送信します。

送信時は opendkim で DKIM の署名を行いますが、リレーするので実際は署名せずに送信し、リレー先で署名することになります。受信時は DNSBL で変なアクセスを排除します。

main.conf はデフォルトのファイルをベースに、以下の設定をしました。

smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
myhostname = tyd4.com
mydomain = tyd4.com
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = $mydomain
mydestination = $myhostname, localhost
relayhost = [www99999.sakura.ne.jp]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_tls_security_options = noanonymous
smtp_sasl_mechanism_filter = plain
smtp_use_tls = yes
recipient_delimiter = +-

### Access ristriction, DNSBL settings
smtpd_client_restrictions =
 permit_mynetworks,
 reject_unknown_client,
 reject_rbl_client bl.spamcop.net,
 reject_rbl_client zen.spamhaus.org,
 permit

### DKIM Settings
smtpd_milters = inet:127.0.0.1:8891
#smtpd_milters = unix:/run/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters
milter_default_action = accept

さくらインターネットのSMTPサーバは Submission ポートで受信するときはSMTP認証が必要になりますので、smtp_sasl_auth_enable などを設定します。

smtp_sasl_password_maps の sasl_passwd は旧サーバから sasl_passwd と sasl_passwd.db をコピーしてきました。

recipient_delimiter は foo@do.ma.in のようなアドレスに、foo+bar@do.ma.in のように+以降に任意の文字を追加できる拡張アドレスのデリミタで、デフォルトは「+」だけです。メールアドレスとして+を許可していないところも多いので、「-」を追加しています。

smtpd_milters のデフォルトではUNIXソケットなんですが、master.cf のデフォルトが chroot のため、パスが見つからないという問題が発生します。queue_directory (/var/spool/postfix) 以下にソケットを作ればいけるはずですが、めんどくさいのでTCP/IPにします。

OpenDKIM をまだ入れていなかったので、インストールと旧サーバから設定ファイルをコピーします。

$ sudo apt install -y opendkim opendkim-tools
$ ssh old_server 'cd /etc/opendkim && sudo -S tar czf - . ' | sudo tar xzvf -
$ sudo gpasswd -a postfix opendkim
$ sudo chown -R opendkim:opendkim /etc/opendkim/
$ sudo chmod 700 keys/

旧サーバのディレクトリのオーナー、パーミッションが変だったので、opendkim のみアクセスできるように変更しました。

opendkim と postfix を再起動して /var/log/mail.log を確認して、問題がなければOKです。

$ sudo systemctl restart opendkim.service
$ sudo systemctl restart postfix.service

mail コマンドで実際に送ってみます。

$ mail mtystg@gmail.com
Cc
Subject: test
test
(C-d)

mail.log を見ると以下のようなエラーが出力されていました。

postfix/smtp[7104]: 56FE11E1C55: to=<mtystg@gmail.com>, relay=www9999.sakura.ne.jp[XXXX:XXXX:...]:587, delay=1.4, delays=0.03/0.05/1.2/0.12, dsn=5.1.8, status=bounced (host www99999.sakura.ne.jp[[XXXX:XXXX:...] said: 553 5.1.8 <mtystg@new-sv>... Domain of sender address mtystg@new-sv does not exist (in reply to MAIL FROM command))

MAIL FROM で指定する sender アドレスのドメイン「new-sv」が見つからない、というものでした。new-sv は hostname です。

$ postconf |grep new-sv
$

main.cf の mydomainmyoriginmyhostname は tyd4.com にしているのに、なぜか new-sv になってしまいます。

$ mail -r mtystg@tyd4.com mtystg@gmail.com

と明示的に指定すれば送信できます。メール本文を終了するときも「. Enter」で終わらないから、旧サーバの mail コマンドと違うと思っていたのですが、sender は Postfix が勝手につけてくれると思っていたので、気づくのにちょっと時間がかかりました。

旧サーバの mail コマンドは BSD mailx で、新サーバのは GNU mailutils の mail でした。

man mail で GNU mailutils のマニュアルを見ると --config-help オプションがありました。

$ mail --config-help
# Configuration file structure for mail utility.
# For use in global configuration file (/etc/mailutils.conf), enclose it in
# `program mail { ... };
# For more information, use `info mail'.
[...]
address {
  # Set the current user email address (default is loginname@defaultdomain).
  email-addr <email: address>;
  # Set e-mail domain for unqualified user names (default is this host)
  email-domain <domain: string>;
};
[...]

ということで、/etc/mailutils.conf に以下の内容を記載しました。

program mail {
  address {
    email-domain tyd4.com;
  };
};

この状態で mail を送ると、sender が <アカウント>@tyd4.com になって、正常に送信できました。

なお、後でマニュアルを見返したら https://www.gnu.org/software/mailutils/manual/index.html にオンラインの詳しいマニュアルがありました。/etc/mail.rc に記載してもOKだったようです。

/etc/aliases で root などを自分のアカウントに転送します。

root: mtystg
www-data: mtystg

newaliases も忘れずに。

自分宛てに届いたメールはすべて GMail にも転送します。

$ cat ~/.forward 
\mtystg,mtystg@gmail.com

Samba

Windowsなどで使用する共有フォルダを作成します。

$ sudo apt install samba
$ vi /etc/samba/smb.conf

[homes]と [share] を有効化します。[homes] は各ユーザごとの共有フォルダ。[share] は全ユーザ共通。認証なしは利用不可。

[homes]
   comment = Home Directories
   browseable = no
   path = /mnt/buffslo/%S
   read only = no
   create mask = 0700
   directory mask = 0700
   valid users = %S

[share]
  comment = Share area
  browseable = yes
  path = /mnt/buffslo/share
  read only = no   
  guest ok = no
  create mask = 0777
  directory mask = 0777

再起動します。

$ sudo systemctl restart samba.service

他の人の Linux アカウントを作ってなかったので作成します。旧サーバの /etc/passwd, /etc/shadow, /etc/group, /etc/gshadow からコピーしたものを vipw で追加します。

$ sudo vipw
$ sudo vipw -s
$ sudo vipw -g
$ sudo vipw -gs

あとは、Samba で共有できるアカウントを pdbedit で追加すればOKなんですが、passdb なら tdb ファイルのコピーでOK。

一旦 smbd を止めてから、passdb.tdb をコピーして、再起動。

$ sudo systemctl stop smb
$ sudo ssh mtystg@old_server sudo -S cat /var/lib/samba/private/passdb.tdb | sudo sh -c "cat > /var/lib/samba/private/passdb.tdb"
$ sudo systemctl start smb

これで Windows の Explorer から \\ホスト\アカウント で行けるようになります。

MariaDB

旧サーバの MariaDB のデータファイルをそのままコピーします。コピーする前に MariaDB を正常終了させておかないと、新サーバで起動できなくなりますので、必ずコピーする前に正常終了させます。

$ sudo systemctl stop mariadb.service

新サーバも同様に MariaDB を停止しておいたほうがいいですね。

データファイルをコピーします。旧サーバのSDカードには nginx のドキュメントルートもあるので、まとめてコピーします。

$ cd /mnt/sd
$ ssh old_server 'cd /mnt/sd && sudo -S tar czf - *' | sudo tar xzvf -

scp でなく tar でコピーしているのは、シンボリックリンクがあるためです。また旧サーバで sudo -S にしているのは、パイプを通しているため、標準入力からパスワードを送信する必要があるためです。

mariadb.conf の datadir をコピーしたパスに変更します。

  datadir                 = /mnt/sd/mysql_datafiles

で、再起動。

$ sudo systemctl restart mariadb

つないでみます。

$ mysql -u wpadmin -p wp
Enter password: 
[...]
MariaDB [wp]> show tables;
+---------------------------------------------+
| Tables_in_wordpress                         |
+---------------------------------------------+
[...]
+---------------------------------------------+
156 rows in set (0.001 sec)

MariaDB [wp]>

大丈夫そうです。

Nginx, Certbot, WordPress

まずはいろいろインストール。

$ sudo apt install nginx-full php-fpm php-mysql python3-certbot-nginx

Nginx の Document root はコピー済みなので、conf ファイルをコピーします。

$ cd /etc/nginx
$ ssh old_server 'cd /etc/nginx && sudo -S tar czf - .' | sudo tar xzvf -

sites-enabled などにシンボリックリンクがありますので、tar でコピーします。

nginx.conf は「server_tokens off;」を追加します。セキュリティ対策のためですね。

Certbot のファイルもコピーします。

$ cd /etc/letsencrypt
$ ssh old_server 'cd /etc/letsencrypt && sudo -S tar czf - .' | sudo tar xzvf -

翌日とかにログ(/var/log/letsencrypt/letsencrypt.log)を確認して、エラーがないことを確認します。

しばらくして、Certbot の renew が失敗していました。調べたら、hook で呼ばれたシェルスクリプトでエラーになっていました。

一つは、manual_auth_hook でチャレンジトークンをWebサーバーの所定のファイルとして設置する処理で ssh を使用しているのですが、root の known_hosts に Web サーバが存在していなかったために、ssh が失敗していました。

root で一度Webサーバに ssh ログインして解決しました。

$ sudo bash
# ssh account@webserver

もう一つは deploy_hook で証明書を Zip で固めてメール送信する処理で、zip コマンドがないために失敗していました。

zip をインストールして解決です。

$ sudo apt install zip

(2024/12/24追記)

サイトヘルスでエラーが出ていました。

PHPモジュールをインストールします。

$ sudo apt install php-curl php-imagick php-mbstring php-zip php-gd php-intl php-igbinary

サイトヘルスのページをリロードしたらすべての警告が消えました。

最後の php-igbinary はエラーは表示されていませんでしたが、ハンドブックで強く推奨されているもので、php -m で確認して入っていなかったので追加しました。

UFW

ファイアーウォールを設定します。

$ ufw allow ssh
$ ufw allow http
$ ufw allow https
$ ufw allow samba
$ ufw allow postfix
$ ufw deny to 244.0.0.1/4

最後のマルチキャストはルータから頻繁に出ているIGMPで、syslog に大量に出力されるので無視しています。

ssh はルータで閉じておきます。

タイムゾーン

syslog に出力される日時がUTCだったので、JSTに変更します。

$ sudo timedatectl set-timezone Asia/Tokyo
$ date
Wed Dec 18 16:29:03 JST 2024
$ timedatectl 
               Local time: Wed 2024-12-18 16:29:10 JST
           Universal time: Wed 2024-12-18 07:29:10 UTC
                 RTC time: Wed 2024-12-18 07:29:10
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
$ shutdown -r now

apt upgrade の自動化

Ubuntu には unattended-upgrades がデフォルトで用意されており、セキュリティ関連のアップデートは自動で適用されます。

セキュリティ関連以外もアップデートし、リブートが必要ならば夜間に自動でリブートする設定をします。ちなみに、前のサーバーはACPIがなかったので、自動リブートはNGでした。

unattended-upgrades の設定ファイルは /etc/apt/apt.conf.d/50unattended-upgrades ですが、このファイルを直接編集せずに、50より大きい番号のファイルで設定を上書きしたほうがメンテナンス性がよいです。

セキュリティ関連以外もアップデートしてメールする設定は 51unattended-upgrades ファイルに、自動リブートは 51unattended-upgrades-reboot-policy ファイルとして作成します。

Unattended-Upgrade::Allowed-Origins {
      "${distro_id}:${distro_codename}-updates";
      "${distro_id}:${distro_codename}-proposed";
      "${distro_id}:${distro_codename}-backports";
};
Unattended-Upgrade::Mail "root";
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

(2024/12/24追記)

旧サーバでは更新の有無にかかわらず、毎日メールが届いたのですが、新サーバでは変更があったときしかメールが届かなくなりました。

動いていないのか、更新がないのかがわからないので、毎日メールを送るように、51unattended-upgrades に以下を追加しました。

Unattended-Upgrade::MailReport "always";

旧サーバの設定ファイルを見ても、これは設定していなかったんですが、デフォルト値が変わったのかな?

ホームディレクトリ、cron

ホームディレクトリを全部、旧サーバから持ってきます。

$ cd
$ ssh old_server tar czf - . | tar xzf -

cron をセットします。

$ crontab -e
$ crontab -l
*/3 * * * * $HOME/update_mydns.sh
2 4 * * 3 $HOME/reboot_router.sh

ルーター

外部から接続できるようにルーターのポートマッピングを変更します。IPを新サーバーのに変更するだけです。

終わりに

なんやかんやで1週間くらいかけて移行しました。結構疲れましたが、たまにやるといろいろな発見があって面白いですね。

メモを残したくて記事を書いたのですが、なんやかんやで記事を書くのも1週間くらいかかった気がします。

まだ残作業があるかもしれませんが、おおむね完了した感じですので、一旦アップして終了です。お疲れさま!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

プログラミング

前の記事

WSL2の引っ越し