「ubuntu」タグアーカイブ

SendGridからOCI Email Deliveryに乗り換えた話

** この記事はClaude Codeと作業した記録をClaude Codeに記事にてもらい、Claude in Chromeを通してClaude Codeが投稿しています。 **

自宅サーバで長年お世話になっていたTwilio SendGridのFreeプランが、2026年3月31日で終了することになりました。4月1日から60日間のトライアルに移行し、5月末にはメール送信が止まってしまうとのこと。

うちのサーバではPostfix経由でSendGridを使って、Redmineの通知メールを飛ばしたり、lambeden.jpに届いたメールをGmailに転送したりしていました。さてどうしましょうか。

OCI Email Deliveryを選んだ理由

うちのサーバはOracle Cloud Infrastructure(OCI)のAmpere A1インスタンスで動いています。OCIにはEmail Deliveryというメール配信サービスがあって、月3,000通まで無料で使えます。同じプラットフォーム内で完結するので、これが一番スマートな選択肢かなということで移行してみました。

Claudeに手順を聞きながら作業しました (^_^)/

OCI Email Deliveryの設定

1. SMTP資格証明の生成

OCIコンソールで「アイデンティティ」→「ドメイン」→「Default」→「ユーザー」から自分のユーザーを開いて、SMTP資格証明を生成します。

⚠️ 生成されたユーザー名とパスワードはその場でコピー必須。画面を閉じると二度と確認できません!

2. 承認済み送信者の登録

「開発者サービス」→「電子メール配信」→「承認済送信者」で、メールのFromアドレスとして使うアドレスを登録します。

3. SPFの設定

承認済送信者の画面から「SPFの表示」でTXTレコードを確認して、お名前.comのDNS管理画面に追加します。

v=spf1 include:ap.rp.oracleemaildelivery.com ~all

4. DKIMの設定

「電子メール配信」→「電子メール・ドメイン」でドメインを作成して「DKIMの追加」からCNAMEレコードを生成、DNSに追加します。セレクター名はmail-tokyo-20260305みたいな形式が推奨されています。

10〜30分待って「Refresh DKIM Status」でActiveになれば完了です。

5. Postfixの設定変更

/etc/postfix/main.cfのリレーホストをOCIに変更します。

relayhost = [smtp.email.ap-tokyo-1.oci.oraclecloud.com]:587

/etc/postfix/sasl_passwdの認証情報も更新。

[smtp.email.ap-tokyo-1.oci.oraclecloud.com]:587    SMTPユーザー名:パスワード

あとSMTPUTF8関連のエラーが出たのでmain.cfに以下も追加しました。

smtputf8_enable = no

反映して動作確認。

sudo postmap /etc/postfix/sasl_passwd
sudo systemctl reload postfix
echo "テスト" | mail -s "テスト" -r xxxx@lambeden.jp 宛先アドレス

Redmineの通知メールもバッチリ届くようになりました。

問題発覚:転送メールが弾かれる

実はlambeden.jpに届いたメールをGmailに転送する設定もしていて、ここでハマりました。

OCI Email DeliveryはエンベロープFromとヘッダFromの両方が承認済み送信者に登録されていないと拒否する仕様です。転送メールの場合、Fromは外部の不特定の送信者になるので、これは構造的にどうにもなりません。

解決策:転送だけGmail SMTPを使う

PostfixのTransport Mapsで、自分のGmailアドレス宛の転送メールだけGmailのSMTPサーバー経由で送るようにしました。

/etc/postfix/transportに追記:

xxxx@gmail.com    smtp:[smtp.gmail.com]:587

/etc/postfix/sasl_passwdにGmailのアプリパスワードを追記:

[smtp.gmail.com]:587    xxxx@gmail.com:アプリパスワード

/etc/postfix/main.cfにtransport_mapsを追加:

transport_maps = hash:/etc/postfix/transport

反映して動作確認:

sudo postmap /etc/postfix/transport
sudo postmap /etc/postfix/sasl_passwd
sudo systemctl reload postfix

iCloudからlambeden.jpにテストメールを送ったら、ちゃんとGmailに届きました!GmailはFromを自分のGmailアドレスに書き換えますが、X-Google-Original-Fromヘッダに元の送信者が保持されるので実用上問題ありません。

まとめ

最終的なPostfixの構成はこうなりました。

用途 経路
Redmine通知・外部への送信 OCI Email Delivery
Gmailへの転送 Gmail SMTP

OCI Email Deliveryは同じプラットフォーム内で完結するので管理が楽で良いですね。SendGridよりも設定の自由度が低い部分もありましたが、無事移行できて一安心です。

GOGETSSLからLet’s Encryptに乗り換え

今までGOGETSSLの証明書を使っていましたが、更新期限が来たのと、今後、証明書の期限が200日以内になるという話もあるので、これを機にLet’s Encryptに乗り換えてみました。

Let’s Encryptは無料で使えますが、有効期限が90日なので、自動更新でもしないとやってられません。はい。自動更新の仕組みあります(^^;

今回は、Claude Codeに手順を出してもらって実施しました。完璧に動きました。すごい。(操作も含めて実行してもらうこともできるのですが、ちょっと怖かったので手順を出してもらって自分で事項しましたが、全く問題ありませんでした。本当にびっくりです。)

手順は以下の通り

Let’s Encrypt SSL証明書の自動更新(Apache + Postfix)

1. Certbot のインストール

# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-apache

# RHEL/CentOS/Rocky Linux
sudo dnf install certbot python3-certbot-apache

2. Apache 用の証明書取得

# Certbot が Apache の設定を自動的に更新する場合
sudo certbot --apache -d example.com -d www.example.com

# 証明書のみ取得(Apache 設定は手動)
sudo certbot certonly --apache -d example.com -d mail.example.com

mail.example.com を Postfix 用に同じ証明書に含めることを推奨

3. Postfix の SSL 設定

sudo nano /etc/postfix/main.cf
# TLS 設定
smtpd_tls_cert_file = /etc/letsencrypt/live/example.com/fullchain.pem
smtpd_tls_key_file  = /etc/letsencrypt/live/example.com/privkey.pem
smtpd_tls_security_level = may

smtp_tls_cert_file = /etc/letsencrypt/live/example.com/fullchain.pem
smtp_tls_key_file  = /etc/letsencrypt/live/example.com/privkey.pem
smtp_tls_security_level = may
sudo systemctl reload postfix

4. 自動更新の設定(重要)

Certbot はインストール時に systemd タイマーまたは cron を自動登録します。確認:

# systemd の場合
sudo systemctl status certbot.timer
sudo systemctl enable certbot.timer

# cron の場合(/etc/cron.d/certbot が存在するか確認)
cat /etc/cron.d/certbot

5. 更新後フック(サービス自動リロード)

更新後に Apache と Postfix を自動リロードするフックを作成:

sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
#!/bin/bash
# Let's Encrypt 更新後に Apache と Postfix をリロード

echo "Reloading Apache and Postfix after certificate renewal..."
systemctl reload apache2   # Ubuntu/Debian
# systemctl reload httpd   # RHEL/CentOS

systemctl reload postfix

echo "Done: $(date)"
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

6. 動作テスト

# ドライランで更新をテスト(実際には更新しない)
sudo certbot renew --dry-run

# フックも含めてテスト
sudo certbot renew --dry-run --deploy-hook /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

7. 証明書の状態確認

# 証明書一覧と有効期限
sudo certbot certificates

# Postfix の TLS 確認
openssl s_client -connect mail.example.com:25 -starttls smtp 2>/dev/null | openssl x509 -noout -dates

まとめ・ポイント

項目 内容
証明書の場所 /etc/letsencrypt/live/example.com/
自動更新タイミング 有効期限 30 日前(Certbot が自動判断)
フックの場所 /etc/letsencrypt/renewal-hooks/deploy/
更新頻度 1 日 2 回チェック(systemd timer)

ポイント:

  • Apache と Postfix で 同じ証明書ファイルを共有 できる
  • deploy/ フォルダのスクリプトは更新成功時のみ実行される
  • ポート 80 が外部から到達可能である必要がある(HTTP-01 チャレンジ)

ドメイン名や OS の種類を教えていただければ、より具体的な設定を出せます。

以上、本当にすごい時代になったものです。

最近メールが届いてないなと思ったら。。。

いつの間にかSpamhausでアカウント登録になってたんですね。以下は、さくらユーザー向けのBLOGですが2021年11月30日以降使えなくなると書いてありました。

https://www.spamhaus.org/resource-hub/email-security/sakuraspamhaus/#lessfont-style%22vertical-align:-inherit%22greaterlessfont-style%22vertical-align:-inherit%22greaterspamhauslessfontgreaterlessfontgreater

私のPostfix main.cfではこんなことが書いてあったのですが、

smtpd_client_restrictions = permit_mynetworks,
reject_rbl_client bl.spamcop.net,
reject_rbl_client sbl-xbl.spamhaus.org,
permit

LOGを見るとあるときから、こんなエラーを吐いてメールを全拒否してました。。。

postfix/smtpd[72758]: NOQUEUE: reject: RCPT from mail-xxxx.google.com[xxx.xx.xxx.xxx]: 554 5.7.1 Service unavailable; Client host [xxx.xx.xxx.xxx] blocked using sbl-xbl.spamhaus.org; Error: excess volume; https://check.spamhaus.org/returnc/vol/xxx.xxx.x.xx/; from=<XXXX@gmail.com> to=<xxxx@lambeden.jp> proto=ESMTP helo=<xxxxx.google.com>

ユーザー登録せずにRBLを利用するとError: excess volumeと言われて全拒否する様です。。。それもきついですが。

対応は簡単で、https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account/ ここからユーザー登録するとメールが届くのでVerify Email押してパスワードを付けたのちダッシュボードに入って赤丸のところを押すと、自分用のRBLサーバが出て聞きます。

smtpd_client_restrictions =
permit_mynetworks,
reject_rbl_client <自分のキー>.zen.dq.spamhaus.net,
permit

こんな感じで、出てきたサーバ名を書けば使えます。ちなみに、SBL、XBL、PBL。。。色々あるのですが、ZENは全部入りなのでこれを使いました。まぁ、smtpd_client_restrictionsに入れるならSBLで十分なのですが、一応(笑)。他のRBLも使ってたんですが、まぁ、SpamHausだけでいいかな。

これで、systemctl restart postfixするなりして、ログ見ながらテストメール送ってみてください。届くようになったと思います(^_^)

UBUNTU 22.04 redmine 5.0移行

前回、サクッとubuntu 20.04 to 22.04にdo-release-upgradeしたらredmineが無くなっていてがっかりして20.04に戻したのですが。。。コロナにかかって自宅待機になったことを機に(笑)、移行実施しました。

前提: gcp上で動いてるubuntu 20.04マシンをライブで22.04に上げます。

まずはsnapshotを取って、サクッと do-release-upgrade。基本元のコンフィグ残す方向で Nを選択。

終わったら不具合ないか確認。私の場合は何点かあった。

1.apache2が上がらない。/etc/apache2/mod-enabled/php7*が残ってたのが原因。

$ cd /etc/apache2/mod-enabled; sudo rm php7*
$ sudo a2enmod php8.1
$ sudo systemctl start apache2 で復旧

2.TeraTERMから繋がらなくなった。sshでssh-rsaが禁止されたのが原因。

https://blog.hitsujin.jp/entry/2022/04/24/010000

という訳で、putty-keygenでssh-ed25519でキーを作りなおした。

3.muninで一部値が取れなくなってる。。。これは急がないのでそのうち直す。

4.redmineが無くなった。これが今日の主題!

Redmine 5.0インストール

ないものは持ってきて入れるしかないので以下のBLOGを参考にRedmineをインストール。せっかくなので5.0で。

https://blog.redmine.jp/articles/5_0/install/ubuntu/

方針: データは20.04のパッケージredmineのデータを引き継ぐ。パッケージでもいいものはパッケージを利用する。

1.何はともあれバックアップ

$ mysqldump -u root -p redmine_default >redmine_default.sql
$ sudo tar cvfz /work/ubuntu2004redminebakup.tar.gz usr/share/redmine var/lib/redmine etc/redmine var/log/redmine var/cache/redmine

2.必要なパッケージインストール

DBは元々MySQLを使っていたので引き続きMySQLを使う(インストール済みの想定)。Rubyはパッケージの3.0.2を使う。Passengerもパッケージを利用。

$ sudo locale-gen ja_JP.UTF-8
$ sudo apt install -y build-essential zlib1g-dev libssl-dev libreadline-dev libyaml-dev libcurl4-openssl-dev libffi-dev
$ sudo apt install -y apache2 apache2-dev
$ sudo apt install -y imagemagick fonts-takao-pgothic
$ sudo apt install -y subversion git
$ sudo apt install -y passenger libapache2-mod-passenger

3.DB移行

ubuntu 20.04のパッケージredmineはredmine_defaultという名前のdatabeseになっているので、今回は、redmineという名前で作り直してデータをストアすることにした。

$ mysql -u root -p
mysql> CREATE DATABASE redmine CHARACTER SET utf8mb4;
mysql> CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'ぱすわーど';
mysql> GRANT ALL PRIVILEGES ON redmine.* TO 'redmine'@'localhost';

$ mysql -u redmine -p redmine < redmine_default.sql

4.Redmineインストール

ubuntu20.04パッケージ版のredmineは /var/lib/redmine/defaultを使っているので、/var/lib/redmineをそのまま使う。

$ cd /var/lib/redmine
$ sudo -u www-data svn co https://svn.redmine.org/redmine/branches/5.0-stable /var/lib/redmine

パッケージの添付ファイルフォルダとpluginsフォルダをコピーしておく
$ sudo cp -rp default/files .
$ sudo cp -rp /usr/share/redmine/plugins .

コンフィグも流用して一部修正
$ cd config
$ sudo cp -p /etc/redmine/default/database.yml .
usernameがredmine/instanceになってるのでredmineに変更
databaseがredmine_defaultになってるのでredmineに変更
$ sudo cp -p  /etc/redmine/default/configuration.yml .
これは特に直すとこなし

$ cd /var/lib/redmine
rootでbundle実行していいのか?とも思うが。。。
$ sudo bundle install --without development test
$ sudo -u www-data bin/rake generate_secret_token
$ sudo -u www-data RAILS_ENV=production bin/rake db:migrate
$ sudo -u www-data RAILS_ENV=production bin/rake redmine:plugins:migrate
$ sudo -u www-data RAILS_ENV=production bin/rake tmp:cache:clear

5.apche2設定変更

/etc/apache2/conf-enabled/redmine.conf修正
Alias "/redmine" /var/lib/redmine/public
<Location /redmine>
        PassengerBaseURI /redmine
        PassengerAppRoot /var/lib/redmine
</Location>
<Directory "/var/lib/redmine/public">
        Allow from all
        Options -MultiViews
        Require all granted
</Directory>

apache再読み込み
$ sudo apachectl configtest
$ sudo systemctl reload apache2

これで、redmineが見られるようになったはず。

6.その他微調整

i. logrotate設定

/etc/logrotate.d/redmine
# Redmine logs:
/var/lib/redmine/log/*.log {  # ←ここ直す
  daily
  missingok
  rotate 14
  compress
  delaycompress
  notifempty
  copytruncate
}

ii. cron.d修正

/etc/cron.d/redmine修正 (redmineのパス修正)
30 6 * * * root cd /var/lib/redmine; bundle exec rake redmine:send_reminders days=3 RAILS_ENV=production > /dev/null 2>&1

iii. checklists pluginを入れていたのだが、うまく引き継がれなかったので、再度、インストールした。

7.ubuntu 20.04のパッケージredmineさようなら

動作確認が終わったら、古いredmineを消す。

$ sudo apt remove redmine redmine-sqlite
$ sudo rm -r /etc/redmine/default
$ sudo rm -r  /var/cache/redmine
$ sudo rm -r /var/log/redmine
$ sudo rm -r /usr/share/redmine
$ mysql -u root -p
mysql> drop database redmine_default;
mysql> drop user 'redmine/instance'@'localhost';

以上

p.s.

やらなくてもいいと言えばいいのですが。。。redmineパッケージを削除すると、apt upgradeするたびに、redmineパッケージインストール時に依存関係で一緒にインストールされたであろうrubyのサブモジュールパッケージが大量にもう使ってないよ。apt autoremoveで削除できるよと言ってくるんですよね。うざいのでautoremoveを実行したら見事に、redmine動かなくなりました(笑)

まぁ、再度

$ sudo bundle install –without development test

してやれば問題なく動きました。gemはパッケージでもbundleで入れても問題ないようですね。

Redmine checklists Pluginで日本語が使えない

Ubuntu 20.04のRedmineに入れたchecklistsプラグイン 3.1.20で日本語を入れてみたところInternal Server Errorが出てしまった。production.logを確認したところ以下の様なエラーが出ていた。

ActiveRecord::StatementInvalid (Mysql2::Error: Incorrect string value: '\xE2\x91\xA0202...' for column 'subject' at row 1: INSERT INTO `checklists` (`subject`, `issue_id`, `created_at`, `updated_at`) VALUES ('ほげほげ', 306, '2022-01-14 22:26:46', '2022-01-14 22:26:46')):

調べてみると以下の情報がヒットした。

https://qiita.com/tomaaaaaaaa/items/08ce75b95df3d310817a

確かにcharacter_set_databaseがlatin1になっていた。。。これは、database.yml にcharset: utf8が入ってなかったためのようです。(encoding: utf8は入っていたので、Redmine自体は日本語が使えており気づきませんでした。)

作ってしまった今から設定を変えても作ってしまったDBには影響しないので、変換してやる必要があります。以下の情報をもとに、どのテーブルがlatin1でできてしまっているか調べてみると、checklist系のテーブルだけでした。

https://www.karakaram.com/changing-the-character-set-to-utf8mb4-after-creating-mysql-table/

SELECT TABLE_NAME,TABLE_COLLATION FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=’DB名’;

| checklist_template_categories | latin1_swedish_ci|
| checklist_templates           | latin1_swedish_ci|
| checklists                    | latin1_swedish_ci|

この3つのテーブルをutf8に変換します。

ALTER TABLE checklist_template_categories
    CONVERT TO CHARACTER SET utf8
    COLLATE utf8_general_ci;

ALTER TABLE checklist_templates
    CONVERT TO CHARACTER SET utf8
    COLLATE utf8_general_ci;

ALTER TABLE checklists
    CONVERT TO CHARACTER SET utf8
    COLLATE utf8_general_ci;

とりあえず、直りました 🙂

今後のために、以下を入れておきました。

/etc/redmine/default/database.yml
charset: utf8
encoding: utf8

/etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
character-set-server=utf8

あと気になったのが、chrome 97.0.4692.71ではなぜか、作ったチェックリストを削除できませんでした。(ゴミ箱アイコンをクリックしても何も反応しない)試しに、Edge 97.0.1072.62 で同じことをしたらできたので、JavaScriptの動きの問題のようです。。。うーん。

ubuntu 19.10 to 20.04 TLS

Windows に嫌気が差したときに時々使っているubuntu desktop環境を放っておいたらうっかりサポート期限が切れて通常のリポジトリから消えてしまった。。。そのままではメンテナンスバージョンへのアップデートもできないのでなんとか、19.10が残ってるサイト内かとミラーサイトを探したのですが、どこにもない(同期されてしまっている模様)

そんな中、ありがたい記事発見。なるほど、old-releasesというサイトが用意されてるのね。これもありがたい。

さくっと /etc/apt/sources.list のdeb http://jp.archive.ubuntu.com/ubuntu/ をhttp://old-release.ubuntu.com/ubuntu/ に変えて sudo apt update、sudo apt upgrade、 sudo do-release-upgrade で20.04 TLSに上げられました。

ちなみに http://security.ubuntu.com/ubuntuは何に変えたらいいのかよくわからんのでコメントアウトしておいたが、問題なくアップデートできた。(残しておくとエラー出る)

JetPackの接続エラー

サイトは普通に見えているし証明書エラーも出ていないのですが、JetPackの接続時に “cURL error 60: SSL certificate problem: certificate has expired”と言われて接続できない。もちろん証明書の期限は切れていない。

色々調べた結果、安い証明書を使っているので、中間証明書を入れないといけなかったようだ。Ubuntu 20.04の場合こんな感じ。中間証明書は証明書を買ったところに行けば入手できると思います。

$ sudo vi /etc/apache2/sites-enabled/default-ssl.conf
SSLCertificateChainFile /etc/ssl/certs/lambeden_dyndns_org.ca
$ sudo systemctl restart apache2

今更ながらWSL便利

Windows 10でLinuxディストリビューションを使えるって話題になって久しいですが、今更ながらWSL(Windows Subsystem for Linux)を使い始めました。

選択ディストリビューションはubuntu。20.04LTSが使えるようになってました。

普通に使ってる分にはネイティブなubuntuを使ってるのと変わらないレベルですね。びっくりです。

systemctl statusとか打って

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: ホストが落ちています

と言われて初めてあーほんとに偽物なんだと気づく(笑)

普通に /mnt/c/Users/XXX/Documentsとかにアクセスできてしまうし。これは確かに便利だは。

とりあえず、やっておくこと。

sudo apt update
sudo apt upgrade
sudo apt install language-pack-ja
sudo update-locale LANG=ja_JP.UTF-8
sudo apt install manpages-ja manpages-ja-dev

timezoneは元々JSTになってました。

参考

https://www.atmarkit.co.jp/ait/articles/1903/18/news031.html

ubuntu 20.04 mysqlが起動しない問題

18.04 LTSから20.04に上げた時に確認したら普通に上がっていたと思うのですが。。。後日、再起動したらmysqldが正しく上がってきませんでした。

確認したら以下のログが

May 9 23:30:24 abel kernel: [ 5967.758467] audit: type=1400 audit(1589034624.217:34): apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld" name="/proc/sys/kernel/random/boot_id
" pid=6850 comm="mysqld" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

/etc/apparmor.d/usr.sbin.mysqldを確認すると、確かに許可されていなかったので、以下を追加したら問題なく起動しました。

/proc/sys/kernel/random/boot_id r,

MySQLが8系になって起動時にランダム値を使うようになったのかな。