量子コンピュータの実用化により、現在主流の公開鍵暗号は将来的に破られる可能性があります。こうした背景から注目されているのが、量子コンピュータによる攻撃でも解読が困難と考えられている新しい暗号技術 PQC(耐量子計算機暗号)です。本記事では、PQC とは何か、その必要性や仕組みについて、できるだけ分かりやすく5分で解説します。
現在主流の公開鍵暗号は、「巨大な数の素因数分解には膨大な時間がかかる」などの、現代のコンピュータでは効率的に解くことが困難な数学的問題によって安全性が保たれています。しかし、量子コンピュータの実用化が進むと、これらの問題を極めて短時間で解くことが可能になると考えられており、現在の暗号技術が通用しなくなると危惧されています。
例えば、インターネット通信で広く使われている RSA暗号や楕円曲線暗号(ECC) などの公開鍵暗号は、これらの数学的問題に安全性を依存しているため、量子コンピュータの影響を受ける可能性があると指摘されています。
2024年11月12日、NIST(米国国立標準技術研究所)は、耐量子暗号への移行計画を示したドラフト文書 NIST IR 8547「Transition to Post-Quantum Cryptography Standards」を公開しました。この草案では、RSAやECDSAなど量子コンピュータに脆弱な公開鍵暗号について、2030年以降は非推奨とし、2035年以降は使用不可とする移行方針が示されています。
現時点(2026年3月)では、既存の暗号を完全に解読できる規模の量子コンピュータは実用化されていません。しかし、大きな脅威として注目されているのが「ハーベスト攻撃(Harvest Now, Decrypt Later:HNDL)」です。これは、将来の解読を見越して、現時点で暗号化されている通信データをあらかじめ収集・保存しておき、将来量子コンピュータが実用化された時点で解読するという攻撃手法です。
例えば、攻撃者がAくんとB子さんの機密性の高い通信を盗聴しているとします。しかし、通信は暗号化されているため、現時点では内容を読むことはできません。そこで攻撃者は、この暗号化された通信データを収集・保存しておき、将来量子コンピュータが実用化された時点で解読することを狙います。
量子コンピュータが実用化されると、攻撃者は量子コンピュータを使って暗号化された通信データを解読し、その内容を読み取れるようになる可能性があります。
「将来解読されるとしても、数年後なら大丈夫ではないか?」と思うかもしれません。しかし、世の中には10年、20年経っても価値が失われない情報が数多く存在します。
もし量子コンピュータが10年後に実用化されるなら、今日送った「10年以上守るべき秘密」は、すでに危険にさらされていることになります。そのため、データが将来にわたって機密性を保つ必要があるものであるほど、今すぐの対策が必要になります。そこで注目されているのが、量子コンピュータでも解読が困難な PQC(耐量子計算機暗号) です。
PQC(耐量子計算機暗号)とは、Post-Quantum Cryptography の略称で、量子コンピュータによる攻撃に対しても解読が困難と考えられている数学的問題を利用した暗号方式です。代表的なアプローチには、格子に基づく暗号方式、符号に基づく暗号方式、多変数多項式に基づく暗号方式などがあります。
なお、量子力学の性質を利用する暗号技術である「量子暗号」と名前は似ていますが、仕組みはまったく異なります。そのため、両者を混同しないよう注意が必要です。
2015年にNSA(アメリカ国家安全保障局)が PQC への移行計画を発表したことを受け、米国の標準化機関であるNIST(米国国立標準技術研究所)は2016年から PQC の標準化プロジェクトを開始しました。世界中の研究者から82の候補方式が提案され、長年にわたる評価と選考のプロセスを経て、2024年8月に主要な方式が FIPS(連邦情報処理標準)として標準化されました。
| 標準番号 | 採用方式 | アルゴリズム名(旧名称) | 用途 |
|---|---|---|---|
| FIPS 203 | 格子に基づく暗号方式 | ML-KEM (CRYSTALS-Kyber) | 公開鍵暗号/鍵交換 |
| FIPS 204 | 格子に基づく署名方式 | ML-DSA (CRYSTALS-Dilithium) | デジタル署名 |
| FIPS 205 | ハッシュ関数に基づく署名方式 | SLH-DSA (SPHINCS+) | デジタル署名 |
これにより、世界中の企業や政府機関は「どの方式を採用すればよいか」という共通の指標を得ることができ、量子コンピュータ時代に備えた暗号技術への移行が本格的に進みつつあります。
量子コンピュータ時代に備えるうえで重要な考え方が「クリプトアジリティ」です。これは、特定の暗号アルゴリズムに依存せず、状況に応じて別の暗号方式へ柔軟に切り替えられるようにしておく設計思想を指します。暗号の安全性は技術の進歩によって変化するため、標準化されたアルゴリズムであっても、将来的に新たな脆弱性が発見される可能性があります。そのため、PQCを導入する際には、従来の暗号方式から新しい方式へスムーズに移行できる仕組みをあらかじめ用意しておくことが重要です。
PQC の中でも有力とされ、すでに標準化もされている「格子に基づく暗号方式」について、少し簡単に説明します。ここでいう格子とは、空間の中に点が規則正しく並んだ数学的な構造を指します。
これをイメージしやすくするために、山の中で山小屋を探す場面を考えてみましょう。広い山の中に、山小屋が規則的な間隔でたくさん建っているとします。もし自分が山のある地点に立っているとして、「一番近い山小屋はどこか」を見つけるのは簡単そうに思えるかもしれません。
しかし、山の地形が非常に複雑で、しかも空間が何百次元、何千次元にも広がっているとしたらどうでしょう。このとき「最も近い山小屋を見つける問題」は、コンピュータでも解くのが非常に難しくなります。
格子に基づく暗号方式は、このような「近い点を見つけるのが極めて難しい問題」を安全性の基盤として利用した暗号方式です。現在知られている限りでは、量子コンピュータを使っても効率的に解く方法が見つかっていないため、量子コンピュータ時代の暗号として有力視されています。
PQC の必要性や仕組みについて、イメージはつかめたでしょうか。さらに詳しく知りたい方は、以下の参照文献をご参照ください。
量子コンピュータの実用化にはまだ時間がかかると考えられていますが、すでにハーベスト攻撃という現実的な脅威が存在します。これに対応できる PQC(耐量子計算機暗号) はすでに標準化されており、今から対策を進めることが可能です。企業や行政機関のセキュリティ担当者の方は、将来のリスクに備えるためにも PQC への移行計画の検討を始めておくことをお勧めします。
CRYPTREC 暗号技術ガイドライン(耐量子計算機暗号)2024年度版
預金取扱金融機関の耐量子計算機暗号への対応に関する検討会報告書
2026年1月19日、日本円ステーブルコインJPYCのテスト用トークンを取得できる開発者向けツール「JPYC Faucet」の提供が開始されました。コストを気にせず開発に集中できる環境は、開発者にとって非常にありがたいものです。そこで今回は、JPYCテスト用トークンの入手方法について、はじめて暗号資産を扱う方にも分かりやすく解説します。
※この記事は、JPYC株式会社による公式コンテンツではありません。
※最新の情報は JPYCの公式ページ でご確認ください。
JPYCやビットコインなどを利用するには、「暗号資産ウォレット」と呼ばれる専用のツールが必要です。暗号資産ウォレットは、デジタル上のお財布のようなもので、資産を保管したり、送ったり、受け取ったりする役割を担っています。なお、JPYCは厳密には暗号資産ではなく電子決済手段に分類されますが、ブロックチェーン上で管理される点は暗号資産と同じで、利用方法も共通しています。
代表的な暗号資産ウォレットとして「MetaMask」があり、Webブラウザに拡張機能としてインストールすることで、簡単にウォレットを作成できます。初めての方でも画面の案内に沿って進めるだけで利用を開始できますので、暗号資産ウォレットをお持ちでない場合は、お使いの Webブラウザに MetaMask をインストールしてウォレットを作成してください。
MetaMask の公式サイト https://metamask.io/ の「開始」をクリックすればインストールページが開きますので、お使いの Webブラウザに MetaMask をインストールしてください。
JPYCテスト用トークンを利用するテストネットのネイティブトークンが必要になります。2026年1月現在、対応しているテストネットは次の通りです。今回は、Ethereum のテストネット Sepolia(セポリア)のネイティブトークンを入手します。
Webブラウザにインストールした MetaMask で Ethereum Sepolia と JPYC が表示できるように設定しておきましょう。
MetaMask を開き、「トークン」→「すべての人気ネットワーク」をクリックします。

ネットワークの選択画面が開きますので「カスタム」→「Sepolia」をクリックします。

トークンに「SepoliaETH」(Ethereum Sepolia)が表示されますので、縦三点リーダー「︙」→「+トークンをインポート」をクリックします。

「トークンコントラクトアドレス」にJPYCのコントラクトアドレス
0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29 をコピペして「次へ」をクリックします。

【補足】上記にJPYCのコントラクトアドレスを掲載していますが、現在、偽トークンに関する注意喚起が行われています。必ずJPYC公式資料に記載されているコントラクトアドレスと一致していることを確認してください。
公式資料:偽のトークン(偽JPYC)取引に関する注意喚起 | JPYC FAQ Site
「JPY Coin」が表示されていることを確認して「インポート」をクリックします。

続いて Ethereum Sepolia トークン を入手します。以下の手順でウォレットアドレスを確認しておきましょう。
Ethereum 右側のコピーアイコンをクリックすれば、ウォレットアドレスをコピーできます。

Ethereum Sepolia Faucet(テスト用トークンの無料配布所)のページを開き、先ほどコピーしたウォレットアドレスを入力して「Get 0.05 Sepolia ETH」ボタンをクリックすれば、Ethereum Sepolia のテスト用トークンを受け取ることができます。

処理が完了するとウォレットに 0.05 Sepolia ETH が入金されていることが確認できます。

本題の JPYCテスト用トークンを入手します。
JPYC Faucet 公式サイト を開き「ウォレットを接続する」をクリックします。

MetaMaskが開きますので、接続するアカウントが正しいことを確認して「接続」をクリックします。別のアカウントを接続する場合は「アカウントを編集」をクリックして正しいアカウントを選択してください。

ネットワークとウォレットアドレスが正しいことを確認し、入手したい JPYCテスト用トークンの量を入力して「受け取る」をクリックします。

処理のため MetaMaskが開きますので「確認」をクリックします。

処理が完了するとウォレットに JPYCテスト用トークンが入金されていることが確認できます。

本記事では、JPYCを用いた開発・検証を行うために必要なウォレットの準備から、Ethereum Sepolia および JPYCテスト用トークンの入手方法までを解説しました。JPYC Faucet を活用することで、実コストをかけることなくスマートコントラクトやアプリケーションの動作確認を行えます。開発初期の検証やテスト環境構築に、ぜひお役立ててください。
]]>2025年12月4日 Apache httpd 2.4.66 がリリースされました。約8ヶ月ぶりのバージョンアップです。Apache httpd 2.4.66 では、5件の脆弱性が修正され、各種機能の不具合も改善されています。そこで今回は、AlmaLinux 8、Rocky Linux 8、AlmaLinux 9、Rocky Linux 9、CentOS Stream 9、 AlmaLinux 10、Rocky Linux 10、CentOS Stream 10 に Apache httpd 2.4.66 をインストールする手順をまとめてみました。
参考資料:Complete ChangeLog for 2.4
Apache httpd や各種ライブラリをソースからコンパイルしますので、パッケージを「最小限のインストール」でインストールしている場合は、基本パッケージと開発ツールをインストールしておきましょう。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
サーバOSが AlmaLinux 8、Rocky Linux 8 の場合は、OpenSSL 3.5 をインストールします。
OpenSSL のコンパイルに必要なパッケージをインストールしておきます。
OpenSSL 3.5 のダウンロード(ダウンロードの前に OpenSSL 3.5 の最新リリース を確認しておきましょう)
OpenSSL 3.5 のインストール
OpenSSL 3.5 のライブラリにパスを通しておきます。
OpenSSL 3.5 の動作確認(バージョンが表示されればOKです)
/usr/local/openssl-3.5.4/bin/openssl version OpenSSL 3.5.4 30 Sep 2025 (Library: OpenSSL 3.5.4 30 Sep 2025)
HTTP/2(mod_http2)のコアエンジン Nghttp2 をインストールします。
Nghttp2 のダウンロード(ダウンロードの前に Nghttp2の最新リリース を確認しておきましょう)
Nghttp2 のライブラリをコンパイルしてインストールします。
以上で HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib/ 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Brotli のコンパイルに cmake を使いますので、インストールしておきます。
Brotli のダウンロード(ダウンロードの前に Brotliの最新リリース を確認しておきましょう)
Brotli をコンパイルしてインストールします。
Brotli のライブラリが /usr/local/lib64 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Apache httpd のコンパイルに必要なパッケージをインストールしておきます。
また、Apache 2.4系をソースコードからインストールする場合は、APR と APR-util が必要になりますので、インストールしておきます。
本題の Apache httpd のインストールです。
Apache httpd のソースコードのダウンロード
ダウンロードしたソースコードを解凍して、ディレクトリを移動します。
Apache httpd をインストールします。AlmaLinux8、RockyLinux8 の場合は、「--with-ssl」オプションで OpenSSL 3.5 のインストールディレクトリを指定します。
Apache httpd をインストールします。AlmaLinux 9、Rocky Linux 9、CentOS Stream 9、 AlmaLinux 10、Rocky Linux 10、CentOS Stream 10 の場合は「--with-ssl」オプションの指定は必要ありません。
以上で Apache が /usr/local/apache2/ 以下にインストールされました。続いてSSLサーバー証明書の作成と、Apacheの設定を行います。
HTTP/2 および Brotli は HTTPS が必須になりますので Apache の設定の前に、SSLサーバー証明書を作成しておきます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
ログの出力先を変更
(補足)Linuxディストリビューションによっては logrotate の設定により /usr 以下に出力されたログがローテーションできないことがありますので /var/log/ 以下に出力することをオススメします。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します(コピペしてください)
vim /usr/local/apache2/conf/httpd.conf
vim /usr/local/apache2/conf/extra/httpd-ssl.conf
Apache httpd 用の systemd ユニットファイル(起動スクリプトのようなもの)を作成します。
vim /etc/systemd/system/httpd.service
作成したサービスファイルを systemd に反映
systemd に反映されているか確認
systemctl list-unit-files | grep httpd httpd.service disabled disabled ←この表示があればOK
起動
自動起動設定
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
firewall-cmd --list-all
・設定ファイルを作成します
vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 daemon daemon
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示であればOKです)-----
以上です。設定お疲れ様でした!
]]>2025年10月27日、国内初となる日本円ステーブルコイン JPYC が正式に発行を開始しました。JPYC は、日本円と1:1で交換可能で、ブロックチェーンを活用することで低コストに送金することができる、資金決済法第2条第5項に基づく「電子決済手段」です。(暗号資産ではありません)そこで今回は、JPYCの発行から送金、そして日本円に償還するまでの一連の流れをわかりやすくまとめました。
※この記事は、JPYC株式会社による公式コンテンツではありません。
※最新の情報は JPYCの公式ページ でご確認ください。
日本円と JPYC の交換は、JPYC の発行および償還の受付を行う専用プラットフォーム「JPYC EX」で行います。
JPYC EX でアカウントを作成し、JPYC を発行して送金するには、次の5点が必要です。事前に準備しておきましょう。
ウォレットアプリは、以下の条件を満たしている必要があります。(2025年11月現在)
JPYC では、大阪・関西万博でも利用された HashPort Wallet が推奨されています。また、ウォレットアプリの定番 MetaMask もこの条件を満たしていますので、問題なく利用できます。
JPYCは「ノンカストディ型」と呼ばれる電子決済手段です。そのため、JPYCの発行は、JPYC株式会社が行いますが、発行したJPYCは、利用者自身が管理、すなわちウォレットの秘密鍵やシークレットリカバリーフレーズを安全に管理する必要があります。
少し補足するとJPYCは電子決済手段ですが、その仕組みはブロックチェーン技術を基盤にしていますので暗号資産とまったく同じです。実際に、JPYCの取引記録は Ethereum、Polygon、Avalanche といった暗号資産のネットワーク(=ブロックチェーン)上に保存されます。
暗号資産を普段から利用している方はお気付きかと思いますが、JPYCの送金には「ガス代」と呼ばれる手数料がわずかですが発生します。(利用するネットワークによって異なりますが、公式情報では 1円未満とされています。)
そのため、JPYCで利用するネットワークの暗号資産を少額で構いませんので、ウォレットへ送金しておきましょう。対応している暗号資産のネットワークや、発行・償還には上限額が設定されていますので、事前に以下の公式資料を確認しておくことをおすすめします。
公式資料:JPYCが対応しているネットワーク一覧 | JPYC FAQ Site
2026年1月現在の各ネットワークの特徴を簡単にまとめてみました。
時価総額ベースでは、この中で Ethereum が最も普及しており、セキュリティにも定評がありますが、ネットワーク混雑時にはガス代が高騰しやすい傾向があります。ガス代を抑えたい場合は、Polygon または Avalanche のネットワークを選択することになります。
| Ethereum(イーサリアム) | Ethereum は、スマートコントラクトという「自動で動くプログラム」を使える代表的なブロックチェーンです。DeFi や NFT、DAO など多くの web3 サービスがこの上で動いています。また、PoS への移行で省エネ化が進み、最近は L2 技術の発展によって手数料の高さや処理の遅さも改善されてきています。開発者が多く、今後も成長が期待される基盤です。 |
| Polygon(ポリゴン) | Polygon は、Ethereum の弱点である「手数料」と「速度」を改善するためのスケーリング技術を提供するプラットフォームです。アプリを簡単に移植できる互換性の高さが強みで、ゲームや企業プロジェクトでの採用が増えています。Polygon PoS などのサイドチェーンに加え、zkEVM といった最新のレイヤー2も展開しており、より使いやすい web3 環境づくりが進んでいます。 |
| Avalanche(アバランチ) | Avalanche は「速さ」と「拡張性」に特化したブロックチェーンで、独自のコンセンサス方式によって数秒以内で取引が確定するのが特徴です。DeFi や企業利用で特に注目されており、用途に合わせた“専用チェーン”を作れる Subnet という仕組みも強みです。EVM 互換のため、Ethereum 系のアプリや資産を扱いやすい点もメリットです。 |
JPYC公式ページで、JPYC EX アカウントを開設します。本人確認のためスマートフォンアプリのインストールやマイナンバーカードの読み取りなどの手続きがありますが、特に問題がなければ審査も含めて10分程度で開設できます。
アカウントの開設が終わったら、JPYC EX にログイン して、ウォレットアドレスを登録します。
「ウォレット」接続をクリックします。
今回ウォレットアプリは MetaMask を使いますので「MetaMask」をクリックします。
利用するネットワークを選択して「登録」をクリックすれば、ウォレットアドレスの登録完了です。登録した「ウォレットアドレス」は、「マイページ」で確認できます。
記載の通り、発行サービスの利用にも、出金先口座の登録が必要になりますので、償還時の出金先口座を登録しておきます。
以上で準備完了です。実際にJPYCを発行してみましょう。
自分の銀行口座からJPYCが指定する入金先口座へ振り込みを行いますが、いくつか注意事項があります。スムーズに発行手続きを進めるためにも、事前にしっかり確認しておきましょう。
公式資料:入出金ルール・入出庫ルール① - 日本円を入金する際の注意事項 | JPYC FAQ Site
画面左メニューの「発行」をクリックします。
「ネットワーク」と「受取アドレス」を選択して、「注文額」に発行したいJPYCの数量(1JPYC=1円です)を入力して、「発行予約を確定する」をクリックします。
次のページに、入金金額と振込口座情報が表示されていますので、入金を行います。
入金確認が終わるとJPYCが発行され「履歴照会」の画面でその取引が確認できます。今回は祝日に楽天銀行から入金を行いましたが、20分程度で発行されました。
ウォレットアプリ(MetaMask)でも、JPYCの残高が正しく反映されていることを確認できます。今回の例では、もともとウォレットに 2,900 JPYC が入っていたところへ、発行した 3,000 JPYC が追加され、合計 5,900 JPYC と表示されています。
続いて、JPYCを別のウォレットアドレスに送金してみます。
送金を行う前に、受け取り側のウォレットアプリ(今回は MetaMask)で JPYC が表示されるように設定しておきましょう。以下の公式手順に沿ってJPYCトークンを追加しておくことで、受け取り時に残高を確認できます。
公式資料:JPYCのトークン表示追加・残高表示・確認手順 | JPYC FAQ Site
受け取り側のウォレットアプリに「JPY Coin」が表示されていれば準備完了です。
受け取り側のアドレスを確認しますので「受取」をクリックします。
JPYCで利用するネットワークに対応したアドレスを確認してください。ネットワークによってアドレスが異なる場合がありますので注意しましょう。
送金側のウォレットで、確認した受け取り側のアドレスに送金を実行します。
「送金」をクリックします。
「JPY Coin」をクリックします。
「移動先」に送金先のアドレスを入力し、「金額」に送金するJPYCの数量を入力したら「続行」ボタンをクリックします。
内容に間違いが無いことを確認して「確認」ボタンをクリックすれば、送金が実行されます。
時間帯にもよりますが、数秒で送金が完了すると思います。今回のガス代(Transaction Fee)は、わずか 0.24円でした。
受け取り側のウォレットで、JPYCが入金されていることが確認できます。
Ethereumネットワークで送金した場合のガス代は約60円でした(※ネットワークの混雑状況によって変動するため、あくまで参考値です)。Avalancheのガス代と比較すると高い印象はありますが、SWIFTを利用した国際送金手数料(1回あたり約2,000〜5,000円とされています)を考えれば、非常に低コストと言えるでしょう。
高額な取引を行う場合、セキュリティ要件の観点から Ethereumネットワークの利用が求められるケースもあります。そのため、JPYC の利用用途によっては、Ethereum ネットワークの利用を検討してみるのも良いでしょう。
最後に、JPYC を日本円と交換してみましょう。
JPYC EX にログインして、画面左メニューの「償還」をクリックします。
「ネットワーク」と「送信元アドレス」を選択して、「送信数量」に日本円へ交換したいJPYCの数量を入力します。内容を確認したら「償還予約を確定する」をクリックします。
次のページに、JPYCの送信数量と送金先アドレスが表示されますので、ウォレットアプリで、指定の送金先アドレスへJPYCを送金します。いくつか注意事項が記載されていますので、送金する前にしっかり確認しておきましょう。
今回のガス代は、0.17円でした。おそらく Avalancheネットワークであれば、公式情報の通り送金手数料は1円未満に収まると思われます。
送金が完了すると、約10分ほどで登録している銀行口座へ入金が反映されます。取引状況は、JPYC EX の「履歴照会」画面で確認できます。
ブロックチェーン技術を活用した JPYC は、1円以下の手数料で世界中どこへでも、わずか数秒で送金できるという大きな特徴があります。従来の国際送金では、高額な手数料や到着まで数日かかることが一般的でしたが、それらの課題を一気に解決するのがステーブルコインです。まさに「金融革命」と言えるでしょう。
JPYC に続いて、2025年11月、日本のメガバンク3行も円建てステーブルコインの実証実験に取り組むと発表しています。これまで銀行や決済代行会社が担ってきた送金・決済、さらには預金の仕組みまでが、ブロックチェーン技術によって大きく変わろうとしています。
2025年7月23日 Apache httpd 2.4.65 がリリースされました。Apache httpd 2.4.64 において RewriteCond expr 条件式が常に true と評価してしまうバグが見つかったため、わずか2週間でバージョンアップされました。このバグは CVE-2025-54090 として識別されています。そこで今回は、AlmaLinux 8、Rocky Linux 8、AlmaLinux 9、Rocky Linux 9、CentOS Stream 9、 AlmaLinux 10、Rocky Linux 10、CentOS Stream 10 に Apache httpd 2.4.64 をインストールする手順をまとめてみました。
参考資料:Complete ChangeLog for 2.4
Apache httpd や各種ライブラリをソースからコンパイルしますので、パッケージを「最小限のインストール」でインストールしている場合は、基本パッケージと開発ツールをインストールしておきましょう。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
サーバOSが AlmaLinux 8、Rocky Linux 8 の場合は、OpenSSL 3.0 をインストールします。
OpenSSL のコンパイルに必要なパッケージをインストールしておきます。
OpenSSL 3.0 のダウンロード(ダウンロードの前に OpenSSL 3.0 の最新リリース を確認しておきましょう)
OpenSSL 3.0 のインストール
OpenSSL 3.0 のライブラリにパスを通しておきます。
OpenSSL 3.0 の動作確認(バージョンが表示されればOKです)
/usr/local/openssl-3.0.17/bin/openssl version OpenSSL 3.0.17 1 Jul 2025 (Library: OpenSSL 3.0.17 1 Jul 2025)
HTTP/2(mod_http2)のコアエンジン Nghttp2 をインストールします。
Nghttp2 のダウンロード(ダウンロードの前に Nghttp2の最新リリース を確認しておきましょう)
Nghttp2 のライブラリをコンパイルしてインストールします。
以上で HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib/ 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Brotli のコンパイルに cmake を使いますので、インストールしておきます。
Brotli のダウンロード(ダウンロードの前に Brotliの最新リリース を確認しておきましょう)
Brotli をコンパイルしてインストールします。
Brotli のライブラリが /usr/local/lib64 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Apache httpd のコンパイルに必要なパッケージをインストールしておきます。
また、Apache 2.4系をソースコードからインストールする場合は、APR と APR-util が必要になりますので、インストールしておきます。
本題の Apache httpd のインストールです。
Apache httpd のソースコードのダウンロード
ダウンロードしたソースコードを解凍して、ディレクトリを移動します。
Apache httpd をインストールします。AlmaLinux8、RockyLinux8 の場合は、「--with-ssl」オプションで OpenSSL 3.0 のインストールディレクトリを指定します。
Apache httpd をインストールします。AlmaLinux 9、Rocky Linux 9、CentOS Stream 9、 AlmaLinux 10、Rocky Linux 10、CentOS Stream 10 の場合は「--with-ssl」オプションの指定は必要ありません。
以上で Apache が /usr/local/apache2/ 以下にインストールされました。続いてSSLサーバー証明書の作成と、Apacheの設定を行います。
HTTP/2 および Brotli は HTTPS が必須になりますので Apache の設定の前に、SSLサーバー証明書を作成しておきます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
ログの出力先を変更
(補足)Linuxディストリビューションによっては logrotate の設定により /usr 以下に出力されたログがローテーションできないことがありますので /var/log/ 以下に出力することをオススメします。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します(コピペしてください)
vim /usr/local/apache2/conf/httpd.conf
vim /usr/local/apache2/conf/extra/httpd-ssl.conf
Apache httpd 用の systemd ユニットファイル(起動スクリプトのようなもの)を作成します。
vim /etc/systemd/system/httpd.service
作成したサービスファイルを systemd に反映
systemd に反映されているか確認
systemctl list-unit-files | grep httpd httpd.service disabled disabled ←この表示があればOK
起動
自動起動設定
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
firewall-cmd --list-all
・設定ファイルを作成します
vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 daemon daemon
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示であればOKです)-----
以上です。設定お疲れ様でした!
]]>2025年06月11日、Rocky Linux 10.0 がリリース されました。約3年ぶりのメジャーバージョンアップです。Rocky Linux 10.0 では、各種ミドルウェアが更新され Python 3.12、PHP 8.3、Apache HTTP 2.4.63、MySQL 8.4 などが利用できるようになっています。また、最も大きな変更点として Rocky Linux 10.0 から x86-64-v2アーキテクチャのサポートがなくなり x86-64-v3アーキテクチャが必須になっているのことが挙げられています。そこで今回は、Rocky Linux 10.0 で LAMP環境を構築する手順をまとめてみました。
Rocky Linux 10.0 の全ての変更点は、アップストリームとなる Red Hat Enterprise Linux 10.0 のリリースノートをご参照ください。
Rocky Linux のダウンロードページ から インストール先マシンのアーキテクチャに合わせて「Default Images」の「Minimal ISO」イメージと「CHECKSUM」をダウンロードします。アーキテクチャは x86_64 のマシンが多いですが、Appleシリコンの macOS 上の仮想マシンにインストールする場合はARMアーキテクチャ(aarch64)の ISOイメージをダウンロードしてください。
ISOイメージのダウンロードが終わったら、チェックサムが一致していることを確認しましょう。
$ shasum -a 256 Rocky-10.0-aarch64-minimal.iso 042be2dfd33e0a8cf4262c160d793660e16c3eee46b236120e86a40e867ddc96 Rocky-10.0-aarch64-minimal.iso $ grep Rocky-10.0-aarch64-minimal.iso CHECKSUM # Rocky-10.0-aarch64-minimal.iso: 1969881088 bytes SHA256 (Rocky-10.0-aarch64-minimal.iso) = 042be2dfd33e0a8cf4262c160d793660e16c3eee46b236120e86a40e867ddc96
Rocky Linux 10.0 を GUIモードでインストールする場合のシステム要件は次の通りです。
参考資料:Rocky Linux 10 (Red Quartz) – Minimum Hardware Requirements
今回は、VirtualBox の仮想マシンに Rocky Linux 10.0 をインストールします。
VirtualBoxの仮想マシンのタイプに Rocky Linux および RHEL はありませんのでアップストリームの「Linux Fedora」を選択してください。
■仮想マシン構成
タイプ:Linux
subtype:Fedora
メモリ:2048MB
HDD:20GB
CPU:2コア
■ネットワーク
アダプター1:NAT
アダプター2:ホストオンリーネットワーク(固定IPアドレスを設定)
■ネットワーク設定(※ご自分の環境に合わせて設定してください)
ホスト名: rocky10
固定IPアドレス:192.168.56.201/24
DNSサーバ: 1.1.1.1
DNSサーバ: 8.8.8.8
ダウンロードした ISOイメージ(もしくはそれを書き込んだメディア)からマシンを起動します。
[↑]キーで「Install Rocky Linux 10.0」を選択して、エンターを押します。
GUI画面が表示されたら「日本語 Japanese」「日本語(日本)」を選択して「続行」をクリックします。
下のような表示になるまで少し待ってから「インストール先」をクリックします。
インストール先のハードディスクを選択して、「完了」をクリックします。
ソフトウェアの選択が「最小限のインストール」になっていることを確認してください。(もし違うようでしたら「最小限のインストール」に変更してください)
下にスクロールして「ユーザーの作成」をクリックします。セキュリティ対策のため root アカウントは無効になっていますので、root アカウントの代わりとなる管理者ユーザーを作成しておきましょう。
以下のように入力/選択して「完了」をクリックします。(必ず「このユーザーを管理者にする」にチェックを入れてください)下で入力しているユーザー名はあくまで例です、オリジナルのユーザー名を設定しましょう。
「インストールの開始」をクリックします。パーティションの作成とインストールが開始します。
インストールが完了するまでしばらく待ちます。
インストールが完了したら「システムの再起動」をクリックします。
再起動できない場合やインストーラーが起動してしまう場合は、マシンの電源を一度オフにして、ISOイメージ(もしくはそれを書き込んだメディア)を取り除いてから起動してください。
Rocky Linux 10.0 が起動したら作成した管理者ユーザーでログインします。
この記事では rootユーザーで設定を行うことを前提にしています。これ以降の手順は、管理者ユーザーでログインしたら次のコマンドで rootユーザーになってから実施してください。
sudo -s
※通常の運用時は sudo <コマンド> を利用することをオススメします。
ネットワーク関連の設定は、ご自分の環境に合わせて設定してください。
固定IPアドレスを設定する場合は、nmcli コマンドでNICのコネクション名を確認します。
以下は VirtualBox 仮想マシンの出力例ですが、アダプター1(NAT)はのコネクション名は「enp0s8」、アダプター2(ホストオンリーネットワーク)のコネクション名は「enp0s9」であることが確認できます。(コネクション名に対応するアダプターは ip addr の出力などを参考にして判断してください)
nmcli dev s DEVICE TYPE STATE CONNECTION enp0s8 ethernet connected enp0s8 enp0s9 ethernet connected enp0s9 lo loopback connected (externally) lo
アダプター2(ホストオンリーネットワーク)のコネクション名指定して、固定IPアドレスを設定します。
NICを再起動して設定を反映させます。
以上で、仮想マシンに ssh ログインができるようになります。
DNSサーバを手動で設定する場合は、DHCPによるDNSサーバの自動設定を無効にします。
(以下はアダプター1(NAT)のDNSサーバの設定例です)
DNSサーバを設定し、NetworkManager を再起動します。
DNSサーバが設定されていることを確認します。
ホスト名「rocky10」を設定し、hostnamed を再起動します(一度ログアウトしログインすると設定したホスト名が反映されていることを確認できます)
開発ツールなど、基本的なパッケージをインストールしておきます。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
必要がなければ cockpit(Webベースのサーバー管理ツール)を停止します。
・現在の設定の確認
firewall-cmd --list-all
初期設定では publicゾーンの cockpit、dhcpv6-client、ssh サービスが許可されています。
cockpit を使わない場合は、削除しておきましょう。
追加で HTTP(80/tcp) と HTTPS(443/tcp) を許可しておきます
設定を読込みます
・設定を確認します
firewall-cmd --list-all
-----(以下の表示であればOK)-----
タイムゾーンを日本に変更
・参照先のNTPサーバーを変更します。
vi /etc/chrony.conf
chronyd を再起動
自動起動設定
・10分ほど経過したら動作を確認します。
chronyc sources -v
-----(以下のような表示があればOK)-----
時刻があまりにもズレている場合は、dateコマンドで手動で時刻を合わせてください。
サーバーから Gmail 経由でメールを送信できるように設定します。(必要がなければこの設定は不要です)
Postfix をインストールします。
Googleアカウントの設定、および Postfix の設定手順は以下の記事をご参照ください。
PostfixからGmail経由でメールを送信するための設定メモ
メールが送信できることが確認できたら以下を設定します。
自動起動設定
・root宛メールの送信先を変更します
vi /etc/aliases
-----(下記を最終行に追加)-----
メールエイリアスのDBファイルを更新します
root宛のメールが、自分のメールアドレス宛に届くことを確認します
EPEL
Remi
Remi リポジトリから PHP8.4 がインストールされるように php:remi-8.4 モジュールをインストールします。
【補足】
Remi リポジトリからは PHP8.4 以外に 以下のバージョンの PHPモジュールをインストールすることができます。
dnf module list php Remi's Modular repository for Enterprise Linux 10 - aarch64 Name Stream Profiles Summary php remi-7.4 common [d], devel, minimal PHP scripting language php remi-8.0 common [d], devel, minimal PHP scripting language php remi-8.1 common [d], devel, minimal PHP scripting language php remi-8.2 common [d], devel, minimal PHP scripting language php remi-8.3 common [d], devel, minimal PHP scripting language php remi-8.4 [e] common [d] [i], devel, minimal PHP scripting language ヒント: [d]efault, [e]nabled, [x]disabled, [i]nstalled
Rocky Linux 10.0 ではDNFモジュール機能が非推奨になっています。
参考資料:Modularity | Rocky Linux 10.0 Release Notes
しかし、Red Hat Enterprise Linux 10.0 のリリースノートには、DNFモジュール機能が非推奨になった旨の記載が無いため、この記事では dnf module コマンドを使う手順としています。
※バージョンは2025年7月25日時点のものです。
Apache httpd(2.4.63-1)
PHP(8.4.10-1)
MySQL(8.4.4-2)
・PHPの設定
vi /etc/php.ini
php-fpm を自動起動を設定し起動します。
不要なコンフィグを読込まないようにしておきます。
オリジナルのコンフィグをバックアップ
・コンフィグを作成します。
vi /etc/httpd/conf/httpd.conf
Apache httpd の自動起動を設定し起動ます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
SSL設定ファイルのオリジナルをバックアッップします
SSL設定ファイルを作成します。
vi /etc/httpd/conf.d/ssl.conf
Apache httpd を再起動します。
WEBブラウザで HTTPSで接続できることを確認します。
【補足】
自己署名のサーバー証明書の場合は警告が表示され、接続できない場合があります。FireFox で「危険性を承知で続行」ボタンを押して接続するか、Google Chrome の場合は「thisisunsafe」とタイプすると接続できます。
・MySQLの設定ファイルに以下を追加します。
vi /etc/my.cnf.d/mysql-server.cnf
MySQL の自動起動を設定し起動します。
初期状態では、rootユーザーがパスワードなしで MySQLに接続できるようになっていますのでパスワードを設定しておきます。
mysql_secure_installation コマンドを実行すると、root ユーザーのパスワードを変更し、不要なユーザーやDBも削除してくれます。パスワードは、8文字以上で英数大文字小文字と記号が含まれていないとポリシー違反で弾かれてしまいますので注意です。パスワードポリシーを変更したい場合は「--use-default」オプションなしで実行してください。
設定ファイルのバックアップ用ディレクトリを作成しておきます。
オリジナルの設定ファイルをバックアップします
・設定ファイルを作成します
vi /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 apache apache
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示があればOKです)-----
(略) rotating pattern: /var/log/httpd/*log after 1 days empty log files are rotated, (365 rotations), old logs are removed considering log /var/log/httpd/access_log (略)
オリジナルの設定ファイルをバックアップします
・設定ファイルを作成します
vi /etc/logrotate.d/mysqld
/var/log/mysql/*log {
daily
missingok
dateext
rotate 365
sharedscripts
postrotate
/usr/bin/kill -USR1 $(systemctl show --property MainPID --value mysqld)
endscript
}
・確認します
logrotate -v /etc/logrotate.d/mysqld
-----(下記のような表示があればOKです)-----
(略) rotating pattern: /var/log/mysql/*log after 1 days empty log files are rotated, (365 rotations), old logs are removed considering log /var/log/mysql/mysqld.log (略)
systemctl list-unit-files | grep -e httpd.service -e php-fpm.service -e mysqld.service -e chronyd.service -e 'UNIT FILE '
-----(STATE列がすべて「enabled」であればOKです)-----
UNIT FILE STATE PRESET chronyd.service enabled enabled httpd.service enabled disabled mysqld.service enabled disabled php-fpm.service enabled disabled
一度OSを再起動して、各種サービスが起動している事を確認しましょう。
以上です。設定お疲れ様でした!
]]>
2025年7月10日 Apache httpd 2.4.64 がリリースされました。約半年ぶりのバージョンアップです。Apache httpd 2.4.64 では、8件の脆弱性が修正され、各種機能の不具合も改善されています。そこで今回は、AlmaLinux 8、Rocky Linux 8、AlmaLinux 9、Rocky Linux 9、CentOS Stream 9、 AlmaLinux 10、Rocky Linux 10、CentOS Stream 10 に Apache httpd 2.4.64 をインストールする手順をまとめてみました。
参考資料:Complete ChangeLog for 2.4
Apache httpd や各種ライブラリをソースからコンパイルしますので、パッケージを「最小限のインストール」でインストールしている場合は、基本パッケージと開発ツールをインストールしておきましょう。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
サーバOSが AlmaLinux 8、Rocky Linux 8 の場合は、OpenSSL 3.0 をインストールします。
OpenSSL のコンパイルに必要なパッケージをインストールしておきます。
OpenSSL 3.0 のダウンロード(ダウンロードの前に OpenSSL 3.0 の最新リリース を確認しておきましょう)
OpenSSL 3.0 のインストール
OpenSSL 3.0 のライブラリにパスを通しておきます。
OpenSSL 3.0 の動作確認(バージョンが表示されればOKです)
/usr/local/openssl-3.0.17/bin/openssl version OpenSSL 3.0.17 1 Jul 2025 (Library: OpenSSL 3.0.17 1 Jul 2025)
HTTP/2(mod_http2)のコアエンジン Nghttp2 をインストールします。
Nghttp2 のダウンロード(ダウンロードの前に Nghttp2の最新リリース を確認しておきましょう)
Nghttp2 のライブラリをコンパイルしてインストールします。
以上で HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib/ 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Brotli のコンパイルに cmake を使いますので、インストールしておきます。
Brotli のダウンロード(ダウンロードの前に Brotliの最新リリース を確認しておきましょう)
Brotli をコンパイルしてインストールします。
Brotli のライブラリが /usr/local/lib64 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Apache httpd のコンパイルに必要なパッケージをインストールしておきます。
また、Apache 2.4系をソースコードからインストールする場合は、APR と APR-util が必要になりますので、インストールしておきます。
本題の Apache httpd のインストールです。
Apache httpd のソースコードのダウンロード
ダウンロードしたソースコードを解凍して、ディレクトリを移動します。
Apache httpd をインストールします。AlmaLinux8、RockyLinux8 の場合は、「--with-ssl」オプションで OpenSSL 3.0 のインストールディレクトリを指定します。
Apache httpd をインストールします。AlmaLinux 9、Rocky Linux 9、CentOS Stream 9、 AlmaLinux 10、Rocky Linux 10、CentOS Stream 10 の場合は「--with-ssl」オプションの指定は必要ありません。
以上で Apache が /usr/local/apache2/ 以下にインストールされました。続いてSSLサーバー証明書の作成と、Apacheの設定を行います。
HTTP/2 および Brotli は HTTPS が必須になりますので Apache の設定の前に、SSLサーバー証明書を作成しておきます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
ログの出力先を変更
(補足)Linuxディストリビューションによっては logrotate の設定により /usr 以下に出力されたログがローテーションできないことがありますので /var/log/ 以下に出力することをオススメします。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します(コピペしてください)
vim /usr/local/apache2/conf/httpd.conf
vim /usr/local/apache2/conf/extra/httpd-ssl.conf
Apache httpd 用の systemd ユニットファイル(起動スクリプトのようなもの)を作成します。
vim /etc/systemd/system/httpd.service
作成したサービスファイルを systemd に反映
systemd に反映されているか確認
systemctl list-unit-files | grep httpd httpd.service disabled disabled ←この表示があればOK
起動
自動起動設定
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
firewall-cmd --list-all
・設定ファイルを作成します
vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 daemon daemon
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示であればOKです)-----
以上です。設定お疲れ様でした!
]]>2025年5月27日、AlmaLinux 10.0 がリリース されました。約3年ぶりのメジャーバージョンアップです。AlmaLinux 10.0 では、各種ミドルウェアが更新され Python 3.12、PHP 8.3、Apache HTTP 2.4.62、MySQL 8.4 などが利用できるようになっています。また、AlmaLinux 10.0 から x86-64-v2 という新しいアーキテクチャが追加されています。基本的には RHEL10 に準じて x86-64-v3 に最適化しますが、AlmaLinux 10.0 では古いハードウェア用に x86-64-v2 対応のバイナリも提供されます。そこで今回は、AlmaLinux 10.0 で LAMP環境を構築する手順をまとめてみました。
AlmaLinux 10.0 の全ての変更点は、アップストリームとなる Red Hat Enterprise Linux 10.0 のリリースノートをご参照ください。
AlmaLinuxのダウンロードページ から インストール先マシンのアーキテクチャに合わせて 「AlmaLinux OS 10.0 Minimal ISO」のISOイメージをダウンロードします。アーキテクチャは Intel/AMD(x86_64)のマシンが多いですが、Appleシリコンの macOS 上の仮想マシンにインストールする場合は ARM64(AArch64)の ISOイメージをダウンロードしてください。
ISOイメージのダウンロードが終わったら、以下の手順を参考にしてチェックサムを確認しましょう。
Installation instructions | AlmaLinux 10.0 Release Notes
AlmaLinux 10.0 を ISOイメージでインストールする場合のシステム要件は次の通りです。
参考資料:AlmaLinux installation guide (ISOs)
今回は、VirtualBox の仮想マシンに AlmaLinux 10.0 をインストールします。
VirtualBoxの仮想マシンのタイプに AlmaLinux および RHEL はありませんのでアップストリームの「Linux Fedora」を選択してください。
■仮想マシン構成
タイプ:Linux
subtype:Fedora
メモリ:2048MB
HDD:20GB
CPU:2コア
■ネットワーク
アダプター1:NAT
アダプター2:ホストオンリーネットワーク(固定IPアドレスを設定)
■ネットワーク設定(※ご自分の環境に合わせて設定してください)
ホスト名: alma10
固定IPアドレス:192.168.56.201/24
DNSサーバ: 1.1.1.1
DNSサーバ: 8.8.8.8
ダウンロードした ISOイメージ(もしくはそれを書き込んだメディア)からマシンを起動します。
[↑]キーで「Install AlmaLinux 10.0」を選択して、エンターを押します。
GUI画面が表示されたら「日本語 Japanese」「日本語(日本)」を選択して「続行」をクリックします。
下のような表示になるまで少し待ってから「インストール先」をクリックします。
インストール先のハードディスクを選択して、「完了」をクリックします。
ソフトウェアの選択が「最小限のインストール」になっていることを確認してください。(もし違うようでしたら「最小限のインストール」に変更してください)
下にスクロールして「ユーザーの作成」をクリックします。セキュリティ対策のため root アカウントは無効になっていますので、root アカウントの代わりとなる管理者ユーザーを作成しておきましょう。
以下のように入力/選択して「完了」をクリックします。(必ず「このユーザーを管理者にする」にチェックを入れてください)下で入力しているユーザー名はあくまで例です、オリジナルのユーザー名を設定しましょう。
「インストールの開始」をクリックします。パーティションの作成とインストールが開始します。
インストールが完了するまでしばらく待ちます。
インストールが完了したら「システムの再起動」をクリックします。
再起動できない場合やインストーラーが起動してしまう場合は、マシンの電源を一度オフにして、ISOイメージ(もしくはそれを書き込んだメディア)を取り除いてから起動してください。
AlmaLinux 10.0 が起動したら作成した管理者ユーザーでログインします。
この記事では rootユーザーで設定を行うことを前提にしています。これ以降の手順は、管理者ユーザーでログインしたら次のコマンドで rootユーザーになってから実施してください。
sudo -s
※通常の運用時は sudo <コマンド> を利用することをオススメします。
ネットワーク関連の設定は、ご自分の環境に合わせて設定してください。
固定IPアドレスを設定する場合は、nmcli コマンドでNICのコネクション名を確認します。
以下は VirtualBox 仮想マシンの出力例ですが、アダプター1(NAT)はのコネクション名は「enp0s8」、アダプター2(ホストオンリーネットワーク)のコネクション名は「enp0s9」であることが確認できます。(コネクション名に対応するアダプターは ip addr の出力などを参考にして判断してください)
nmcli dev s DEVICE TYPE STATE CONNECTION enp0s8 ethernet connected enp0s8 enp0s9 ethernet connected enp0s9 lo loopback connected (externally) lo
アダプター2(ホストオンリーネットワーク)のコネクション名指定して、固定IPアドレスを設定します。
NICを再起動して設定を反映させます。
以上で、仮想マシンに ssh ログインができるようになります。
DNSサーバを手動で設定する場合は、DHCPによるDNSサーバの自動設定を無効にします。
(以下はアダプター1(NAT)のDNSサーバの設定例です)
DNSサーバを設定し、NetworkManager を再起動します。
DNSサーバが設定されていることを確認します。
ホスト名「alma10」を設定し、hostnamed を再起動します(一度ログアウトしログインすると設定したホスト名が反映されていることを確認できます)
開発ツールなど、基本的なパッケージをインストールしておきます。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
必要がなければ cockpit(Webベースのサーバー管理ツール)を停止します。
・現在の設定の確認
firewall-cmd --list-all
初期設定では publicゾーンの cockpit、dhcpv6-client、ssh サービスが許可されています。
cockpit を使わない場合は、削除しておきましょう。
追加で HTTP(80/tcp) と HTTPS(443/tcp) を許可しておきます
設定を読込みます
・設定を確認します
firewall-cmd --list-all
-----(以下の表示であればOK)-----
タイムゾーンを日本に変更
・参照先のNTPサーバーを変更します。
vi /etc/chrony.conf
chronyd を再起動
自動起動設定
・10分ほど経過したら動作を確認します。
chronyc sources -v
-----(以下のような表示があればOK)-----
時刻があまりにもズレている場合は、dateコマンドで手動で時刻を合わせてください。
サーバーから Gmail 経由でメールを送信できるように設定します。(必要がなければこの設定は不要です)
Postfix をインストールします。
Googleアカウントの設定、および Postfix の設定手順は以下の記事をご参照ください。
PostfixからGmail経由でメールを送信するための設定メモ
メールが送信できることが確認できたら以下を設定します。
自動起動設定
・root宛メールの送信先を変更します
vi /etc/aliases
-----(下記を最終行に追加)-----
メールエイリアスのDBファイルを更新します
root宛のメールが、自分のメールアドレス宛に届くことを確認します
EPEL
Remi
Remi リポジトリから PHP8.4 がインストールされるように php:remi-8.4 モジュールをインストールします。
【補足】
Remi リポジトリからは PHP8.4 以外に 以下のバージョンの PHPモジュールをインストールすることができます。
dnf module list php Remi's Modular repository for Enterprise Linux 10 - aarch64 Name Stream Profiles Summary php remi-7.4 common [d], devel, minimal PHP scripting language php remi-8.0 common [d], devel, minimal PHP scripting language php remi-8.1 common [d], devel, minimal PHP scripting language php remi-8.2 common [d], devel, minimal PHP scripting language php remi-8.3 common [d], devel, minimal PHP scripting language php remi-8.4 [e] common [d] [i], devel, minimal PHP scripting language ヒント: [d]efault, [e]nabled, [x]disabled, [i]nstalled
※バージョンは2025年7月14日時点のものです。
Apache httpd(2.4.63-1)
PHP(8.4.10-1)
MySQL(8.4.4-2)
・PHPの設定
vi /etc/php.ini
php-fpm を自動起動を設定し起動します。
不要なコンフィグを読込まないようにしておきます。
オリジナルのコンフィグをバックアップ
・コンフィグを作成します。
vi /etc/httpd/conf/httpd.conf
Apache httpd の自動起動を設定し起動ます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
SSL設定ファイルのオリジナルをバックアッップします
SSL設定ファイルを作成します。
vi /etc/httpd/conf.d/ssl.conf
Apache httpd を再起動します。
WEBブラウザで HTTPSで接続できることを確認します。
【補足】
自己署名のサーバー証明書の場合は警告が表示され、接続できない場合があります。FireFox で「危険性を承知で続行」ボタンを押して接続するか、Google Chrome の場合は「thisisunsafe」とタイプすると接続できます。
・MySQLの設定ファイルに以下を追加します。
vi /etc/my.cnf.d/mysql-server.cnf
MySQL の自動起動を設定し起動します。
初期状態では、rootユーザーがパスワードなしで MySQLに接続できるようになっていますのでパスワードを設定しておきます。
mysql_secure_installation コマンドを実行すると、root ユーザーのパスワードを変更し、不要なユーザーやDBも削除してくれます。パスワードは、8文字以上で英数大文字小文字と記号が含まれていないとポリシー違反で弾かれてしまいますので注意です。パスワードポリシーを変更したい場合は「--use-default」オプションなしで実行してください。
設定ファイルのバックアップ用ディレクトリを作成しておきます。
オリジナルの設定ファイルをバックアップします
・設定ファイルを作成します
vi /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 apache apache
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示があればOKです)-----
(略) rotating pattern: /var/log/httpd/*log after 1 days empty log files are rotated, (365 rotations), old logs are removed considering log /var/log/httpd/access_log (略)
オリジナルの設定ファイルをバックアップします
・設定ファイルを作成します
vi /etc/logrotate.d/mysqld
/var/log/mysql/*log {
daily
missingok
dateext
rotate 365
sharedscripts
postrotate
/usr/bin/kill -USR1 $(systemctl show --property MainPID --value mysqld)
endscript
}
・確認します
logrotate -v /etc/logrotate.d/mysqld
-----(下記のような表示があればOKです)-----
(略) rotating pattern: /var/log/mysql/*log after 1 days empty log files are rotated, (365 rotations), old logs are removed considering log /var/log/mysql/mysqld.log (略)
systemctl list-unit-files | grep -e httpd.service -e php-fpm.service -e mysqld.service -e chronyd.service -e 'UNIT FILE '
-----(STATE列がすべて「enabled」であればOKです)-----
UNIT FILE STATE PRESET chronyd.service enabled enabled httpd.service enabled disabled mysqld.service enabled disabled php-fpm.service enabled disabled
一度OSを再起動して、各種サービスが起動している事を確認しましょう。
以上です。設定お疲れ様でした!
]]>2024年12月12日、CentOS Stream 10 がリリースされました。約3年ぶりのバージョンアップです。CentOS Stream 10 は、そのダウンストリームにあたる Red Hat Enterprise Linux(RHEL)10 に先駆けて、新機能の追加やバグ修正が行われるのが特徴です。そこで今回は、CentOS Stream 10 における LAMP 構成のインストール手順についてまとめました。
前バージョンからの変更点は以下のリリースノートを参照してください。CentOS Stream 10 では Xorgサーバー、GIMP、LibreOffice、Inkscape、Redis(Valkeyに変更)が削除されています。
次バージョンがリリースされる2030年までサポートされる予定です。正確なサポート期限は RHEL 10 のフルサポートフェーズの終了日になります。
既に EPEL、Remi は CentOS Stream 10 に対応しています。インストール方法は次の通りです。
EPEL は、標準の BaseOSリポジトリからもインストールできますが、公式パーマリンクをインストールすることが推奨されています。(EPELを利用する場合は、CRBリポジトリを有効化する必要があります)
参考資料:Getting started with EPEL
dnf config-manager --set-enabled crb dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm
最新の PHP が利用できる Remiリポジトリは以下のコマンドでインストールできます。(Remiを利用する場合は、EPELリポジトリが必要になります)
参考資料:Repository Configuration - Remi's RPM repository
dnf install https://rpms.remirepo.net/enterprise/remi-release-10.rpm dnf config-manager --set-enabled remi
CentOS Stream のダウンロードページ からインストール先マシンのアーキテクチャに合わせて CentOS Stream 10 の ISOイメージをダウンロードしてください。アーキテクチャは、一般的な Windows PC なら「x86_64」、Appleシリコン搭載の Mac なら「ARM64」になります。
CentOS Stream 10(RHEL 10)を ISOイメージでインストールする場合のシステム要件は次の通りです。詳細は以下の資料をご参照ください。
参考資料:Chapter 1. System requirements and supported architectures | Red Hat Product Documentation
今回は、VirtualBox の仮想マシンに CentOS Stream 10 をインストールします。
VirtualBoxの仮想マシンのタイプに CentOS および RHEL はありませんので「Linux Fedora」を選択してください。
■仮想マシン構成
タイプ:Linux
subtype:Fedora
メモリ:2048MB
HDD:20GB
CPU:2コア
■ネットワーク
アダプター1:NAT
アダプター2:ホストオンリーネットワーク(固定IPアドレスを設定)
■ネットワーク設定(※ご自分の環境に合わせて設定してください)
ホスト名: centos10
固定IPアドレス:192.168.56.201/24
DNSサーバ: 1.1.1.1
DNSサーバ: 8.8.8.8
ダウンロードした ISOイメージ(もしくはそれを書き込んだメディア)からマシンを起動します。
[↑]キーで「Install CentOS Stream 10」を選択して、エンターを押します。
GUI画面が表示されたら「日本語 Japanese」「日本語(日本)」を選択して「続行」をクリックします。
下のような表示になるまで少し待ってから「インストール先」をクリックします。
インストール先のハードディスクを選択して、「完了」をクリックします。
ソフトウェアの選択を「最小限のインストール」に変更します。
下にスクロールして「ユーザーの作成」をクリックします。セキュリティ対策のため root アカウントは無効になっていますので、root アカウントの代わりとなる管理者ユーザーを作成しておきましょう。
以下のように入力/選択して「完了」をクリックします。(必ず「このユーザーを管理者にする」にチェックを入れてください)下で入力しているユーザー名はあくまで例です、オリジナルのユーザー名を設定しましょう。
「インストールの開始」をクリックします。パーティションの作成とインストールが開始します。
インストールが完了するまでしばらく待ちます。
インストールが完了したら「システムの再起動」をクリックします。
再起動できない場合やインストーラーが起動してしまう場合は、マシンの電源を一度オフにして、ISOイメージ(もしくはそれを書き込んだメディア)を取り除いてから起動してください。
CentOS Stream 10 が起動したら作成した管理者ユーザーでログインします。
この記事では rootユーザーで設定を行うことを前提にしています。これ以降の手順は、管理者ユーザーでログインしたら次のコマンドで rootユーザーになってから実施してください。
sudo -s
※通常の運用時は sudo <コマンド> を利用することをオススメします。
ネットワーク関連の設定は、ご自分の環境に合わせて設定してください。
固定IPアドレスを設定する場合は、nmcli コマンドでNICのコネクション名を確認します。
以下は VirtualBox 仮想マシンの出力例ですが、アダプター1(NAT)はのコネクション名は「enp0s8」、アダプター2(ホストオンリーネットワーク)のコネクション名は「enp0s9」であることが確認できます。(コネクション名に対応するアダプターは ip addr の出力などを参考にして判断してください)
nmcli dev s DEVICE TYPE STATE CONNECTION enp0s8 ethernet connected enp0s8 enp0s9 ethernet connected enp0s9 lo loopback connected (externally) lo
アダプター2(ホストオンリーネットワーク)のコネクション名指定して、固定IPアドレスを設定します。
NICを再起動して設定を反映させます。
以上で、仮想マシンに ssh ログインができるようになります。
DNSサーバを手動で設定する場合は、DHCPによるDNSサーバの自動設定を無効にします。
(以下はアダプター1(NAT)のDNSサーバの設定例です)
DNSサーバを設定し、NetworkManager を再起動します。
DNSサーバが設定されていることを確認します。
ホスト名「centos10」を設定し、hostnamed を再起動します(一度ログアウトしログインすると設定したホスト名が反映されていることを確認できます)
開発ツールなど、基本的なパッケージをインストールしておきます。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します
必要がなければ cockpit(Webベースのサーバー管理ツール)を停止します。
・現在の設定の確認
firewall-cmd --list-all
初期設定では publicゾーンの cockpit、dhcpv6-client、ssh サービスが許可されています。
cockpit を使わない場合は、削除しておきましょう。
追加で HTTP(80/tcp) と HTTPS(443/tcp) を許可しておきます
設定を読込みます
・設定を確認します
firewall-cmd --list-all
-----(以下の表示であればOK)-----
タイムゾーンを日本に変更
・参照先のNTPサーバーを変更します。
vi /etc/chrony.conf
chronyd を再起動
自動起動設定
・10分ほど経過したら動作を確認します。
chronyc sources -v
-----(以下のような表示があればOK)-----
時刻があまりにもズレている場合は、dateコマンドで手動で時刻を合わせてください。
サーバーから Gmail 経由でメールを送信できるように設定します。(必要がなければこの設定は不要です)
Postfix をインストールします。
Googleアカウントの設定、および Postfix の設定手順は以下の記事をご参照ください。
PostfixからGmail経由でメールを送信するための設定メモ
メールが送信できることが確認できたら以下を設定します。
自動起動設定
・root宛メールの送信先を変更します
vi /etc/aliases
-----(下記を最終行に追加)-----
メールエイリアスのDBファイルを更新します
root宛のメールが、自分のメールアドレス宛に届くことを確認します
EPEL
Remi
Remi リポジトリから PHP8.4 がインストールされるように php:remi-8.4 モジュールをインストールします。
【補足】
Remi リポジトリからは PHP8.4 以外に 以下のバージョンの PHPモジュールをインストールすることができます。
dnf module list php Remi's Modular repository for Enterprise Linux 10 - aarch64 Name Stream Profiles Summary php remi-7.4 common [d], devel, minimal PHP scripting language php remi-8.0 common [d], devel, minimal PHP scripting language php remi-8.1 common [d], devel, minimal PHP scripting language php remi-8.2 common [d], devel, minimal PHP scripting language php remi-8.3 common [d], devel, minimal PHP scripting language php remi-8.4 [e] common [d] [i], devel, minimal PHP scripting language ヒント: [d]efault, [e]nabled, [x]disabled, [i]nstalled
※バージョンは2025年4月13日時点のものです。
Apache httpd(2.4.63-1)
PHP(8.4.6-1)
MySQL(8.4.2-5)
・PHPの設定
vi /etc/php.ini
php-fpm を自動起動を設定し起動します。
不要なコンフィグを読込まないようにしておきます。
オリジナルのコンフィグをバックアップ
・コンフィグを作成します。
vi /etc/httpd/conf/httpd.conf
Apache httpd の自動起動を設定し起動ます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
SSL設定ファイルのオリジナルをバックアッップします
SSL設定ファイルを作成します。
vi /etc/httpd/conf.d/ssl.conf
Apache httpd を再起動します。
WEBブラウザで HTTPSで接続できることを確認します。
【補足】
自己署名のサーバー証明書の場合は警告が表示され、接続できない場合があります。FireFox で「危険性を承知で続行」ボタンを押して接続するか、Google Chrome の場合は「thisisunsafe」とタイプすると接続できます。
・MySQLの設定ファイルに以下を追加します。
vi /etc/my.cnf.d/mysql-server.cnf
MySQL の自動起動を設定し起動します。
初期状態では、rootユーザーがパスワードなしで MySQLに接続できるようになっていますのでパスワードを設定しておきます。
mysql_secure_installation コマンドを実行すると、root ユーザーのパスワードを変更し、不要なユーザーやDBも削除してくれます。パスワードは、8文字以上で英数大文字小文字と記号が含まれていないとポリシー違反で弾かれてしまいますので注意です。パスワードポリシーを変更したい場合は「--use-default」オプションなしで実行してください。
設定ファイルのバックアップ用ディレクトリを作成しておきます。
オリジナルの設定ファイルをバックアップします
・設定ファイルを作成します
vi /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 apache apache
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示があればOKです)-----
(略) rotating pattern: /var/log/httpd/*log after 1 days empty log files are rotated, (365 rotations), old logs are removed considering log /var/log/httpd/access_log (略)
オリジナルの設定ファイルをバックアップします
・設定ファイルを作成します
vi /etc/logrotate.d/mysqld
/var/log/mysql/*log {
daily
missingok
dateext
rotate 365
sharedscripts
postrotate
if test -x /usr/bin/mysqladmin && \
/usr/bin/mysqladmin --defaults-extra-file=/root/.my.cnf ping &>/dev/null
then
/usr/bin/mysqladmin --defaults-extra-file=/root/.my.cnf flush-logs
fi
endscript
}
・MySQL の root ユーザのパスワードファイルを作成
vi /root/.my.cnf
パスワードを書いているのでパーミッションを変更
・確認します
logrotate -v /etc/logrotate.d/mysqld
-----(下記のような表示があればOKです)-----
(略) rotating pattern: /var/log/mysql/*log after 1 days empty log files are rotated, (365 rotations), old logs are removed considering log /var/log/mysql/mysqld.log (略)
systemctl list-unit-files | grep -e httpd.service -e php-fpm.service -e mysqld.service -e chronyd.service -e 'UNIT FILE '
-----(STATE列がすべて「enabled」であればOKです)-----
UNIT FILE STATE PRESET chronyd.service enabled enabled httpd.service enabled disabled mysqld.service enabled disabled php-fpm.service enabled disabled
一度OSを再起動して、各種サービスが起動している事を確認しましょう。
以上です。設定お疲れ様でした!
]]>前回の記事 #7 では、各ノード間のデータ同期処理を検証するための検証用ノードを構築しました。最終回となる今回 #8 では各ノード間のデータ同期処理の実装を行います。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
【この記事】ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
検証用ノードの構成とIPアドレスは次の通りです。各ノードに保存されている「トランザクションプール」と「ブロックチェーン」が全てのノードで常に同期するように処理を追加します。
データ同期処理は、トランザクションもしくはチェーンを受信して保存したノードが、そのトランザクションもしくはチェーンを全てのノードに送信(ブロードキャスト)する形で実装します。
トランザクションの受信を処理する receiv_tx メソッドと、チェーンの受信を処理する receiv_chain メソッドのそれぞれ引数に broadcast を追加して初期値を on とし、ブロードキャスト処理を追加します。(ブロードキャストの具体的な処理は BlockChain クラスに実装します)
これにより、ノードがトランザクションもしくはチェーンを受信して検証をパスしたら、そのノードはトランザクションもしくはチェーンをブロードキャストしますので、全てのノードのデータが同期されるようになります。
(略) # トランザクションの受信 @app.post('/tx-pool') (↓変更↓) def receiv_tx(tx :Tx): ↓ def receiv_tx(tx :Tx, broadcast :str = 'on'): (↑変更ここまで↑) # データモデルインスタンスを辞書(dict)型に変換 tx_dict = tx.model_dump() # トランザクションの検証 if bc.validate_tx(tx_dict) and bc.validate_duplicate_tx(tx_dict): # 受信したトランザクションをトランザクションプールに追加 bc.add_tx_pool(tx_dict) (↓処理の追加↓) # トランザクションのブロードキャスト if (broadcast == 'on'): bc.broadcast_tx(tx_dict) (↑処理の追加ここまで↑) # 成功のレスポンス return 'ok' else: # 失敗のレスポンス return 'error' (略) # チェーンの受信 @app.post('/chain') (↓変更↓) def receiv_chain(chain :Chain): ↓ def receiv_chain(chain :Chain, broadcast :str = 'on'): (↑変更ここまで↑) # データモデルインスタンスを辞書(dict)型に変換 chain_dict = chain.model_dump() # チェーンの検証 if bc.validate_chain(chain_dict): # チェーンの入替え bc.replace_chain(chain_dict) (↓処理の追加↓) # チェーンのブロードキャスト if (broadcast == 'on'): bc.broadcast_chain(chain_dict) (↑処理の追加ここまで↑) # 成功のレスポンス return 'ok' else: # 失敗のレスポンス return 'error'
ブロードキャストの処理を並列して行うため ThreadPoolExecutor モジュールを使いますのでインポートしておいてください。
(略) (↓モジュールを追加↓) from concurrent.futures import ThreadPoolExecutor class BlockChain: def __init__(self): # ノードのIPアドレス self.node_ips = [ (↓変更↓) '127.0.0.1' ↓ '192.168.56.101', '192.168.56.102', '192.168.56.103' (↑変更ここまで↑) ] (略) (↓メソッドを追加↓) # トランザクションのブロードキャスト def broadcast_tx(self, tx): # マルチスレッドで処理する with ThreadPoolExecutor() as executor: for node_ip in self.node_ips: # ブロードキャストがループしないように broadcast パラメータを off にする url = 'http://' + node_ip + ':8000/tx-pool?broadcast=off' executor.submit(requests.post, url, json.dumps(tx)) (↓メソッドを追加↓) # チェーンのブロードキャスト def broadcast_chain(self, chain): # マルチスレッドで処理する with ThreadPoolExecutor() as executor: for node_ip in self.node_ips: # ブロードキャストがループしないように broadcast パラメータを off にする url = 'http://' + node_ip + ':8000/chain?broadcast=off' executor.submit(requests.post, url, json.dumps(chain))
【コードの要点】
self.node_ips リスト
ノードのIPアドレスを検証用ノードのIPアドレスに変更します。リスト形式で全てのノードのIPアドレスを設定してください。
broadcast_tx メソッド、broadcast_chain メソッド
self.node_ips リストに設定されたIPアドレス宛にブロードキャストを行います。ブロードキャストのループを防ぐため broadcast パラメータに off を指定して、ブロードキャストを受信したノードが再度ブロードキャストしないようにします。
また、自分のノードにもブロードキャストしてしまいますが、検証処理でトランザクションの重複や保持しているチェーンと同じ長さのため弾かれますので問題ありません。
全てのノードで「トランザクションプール」と「ブロックチェーン」の内容が同期していることを確認してください。
また、各ノードのログを表示しながら、トランザクションの送信やマイニングを実行すると同期処理が実行されていることを確認できると思います。ログの出力が処理の順番と異なるため少し分かりづらいのですが、ノードbc02 が受信したトランザクションがブロードキャストされていること、ノードbc03 が受信したチェーンがブロードキャストされていることが確認できます。
bcdmin@bc01:~$ journalctl -u blockchain -f Mar 22 01:12:54 bc01 python[1181]: INFO: 192.168.56.102:57886 - "POST /tx-pool?broadcast=off HTTP/1.1" 200 OK Mar 22 01:13:14 bc01 python[1181]: INFO: 192.168.56.1:61474 - "GET /tx-pool HTTP/1.1" 200 OK Mar 22 01:13:14 bc01 python[1181]: INFO: 192.168.56.103:55964 - "POST /chain?broadcast=off HTTP/1.1" 200 OK
bcdmin@bc02:~$ journalctl -u blockchain -f Mar 22 01:12:54 bc02 python[1153]: トランザクションプールに同じトランザクションがある Mar 22 01:12:54 bc02 python[1153]: INFO: 192.168.56.102:54000 - "POST /tx-pool?broadcast=off HTTP/1.1" 200 OK Mar 22 01:12:54 bc02 python[1153]: INFO: 192.168.56.1:61469 - "POST /tx-pool HTTP/1.1" 200 OK Mar 22 01:13:14 bc02 python[1153]: INFO: 192.168.56.1:61473 - "GET /chain HTTP/1.1" 200 OK Mar 22 01:13:14 bc02 python[1153]: INFO: 192.168.56.103:37890 - "POST /chain?broadcast=off HTTP/1.1" 200 OK
bcdmin@bc03:~$ journalctl -u blockchain -f Mar 22 01:12:54 bc03 python[1211]: INFO: 192.168.56.102:39500 - "POST /tx-pool?broadcast=off HTTP/1.1" 200 OK Mar 22 01:13:14 bc03 python[1211]: 保持しているチェーンより短い Mar 22 01:13:14 bc03 python[1211]: INFO: 192.168.56.103:59336 - "POST /chain?broadcast=off HTTP/1.1" 200 OK Mar 22 01:13:14 bc03 python[1211]: INFO: 192.168.56.1:61475 - "POST /chain HTTP/1.1" 200 OK
以上でブロックチェーンは完成です。おつかれさまでした!!
実際にブロックチェーンとして運用するには、報酬やマイニング難易度の調整などの課題がありますが、ブロックチェーンの仕組みは理解できたのではないでしょうか?
暗号資産だけでなく様々な組織や活動においてブロックチェーンが利用され、分散型の社会が実現されることを心から祈ります。
最後に、ブロックチェーンの作り方(全8回)の記事を書くために参考にさせて頂いた書籍を2冊ご紹介します。
書籍名の通りブロックチェーンを作ってみよう!と思ったきっかけがこの書籍です。ブロックチェーンの仕組みから実装までとても分かりやすく解説してくれていますので、ブロックチェーンについてほとんど知識のない方でも、この1冊があれば実際に動くブロックチェーンを作れると思います。
ブロックチェーンの仕組みについてさらに深く学びたい方にオススメの書籍です。ブロックチェーンの技術的要素だけでなく、非中央集権型システムの考え方や課題、ゲーム理論、ナッシュ均衡、ピザンチン将軍問題など、ブロックチェーンを構成する要素を幅広く解説されています。また、代表的なパブリックブロックチェーンとなるビットコインとイーサリアムの仕組みについても詳しく解説されていますので、本格的なレイヤー1ブロックチェーンを構築する際にも参考になると思います。
前回の記事 #6 まででブロックチェーンの実装がほぼ終わり、残すところ各ノード間のデータ同期処理の実装のみになりました。各ノード間のデータ同期処理を検証するため、実装に先立って検証用のサーバーを何台か用意しておく必要がありますので、今回 #7 ではノード用サーバーの構築手順をまとめてみました。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
【この記事】ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
ノード間のデータ同期の検証を行うことになりますので、サーバーを3台程度用意してください。サーバー本体はオンプレでもクラウドでも構いませんが VitrualBox などの仮想マシンを利用するのが費用もかからず手軽です。
サーバーOSも Python バージョン3 が動けばなんでも構いませんが、この記事では Ubuntu Server 24.04 での構築手順になることをご了承ください。
Python バージョン3がインストールされていることを確認します。
python3 --version Python 3.12.3
Python のパッケージング管理システム pip をインストールします。
sudo apt install python3-pip
続いて必要な Python モジュール(正確には「Python パッケージ」と呼ばれます)をインストールするのですが、モジュールをシステム全体で利用できる領域にインストールする場合、使いたいバージョンのモジュールがインストールできないことがあります。その場合、システム全体で利用するモジュールをアンインストールして、使いたいバージョンのモジュールをインストールすることになるのですが、アンインストールしたモジュールを利用しているツールなどに不具合が発生する可能性があります。
このような問題を解決するために Python には仮想環境という仕組みが用意されていますので、今回はこの Python の仮想環境にブロックチェーンプログラムの実行環境を構築します。
Python 仮想環境の作成や管理を行う venv というツールをインストールします。
sudo apt install python3-venv
ホームディレクトリに仮想環境を作成します。(「venv」というディレクトリが作成されそこに仮想環境が作成されます)
cd ~ python3 -m venv venv
仮想環境を起動します。
source venv/bin/activate
ターミナルの先頭に仮想環境名が表示されていると思います。
(venv)
この状態でブロックチェーンプログラムに必要なモジュールをインストールします。
(venv) pip install ecdsa (venv) pip install pandas (venv) pip install fastapi (venv) pip install uvicorn (venv) pip install requests (venv) pip install pydantic
サーバーにブロックチェーンプログラムをアップロードして実行できることを確認してください。
(venv) python blockchain/node.py INFO: Started server process [2427] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
ブロックチェーンプログラムを実行できることが確認できたら仮想環境を終了してください。
deactivate
続いてノードの起動スクリプト(正確には systemd の「unit file」)を作成します。
事前に仮想環境の python のフルパスを確認しておいてください。
source venv/bin/activate
(venv) which python
/home/bcadmin/venv/bin/python (←仮想環境の python のフルパス)
/etc/systemd/system/ の配下にノードの起動スクリプトを作成します。
[Unit]
Description=blockchain node
After=network.target
[Service]
Type=simple
Restart=always
User=bcadmin
WorkingDirectory=/home/bcadmin
ExecStart=/home/bcadmin/venv/bin/python /home/bcadmin/blockchain/node.py
[Install]
WantedBy=multi-user.target
【起動スクリプトの要点】
User
ノードの実行ユーザーを指定します。今回は bcadmin というユーザーのホームディレクトリにブロックチェーンプログラムを配置し、Python 仮想環境を作成しましたので、そのユーザーを指定しています。
WorkingDirectory
ブロックチェーンプログラムを配置したディレクトリをフルパスで指定します。
ExecStart
事前に調べておいた <仮想環境の python のフルパス> <ノードの実行ファイルのフルパス> の形式で指定してください。
作成した起動スクリプトを systemd に反映させます。
sudo systemctl daemon-reload
systemd に反映していることを確認します。
systemctl list-unit-files | grep blockchain blockchain.service disabled enabled
ノードの自動起動を設定します。
sudo systemctl enable blockchain
ノードを起動します。
sudo systemctl start blockchain
ノードが起動していることを確認してください。
systemctl status blockchain
● blockchain.service - blockchain node
Loaded: loaded (/etc/systemd/system/blockchain.service; enabled; preset: enabled)
Active: active (running) since Sun 2025-03-16 07:40:03 UTC; 2min 46s ago
Main PID: 2679 (python)
Tasks: 1 (limit: 2212)
Memory: 65.9M (peak: 66.2M)
CPU: 692ms
CGroup: /system.slice/blockchain.service
└─2679 /home/bcadmin/venv/bin/python /home/bcadmin/blockchain/node.py
Mar 16 07:40:03 vb14 systemd[1]: Started blockchain.service - blockchain node.
Mar 16 07:40:03 vb14 python[2679]: INFO: Started server process [2679]
Mar 16 07:40:03 vb14 python[2679]: INFO: Waiting for application startup.
Mar 16 07:40:03 vb14 python[2679]: INFO: Application startup complete.
Mar 16 07:40:03 vb14 python[2679]: INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
また、サーバーを再起動してノードが自動起動することも確認しておきましょう。
sudo shutdown -r now
最後にブラウザで「http://<サーバーのIPアドレス>:8000/chain」にアクセスしてチェーンが表示できることを確認してください。(表示できない場合は ufw などのファイアウォールが有効になっている可能性があります)

ノードのログを確認するためによく使いそうなコマンドです。
ノードが起動してからのログを表示
journalctl -u blockchain -b
追記されるログをリアルタイムに表示(tail -f と同じ)
journalctl -u blockchain -f
ログの最後の3行を表示
journalctl -u blockchain -n 3
今回は、データ同期処理を検証するためのノード用サーバーを構築しました。次回は本題の各ノード間のデータ同期処理の実装を行います。
]]>前回ブロックチェーンの作り方 #5 ではブロックチェーンの中核を担うマイニング処理とチェーンの受信処理をを実装しました。今回 #6 ではコインを持っていないユーザーが送金できてしまうという問題の対策として各アカウントの残高チェックを実装していきます。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
【この記事】ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
送信者の残高チェックに必要な処理とメソッドを BlockChain クラスに実装します。
class BlockChain:
(略)
# チェーンの正当性の検証
def verify_chain(self, chain):
(略)
# トランザクションが再利用されていないことをチェック
if tx not in all_block_txs:
all_block_txs.append(tx)
else:
print('トランザクションが再利用されている')
return False
(↓処理を追加↓)
# 各アカウントの残高チェック
if all_block_txs:
# 各アカウントの残高を計算
accounts = self.calc_accounts_balance(all_block_txs)
# 各アカウントの残高のみを取り出す
accounts_values = accounts.values()
# 残高がマイナスになるアカウントがある場合はそのチェーンは不正とする
if min(accounts_values) < 0:
print('残高がマイナスになるアカウントがある')
return False
(↑処理を追加ここまで↑)
# 検証OK
return True
(略)
(↓メソッドを追加↓)
# 各アカウントの残高の計算
def calc_accounts_balance(self, txs):
# 各カウントの残高の入れ物
accounts = {}
# 初期化処理
accounts['reward'] = 0
for tx in txs:
accounts[tx['sender']] = 0
accounts[tx['to']] = 0
# 残高の計算
for tx in txs:
# 送信者の残高を減らす
accounts[tx['sender']] -= int(tx['coin'])
# 受信者の残高を増やす
accounts[tx['to']] += int(tx['coin'])
# 報酬の送金総額は削除する
del accounts['reward']
# 各アカウントの残高を返す
return accounts
【コードの要点】
verify_chain メソッドに各アカウントの残高チェック処理を追加
チェーン上の全てのトランザクションから各アカウントの残高を計算して、残高がマイナスになるアカウントがある場合は不正なチェーンとして処理します。残高の計算は下の calc_accounts_balance メソッドを使います。
calc_accounts_balance メソッド
各アカウント(正確にはブロックチェーンアドレスとなる公開鍵)ごとに所有しているコインの枚数を計算するメソッドです。
確認用に node.py に各アカウントの残高を返す関数を追加します。
(略) # ブロックチェーンインスタンス bc = BlockChain() (略) (↓関数を追加↓) # 各アカウントの残高を返す @app.get('/accounts') def get_accounts(): return bc.calc_accounts_balance(bc.all_block_txs)
node.py を再起動し、ブラウザで「http://127.0.0.1:8000/accounts」にアクセスして各アカウントの残高が表示されることを確認してください。(残高がマイナスのアカウントが表示される場合もあります)
これまでは各アカウントの残高をチェックせずにトランザクションをブロックチェーンに追加していたために残高がマイナスとなっているアカウントがあるかもしれませんので、tx_pool.pkl と chain.pkl を削除して node.py を再起動してください。
rm blockchain/data/tx_pool.pkl rm blockchain/data/chain.pkl
ユーザーAからユーザーBに送金するとユーザーAの残高がマイナスになります。この状態でユーザーCでマイニングしてエラーになることを確認してください。
python blockchain/send_tx.py(ユーザーAからユーザーBに送金) python blockchain/mining.py(ユーザーCでマイニング) mining success. nonce: 26687 hash: 000030f255c11315afcc471265cad7d4d48e720052f5415837bc04e8440c5cad mining time: 0.24599695205688477 second "error"
ノード側では以下のログが表示されていると思います。
INFO: 127.0.0.1:62737 - "GET /tx-pool HTTP/1.1" 200 OK
残高がマイナスになるアカウントがある
最後にマイニング側にもチェーンの検証処理と各アカウントの残高チェックの処理を追加します。ノード側で検証処理を行っているので不要と思われるかもしれませんが、コインを不正に入手するためノード側がトランザクションを偽装している可能性もありますので、マイニング前に検証処理を追加してせっかくマイニングに成功したのに、正規ノードに弾かれてしまうことを防ぎます。
ノードから取得したチェーンが不正な場合は処理を終了させますので冒頭で sys モジュールをインポートします。
from mod.BlockChain import BlockChain from mod.users import users (↓モジュールを追加↓) import time # ブロックチェーンインスタンス bc = BlockChain() # チェーンの取得 chain = bc.get_chain() (↓処理を追加↓) # チェーンを検証 bc.chain['blocks'] = [] # インスタンス内のチェーンを空にする if not bc.validate_chain(chain): sys.exit('取得したチェーンが不正なため処理を終了しました') (↑処理を追加ここまで↑) # 最後のブロックのハッシュ値を生成 last_block = chain['blocks'][-1] last_block_hash = bc.gen_hash(last_block) # ブロックに含めるトランザクション tx_pool = bc.get_tx_pool() target_txs = tx_pool['txs'] (↓処理を追加↓) # 全ブロックのトランザクションリストを作成(残高チェック用) bc.chain = chain bc.set_all_block_txs() all_block_txs = bc.all_block_txs.copy() # 残高がマイナスになるトランザクションは除外する for tx in target_txs.copy(): all_block_txs.append(tx) if min(bc.calc_accounts_balance(all_block_txs).values()) < 0: target_txs.remove(tx) all_block_txs.remove(tx) (↑処理を追加ここまで↑) # マイナーの公開鍵 miner_public_key = users['C']['public_key'] (略)
【コードの要点】
# チェーンを検証
BlockChain クラスの validate_chain メソッドでノードから取得したチェーンの正当性を検証するのですが、ノードから取得したチェーンにジェネシスブロックしか含まれていない場合、インスタンス内のチェーン bc.chain と長さが同じになるため検証で弾かれてしまいます。そのため bc.chain['blocks'] = [] でインスタンス内のチェーンを空にしてからチェーンの検証を行います。
# 残高がマイナスになるトランザクションは除外する
ブロックに含めようとしているトランザクションの送信者の残高がマイナスになる場合は、そのトランザクションをブロックに含めないようにしてマイニングを行います。
今回は、各アカウントの残高の計算とチェックとマイニング側にも検証処理を追加しました。残る実装は各ノード間のデータ同期処理になるのですが、検証用のサーバーを何台か用意しておく必要がありますので、次回はノード用サーバーの準備を行います。
]]>前回ブロックチェーンの作り方 #4 ではジェネシスブロックとチェーンの土台となる部分を実装しました。今回 #5 ではブロックチェーンの中核を担うマイニング処理を実装していきます。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
【この記事】ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
マイニングの方式(「コンセンサスアルゴリズム」と呼ばれます)には大きく分けて PoW(Proof of Work)プルーフ・オブ・ワークと PoS(Proof of Stake)プルーフ・オブ・ステイクがあり、今回は PoW でマイニングを実装します。
PoW は、誰よりも早くマイニングの成功条件を満たすナンスを計算したマイナーがブロックを追加しその対価として報酬を得る方式のため、マイナーは計算能力の高いコンピューターを所有する必要があり、その計算には膨大な電力が必要になります。現在では温室効果ガスの排出削減が求められているため、マイニングに膨大な電力を必要とするビットコインをはじめとする暗号資産は環境負荷の観点から批判されることが多くあります。
一方 PoS は、コイン(暗号資産)の保有量が多いほどブロック追加し報酬を得る確率が高くなる方式のため、膨大な電力は必要無く環境負荷もほとんどありません。(例えばイーサリアムは、2022年9月にマイニングの方式を PoW から PoS に移行し電力を99%以上も削減できたとされています)
今回は、説明を簡単にするためにあえて高い計算能力が必要な PoW でマイニングを実装していますが、本番のブロックチェーンを開発するのであれば PoS もしくは環境負荷の低いコンセンサスアルゴリズムを採用することを強くオススメします。
マイニング処理に必要なメソッドを BlockChain クラスに実装します。hashlib モジュールと time モジュールを使いますので追加でインポートしておきましょう。
(略) (↓モジュールを追加↓) import hashlib import time class BlockChain: def __init__(self): (略) (↓変数を追加↓) # マイニングの報酬 self.reward_coin = 50 # マイニングの難易度(数が多いほど難しくなる) self.difficulty = 4 (略) (↓メソッドを追加↓) # チェーンの取得 def get_chain(self): # ノードのIPアドレス node_ip = self.get_node_ip() # トランザクションプールのURL url = 'http://' + node_ip + ':8000/chain' # 取得実行 res = requests.get(url) # JSONを辞書(dict)型に変換して返す chain_dict = res.json() return chain_dict # ハッシュ値の生成 def gen_hash(self, target_dict): # 対象をJSONに変換してからハッシュ化(辞書型のままだとエラーになる) target_json = json.dumps(target_dict).encode('utf-8') hash = hashlib.sha256(target_json) # ハッシュ値(16進数)を返す return hash.hexdigest() # 報酬用トランザクションの作成 def make_reward_tx(self, miner_public_key): # 報酬用トランザクションを返す return { 'time': time.time(), 'sender': 'reward', 'to': miner_public_key, 'coin': self.reward_coin, 'signature': 'none' } # ナンスの検証 def validate_nonce(self, hash): # ハッシュ値の先頭 self.difficulty 文字が 0 であればマイニング成功(ナンスが正しい)とする if hash[:self.difficulty] == '0' * self.difficulty: return True else: return False # チェーンの送信 def send_chain(self, chain_dict): # ノードのIPアドレス node_ip = self.get_node_ip() # チェーンの送信先URL url = 'http://' + node_ip + ':8000/chain' # チェーンをJSONに変換(辞書型のままでは送信できない) chain_json = json.dumps(chain_dict).encode('utf-8') # 送信 res = requests.post(url, chain_json) # 送信結果を返す return res
【コードの要点】
これらのメソッドは主にマイニングの実行ファイルから利用します。
gen_hash メソッド
ブロックのハッシュ値を生成するためのメソッドです。ハッシュアルゴリズムは SHA-256 を使います。
make_reward_tx メソッド
マイニングの報酬用トランザクションを作成するためのメソッドです。マイニングの報酬となるコインの枚数は self.reward_coin 変数に指定してください。例として報酬コインを50枚に設定していますが、適切なインセンティブになるように調整してください。
また、このメソッドを利用する時に引数 miner_public_key にマイナーの公開鍵を渡して報酬用トランザクションの to に指定します。こうすることで、この報酬用トランザクションがブロックチェーンに追加されれば、マイナーは報酬を得ることになります。報酬の送信者となる sender は、報酬用トランザクションであることを示す「reward」を指定します。トランザクション署名は必要ありませんので signature には「none」を指定します。報酬用トランザクションはトランザクション署名の検証を行いませんので検証エラーになることはありません。
validate_nonce メソッド
PoW(Proof of Work)は、マイニングの成功条件として計算と時間という観点から生成が難しいがその検証は容易となるデータの計算が求められます。具体的には、マイナーは追加するブロックのハッシュ値の先頭文字が指定した数だけ「0」になるナンスを計算します。
例えばハッシュ値の先頭8文字が「0」になるナンスは、ナンスの値を変えて先頭8文字が「0」になるのハッシュ値が見つかるまでひたすら計算するしかありません。一方のその検証は、計算済みのナンスでハッシュ値を1回求めるだけで済みます。ハッシュ値先頭の「0」の数は、難易度を設定する self.difficulty 変数に指定してください。開発中のため「4」を指定していますが、おそらく数秒で計算が終わってしまいますので、実際の運用では適切な難易度になるように調整してください。
マイニングの報酬と難易度の調整はブロックチェーンの実装と運用において最も重要な部分になります。この記事では割愛しますが、マイニングの報酬と難易度は柔軟に調整できるように実装しておくのが良いでしょう。(詳しくは「マイニング難易度調整」などで検索してださい)
マイニングを実行してノードにチェーンを送信するための実行ファイル mining.py を新たに作成します。BlockChain.py と users.py 、time モジュールをインポートしてください。
from mod.BlockChain import BlockChain
from mod.users import users
import time
# ブロックチェーンインスタンス
bc = BlockChain()
# チェーンの取得
chain = bc.get_chain()
# 最後のブロックのハッシュ値を生成
last_block = chain['blocks'][-1]
last_block_hash = bc.gen_hash(last_block)
# ブロックに含めるトランザクション
tx_pool = bc.get_tx_pool()
target_txs = tx_pool['txs']
# マイナーの公開鍵
miner_public_key = users['C']['public_key']
# 報酬用トランザクションを作成
reward_tx = bc.make_reward_tx(miner_public_key)
# ブロックに含めるトランザクションに報酬用トランザクションを追加
target_txs.append(reward_tx)
# ナンスの初期値
nonce = 0
# マイニング処理
mining_start_time = time.time()
while True:
# 新しいブロックを作成
new_block = {
'time': time.time(),
'previous_hash': last_block_hash,
'nonce': nonce,
'txs': target_txs,
}
# 新しいブロックのハッシュ値を生成
new_block_hash = bc.gen_hash(new_block)
# ナンスの検証
if bc.validate_nonce(new_block_hash):
# マイニングが成功したらナンスとハッシュ値とマイニング時間を表示してマイニング処理を終了する
print('mining success.')
print('nonce: ' + str(nonce))
print('hash: ' + new_block_hash)
print('mining time: ' + str(time.time() - mining_start_time) + ' second')
break
else:
# マイニングが失敗している場合はナンスを増やして再度マイニング処理を実行
nonce += 1
# チェーンに新しいブロックを追加
chain['blocks'].append(new_block)
# ノードにチェーンを送信
res = bc.send_chain(chain)
print(res.text)
【コードの要点】
last_block_hash = bc.gen_hash(last_block)
チェーンの最後のブロックのハッシュ値を求めます。これから追加する新しいブロックから見ると「前のブロックのハッシュ値」になりますので、これをマイニング処理で作成する新しいブロック new_block のキー previous_hash に指定します。
target_txs = tx_pool['txs']
ブロックに含めるトランザクションを target_txs にまとめます。今の段階ではトランザクションプール内のすべてのトランザクションを対象にしていますが、不正なトランザクションが混じっている可能性もありますので、次回の記事でトランザクションを検証する処理を追加します。
reward_tx = bc.make_reward_tx(miner_public_key)
マイナーの公開鍵を引数に指定して報酬用トランザクションを作成し、target_txs に追加します。こうすることで、マイニングが成功し報酬用トランザクションを含んだブロックがチェーンに追加されれば、マイナーは報酬を得ることになります。
マイニング処理は whileループの中で新しいブロック new_block を作成し、BlockChain クラスの gen_hash に渡して新しいブロックのハッシュ値を生成します。
次に新しいブロックのハッシュ値を BlockChain クラスの validate_nonce に渡してマイニングが成功したか否かを判定し、マイニングに成功した場合は、成功したナンスの値などの情報を表示して、whileループを抜けてチェーンに新しいブロックを追加してノードに送信します。マイニングに失敗した場合は、ナンスの値に1を加えて再度同じ処理をマイニングに成功するまで繰り返します。
mining.py を実行してマイニングが成功したナンスとハッシュ値、マイニングに要した秒数が表示されることを確認してください。ハッシュ値の先頭文字が指定した数だけ「0」になっていると思います。(ノード側にチェーンの受信処理を実装していませんので、レスポンスとして「Method Not Allowed」が返ってくると思います)
python blockchain/mining.py
mining success.
nonce: 62211
hash: 000017ef7eb448eeccc9547fbdc438cc089d2b080ee0d17fd14bfb211a0880eb
mining time: 0.36821413040161133 second
{"detail":"Method Not Allowed"}
上の例では、1秒以下でマイニングに成功していますが、ハッシュ値の先頭の「0」の数を8文字にすると、CPU が Apple M3 Pro のマシンではマイニングに10時間程度かかっています。
python blockchain/mining.py
mining success.
nonce: 6053757078
hash: 000000009cde2291a4bc77b8531c3f2d063a43e1e6a44960c5e23c32ac039427
mining time: 36141.47594499588 second
{"detail":"Method Not Allowed"}
続いて、ノード側にチェーンの受信処理を追加していきましょう。
今回作成するブロックチェーンでは、新しいブロックも含めて受信したチェーン上のすべてのブロックとトランザクションの正当性を検証し、問題がなければノードに保持しているチェーンを入れ替える形で実装します。
チェーンの受信処理に必要なメソッドを BlockChain クラスに実装します。
(略) class BlockChain: def __init__(self): (略) (↓変数を追加↓) # 全ブロックのトランザクションリスト set_all_block_txs() メソッドでセットする self.all_block_txs = [] (略) # トランザクションの重複チェック(二重支払い問題対策) def validate_duplicate_tx(self, tx): (略) (↓処理を追加↓) # 全ブロックのトランザクションリストに同じトランザクションがないか? if tx in self.all_block_txs: print('全ブロックのトランザクションリストに同じトランザクションがある') return False (略) (↓メソッドを追加↓) # チェーンの正当性の検証 def validate_chain(self, chain): # 保持しているチェーンよりも長いことをチェック if len(self.chain['blocks']) >= len(chain['blocks']): print('保持しているチェーンより短い') return False # ジェネシスブロックが改ざんされていないことをチェック if self.genesis_block != chain['blocks'][0]: print('ジェネシスブロックが改ざんされている') return False # トランザクションの入れ物(全ブロックのトランザクションをここに入れる) all_block_txs = [] # 各ブロックの正当性の検証 for i in range(len(chain['blocks'])): # ジェネシスブロックはチェック済みなので検証をスキップ if i == 0: continue # チェック対象のブロック block = chain['blocks'][i] # 1つ前のブロック previous_block = chain['blocks'][i-1] # 1つ前のブロックのハッシュ値が正しいことをチェック if block['previous_hash'] != self.gen_hash(previous_block): print('1つ前のブロックのハッシュ値に誤りがある') return False # ナンスのチェック block_hash = self.gen_hash(block) if not self.validate_nonce(block_hash): print('ナンスに誤りがある') return False # 報酬用トランザクションの重複チェック用 reward_duplication = False # 各トランザクションの正当性の検証 for tx in block['txs']: # 報酬用のトランザクションのチェック if tx['sender'] == 'reward': # 報酬用のトランザクションが重複チェック if reward_duplication: print('報酬用のトランザクションが重複している') return False else: reward_duplication = True # マイニングの報酬が正しく設定されていることをチェック if tx['coin'] != self.reward_coin: print('マイニングの報酬が誤っている') return False else: # トランザクションの正当性の検証 if not self.validate_tx(tx): print('トランザクションに異常がある') return False # トランザクションが再利用されていないことをチェック if tx not in all_block_txs: all_block_txs.append(tx) else: print('トランザクションが再利用されている') return False # 検証OK return True # チェーンの入替え def replace_chain(self, chain): self.chain = chain # チェーンを入替えたので全ブロックのトランザクションリストを作り直す self.set_all_block_txs() # ブロックに存在するトランザクションはトランザクションプールから削除する for tx in self.all_block_txs: if tx in self.tx_pool['txs']: self.tx_pool['txs'].remove(tx) # トランザクションプールをファイルに保存する self.save_tx_pool() # チェーンをファイルに保存する self.save_chain() # 全ブロックのトランザクションリストの作成 def set_all_block_txs(self): self.all_block_txs = [] for i in range(len(self.chain['blocks'])): block = self.chain['blocks'][i] for tx in block['txs']: self.all_block_txs.append(tx) # チェーンをファイルに保存する def save_chain(self): pd.to_pickle(self.chain, self.chain_file)
【コードの要点】
self.all_block_txs 変数
チェーン上の全てのトランザクションのリストを格納します。ブロックチェーンの作り方 #3 でも少し触れましたが、「二重支払い問題」を解決するためには、”全てのトランザクションが重複していないこと”をチェックする必要があるため、このリストを使ってチェックを行います。全てのトランザクションのリストは set_all_block_txs メソッドで作成します。
validate_duplicate_tx メソッド
チェーンの受信処理ではありませんが、トランザクションの重複チェックに全ブロックのトランザクションリスト self.all_block_txs に対する重複チェック処理を追加しています。この処理の追加により、ノードがトランザクションを受信した次点でトランザクションの重複を排除することができます。
validate_chain メソッド
マイナーから送られてきたチェーン上の全ブロック、全トランザクションの正当性を検証します。ブロックチェーンの信頼性を担う最も重要な処理になります。処理の詳細はコードのコメントをご参照ください。
replace_chain メソッド
チェーンの正当性が確認できたら、ノードに保持しているチェーンを入れ替えて、チェーン上に存在するトランザクション(すなわちマイナーが新しいブロックに含めたトランザクション)は、トランザクションプールから削除します。
node.py に、チェーンの受信処理を追加します。
(略) # ブロックチェーンインスタンス bc = BlockChain() # ノードの起動処理 (略) (↓起動処理を追加↓) bc.set_all_block_txs() # 全ブロックのトランザクションリストの作成 (略) (↓データ定義を追加↓) # ブロックデータの定義 class Block(BaseModel): time: float previous_hash: str nonce: int txs: List[Tx] # チェーンデータの定義 class Chain(BaseModel): blocks: List[Block] (略) (↓関数を追加↓) # チェーンの受信 @app.post('/chain') def receiv_chain(chain :Chain): # データモデルインスタンスを辞書(dict)型に変換 chain_dict = chain.model_dump() # チェーンの検証 if bc.validate_chain(chain_dict): # チェーンの入替え bc.replace_chain(chain_dict) # 成功のレスポンス return 'ok' else: # 失敗のレスポンス return 'error'
【コードの要点】
class Block(BaseModel): class Chain(BaseModel):
pydantic の BaseModel を継承してブロックとチェーンのデータ要素を定義しておきます。
@app.post('/chain')
チェーンを受信するエンドポイントを指定します。エンドポイント名に決まりはありませんが BlockChain クラスの send_chain メソッドのチェーンの送信先URLに対応するようにしてください。この直下の関数 receiv_chain が受信したチェーンを処理します。
node.py を再起動して mining.py を実行してください。レスポンス「ok」が返ってくると思います。
python blockchain/mining.py mining success. nonce: 30012 hash: 0000d83d53530b77a3abc6700526791b3deabb56bd26e4f8d749d2e31ad6cf80 mining time: 0.1790330410003662 second "ok"
ブラウザで「http://127.0.0.1:8000/chain」にアクセスしてブロックが追加されていることを確認してください。
今回は、ブロックチェーン開発の山場となるマイニング処理とチェーンの受信処理を実装しました。チェーンを受信するノード側で受信したチェーン上の全てのブロックと全てのトランザクションの正当性を検証していますが、コインを持っていないユーザーが送金できてしまうという問題がまだ残ります。次回は、各アカウントの残高チェックの処理を実装していきます。
]]>
2025年1月23日 Apache httpd 2.4.63 がリリースされました。約半年ぶりのバージョンアップです。Apache httpd 2.4.63 では mod_md モジュールがアップデートされたほか、各種機能の不具合が改善されています。そこで今回は AlmaLinux8、RockyLinux8、CentOS Stream 9、AlmaLinux9、RockyLinux9 に Apache httpd 2.4.63 をインストールする手順をまとめてみました。
参考資料:Complete ChangeLog for 2.4
Apache httpd や各種ライブラリをソースからコンパイルしますので、パッケージを「最小限のインストール」でインストールしている場合は、基本パッケージと開発ツールをインストールしておきましょう。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
AlmaLinux8、RockyLinux8 など RHEL8系のOSの場合は、OpenSSL 3.0 をインストールします。
OpenSSL のコンパイルに必要なパッケージをインストールしておきます。
OpenSSL 3.0 のダウンロード(ダウンロードの前に OpenSSL 3.0 の最新リリース を確認しておきましょう)
OpenSSL 3.0 のインストール
OpenSSL 3.0 のライブラリにパスを通しておきます。
OpenSSL 3.0 の動作確認(バージョンが表示されればOKです)
/usr/local/openssl-3.0.15/bin/openssl version OpenSSL 3.0.15 3 Sep 2024 (Library: OpenSSL 3.0.15 3 Sep 2024)
HTTP/2(mod_http2)のコアエンジン Nghttp2 をインストールします。
Nghttp2 のダウンロード(ダウンロードの前に Nghttp2の最新リリース を確認しておきましょう)
Nghttp2 のライブラリをコンパイルしてインストールします。
以上で HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib/ 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Brotli のコンパイルに cmake を使いますので、インストールしておきます。
Brotli のダウンロード(ダウンロードの前に Brotliの最新リリース を確認しておきましょう)
Brotli をコンパイルしてインストールします。
Brotli のライブラリが /usr/local/lib64 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Apache httpd のコンパイルに必要なパッケージをインストールしておきます。
また、Apache 2.4系をソースコードからインストールする場合は、APR と APR-util が必要になりますので、インストールしておきます。
本題の Apache httpd のインストールです。
Apache httpd のソースコードのダウンロード
ダウンロードしたソースコードを解凍して、ディレクトリを移動します。
Apache httpd をインストールします。AlmaLinux8、RockyLinux8 など RHEL8系のOSの場合は、「--with-ssl」オプションで OpenSSL 3.0 のインストールディレクトリを指定します。
Apache httpd をインストールします。CentOS Stream 9 および AlmaLinux9、RockyLinux9 など RHEL9系のOSの場合は「--with-ssl」オプションの指定は必要ありません。
以上で Apache が /usr/local/apache2/ 以下にインストールされました。続いてSSLサーバー証明書の作成と、Apacheの設定を行います。
HTTP/2 および Brotli は HTTPS が必須になりますので Apache の設定の前に、SSLサーバー証明書を作成しておきます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
ログの出力先を変更
(補足)Linuxディストリビューションによっては logrotate の設定により /usr 以下に出力されたログがローテーションできないことがありますので /var/log/ 以下に出力することをオススメします。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します(コピペしてください)
vim /usr/local/apache2/conf/httpd.conf
vim /usr/local/apache2/conf/extra/httpd-ssl.conf
Apache httpd 用の systemd ユニットファイル(起動スクリプトのようなもの)を作成します。
vim /etc/systemd/system/httpd.service
作成したサービスファイルを systemd に反映
systemd に反映されているか確認
systemctl list-unit-files | grep httpd httpd.service disabled disabled ←この表示があればOK
起動
自動起動設定
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
firewall-cmd --list-all
・設定ファイルを作成します
vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 daemon daemon
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示であればOKです)-----
以上です。設定お疲れ様でした!
]]>ブロックチェーンの作り方 #2 と #3 で、トランザクションの送受信と検証処理がほぼ完成しました。今回 #4 では、ブロックチェーンのジェネシスブロックとチェーン部分を実装していきます。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
【この記事】ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
ブロックチェーンは、複数のトランザクションを含んだブロックがチェーンのようにつながりブロックチェーンを構成します。(詳しくは、ブロックチェーンの作り方 #1 の「今回作成するブロックチェーンの構造」)をご参照ください)
各ブロックはマイナーが作成して追加していくのですが、一番先頭のブロックは「ジェネシスブロック」と呼ばれプログラムにハードコーディングする特別なブロックですので、今回はジェネシスブロックのみが登録されたチェーンの読み出しができるところまでを実装します。
BlockChain クラスにジェネシスブロックをハードコーディングしてチェーンに追加し、チェーンの読出し処理を実装します。
(略) class BlockChain: def __init__(self): (略) (↓変数を追加↓) # ジェネシスブロック self.genesis_block = { 'time': 1736575754.072457, 'previous_hash': 'none', 'nonce': 0, 'txs': [] } # チェーン self.chain = {'blocks': []} self.chain['blocks'].append(self.genesis_block) # チェーンの保存先 self.chain_file = './blockchain/data/chain.pkl' (略) (↓メソッドを追加↓) # ファイルに保存されているチェーンを読み出す def load_chain(self): if os.path.isfile(self.chain_file): return pd.read_pickle(self.chain_file) else: # ファイルが無ければ初期状態のチェーンを返す return self.chain
【コードの要点】
ジェネシスブロック self.genesis_block の各キーに指定している値の補足です。txs 以外の値には特に決まりはありませんので、適当な値を指定してください。
time ジェネシスブロックをハードコーディングした時間をUNIX時間で指定しています。
previous_hash 前のブロックのハッシュ値はありませんので「none」を指定しています。
nonce マイニングの成功条件を満たすための値ですがマイニングをしていないため「0」を指定しています。
txs 空のリスト「[]」を指定してください。
self.chain_file 変数
まだチェーンの保存処理は実装しませんが、下の load_chain メソッドでチェーンを読み出す際に参照するため追加しておきます。実行ファイルを実行する時のカレントディレクトリからの相対パスで指定してください。ファイルパスを ./blockchain/data/chain.pkl とした場合は python blockchain/node.py のように実行する必要があります。
node.py のノードの起動処理にチェーンの読出しを追加して、チェーンを返す関数を追加します。
(略) # ブロックチェーンインスタンス bc = BlockChain() # ノードの起動処理 bc.tx_pool = bc.load_tx_pool() # トランザクションプールの読出し (↓起動処理を追加↓) bc.chain = bc.load_chain() # チェーンの読出し (略) (↓関数を追加↓) # チェーンを返す @app.get('/chain') def get_chain(): return bc.chain
【コードの要点】
@app.get('/chain')
このエンドポイントにGETでリクエストすると、直下の関数 get_chain が実行されチェーンを返します。今の段階では動作確認用に使いますが、後ほどマイニングを実装する時にこのエンドポイントを使います。
node.py を実行します。
python blockchain/node.py
ブラウザで「http://127.0.0.1:8000/chain」にアクセスしてジェネシスブロックが表示されることを確認してください。
今回は、ジェネシスブロックとチェーン部分を実装しました。次回はブロックチェーンの中核となるマイニング処理を実装していきます。
]]>前回 ブロックチェーンの作り方 #2 では、トランザクションの送信とノード側での受信処理を実装しました。#1でも書きましたが、ブロックチェーンのノードは、他のノードや利用者を一切信用できず不正にコインを手に入れようとしてくることを前提にプログラムを実装しなければなりません。そのためトランザクションの処理についても不正なトランザクションをトランザクションプールに登録させないように、しっかり検証する必要があります。今回 #3 では、ノード側のプログラムにトランザクションの検証処理を追加していきましょう。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
【この記事】ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
トランザクションの正当性を検証するための処理を追加します。トランザクションのデータ型チェックは pydantic に任せられますので、以下の検証処理を追加します。
BlockChain クラスに validate_tx メソッドを追加してこのメソッドに検証処理を実装します。
(略) class BlockChain: (略) (↓メソッドを追加↓) # トランザクションの正当性の検証 def validate_tx(self, tx): # トランザクションのコピー(値渡し)で検証を行う tx_copy = tx.copy() # マイナスのコインは許可しない if (tx_copy['coin'] < 0): print('コインの枚数がマイナス') return False # 送信者の公開鍵をオブジェクト化 public_key_obj = VerifyingKey.from_string(binascii.unhexlify(tx_copy['sender']), curve=SECP256k1) # トランザクションから署名を取出す signature = binascii.unhexlify(tx_copy['signature']) del tx_copy['signature'] # トランザクションをJSONに変換 tx_json = json.dumps(tx_copy).encode('utf-8') # トランザクション署名の検証 try: return public_key_obj.verify(signature, tx_json) except BadSignatureError: print('トランザクションの署名が不正') return False
【コードの要点】
tx_copy = tx.copy()
普段から Python を扱っている方には説明不要かと思いますが tx は辞書型のため、参照の引渡しとなります。そのまま tx の値をいじってしまうと参照元の tx にも影響があるため、トランザクションをコピー(値渡し)して、コピーした tx_copy に対して検証を行います。
トランザクション署名の検証は、トランザクションから署名を削除し、JSONに変換したトランザクションに対して行ってください。
続いていわゆる「二重支払い問題」を解決するため、トランザクションの重複チェックの処理を追加します。
余談ですが、ブロックチェーンの概念となっているサトシナカモトの論文ですが、実はこの二重支払い問題の解決策の提案が本題になっています。
概要 完全な P2P 電子通貨の実現により、金融機関の介在無しに、利用者同士の直接的なオンライン決済が可能となるだろう。電子署名により、P2P 電子通貨の機能の一部は実現可能であるが、その機能の主な利点は、信用が置ける第三者機関が二重支払いを防ぐために必要とされる場合、失われることとなる。本論文では、P2P ネットワークの使用による、二重支払い問題の解決策を提案する。(略)
ビットコイン: P2P 電子通貨システム(日本語)より引用
そしてその解決策は実にシンプルで「全トランザクションを監視する事である」とされています。これを実装するにはブロックチェーンに格納されている全てのトランザクションと、ブロックチェーンに追加しようとしているトランザクションを比較し重複していないことをチェックする必要があります。
まだチェーン部分を実装していませんので、今の段階ではトランザクションプールに重複したトランザクションが無いことをチェックします。BlockChain クラスに validate_duplicate_tx メソッドを追加してこのメソッドに重複チェックの処理を実装していきます。
(略) class BlockChain: (略) (↓メソッドを追加↓) # トランザクションの重複チェック(二重支払い問題対策) def validate_duplicate_tx(self, tx): # トランザクションプールに同じトランザクションがないか? if tx in self.tx_pool['txs']: print('トランザクションプールに同じトランザクションがある') return False # チェックOK return True
【コードの要点】
特に難しい処理はありません。コメントの通りトランザクションプールに同じトランザクションがないかをチェックしているのみです。
追加した検証用のメソッドを実行ファイル node.py に実装していきましょう。
受信したトランザクションをトランザクションプールに追加する前に、トランザクションの検証処理を追加して検証NGの場合は失敗のレスポンスを返すようにします。
(略) # トランザクションの受信 @app.post('/tx-pool') def receiv_tx(tx :Tx): # データモデルインスタンスを辞書(dict)型に変換 tx_dict = tx.model_dump() (↓処理の追加↓) # トランザクションの検証 if bc.validate_tx(tx_dict) and bc.validate_duplicate_tx(tx_dict): # 受信したトランザクションをトランザクションプールに追加 bc.add_tx_pool(tx_dict) # 成功のレスポンス return 'ok' else: # 失敗のレスポンス return 'error'
send_tx.py を以下のように変更して、それぞれのトランザクション検証処理が正しく動作していることを確認してください。
トランザクションの重複チェックについては、テスト用の実行ファイル duplicate_tx.py を作成して確認します。
BlockChain クラスにトランザクションプールを取得するためのメソッド get_tx_pool を追加します。(後ほどマイニングの処理でもこのメソッドを使います)
(略) class BlockChain: (略) (↓メソッドを追加↓) # トランザクションプールの取得 def get_tx_pool(self): # ノードのIPアドレス node_ip = self.get_node_ip() # トランザクションプールのURL url = 'http://' + node_ip + ':8000/tx-pool' # 取得実行 res = requests.get(url) # JSONを辞書(dict)型に変換して返す tx_pool_dict = res.json() return tx_pool_dict
テスト用の実行ファイル duplicate_tx.py を作成します。
from mod.BlockChain import BlockChain # ブロックチェーンインスタンス bc = BlockChain() # トランザクションプールを取得 tx_pool = bc.get_tx_pool() # 先頭のトランザクションを送信(トランザクションを重複させる) res = bc.send_tx(tx_pool['txs'][0]) print(res.text)
duplicate_tx.py を実行して「error」と表示されることを確認してください。
python blockchain/duplicate_tx.py "error"
node.py 側では以下のログが出力されるはずです。
INFO: 127.0.0.1:57098 - "GET /tx-pool HTTP/1.1" 200 OK
トランザクションプールに同じトランザクションがある
INFO: 127.0.0.1:57099 - "POST /tx-pool HTTP/1.1" 200 OK
今回は、ノード側で受信したトランザクションを検証する処理を実装しました。次回はジェネシスブロックとチェーンを実装していきます。
]]>前回 ブロックチェーンの作り方#1 では、今回作成するブロックチェーンの概要と Python でブロックチェーンを作成するための開発環境の準備について説明しました。今回 #2 では、ブロックチェーンに格納されるトランザクションの処理を実装します。具体的には、利用者がトランザクションを送信するためのプログラムと、ノード側でトランザクションを受信しトランザクションプールに保存するプログラムを作成します。
ブロックチェーンの作り方 #1(概要と開発環境の準備)
【この記事】ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
ブロックチェーンの利用者は個別に秘密鍵と公開鍵のペアを持つ必要があります。秘密鍵はトランザクションに署名を行うために利用し、公開鍵はブロックチェーンアドレスとして利用します。
作成の手順はまず秘密鍵を作成し、その秘密鍵から公開鍵を作成します。作成する秘密鍵は暗号化方式によって色々な種類があるのですが、今回は楕円曲線暗号(ECDSA:Elliptic Curve Digital Signature Algorithm)を使い楕円曲線は secp256k1 を採用します。(ビットコインやイーサリアムでもこの楕円曲線暗号と楕円曲線が使われています)
Python で楕円曲線暗号方式の秘密鍵と公開鍵の作成を実装すると以下のようなプログラムになります。ecdsa モジュールを使いますので事前にインストールしておきましょう。
from ecdsa import SigningKey, SECP256k1
secret_key = SigningKey.generate(curve = SECP256k1)
print("秘密鍵:" + secret_key.to_string().hex())
public_key = secret_key.verifying_key
print("公開鍵:" + public_key.to_string().hex())
コードを実行して秘密鍵と公開鍵が表示されることを確認してください。
python blockchain/tool/gen_key.py 秘密鍵:<実際には秘密鍵が表示されます> 公開鍵:30ccdd8209ff3d9fb8a4b08d2f5d20e66af2650db26a470287372691e9a7c4c97e52bf8af7b6c1c9698eaee822bc794d48fb1526a9a3d2d1c249e365f0fc9157
これは説明の都合になりますが、トランザクションの送信処理などで使う検証用ユーザーの秘密鍵と公開鍵は users.py にまとめておいて各実行ファイルにインポートして利用することとします。
先ほど作成した gen_key.py で各検証用ユーザーの秘密鍵と公開鍵と作成して、秘密鍵は private_key に、公開鍵は public_key に設定してください。
users = {
# Aさんの秘密鍵と公開鍵
'A': {
'private_key': '<Aさんの秘密鍵>',
'public_key': '<Aさんの公開鍵>'
},
# Bさんの秘密鍵と公開鍵
'B': {
'private_key': '<Bさんの秘密鍵>',
'public_key': '<Bさんの公開鍵>'
},
# Cさんの秘密鍵と公開鍵
'C': {
'private_key': '<Cさんの秘密鍵>',
'public_key': '<Cさんの公開鍵>'
}
}
下準備ができたところで、本題のトランザクションを処理するためのプログラムを作成していきましょう。
まずは、利用者がトランザクションを送信するためのプログラムを作成します。この記事では、ブロックチェーンのコアとなる機能を BlockChain.py に実装し、実行ファイルにインポートする形でプログラムを作成していきます。requests モジュールを使いますので事前にインストールしておきましょう。
BlockChain.py ファイルを作成して、ブロックチェーンのコア機能を実装するための BlockChain クラスを定義して必要な機能を実装していきます。
import random
from ecdsa import SECP256k1, SigningKey, VerifyingKey, BadSignatureError
import binascii
import json
import requests
# ブロックチェーンのコア機能を実装するためのクラス
class BlockChain:
def __init__(self):
# ノードのIPアドレス
self.node_ips = [
'127.0.0.1'
]
# ノードのアドレスをどれか1つ返す
def get_node_ip(self):
return random.choice(self.node_ips)
# 署名の生成
def gen_signature(self, target_dict, private_key):
# 秘密鍵をオブジェクト化
private_key_obj = SigningKey.from_string(binascii.unhexlify(private_key), curve=SECP256k1)
# 署名対象をJSONに変換してから署名(辞書型のままでは署名できない)
target_json = json.dumps(target_dict).encode('utf-8')
signature = private_key_obj.sign(target_json)
# 署名(16進数)を返す
return signature.hex()
# トランザクションの送信
def send_tx(self, tx_dict):
# ノードのIPアドレス
node_ip = self.get_node_ip()
# トランザクションの送信先URL
url = 'http://' + node_ip + ':8000/tx-pool'
# トランザクションをJSONに変換(辞書型のままでは送信できない)
tx_json = json.dumps(tx_dict).encode('utf-8')
# 送信
res = requests.post(url, tx_json)
# 送信結果を返す
return res
ecdsa モジュールの VerifyingKey と BadSignatureError は、今の段階では使いませんが後々使いますのでインポートしておいてください。
self.node_ips 変数
ノードのIPアドレスをリストで指定します。開発段階ではノード側のプログラムも同じパソコンで動作確認を行いますので、今の段階ではローカルループバックアドレスの「127.0.0.1」を1つのみ指定しておきます。
get_node_ip メソッド
self.node_ips 変数に指定されたノードのIPアドレスうち1つをランダムに返します。
gen_signature メソッド
トランザクション署名を作成するためのメソッドです。引数 target_dict にトランザクションを辞書型(dict型)で指定し、引数 private_key に送信者の秘密鍵を指定することで、target_dict に指定されたトランザクションデータの署名を作成して返します。
send_tx メソッド
トランザクションをノードに送信するためのメソッドです。引数 tx_dict に指定された署名付きのトランザクションをノードの指定されたエンドポイントに送信します。
send_tx.py は、トランザクションを作成して送信するための実行ファイルです。作成した users.py と BlockChain.py をインポートしてください。また、トランザクションの作成に使いますので time モジュールもインポートしておきましょう。
from mod.BlockChain import BlockChain
from mod.users import users
import time
# ブロックチェーンインスタンス
bc = BlockChain()
# トランザクションの作成
tx = {
'time': time.time(),
'sender': users['A']['public_key'],
'to': users['B']['public_key'],
'coin': 3
}
# トランザクション署名の追加
tx['signature'] = bc.gen_signature(tx, users['A']['private_key'])
# 送信
res = bc.send_tx(tx)
print(res.text)
トランザクション tx の各キーに指定する値は次の通りです。
time UNIX時間(1970年1月1日午前0時0分0秒からの経過秒数)を指定します。
sender 送信者の公開鍵を指定します。
to 受信者の公開鍵を指定します。
coin 送信するコインの枚数を指定します。コインの枚数は整数のみとしマイナスは許可しないものとします。
signature 上記4つのキーを指定したトランザクション tx と送信者の秘密鍵を BlockChain クラスの gen_signature メソッドに渡して、作成されたトランザクション署名を指定します。
完成した署名付きのトランザクションを BlockChain クラスの send_tx メソッドに渡して実行すれば、ノードの指定されたエンドポイントにトランザクションが送信されます。
今の段階ではノードが起動していない状態ですので send_tx.py を実行してもエラーになります。
python blockchain/send_tx.py (略) ConnectionRefusedError: [Errno 61] Connection refused
続いて、ノード側で実行するトランザクションを受信するためのプログラムを作成していきましょう。
とりあえずトランザクションを受信して表示するだけのプログラムを作成して、順を追って処理を追加していきます。Python での Web API 構築フレームワークの定番 fastapi モジュールとデータ検証を行う pydantic モジュール、ASGI Webサーバーとして uvicorn モジュールを使いますので事前にインストールしておきましょう。
from mod.BlockChain import BlockChain
from fastapi import FastAPI
from pydantic import BaseModel
import uvicorn
# FastAPIインスタンス
app = FastAPI()
# ブロックチェーンインスタンス
bc = BlockChain()
# トランザクションデータの定義
class Tx(BaseModel):
time: float
sender: str
to: str
coin: int
signature: str
# (仮)トランザクションの受信
@app.post('/tx-pool')
def receiv_tx(tx :Tx):
print(tx)
return 'ok'
# Webサーバー起動
if __name__ == '__main__':
uvicorn.run('node:app', host='0.0.0.0', port=8000)
【コードの要点】
class Tx(BaseModel):
pydantic の BaseModel を継承してトランザクションデータを定義しておきます。(fastapi は pydantic に依存しているため、受信するデータの定義が必須になります)
@app.post('/tx-pool')
トランザクションを受信するエンドポイントを指定します。エンドポイント名に決まりはありませんが BlockChain クラスの send_tx メソッドの送信先URLに対応するようにしてください。この直下の関数 receiv_tx が受信したトランザクションを処理しますので、とりあえトランザクションを表示し、レスポンスとして「ok」の文字列を返すようにしておきます。
uvicorn.run('node:app', host='0.0.0.0', port=8000)
待ち受けポート「8000」で ASGI Webサーバーを起動します。待ち受けポートに決まりはありませんが、こちらも BlockChain クラスの send_tx メソッドの送信先URLに対応するようにしてください。
node.py を実行して以下のような表示になればトランザクションを受信できる状態です。
python blockchain/node.py INFO: Started server process [10899] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
この状態で send_tx.py を実行すると、先ほどのようなエラーは発生せず「ok」の文字列が表示されるはずです。
python blockchain/send_tx.py "ok"
node.py 側では受信したトランザクションが表示されていると思います。
python blockchain/node.py
(略)
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
time=1734163524.491963 sender='f4561c9d3d2d12f62577024408f0cc40e238ef78b1b4611b80b32792e2c72a5bd1d12c4b99a47a2f2a1fefe445ec27cc69aa22b6d337655412fb3a8511079328' to='0b0150759100ba4b73fab109f76139d4ec3499c57bbf747244d603b972651ad22136720800da22a120baeb42516494bf89fcd88325be28e59309fe0857f7ea2a' coin=3 signature='ac9a19e3a69e672426a3a29c23aabe56788c1c38684ee439a3a5489e8601249b8b64f8da21ec8d8896548e910171465196a18f1625ab0
INFO: 127.0.0.1:52469 - "POST /tx-pool HTTP/1.1" 200 OK
受信したトランザクションをトランザクションプールに保存するための処理を追加します。
トランザクションプールの処理に pandas モジュールと os モジュールを使いますので BlockChain.py の冒頭でインポートし、以下の変数とメソッドを追加します。
また、blockchain ディレクトリの下に data ディレクトリを作成してください。ここにトランザクションプールを保存します。
(↓モジュールを追加↓) import pandas as pd import os class BlockChain: def __init__(self): (↓変数を追加↓) # トランザクションプール self.tx_pool = {'txs': []} # トランザクションプールの保存先 self.tx_pool_file = './blockchain/data/tx_pool.pkl' (↓メソッドを追加↓) # トランザクションプールをファイルに保存する def save_tx_pool(self): pd.to_pickle(self.tx_pool, self.tx_pool_file) # 受取ったトランザクションをトランザクションプールに追加する def add_tx_pool(self, tx): self.tx_pool['txs'].append(tx) # トランザクションプールをファイルに保存する self.save_tx_pool() # ファイルに保存されているトランザクションプールを読み出す def load_tx_pool(self): if os.path.isfile(self.tx_pool_file): return pd.read_pickle(self.tx_pool_file) else: # ファイルが無ければ初期状態のトランザクションプールを返す return self.tx_pool
【コードの要点】
self.tx_pool_file 変数
トランザクションプールの保存先のファイルパスを指定します。実行ファイルを実行する時のカレントディレクトリからの相対パスで指定してください。ファイルパスを ./blockchain/data/tx_pool.pkl とした場合は python blockchain/node.py のように実行する必要があります。
node.py に受信したトランザクションをトランザクションプールに保存するための処理を追加していきます。また、確認用にトランザクションプールを返す関数も追加しておきましょう。
(略) # ブロックチェーンインスタンス bc = BlockChain() (↓起動処理を追加↓) # ノードの起動処理 bc.tx_pool = bc.load_tx_pool() # トランザクションプールの読出し (↓関数を追加↓) # トランザクションプールを返す @app.get('/tx-pool') def get_tx_pool(): return bc.tx_pool (↓処理を追加↓) # トランザクションの受信 @app.post('/tx-pool') def receiv_tx(tx :Tx): # データモデルインスタンスを辞書(dict)型に変換 tx_dict = tx.model_dump() # 受信したトランザクションをトランザクションプールに追加 bc.add_tx_pool(tx_dict) # レスポンス return 'ok'
【コードの要点】
bc.tx_pool = bc.load_tx_pool()
ノードの起動処理として、BlockChain クラスの load_tx_pool メソッドを実行してファイルに保存されているトランザクションプールを読出し、インスタンス変数 tx_pool にセットします。
@app.get('/tx-pool')
このエンドポイントにGETでリクエストすると、直下の関数 get_tx_pool が実行されトランザクションプールを返します。今の段階では動作確認用に使いますが、後ほどマイニングを実装する時にこのエンドポイントを使います。
トランザクションを送信します。
python blockchain/send_tx.py
ブラウザで「http://127.0.0.1:8000/tx-pool」にアクセスしてトランザクションプールが表示されることを確認してください。
また、node.py を再起動(実行を停止して再度実行)して、トランザクションプールが保持されていることも確認しておきましょう。
今回は、利用者がトランザクションを送信し、それをノード側で受信してトランザクションプールに保存するところまでを実装しました。しかし、このままでは利用者が不正なトランザクションを送信したとしても、無条件でトランザクションプールに登録されてしまいますので、次回はトランザクションの検証処理を実装していきます。
]]>ある日突然、iPhone の LINE の写真ライブラリへのアクセス権が「なし」か「写真の追加のみ」になってしまい、LINE から写真が送信できなくなってしまいました。通常であれば写真ライブラリへのアクセス権はこの他に「制限付きアクセス」と「フルアクセス」が表示されるはずなのですが、どこをどういじっても表示されません、、そこで今回は、LINEのアクセス権が「写真の追加のみ」になってしまった場合に、手っ取り早く LINE で写真を送信する方法をまとめてみました。
LINEのアクセス権が「なし」や「写真の追加のみ」だとしても、写真アプリから送信したい写真を選択し、「共有 → LINE → 送信先」を選択して「転送」をタップすれば LINE で写真を送信できます。
写真アプリから送信したい写真を選択して「共有」アイコンをタップします。

LINE の送信先(LINEで言うところのトークの相手)を選択して「転送」をタップすれば、LINE で写真が送信されます。

根本的に対処するには LINEアプリの再インストールなどが必要になるようですが、手っ取り早く LINE で写真を送信したい場合などにご活用ください。
]]>ブロックチェーンとは「分散型台帳技術」とも呼ばれ、中央の管理者なしに、P2Pネットワークで暗号資産やNFTなど「価値」の取引を可能にするための仕組みです。2008年にサトシナカモトという正体不明の人物(もしくは組織)によって、ビットコイン(P2P電子通貨システム)を実現するために発明されました。最近では暗号資産だけではなくブロックチェーンを活用したゲームやシステムを見かけることも多くなりましたね。そこで今回は、Python で簡単なブロックチェーンを実装する流れを全8回の記事に分けてまとめてみました。
【この記事】ブロックチェーンの作り方 #1(概要と開発環境の準備)
ブロックチェーンの作り方 #2(トランザクションの送受信)
ブロックチェーンの作り方 #3(トランザクションの検証)
ブロックチェーンの作り方 #4(ジェネシスブロックとチェーンの実装)
ブロックチェーンの作り方 #5(マイニング処理)
ブロックチェーンの作り方 #6(各アカウントの残高チェック)
ブロックチェーンの作り方 #7(ノード用サーバーの準備)
ブロックチェーンの作り方 #8(データ同期処理)
完成したブロックチェーンのソースコード
ブロックチェーンの概念となるサトシナカモトの原論文「Bitcoin: A Peer-to-Peer Electronic Cash System」は、各言語に翻訳されたものが以下のページで読むことができます。ブロックチェーンによってどのような課題を解決するのか、それはどのように実現するのかなどが約10ページの論文に簡潔にまとめられていますので、一度読んでおくことをオススメします。
ビットコイン: P2P電子通貨システム
また、ブロックチェーンの実装となるビットコインのコードはGitHubで公開されています。本格的なブロックチェーンを開発する場合は参考になるでしょう。
https://github.com/bitcoin/bitcoin
今回作成するブロックチェーンは、下図のようなシンプルなブロックチェーンです。
ブロックチェーンの先頭は「ジェネシスブロック」と呼ばれる特別なブロックです。続いて複数のトランザクション(これがデータ部分です)を含んだブロックがチェーンのようにつながりブロックチェーンを構成します。各ブロックには前のブロックのハッシュ値が格納されていますので、これを使ってブロックが改ざんされていないことを検証することができます。仮に1,000ブロックあるブロックチェーンに保存されているトランザクションがどれか1つでも改ざんされていれば、少なくとも最後のブロックのハッシュ値は変わりますので、これにより改ざんが検知されそのブロックチェーンが不正なものであることが分かります。
ブロックの構造は次の通りです。データ部分となる複数のトランザクション以外の要素をまとめて「ブロックヘッダー」と呼びます。また、ブロックヘッダーには「マークル・ルート」と呼ばれるトランザクションの検索を効率的に行うための要素を含むことがありますが、今回作成するブロックチェーンでは割愛しています。
| 要素 | 内容 |
|---|---|
| タイムスタンプ | ブロックを作成した時点のUNIX時間です。 |
| 前のブロックのハッシュ値 | 1つ前のブロック全体をハッシュ化した値です。今回作成するブロックチェーンではハッシュ化アルゴリズムにSHA-256を使います。 |
| ナンス | マイニングの成功条件を満たすための値です。 |
| 複数のトランザクション | 複数のトランザクションをリスト形式で格納します。 |
ブロックに格納されるトランザクションの構造は次の通りです。トランザクションについても送信者から受信者へコインを送金するだけのシンプルなものです。トランザクションの匿名性を高めたい場合は、トランザクション毎に新しい鍵のペア(公開鍵と秘密鍵)を用いるなどの工夫が必要なことに留意してください。
| 要素 | 内容 |
|---|---|
| タイムスタンプ | トランザクションを作成した時点のUNIX時間です。 |
| 送信者の公開鍵(アドレス) | 送信者の公開鍵をそのまま送信者のアドレスとします。今回は説明を簡単にするために公開鍵をそのままアドレスにしていますが、例えばビットコインでは公開鍵を二重にハッシュ化しBase58でエンコードしたものをアドレスにしています。 |
| 受信者の公開鍵(アドレス) | 上記と同じく受信者の公開鍵をそのまま受信者のアドレスとします。 |
| コインの枚数 | 送信するコインの枚数です。コインの枚数は整数のみとしマイナスは許可しないものとします。 |
| トランザクション署名 | トランザクション(具体的には上記4つの要素)に対して送信者の秘密鍵でに署名します。この署名を検証することにより送信者のなりすましやトランザクションが改ざんされていないことを証明できます。 |
今回作成するブロックチェーンを構成するためのノードと登場人物は次の図の通りです。
(補足)「ノード」はサーバーと呼んでも差し支えないのですが、P2Pネットワークではサーバーとクライアントという区別がないため、この記事でもブロックチェーンを構成するコンピュータのことを「ノード」と表記します。
各ノードは「トランザクションプール」と「ブロックチェーン」の2つのデータを持ち、そのデータはすべてのノードで同期しています。
| 要素 | 内容 |
|---|---|
| トランザクションプール | 利用者から送られてくるトランザクションを一時的に保管しておく場所です。トランザクションがトランザクションプールに登録されただけでは送金は完了せず、マイナーがトランザクションプールからトランザクションを取り出し、そのトランザクションを含んだブロックをチェーンに追加することで、そのトランザクションが承認され送金完了となります。 |
| ブロックチェーン | ブロックチェーン本体のデータです。上の説明の通りマイナーによって更新されます。 |
上の図では、中央のノードに対して利用者とマイナーがデータの更新を行なっていますが、そのデータは他のノードにも反映されます。ゆえに、利用者とマイナーはどのノードに対してデータの更新を行なっても問題ないとご理解ください。また、ビットコインなど実際のブロックチェーンではマイナー(マニイニングしてブロックを追加する人)がノードを管理することもあるのですが、この記事ではマイナーはマイニングのみを行う役割とします。
トランザクションの登録からブロックの追加されるまでのおおまかな処理の流れは次の通りです。
| No | 処理 |
|---|---|
| ① | 利用者はトランザクションを作成し、トランザクションプールに登録します。 |
| ② | マイナーは、ノードからトランザクションとブロックチェーンをダウンロードします。 |
| ③ | マイナーは、ダウンロードしたトランザクションおよび自分への報酬のトランザクションを含んだ新たなブロックをブロックチェーンに追加します。ブロックを追加するには、マイニングの成功条件を満たすための「ナンス」という値を計算する必要がありこの計算には高性能なコンピューターが必要になります。実際のブロックチェーンではマイナーは複数いるため、いかに早く「ナンス」を計算できるのかがマイニング競争のポイントになります。 |
| ④ | マイニングに成功したマイナーは、ノードのブロックチェーンを更新します。更新されたブロックチェーンは全てのノードにブロードキャストされデータが同期します。今回作成するブロックチェーンではノードのブロックチェーンが更新された時点でトランザクションが承認され送金が完了したとみなします。ただし、実際のブロックチェーンでは同時に別のマイナーが別のノードのブロックチェーンを更新することもありえますので、この後にブロックが4個〜6個程度追加された時点でトランザクションを承認済とみなしています。(詳しくは「孤立ブロック」で検索してください) |
ブロックチェーンの実装にあたって重要なポイントは、ノードと登場人物は、他のノードと登場人物を一切信用しない ことです。例えば、利用者が不正なトランザクションを登録する、ノードの管理者がトランザクションを改ざんする、マイナーがいい加減なナンスでブロックを更新する。などなど、1ビットコインが1,000万円以上で取引されるブロックチェーンでは(2024年11月現在)あの手この手で不正にビットコインを手に入れようとしてきます。
銀行などの中央集権型システムでは、中央の組織が取引の信用をチェックしてくれますが、ブロックチェーンは分散型システムであり中央の組織は存在しないため、取引(トランザクション)の信用は、各ノード、各マイナーが自分でチェックする必要があります。そして信用のキーとなるのが「秘密鍵を持っている事実」と「正しいナンス」が計算されていることの2点です。
ブロックチェーンの利用におけるポイントは秘密鍵の管理です。仮に、利用者Aさんの秘密鍵を盗んだ悪者Xが、利用者Aさんの秘密を使って自分に送金したとしてもブロックチェーンでは「秘密鍵を持っている事実」のみで信用のチェックを行うため正しいトランザクションとして扱われます。そのため、ブロックチェーンの利用者は自分の秘密鍵を盗まれないように大切に管理することが必要です。
今回のブロックチェーンを実装するにあたり次のものをご準備ください。
今回は Python でブロックチェーンを実装しますので Python(バージョン3)が使えるパソコンを開発環境としてご準備ください。とりあえずは、Python が使えるパソコンさえあればブロックチェーンの実装はできますが、最後にノード間のデータ同期をテストするためにサーバーが必要になります。サーバーは VitrualBox などの仮想マシンでも大丈夫です。サーバーOSはなんでも構いませんが、Python が使える必要がありますので Linux OS がオススメです。(この記事では Ubuntu Server 24.04 を使った説明になります)
また、この記事では Python については説明いたしませんので、Python については専門書やWebサイトなどをご参照ください。
今回実装するブロックチェーンでは、以下の Python モジュールを使いますのでインストールしておきましょう。(必要になったタイミングでインストールしても大丈夫です)
pip install ecdsa pip install pandas pip install fastapi pip install uvicorn pip install requests pip install pydantic
ファイル構成について決まりはありませんが、今回は説明の都合のため以下のファイル構成を前提とします。詳細の説明は割愛いたしますが「BlockChain.py」に、ブロックチェーンのコアとなる機能を実装し、実行ファイル「send_tx.py」「node.py」「mining.py」などにインポートして利用します。
blockchain/
├─ data/
├─ mod/
├─ BlockChain.py ・・・ブロックチェーンのコア機能を実装
└─ users.py
├─ tool/
└─ gen_key.py
├─ send_tx.py・・・実行ファイル
├─ node.py・・・・実行ファイル
└─ mining.py・・・実行ファイル
完成したブロックチェーンのソースコードは以下の GitHubリポジトリからダウンロードできます。もしよければ参考にしてください。
https://github.com/sizaki30/blockchain
今回は、作成するブロックチェーンの概要と開発環境の準備について説明しました。それでは実際にブロックチェーンを実装していきましょう。
Thunderbird で Microsoft Exchange Online のメールアカウントを設定する際に、Microsoft OAuth 認証が必要になります。通常は問題なく認証が成功するのですが、Microsoft Intune の条件付きアクセスのポリシーで、許可する条件に「デバイスは準拠しているとしてマーク済みである必要があります」を設定していると「ここからアクセスすることはできません(Thunderbird You can't get there from here)」と表示され認証に失敗することがあります。そこで今回は、この問題の対処法をまとめてみました。
Thunderbird の「設定エディター」で「network.http.windows-sso.enabled」を「true」に変更すればこの問題は解決します。
【補足】過去のWebフォーラムなどには上記を設定しても症状が変わらないとの書き込みがありますが、私の環境(Winodws11 + Thunderbird 128.3.0esr)では Microsoft OAuth 認証に成功していますのでご自身の環境で試してみてください。
Thunderbird の「Ⲷ」メニューから「設定」を選択します。
「一般」を選択して一番下にある「設定エディター」をクリックします。
「network.http.windows-sso.enabled」を検索して変更ボタンをクリックします。
「network.http.windows-sso.enabled」が「true」になれば設定完了です。この状態でアカウント設定を行えば、Microsoft OAuth 認証が成功します。
これは別の問題になりますが、Microsoft OAuth 認証が成功してもメールが送信できない場合があります。
参考資料:IMAP/POP3 受信は動作するが、SMTP 送信が動作しない | Microsoft OAuth 認証と Thunderbird (2024年)
その場合は、Microsoft Exchange Online の SMTP AUTH を有効にする必要があるのですが、SMTP AUTH は、単純にユーザー名とパスワードのみでメールを送信することを許可する仕組みですので、セキュリティを優先するのであれば Microsoft Outlook メーラーの利用を検討してください。(どうしても Thunderbird を使いたい場合は、パスワード強度を高めることを強くオススメします)
参考資料:Exchange Online で認証済みクライアントの SMTP 送信 (SMTP AUTH) を有効または無効にする
ただ、Thunderbird のサーバー設定を見ると SMTP の認証方式は「OAuth2」になっているのですが、なぜ SMTP AUTH なのか、、、、謎ですね。
IT部門としては、Microsoft Exchange Online を使うのであれば、メーラーは Microsoft Outlook を使って欲しいところですが、細かいところにも手が届く Thunderbird を使いたい利用者の気持ちも良くわかります。Thunderbird も OAuth を介した先進認証 (モダン認証) に対応してくれるといいですね。
]]>2024年9月26日、VirtualBox 7.1.2 がリリースされ、Appleシリコン(M1/M2/M3)搭載Macに正式対応したようです。(macOS/Arm UI のベータ版表記が削除されています)Appleシリコン搭載Macを使っている方にとっては待ちに待った対応ではないでしょうか。さっそく、よく利用されているLinuxディストリビューション、Ubuntu、AlmaLinux、Rocky Linux がゲストOSとしてインストールできるか試してみました。
Appleシリコン搭載Macに対応した VirtualBox は、公式ダウンロードサイトの「macOS / Apple Silicon hosts」からダウンロードできます。
余談になりますが、公式サイトが大幅にリニューアルされ、 VirtualBox のロゴも変わりましたね。
ホストマシンは、M3 Pro チップ搭載の MacBook Pro 、macOS Sequoia 15.0 の環境で検証してみました。
現時点(2024年9月)で公式に対応しているゲストOSは以下の通りです。Appleシリコンは、ARMアーキテクチャで設計されているため、ゲストOSもARMアーキテクチャ対応である必要があります。また、現時点では Windows OS には対応していません。
Ubuntu Server 24.04 をゲストOSとしてインストール、公式に対応しているだけあってまったく問題無くインストールできます。
現時点では、AlmaLinuxなどのRHEL系のOSには対応していませんので、仮想マシンのタイプを「Other」にして AlmaLinux 9.4 をインストールしてみましたが、インストールのGUI画面でキーボードやマウス操作ができなくなるなど、動作が安定せずインストールができませんでした。
そこで、仮想マシンのタイプを「Linux」、subtypeを「Fedora」(RHEL系のOSのアップストリームがFedoraなので)にしてインストールしたところ問題なくインストールできました。
Rocky Linux もRHEL系のOSですので、仮想マシンのタイプを「Linux」、subtypeを「Fedora」に設定して Rocky Linux 9.4 をインストール、こちらも問題なくインストールできます。
これまで、VirtualBox が Appleシリコン搭載Mac に対応していなかったため、どうしても VirtualBox が必要な場合は Windows PC を使っていましたが、外出先で作業する際は、PCを2台持ちしなければならないというかなり面倒な環境でした。オラクルさんありがとう!
]]>つい先日新しいWebサーバーを設定したのですが、logrotate で /var/log/ 配下のログは問題なくローテーションされるのに /usr/local/apache2/logs/ 配下のログのみローテーションされないという現象がありました。そこで今回は、/usr/ 配下のログがローテーションできない場合の原因と対処方法をまとめてみました。
原因は、Linuxシステムや各種サービスを管理している systemd にあります。
具体的には logrotate サービスの設定値 ProtectSystem が「full」になっていることが /usr/ 配下のログがローテーションできない原因です。
$ systemctl show logrotate.service -p ProtectSystem ProtectSystem=full
どういうことかと言うと、ProtectSystem の値が「full」に設定されている場合は、/usr/ と /etc/ およびブートローダーディレクトリ配下が logrotateサービスに対して読取り専用でマウントされるため、ログローテーション時に新たにファイルを作成することができず結果としてログローテーションに失敗します。少し厄介な設定でありますが、これはセキュリティ確保のためで、長時間実行されるすべてのサービスに対してこの設定を有効にすることが推奨されています。
参考資料:ProtectSystem | systemd.exec
RHEL系のサーバーOSでは、バージョン8までは ProtectSystem はデフォルトで「no」が設定されていたため、意図して設定を変更しない限りこのような問題は発生しなかったのですが、バージョン9からはデフォルトで「full」に設定されているため、サーバーOSに RHEL9、AlmaLinux9、RockyLinux9などを利用している場合は注意が必要です。
そのままですがLinuxの作法(FHS)に従って素直に /var/log/ 配下にログを出力するようにサービスの設定を変更しましょう。
設定には手をつけずにシンボリックリンクを使ってログの出力先を変更することもできます。例えばログの出力先を /usr/local/apache2/logs/ から /var/log/httpd/ に変更するには次のようにシンボリックリンクを作成します。
sudo systemctl stop httpd sudo mv -i /usr/local/apache2/logs /var/log/httpd sudo ln -s /var/log/httpd /usr/local/apache2/logs sudo systemctl start httpd
セキュリティの観点からはオススメできませんが、やむを得ない事情がある場合は ReadWritePaths の設定で特定のディレクトリへの書込みを許可する方法もあります。
$ sudo systemctl edit logrotate.service ### Editing /etc/systemd/system/logrotate.service.d/override.conf ### Anything between here and the comment below will become the new contents of the file (以下の2行を追記します) [Service] ReadWritePaths=/usr/local/apache2/logs ### Lines below this comment will be discarded (略)
設定が反映されていることを確認します。
$ systemctl show logrotate.service -p ReadWritePaths ReadWritePaths=/usr/local/apache2/logs
logrotate を再起動します。
sudo systemctl restart logrotate.service
logrotate -f /etc/logrotate.d/httpd とかでローテーションを実行すると /usr/ 配下であってもローテーションできるので、原因が分かるまでかなりの時間がかかりました、、、systemd は知れば知るほど奥が深く、ハマりポイントでもありますのでしっかり理解しておきたいものですね。
]]>VSCode(Visual Studio Code)の SFTP 機能拡張をインストールすると、その名の通り SSH File Transfer Protocol で、ローカルにあるファイルやディレクトリをサーバーにアップロードすることができます。便利な機能拡張なのですが、認証情報をプロジェクトフォルダ配下に保存するため、意図せず認証情報がサーバーにアップロードされ、場合によっては公開されてしまうこともあるので注意が必要です。そこで今回は、VSCode + SFTP の安全な使い方をまとめてみました。
国内のレンタルサーバーにおいて実際に VSCode の SFTP 機能拡張の利用による認証情報の公開が確認されています。
VSCodeのSFTPプラグインの設定で除外設定が正しくされておらず、VSCodeの設定ファイル(.vscode/sftp.json等)がWebサーバー上にアップロードされている事象を確認致しました。
サーバー上に設定ファイルがアップロードされている場合、意図せずSSH接続情報などが漏洩する危険があるため、「/.vscode/」というURLにアクセスした際に403エラーになるようサーバの設定を変更致しました。
上記のレンタルサーバー事業者様では、親切にも認証情報が保管されるディレクトリへのアクセスを制限してくれていますが、本来は VSCode の SFTP 機能拡張を使う利用者が気をつけなければなりません。
VSCode の SFTP 機能拡張を安全に使う方法は次の通り実にシンプルです。
上記の原則さえ実施していれば、万が一 VSCodeの設定ファイルが公開サーバーにアップロードされたとしても、認証情報が漏洩することはありません。
上にも書いた通り、接続先のサーバーはSSH公開鍵認証で接続できるように設定しておきましょう。
また、VSCode の SFTP 機能拡張で設定するサーバーは開発用サーバーにとどめ、変更管理の観点からも本番サーバーは設定しないことをオススメします。
サポートが終了しているSFTP機能拡張もありますので(機能拡張名に取り消し線が付きます)現在サポートされているSFTP機能拡張をインストールしましょう。
SFTP機能拡張のインストールが終わったら、「表示」メニューから「コマンドパレット」を選択します。
コマンドパレットに「SFTP」と入力して「SFTP: Config」を選択します。
SFTPの設定ファイル「sftp.json」が開きます。
{
"name": "My Server",
"host": "localhost",
"protocol": "sftp",
"port": 22,
"username": "username",
"remotePath": "/",
"uploadOnSave": false,
"useTempFile": false,
"openSsh": false
}
各オプションの意味は次の通りです。初期状態では「privateKeyPath」オプションがありませんので追加してください。
| name | サーバー名など、このSFTP設定を識別できる名称を設定します。 |
| host | 接続先のサーバーのIPアドレスもしくはFQDNを設定します。 |
| protocol | 「sftp」を設定します。 |
| port | SSHの接続先ポート番号を設定します。 |
| username | SSHのユーザー名を設定します。 |
| privateKeyPath | SSH公開鍵認証に使う秘密鍵のファイルパスを設定します。 |
| remotePath | アップロード先のディレクトリを設定します。 |
| uploadOnSave | 「true」に設定するとVSCodeで保存する度にアップロードが実行されます。 |
| useTempFile | 「true」に設定すると一時ファイルをアップロードし、ファイルがアップロードされたまま(不完全なまま)ユーザがアクセスした場合にウェブページが壊れるのを防ぎます。 |
| openSsh | 「true」に設定するとアトミックファイルアップロードが有効になります。このオプションを「true」に設定する場合は「useTempFile」も「true」に設定する必要があります。 |
参考資料:https://github.com/Natizyskunk/vscode-sftp/wiki/configuration
以上をふまえて「sftp.json」を設定します。 以下は設定例です、ご自分の環境に合わせて設定してください。繰り返しになりますが「sftp.json」にSSHのパスワードを書いてはいけません。
{
"name": "websv01",
"host": "www.example.com",
"protocol": "sftp",
"port": 22,
"username": "sample",
"privateKeyPath": "/Users/sample/.ssh/id_ed25519",
"remotePath": "/var/www/public/",
"uploadOnSave": false,
"useTempFile": true,
"openSsh": true
}
また、GitリポジトリにSFTPなどの設定ファイルが同期されないように、「.vscode」ディレクトリを「.gitignore」に設定して除外しておきましょう。
.vscode/
VSCode の SFTP 機能拡張含め、IDEのアップロード機能にはその利用に賛否がありますが、特に Webアプリケーションの開発ではとても便利な機能です。安全に配慮した上でぜひ活用したいですね。
]]>
2024年7月17日 Apache httpd 2.4.62 がリリースされました。前バージョンの Apache httpd 2.4.61 でコアの脆弱性(CVE-2024-39884)が修正されたのですが、その修正が完全ではなかったため、わずか2週間でバージョンアップされました。Apache httpd 2.4.62 では問題のコアの脆弱性も含めて2件の脆弱性が修正され、各種機能の不具合が改善されています。そこで今回は AlmaLinux8、RockyLinux8、CentOS Stream 9、AlmaLinux9、RockyLinux9 に Apache httpd 2.4.62 をインストールする手順をまとめてみました。
参考資料:Complete ChangeLog for 2.4
Apache httpd や各種ライブラリをソースからコンパイルしますので、パッケージを「最小限のインストール」でインストールしている場合は、基本パッケージと開発ツールをインストールしておきましょう。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
AlmaLinux8、RockyLinux8 など RHEL8系のOSの場合は、OpenSSL 3.0 をインストールします。
OpenSSL のコンパイルに必要なパッケージをインストールしておきます。
OpenSSL 3.0 のダウンロード(ダウンロードの前に OpenSSL 3.0 の最新リリース を確認しておきましょう)
OpenSSL 3.0 のインストール
OpenSSL 3.0 のライブラリにパスを通しておきます。
OpenSSL 3.0 の動作確認(バージョンが表示されればOKです)
/usr/local/openssl-3.0.14/bin/openssl version OpenSSL 3.0.14 4 Jun 2024 (Library: OpenSSL 3.0.14 4 Jun 2024)
HTTP/2(mod_http2)のコアエンジン Nghttp2 をインストールします。
Nghttp2 のダウンロード(ダウンロードの前に Nghttp2の最新リリース を確認しておきましょう)
Nghttp2 のライブラリをコンパイルしてインストールします。
以上で HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib/ 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Brotli のコンパイルに cmake を使いますので、インストールしておきます。
Brotli のダウンロード(ダウンロードの前に Brotliの最新リリース を確認しておきましょう)
Brotli をコンパイルしてインストールします。
Brotli のライブラリが /usr/local/lib64 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Apache httpd のコンパイルに必要なパッケージをインストールしておきます。
また、Apache 2.4系をソースコードからインストールする場合は、APR と APR-util が必要になりますので、インストールしておきます。
本題の Apache httpd のインストールです。
Apache httpd のソースコードのダウンロード
ダウンロードしたソースコードを解凍して、ディレクトリを移動します。
Apache httpd をインストールします。AlmaLinux8、RockyLinux8 など RHEL8系のOSの場合は、「--with-ssl」オプションで OpenSSL 3.0 のインストールディレクトリを指定します。
Apache httpd をインストールします。CentOS Stream 9 および AlmaLinux9、RockyLinux9 など RHEL9系のOSの場合は「--with-ssl」オプションの指定は必要ありません。
以上で Apache が /usr/local/apache2/ 以下にインストールされました。続いてSSLサーバー証明書の作成と、Apacheの設定を行います。
HTTP/2 および Brotli は HTTPS が必須になりますので Apache の設定の前に、SSLサーバー証明書を作成しておきます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
ログの出力先を変更
(補足)Linuxディストリビューションによっては logrotate の設定により /usr 以下に出力されたログがローテーションできないことがありますので /var/log/ 以下に出力することをオススメします。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します(コピペしてください)
vim /usr/local/apache2/conf/httpd.conf
vim /usr/local/apache2/conf/extra/httpd-ssl.conf
Apache httpd 用の systemd ユニットファイル(起動スクリプトのようなもの)を作成します。
vim /etc/systemd/system/httpd.service
作成したサービスファイルを systemd に反映
systemd に反映されているか確認
systemctl list-unit-files | grep httpd httpd.service disabled disabled ←この表示があればOK
起動
自動起動設定
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
firewall-cmd --list-all
・設定ファイルを作成します
vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 daemon daemon
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示であればOKです)-----
以上です。設定お疲れ様でした!
]]>久しぶりに VSCode(Visual Studio Code)を使う機会があったのですが、いつの間にか Git用の便利な機能拡張が充実していました。これまではターミナルから直接 Gitコマンドを叩いて使っていたのですが、機能拡張を使った方が Gitリポジトリの視認性も良くて効率的に作業を行える上にミスも減らせそうです。そこで今回は、VSCode と Git Graph 機能拡張を使った Git の使い方をまとめてみました。
この記事では、Japanese Language Pack 機能拡張をインストールした VSCode での説明になります。「機能拡張」を表示し「Japanese Language Pack」を検索してインストールすることをオススメします。
「機能拡張」を表示し、Git用の便利な機能拡張「Git Graph」を検索してインストールします。
「ソース管理」を表示し「リポジトリの複製」をクリックします。
上のような画面でない場合は「・・・」メニューから「クローン」を選択します。
リモートリポジトリのURLを入力して実行すれば、リポジトリがクローンされます。ローカルリポジトリの保存先はこの後に聞かれますので適当な場所を指定してください。
「ソース管理」を表示し「変更の同期↓」をクリックすれば、リモートリポジトリの状態をプルできます。
上のような画面でない場合は「・・・」メニューから「プル」を選択します。
なにかコードを修正したら「ソース管理」を表示し、コミットメッセージを入力して「コミット」をクリックすれば、コミットを実行できます。
コミットメッセージを省略すると、おなじみの COMMIT_EDITMSG が開くのですが、コミットするには右端の小さなチェックマークをクリックしなければなりません。
もどかしく感じる場合は、VSCodeの「設定」画面で「Use Editor As Commit Input」を検索してチェックを外しておくことをオススメします。
コミットメッセージを入力して、エンターを押せばコミットを実行できるようになります。
「ソース管理」を表示し「変更の同期↑」をクリックすれば、ローカルリポジトリの状態をリモートリポジトリにプッシュできます。
「・・・」メニューから「プッシュ」を選択することもできます。
「ソース管理」を表示し「Git Graph」アイコンをクリックすれば git log と同等の表示が得られます。
「ソース管理」を表示し「Git Graph」アイコンをクリックして Git Graph を開きます。
タグを付けたいコミットを右クリックして「Add Tag」を選択します。
タグの設定画面が表示されますので、タグ名を入力して「Add Tag」をクリックすればタグが作成されます。リモートリポジトリにタグをプッシュしたい場合は「Push to remote」にチェックを入れます。
「ソース管理」を表示し「・・・」メニューから「ブランチ」>「ブランチの作成」を選択します。
ブランチ名を入力してエンターを押すとブランチが作成され、作成したブランチがチェックアウトされます。
「ソース管理」を表示し「Git Graph」アイコンをクリックすれば、作成したブランチがチェックアウトされていることが確認できます。
「↑Branchの発行」をクリックすればリモートリポジトリにブランチを反映できます。
「ソース管理」を表示し「Git Graph」アイコンをクリックして Git Graph を開きます。
チェックアウトしたいブランチを右クリックして「Checkout Branch」を選択すれば、対象のブランチがチェックアウトされます。
「ソース管理」を表示し「Git Graph」アイコンをクリックして Git Graph を開きます。
マージ先のブランチをチェックアウトし(今回は「main」ブランチをマージ先とします)、必要に応じてリモートリポジトリの状態をプルしておきます。
マージするブランチを右クリックして「Merge into current branch」を選択します。
マージの設定画面が表示されますので、必要に応じて設定を行い「Yes, merge」をクリックすればマージが実行されます。
「ソース管理」を表示し「Git Graph」アイコンをクリックして Git Graph を開きます。
削除したいブランチを右クリックして「Delete Branch」を選択します。
ブランチ削除のオプションが表示されますので必要に応じて選択します。(リモートのブランチも削除したい場合は「Delete this branch on the remote」にチェックを入れてください)「Yes, delete」をクリックすれば対象のブランチが削除されます。
Visual Studio Code は、他のIDEと比べて機能が少ない印象があったのですが、いつの間にか超多機能で使いやすいIDEに進化していました。動作も比較的軽いのでしばらく使ってみようと思います。
]]>約10年ぶりに Zabbixサーバーをアップグレードする機会があったのですが、いつからか公式のアップグレード手順のドキュメントがとても充実していて、スムーズに作業を行うことができました。そこで今回は、どの Zabbix公式ドキュメントを参照すればよいかを踏まえつつ、例として Zabbixサーバー 6.4.x から 7.0 へのアップグレード手順をまとめてみました。
関連記事:Zabbix 7.0 インストールと管理画面のSSL設定メモ
冒頭にも書きましたが Zabbix はアップグレードに関してかなり詳細なドキュメントが用意されていますので、アップグレードをする前にどのような準備が必要なのか、機能の変更によって運用に影響はないか、などを確認しておきましょう。
8 Upgrade procedure | Zabbix Documentation
今回は、Zabbix バージョン 6.4.x から 7.0 へのアップグレードになりますので以下のドキュメントを確認します。
11 Upgrade notes for 7.0.0 | Zabbix Documentation
例えば事前の準備として、Zabbix バージョン 7.0 では PHP 8.0 以上が必須になっていますので、Zabbixサーバーの PHP バージョンを確認して、それを満たしていないのであれば事前に PHP のバージョンアップが必要になります。
Zabbixサーバーをアップグレードしても、Zabbixエージェントのアップグレードは推奨はされるものの必須ではありません。ただし逆に、Zabbixサーバーのバージョン以上の Zabbixエージェントはサポートされません。(例えば、Zabbixサーバーが 6.4、Zabbixエージェントが 7.0 というのはNGです)
11 Version compatibility | Zabbix Documentation
具体的なアップグレード手順についても、様々なパターンのドキュメントが用意されていますので、環境に合った手順を確認します。
1 Upgrade from sources | Zabbix Documentation
2 Upgrade from packages | Zabbix Documentation
3 Upgrade from containers | Zabbix Documentation
今回は、RHEL系の Rocky Linux 9 上で稼働する Zabbixバージョン 6.4.x をアップグレードしますので、以下のドキュメントを確認します。
1 Red Hat Enterprise Linux | Zabbix Documentation
Zabbix バージョン 7.0 ではディストリビューションごとにパッケージが用意されていますので、Rocky Linux 用のリポジトリパッケージに更新する必要があるようです。
ここまで確認した Zabbix公式ドキュメントを元に、自分の環境に合わせたアップグレード手順書を作成して実行します。
Zabbix サーバーとエージェントを停止
sudo systemctl stop zabbix-server sudo systemctl stop zabbix-agent
MySQL の設定を変更
mysql -u root -p SET GLOBAL log_bin_trust_function_creators = 1; exit;
バックアップ用ディレクトリの作成
mkdir ~/zabbix64-backup/
Zabbixデータベースのバックアップ
mysqldump -u root -p zabbix > ~/zabbix64-backup/zabbix.sql
設定ファイルのバックアップ
sudo cp /etc/zabbix/zabbix_server.conf ~/zabbix64-backup/ sudo cp /etc/httpd/conf.d/zabbix.conf ~/zabbix64-backup/
PHP ファイルと Zabbix バイナリのバックアップ
sudo cp -R /usr/share/zabbix/ ~/zabbix64-backup/ sudo cp -R /usr/share/zabbix-* ~/zabbix64-backup/
リポジトリパッケージの更新(Rocky Linux 9 用です)
sudo rpm -Uvh https://repo.zabbix.com/zabbix/7.0/rocky/9/x86_64/zabbix-release-7.0-3.el9.noarch.rpm
Zabbix コンポーネントのアップグレード
sudo dnf upgrade zabbix-server-mysql zabbix-web-mysql zabbix-apache-conf sudo dnf upgrade zabbix-selinux-policy sudo dnf upgrade zabbix-agent sudo dnf upgrade zabbix-web-japanese sudo dnf upgrade zabbix-get
Zabbix サーバーとエージェントを起動
sudo systemctl start zabbix-server sudo systemctl start zabbix-agent
MySQL の設定を元に戻す
mysql -u root -p SET GLOBAL log_bin_trust_function_creators = 0; exit;
各種ログにエラーが無いことを確認
sudo systemctl status zabbix-server sudo systemctl status zabbix-agent tail -f /var/log/zabbix/zabbix_server.log tail -f /var/log/zabbix/zabbix_agentd.log
後は実際に Zabbixサーバーの管理画面を確認して正常に動作していることを確認しましょう。
これは Zabbix に限った話ではありませんが、サーバーOSやミドルウェアはバージョンを固定せずにこまめにバージョンアップした方が、バージョンアップにまつわる手間はあるものの、結果として運用負担が少なくなることを最近感じます。少し覚悟が必要ですが、今後は Zabbix もマイナーバージョンアップごとに更新しようと思った今日この頃です。
]]>Git には、コミットやタグに署名を付与することで、そのコミットやタグが確実に本人のものであることを検証できる仕組みがあるのですが、署名にGPG鍵を使うため設定がややこしく使うのには少しハードルが高い仕組みでもありました。しかし、Git バージョン 2.34 以降は SSH鍵を使った署名に対応していますので、手軽に Git のコミットやタグに署名を付与し検証することができるようになりました。そこで今回は、Git のコミットやタグにSSH鍵で署名して、それを検証するための設定方法をまとめてみました。
参考資料:7.4 Git のさまざまなツール - 作業内容への署名
SSH鍵を作成していない場合は、まず SSH鍵(公開鍵と秘密鍵のペア)を作成します。
ssh-keygen -t ed25519 -C 'your_name'
既に SSH鍵を利用している場合はそちらを使います。Git の署名用に新たに SSH鍵を作成する必要はありません。
SSH鍵の準備ができたら、これを署名用の鍵として使うように Git を設定します。(この記事では --global オプションを付けてユーザー設定としていますが、リポジトリごとに設定することもできます。用途に合わせて設定してください)
署名に使用する鍵フォーマットを gpg.format で指定します。SSH鍵を使用するので「ssh」を指定します。
git config --global gpg.format ssh
SSHの秘密鍵または公開鍵のファイルパスを user.signingkey で指定します。
git config --global user.signingkey /home/foo/.ssh/id_ed25519
(補足)user.signingkey に公開鍵を指定するように説明されているドキュメントをよく見かけるのですが、signingkey(署名鍵)に公開鍵を指定するは違和感があるため、上の例では秘密鍵を指定しています。ただ user.signingkey に公開鍵を指定したとしても、実際の署名はペアとなる秘密鍵が使われますので動作的にはまったく問題ありません。
SSH鍵で署名する準備ができましたので、実際に署名してみましょう。
コミットへの署名は git commit コマンドの -S オプションを使います。
git commit -a -S -m '署名付きコミット'
コミットへの署名を常に行いたい場合は commit.gpgSign を「true」に設定します。この設定を行うと git commit コマンドを実行するだけで署名が付与されます。( -S オプションの指定は不要です)
git config --global commit.gpgSign true
タグへの署名は git tag コマンドの -s オプションを使います。
git tag -s v1.5.0 -m '署名付きタグ'
タグへの署名を常に行いたい場合は tag.gpgSign を「true」に設定します。
git config --global tag.gpgSign true
署名の検証を行う前に、信頼する SSH公開鍵を Git に設定する必要があります。信頼する SSH公開鍵が設定されていない状態で署名を検証すると以下のようなエラーが表示されます。
git log --show-signature error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification commit 9b610a103eb2b1d0ecc7aaa405bd7d1c79347467 (HEAD -> master) No signature Author: sampleDate: Sun Jul 7 17:56:12 2024 +0900 署名付きコミット error: gpg.ssh.allowedSignersFile needs to be configured and exist for ssh signature verification
信頼する SSH公開鍵のリスト(ALLOWED_SIGNERS)を以下のフォーマットで作成します。
<メールアドレス> <公開鍵>
リストのファイル名や置き場所に決まりはありませんが、SSH繋がりで ~/.ssh/ ディレクトリ以下に作成するのが分かりやすと思います。
vi /home/foo/.ssh/allowed_signers [email protected] ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJVKszzpPqNCicc89+16+c/gwsliZrLs3QNsZ43Z+V9A
作成した信頼する SSH公開鍵のリストのファイルパスを gpg.ssh.allowedSignersFile で指定すれば署名検証の準備完了です。
git config --global gpg.ssh.allowedSignersFile /home/foo/.ssh/allowed_signers
コミット署名の検証は git log コマンドの --show-signature オプションで確認できます。
git log --show-signature commit 9b610a103eb2b1d0ecc7aaa405bd7d1c79347467 (HEAD -> master) Good "git" signature for [email protected] with ED25519 key SHA256:F4lpKI7hOLEeiiPCz7/SuJ6qXg5RL59cGB9wzk6jH5s Author: sampleDate: Sun Jul 7 17:56:12 2024 +0900 署名付きコミット
タグ署名の検証は git tag コマンドの -v オプションで確認できます。
git tag -v v1.5.0 object 9b610a103eb2b1d0ecc7aaa405bd7d1c79347467 type commit tag v1.5.0 tagger sample1720392377 +0900 署名付きタグ Good "git" signature for [email protected] with ED25519 key SHA256:F4lpKI7hOLEeiiPCz7/SuJ6qXg5RL59cGB9wzk6jH5s
GitHub も署名の検証に対応しています。
[Settings] > [SSH and GPG keys] の設定画面で、SSH公開鍵を署名鍵(Signing Key)として登録します。
署名が検証されたコミットには「Verified」マークが付きます。
参考資料:コミット署名の検証について - GitHub Docs
冒頭にも書きましたが Git の署名の仕組みはかなり手軽に使えるようになっています。コードの完全性を担保するためにも活用してみてはいかがでしょうか。
]]>
2024年7月3日 Apache httpd 2.4.61 がリリースされました。7月1日に Apache httpd 2.4.60 がリリースされたのですが、脆弱性が見つかったためわずか3日でバージョンアップされています。Apache httpd 2.4.61 と 2.4.60 合わせて9件もの脆弱性が修正され、各種機能の不具合が改善されています。そこで今回は AlmaLinux8、RockyLinux8、CentOS Stream 9、AlmaLinux9、RockyLinux9 に Apache httpd 2.4.61 をインストールする手順をまとめてみました。
参考資料:Complete ChangeLog for 2.4
Apache httpd や各種ライブラリをソースからコンパイルしますので、パッケージを「最小限のインストール」でインストールしている場合は、基本パッケージと開発ツールをインストールしておきましょう。
インストール済みのパッケージを、最新版にアップデートします。
OSを再起動します。
AlmaLinux8、RockyLinux8 など RHEL8系のOSの場合は、OpenSSL 3.0 をインストールします。
OpenSSL のコンパイルに必要なパッケージをインストールしておきます。
OpenSSL 3.0 のダウンロード(ダウンロードの前に OpenSSL 3.0 の最新リリース を確認しておきましょう)
OpenSSL 3.0 のインストール
OpenSSL 3.0 のライブラリにパスを通しておきます。
OpenSSL 3.0 の動作確認(バージョンが表示されればOKです)
/usr/local/openssl-3.0.14/bin/openssl version OpenSSL 3.0.14 4 Jun 2024 (Library: OpenSSL 3.0.14 4 Jun 2024)
HTTP/2(mod_http2)のコアエンジン Nghttp2 をインストールします。
Nghttp2 のダウンロード(ダウンロードの前に Nghttp2の最新リリース を確認しておきましょう)
Nghttp2 のライブラリをコンパイルしてインストールします。
以上で HTTP/2 のライブラリ「libnghttp2」が /usr/local/lib/ 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Brotli のコンパイルに cmake を使いますので、インストールしておきます。
Brotli のダウンロード(ダウンロードの前に Brotliの最新リリース を確認しておきましょう)
Brotli をコンパイルしてインストールします。
Brotli のライブラリが /usr/local/lib64 以下にインストールされましたので、ライブラリのパスに追加しておきます。
Apache httpd のコンパイルに必要なパッケージをインストールしておきます。
また、Apache 2.4系をソースコードからインストールする場合は、APR と APR-util が必要になりますので、インストールしておきます。
本題の Apache httpd のインストールです。
Apache httpd のソースコードのダウンロード
ダウンロードしたソースコードを解凍して、ディレクトリを移動します。
Apache httpd をインストールします。AlmaLinux8、RockyLinux8 など RHEL8系のOSの場合は、「--with-ssl」オプションで OpenSSL 3.0 のインストールディレクトリを指定します。
Apache httpd をインストールします。CentOS Stream 9 および AlmaLinux9、RockyLinux9 など RHEL9系のOSの場合は「--with-ssl」オプションの指定は必要ありません。
以上で Apache が /usr/local/apache2/ 以下にインストールされました。続いてSSLサーバー証明書の作成と、Apacheの設定を行います。
HTTP/2 および Brotli は HTTPS が必須になりますので Apache の設定の前に、SSLサーバー証明書を作成しておきます。
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
ログの出力先を変更
(補足)Linuxディストリビューションによっては logrotate の設定により /usr 以下に出力されたログがローテーションできないことがありますので /var/log/ 以下に出力することをオススメします。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します(コピペしてください)
vim /usr/local/apache2/conf/httpd.conf
vim /usr/local/apache2/conf/extra/httpd-ssl.conf
Apache httpd 用の systemd ユニットファイル(起動スクリプトのようなもの)を作成します。
vim /etc/systemd/system/httpd.service
作成したサービスファイルを systemd に反映
systemd に反映されているか確認
systemctl list-unit-files | grep httpd httpd.service disabled disabled ←この表示があればOK
起動
自動起動設定
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
firewall-cmd --list-all
・設定ファイルを作成します
vim /etc/logrotate.d/httpd
/var/log/httpd/*log {
daily
missingok
dateext
rotate 365
create 644 daemon daemon
sharedscripts
postrotate
/bin/systemctl reload httpd.service > /dev/null 2>/dev/null || true
endscript
}
・確認します
logrotate -v /etc/logrotate.d/httpd
-----(下記のような表示であればOKです)-----
以上です。設定お疲れ様でした!
]]>Git 使うときに最初にすべきことは、ユーザー名とメールアドレスを設定することなのですが、ここで設定したメールアドレスは、コミットするたびに記録されて誰でも閲覧できてしまうため注意が必要です。そこで今回は、Git のメールアドレスはどのように設定すれば良いのか、パターン別にまとめてみました。
賛否があると思いますが、Git の使い方に慣れるまでは下のような適当なユーザー名とメールアドレスを設定しておきましょう。
git config --global user.name TOKUMEI git config --global user.email [email protected]
ただし、チームで Git を使う場合、適当なユーザー名とメールアドレスを設定していると誰がコードを変更したのかが分からなくなってしまいますので、Git の使い方に慣れたらユーザー名とメールアドレスの設定を見直しましょう。
会社などの組織で Git を使う場合は、Git の基本設定のルールがあると思いますので、それに従ってユーザー名とメールアドレスなどを設定してください。
GitHub.com には、メールアドレスを非公開にできる設定がありますので、そちらを利用しましょう。
コミットメールアドレスを設定する - GitHub Docs
10年以上前、Git を使い始めた時に特に気にすることなくメインで使っているメールアドレスを設定していたため、あちこちのパブリックリポジトリに私のメールアドレスが記録されています(^^;) 意図してメールアドレスを設定しているのであれば良いのですが、気になる方はぜひ設定を見直しましょう。
]]>2024年6月4日 Zabbix 7.0 がリリース されました。約2年4ヶ月ぶりのメジャーバージョンアップです。Zabbix 7.0 は、長期サポート(LTS)リリースのためサポート期間が5年と長いのが特徴です。Zabbix 7.0 では、ブラウザベースのシナリオ監視、Zabbixプロキシの冗長化と負荷分散、多要素認証など魅力的な機能がたくさん追加されています。そこで今回は、Zabbix 7.0 インストール手順と、Zabbix管理画面(フロントエンド)の SSL設定手順をまとめてみました。
Zabbix 7.0 の新機能や変更点は以下の公式ドキュメントをご参照ください。
What's new in Zabbix 7.0
5 What's new in Zabbix 7.0.0 | Zabbix Documentation 7.0
システム要件について大きなところで Zabbix 7.0 で注意すべき変更点が2つあります。
Zabbix 7.0 では、サポートされる PHPのバージョンが 7.4.0以上 から 8.0.0以上 に変更されました。
Zabbix 7.0 では、バックエンドデータベースとしての Oracle のサポートは非推奨になりました。将来のバージョンではサポートされない予定です。
Zabbixサーバーを RHEL(Red Hat Enterprise Linux)系のサーバーOSにインストールする場合は、標準で PHP 8.0 がサポートされている以下の RHEL9系のサーバーOSを選定することをオススメします。
今回は、AlmaLinux 9 に Zabbix 7.0 をインストールした時の手順になります。Zabbix 7.0 では AlmaLinux や Rocky Linux など RHEL系のサーバーOSには、ディストリビューションごとに専用のインストールパッケージが提供されていますので、ご自分の環境に合ったインストールパッケージからインストールしてください。
Zabbix 7.0 のインストールの前に、下準備として MySQL 8.0 をインストールして設定しておきましょう。
MySQL 8.0 のインストール
MySQL のバージョンが、Zabbix 7.0 のシステム要件を満たす 8.0.30 以上であることを確認してください。
sudo dnf info mysql-server Installed Packages Name : mysql-server Version : 8.0.36
デフォルト状態では MySQLのログの出力時間が UTC(協定世界時)になるため、MySQLの設定ファイルの最後の行に以下を追加します。(気にならなければそのままで構いません)
sudo vi /etc/my.cnf.d/mysql-server.cnf
MySQLの起動と自動起動設定
初期状態では、rootユーザーがパスワードなしで MySQLに接続できるようになっていますのでパスワードを設定しておきます。
mysql_secure_installation コマンドを実行すると、root ユーザーのパスワードを変更し、不要なユーザーやDBも削除してくれます。パスワードは、8文字以上で英数大文字小文字と記号が含まれていないとポリシー違反で弾かれてしまいますので注意です。パスワードポリシーを変更したい場合は「--use-default」オプションなしで実行してください。
サーバーOSの選定のところでも触れましたが、RHEL系のサーバーOSには、ディストリビューションごとに専用のインストールパッケージが用意されていますので、Zabbixのダウンロードページ でご自分の環境のインストール手順を確認してください。
RHEL系のサーバーOSでよく利用されている EPELリポジトリが登録されている場合は、EPELリポジトリから Zabbix をインストールしないように Zabbix 関連のパッケージを除外しておきます。[epel] セクションの最後あたりに「excludepkgs=zabbix*」を追加してください。
sudo vi /etc/yum.repos.d/epel.repo
[epel]
(略)
countme=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-$releasever
---(以下を追加)-----------------
excludepkgs=zabbix*
AlmaLinux 9 用の Zabbix 7.0 のリポジトリを登録します。
Zabbix のインストールの前に、パッケージのキャッシュを削除しておきます。
Zabbix 7.0 関連のパッケージをインストールします。Zabbix管理画面を日本語で使う場合は zabbix-web-japanese もインストールします。動作確認用に zabbix-get もインストールしておきましょう。
MySQLに、Zabbix用のデータベース「zabbix」と、ユーザー「zabbix」を作成します。
次のインポートの下準備として、SUPER権限が無くても関数を作成できるように「log_bin_trust_function_creators = 1」を設定してから MySQLとの接続を終了します。
Zabbix 用のデータベーススキーマとデータをインポート(時間がかかります)
インポートが終わったら「log_bin_trust_function_creators = 0」に戻しておきましょう。
SELinux を有効にしている場合は、以下のコマンドを実行してポリシーを追加します。
Zabbix サーバーの設定ファイルに、先ほど作成した MySQLのユーザー「zabbix」のパスワードを登録します。
sudo vi /etc/zabbix/zabbix_server.conf
Zabbix サーバーの自動起動設定
Zabbix サーバーの起動
Zabbix サーバーが起動していることを確認します。
sudo systemctl status zabbix-server
● zabbix-server.service - Zabbix Server
Loaded: loaded (/usr/lib/systemd/system/zabbix-server.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2024-06-29 16:23:00 JST; 4s ago
Process: 3444 ExecStart=/usr/sbin/zabbix_server -c $CONFFILE (code=exited, status=0/SUCCESS)
Main PID: 3446 (zabbix_server)
(略)
Zabbix 公式ドキュメントのベストプラクティスでは、Zabbixの管理画面(フロントエンドと呼ばれます)の SSL設定が推奨されていますので、Apache httpd および SSLの設定を行います。
2 Best practices for secure Zabbix setup | Zabbix Documentation 7.0
今回の設定手順では、Zabbixサーバーのドメイン名を「zabbix.example.com」として設定していますが、ご自分の環境に合わせて設定してください。
オリジナルの設定ファイルをバックアップ
・設定ファイルを作成します。
sudo vi /etc/httpd/conf/httpd.conf
今回は自己署名の SSLサーバー証明書で設定を行いますが、可能であれば Let's Encrypt など、正規の認証局が発行した SSLサーバー証明書を使うことを強くオススメします。
関連記事:Let's Encrypt サーバー証明書の取得と自動更新設定メモ
秘密鍵の作成
SSLサーバー証明書の作成(有効期限30年)
-subjオプションで C(Country Name)に2文字の国名コード、CN(Common Name)にサイトのドメイン名(FQDN)を指定してください。
秘密鍵とSSL証明書を移動
パーミッションを変更
SELinux を有効にしている場合は、秘密鍵とSSL証明書に正しいセキュリティコンテキストをつけておきましょう。(Apache httpd 起動時にエラーが発生することがあります)
Apache httpd の SSLモジュールをインストールします。
オリジナルのSSL設定ファイルをバックアッップします
SSL設定ファイルを作成します。
sudo vi /etc/httpd/conf.d/ssl.conf
Apache httpd の自動起動を設定し起動ます。
今回の設定手順だとドキュメントルート直下にインデックスファイルが配置されないため、テストページが表示されてしまいます。必須ではありませんがインデックスファイルを配置しておくことをオススメします。
例えば下のようなインデックスファイルを配置しておけば、https://zabbix.example.com/ → https://zabbix.example.com/zabbix/ のようにリダイレクトしてくれるので便利です。
sudo vi /var/www/html/index.php
・PHPの設定
sudo vi /etc/php.ini
expose_php = On ↓ expose_php = Off ;date.timezone = ↓ date.timezone = 'Asia/Tokyo'
php-fpm を自動起動を設定し起動します。
動作確認用に Zabbix エージェントも起動しておきます。
Zabbix エージェントの動作確認(Zabbixのバージョンが表示されればOKです)
HTTP(80/tcp) と HTTPS(443/tcp) を開けておきます。
・確認
sudo firewall-cmd --list-all
ブラウザで下記URLを開き、初期設定を開始します(ドメイン名「zabbix.example.com」はご自分の環境に読替えてください)
https://zabbix.example.com/zabbix/
今回は日本語で設定しますので Default language「Japanese(ja_JP)」を選択して(選択すると以下の表示に変わります)「次のステップ」をクリックします。
前提条件のチェックがすべて「OK」であることを確認して「次のステップ」をクリックします。
「パスワード」欄に、MySQLのユーザー(zabbix)のパスワードを入力し「次のステップ」をクリックします。
適当なサーバー名を入力、デフォルトタイムゾーン「Asia/Tokyo」を選択し、お好みのデフォルトのテーマを選択したら「次のステップ」をクリックします。
設定した内容の最終確認です。間違えがなければ「次のステップ」をクリックします。
「終了」をクリックすれば、初期設定完了です。
初期設定が終了すると、Zabbixのログイン画面が表示されますので、下の初期ユーザーとパスワードでログインします。
ユーザー名:Admin
パスワード:zabbix
メニュー下部の [ユーザー設定]→[プロファイル] をクリックします。
「パスワード変更」をクリックします。
パスワードの入力欄が表示されますので、現在のパスワード(zabbix)と新しいパスワードを入力し、「更新」をクリックすればユーザーパスワードの変更完了です。(一度ログアウトされますので、新しいパスワードでログインし直してください)
初期状態でZabbixサーバー自身のホストが登録されていますので、しばらくしてから [監視データ]→[ホスト]→[最新データ] をクリックすると、Zabbixサーバー自身の監視データを閲覧することができます。
以上です。設定お疲れ様でした!
]]>