【ログ】Ubuntu 20.04: sudo certbot --nginx -d example.com -d www.example.com

  • 実行コマンド:sudo certbot --nginx -d example.com -d www.example.com
  • 実行日:2021/05/09
  • 実行環境:Ubuntu 20.04
$ sudo certbot --nginx -d example.com -d www.example.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): example@gmail.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel: A

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: N
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for graffuhs.com
http-01 challenge for www.graffuhs.com
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/graffuhs.com
Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/graffuhs.com

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/graffuhs.com
Redirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/graffuhs.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://graffuhs.com and
https://www.graffuhs.com

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=graffuhs.com
https://www.ssllabs.com/ssltest/analyze.html?d=www.graffuhs.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/graffuhs.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/graffuhs.com/privkey.pem
   Your cert will expire on 2021-08-07. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

【ログ】Ubuntu 20.04: sudo apt install certbot python3-certbot-nginx

  • 実行コマンド:sudo apt install certbot python3-certbot-nginx
  • 実行日:2021/05/09
  • 実行環境:Ubuntu 20.04
$ sudo apt install certbot python3-certbot-nginx
[sudo] password for ユーザー名: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  python3-acme python3-certbot python3-configargparse python3-future python3-icu python3-josepy python3-mock python3-parsedatetime python3-pbr python3-pyparsing
  python3-requests-toolbelt python3-rfc3339 python3-tz python3-zope.component python3-zope.event python3-zope.hookable
Suggested packages:
  python3-certbot-apache python-certbot-doc python-acme-doc python-certbot-nginx-doc python-future-doc python-mock-doc python-pyparsing-doc
The following NEW packages will be installed:
  certbot python3-acme python3-certbot python3-certbot-nginx python3-configargparse python3-future python3-icu python3-josepy python3-mock python3-parsedatetime
  python3-pbr python3-pyparsing python3-requests-toolbelt python3-rfc3339 python3-tz python3-zope.component python3-zope.event python3-zope.hookable
0 upgraded, 18 newly installed, 0 to remove and 29 not upgraded.
Need to get 1264 kB of archives.
After this operation, 6657 kB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-josepy all 1.2.0-2 [28.1 kB]
Get:2 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 python3-pbr all 5.4.5-0ubuntu1 [64.0 kB]
Get:3 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-mock all 3.0.5-1build1 [25.6 kB]
Get:4 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-requests-toolbelt all 0.8.0-1.1 [35.2 kB]
Get:5 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 python3-tz all 2019.3-1 [24.4 kB]
Get:6 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 python3-rfc3339 all 1.1-2 [6808 B]
Get:7 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-acme all 1.1.0-1 [29.6 kB]
Get:8 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-configargparse all 0.13.0-2 [22.6 kB]
Get:9 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 python3-future all 0.18.2-2 [336 kB]
Get:10 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-parsedatetime all 2.4-5 [32.6 kB]
Get:11 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-zope.hookable amd64 5.0.0-1build1 [11.2 kB]
Get:12 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-zope.event all 4.4-2build1 [7704 B]
Get:13 http://jp.archive.ubuntu.com/ubuntu focal/universe amd64 python3-zope.component all 4.3.0-3 [38.3 kB]
Get:14 http://jp.archive.ubuntu.com/ubuntu focal-updates/universe amd64 python3-certbot all 0.40.0-1ubuntu0.1 [223 kB]
Get:15 http://jp.archive.ubuntu.com/ubuntu focal-updates/universe amd64 certbot all 0.40.0-1ubuntu0.1 [17.9 kB]
Get:16 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 python3-pyparsing all 2.4.6-1 [61.3 kB]
Get:17 http://jp.archive.ubuntu.com/ubuntu focal-updates/universe amd64 python3-certbot-nginx all 0.40.0-0ubuntu0.1 [50.8 kB]
Get:18 http://jp.archive.ubuntu.com/ubuntu focal/main amd64 python3-icu amd64 2.4.2-0ubuntu3 [250 kB]
Fetched 1264 kB in 0s (4485 kB/s)    
Selecting previously unselected package python3-josepy.
(Reading database ... 152075 files and directories currently installed.)
Preparing to unpack .../00-python3-josepy_1.2.0-2_all.deb ...
Unpacking python3-josepy (1.2.0-2) ...
Selecting previously unselected package python3-pbr.
Preparing to unpack .../01-python3-pbr_5.4.5-0ubuntu1_all.deb ...
Unpacking python3-pbr (5.4.5-0ubuntu1) ...
Selecting previously unselected package python3-mock.
Preparing to unpack .../02-python3-mock_3.0.5-1build1_all.deb ...
Unpacking python3-mock (3.0.5-1build1) ...
Selecting previously unselected package python3-requests-toolbelt.
Preparing to unpack .../03-python3-requests-toolbelt_0.8.0-1.1_all.deb ...
Unpacking python3-requests-toolbelt (0.8.0-1.1) ...
Selecting previously unselected package python3-tz.
Preparing to unpack .../04-python3-tz_2019.3-1_all.deb ...
Unpacking python3-tz (2019.3-1) ...
Selecting previously unselected package python3-rfc3339.
Preparing to unpack .../05-python3-rfc3339_1.1-2_all.deb ...
Unpacking python3-rfc3339 (1.1-2) ...
Selecting previously unselected package python3-acme.
Preparing to unpack .../06-python3-acme_1.1.0-1_all.deb ...
Unpacking python3-acme (1.1.0-1) ...
Selecting previously unselected package python3-configargparse.
Preparing to unpack .../07-python3-configargparse_0.13.0-2_all.deb ...
Unpacking python3-configargparse (0.13.0-2) ...
Selecting previously unselected package python3-future.
Preparing to unpack .../08-python3-future_0.18.2-2_all.deb ...
Unpacking python3-future (0.18.2-2) ...
Selecting previously unselected package python3-parsedatetime.
Preparing to unpack .../09-python3-parsedatetime_2.4-5_all.deb ...
Unpacking python3-parsedatetime (2.4-5) ...
Selecting previously unselected package python3-zope.hookable.
Preparing to unpack .../10-python3-zope.hookable_5.0.0-1build1_amd64.deb ...
Unpacking python3-zope.hookable (5.0.0-1build1) ...
Selecting previously unselected package python3-zope.event.
Preparing to unpack .../11-python3-zope.event_4.4-2build1_all.deb ...
Unpacking python3-zope.event (4.4-2build1) ...
Selecting previously unselected package python3-zope.component.
Preparing to unpack .../12-python3-zope.component_4.3.0-3_all.deb ...
Unpacking python3-zope.component (4.3.0-3) ...
Selecting previously unselected package python3-certbot.
Preparing to unpack .../13-python3-certbot_0.40.0-1ubuntu0.1_all.deb ...
Unpacking python3-certbot (0.40.0-1ubuntu0.1) ...
Selecting previously unselected package certbot.
Preparing to unpack .../14-certbot_0.40.0-1ubuntu0.1_all.deb ...
Unpacking certbot (0.40.0-1ubuntu0.1) ...
Selecting previously unselected package python3-pyparsing.
Preparing to unpack .../15-python3-pyparsing_2.4.6-1_all.deb ...
Unpacking python3-pyparsing (2.4.6-1) ...
Selecting previously unselected package python3-certbot-nginx.
Preparing to unpack .../16-python3-certbot-nginx_0.40.0-0ubuntu0.1_all.deb ...
Unpacking python3-certbot-nginx (0.40.0-0ubuntu0.1) ...
Selecting previously unselected package python3-icu.
Preparing to unpack .../17-python3-icu_2.4.2-0ubuntu3_amd64.deb ...
Unpacking python3-icu (2.4.2-0ubuntu3) ...
Setting up python3-configargparse (0.13.0-2) ...
Setting up python3-requests-toolbelt (0.8.0-1.1) ...
Setting up python3-icu (2.4.2-0ubuntu3) ...
Setting up python3-zope.event (4.4-2build1) ...
Setting up python3-pbr (5.4.5-0ubuntu1) ...
update-alternatives: using /usr/bin/python3-pbr to provide /usr/bin/pbr (pbr) in auto mode
Setting up python3-tz (2019.3-1) ...
Setting up python3-mock (3.0.5-1build1) ...
Setting up python3-zope.hookable (5.0.0-1build1) ...
Setting up python3-pyparsing (2.4.6-1) ...
Setting up python3-josepy (1.2.0-2) ...
Setting up python3-future (0.18.2-2) ...
update-alternatives: using /usr/bin/python3-futurize to provide /usr/bin/futurize (futurize) in auto mode
update-alternatives: using /usr/bin/python3-pasteurize to provide /usr/bin/pasteurize (pasteurize) in auto mode
Setting up python3-rfc3339 (1.1-2) ...
Setting up python3-parsedatetime (2.4-5) ...
Setting up python3-zope.component (4.3.0-3) ...
Setting up python3-acme (1.1.0-1) ...
Setting up python3-certbot (0.40.0-1ubuntu0.1) ...
Setting up certbot (0.40.0-1ubuntu0.1) ...
Created symlink /etc/systemd/system/timers.target.wants/certbot.timer → /lib/systemd/system/certbot.timer.
Setting up python3-certbot-nginx (0.40.0-0ubuntu0.1) ...
Processing triggers for man-db (2.9.1-1) ...
$ 

ローカルで作成した Django アプリケーションを Ubuntu の本番環境へ反映する

Mac のローカル環境で作成した Django プロジェクトをさくらの VPS で用意した Ubuntu 環境へ反映する際の流れをメモしています。

下記が完了していることを想定しています。

  • Web サーバーの設定が完了済み(筆者は Nginx を使用)
  • 仮想環境を作るディレクトリが決めてある
  1. データベースを本番環境にコピーする
    • ローカル環境での作業
    • 本番環境での作業
  2. ローカル環境のパッケージを本番環境で再現
    • requirements.txt の作成
    • requirements.txt を本番環境へコピー
    • 本番環境で Python 仮想環境を作成
    • requirements.txt によるパッケージインストール
  3. gunicorn のインストール
  4. settings.py の編集
    • ファイルを分割する必要性
    • 開発環境の runserver 実行時に settings_dev.py を指定
    • settings.py(本番環境用)の編集
  5. Django ソースコードを本番環境に配置
    • 本番環境への git のインストール
    • リモートリポジトリから本番環境へファイルをコピー
  6. データベースのログイン情報をサーバーの環境変数に記述
  7. 静的ファイルの配置

1. データベースを本番環境にコピーする

検証環境で準備したデータベース、テーブル、そしてデータを本番環境でも反映します。

ここはうまくやれば一行スクリプト書いて終了する方法もある様ですが、色々とエラーが出て逆にめんどくさそうだったのでステップバイステップでやっていきます。

ローカル環境での作業

まずローカル環境でコマンド「mysqldump データベース名 > dump.txt」を実行し、dump ファイルを作成します。

% mysqldump graffuhs > dump.txt                                                              
%

それを FTP か何かで本番環境へアップロードします。

本番環境での作業

本番環境に接続し、本番環境の MySQL でデータベースを作成します。

mysql> create database データベース名;

そしてコマンド「sudo mysql データベース名 < dump.txt」を実行します。

$ sudo mysql データベース名 < dump.txt
$

これで本番環境の MySQL にもローカル環境と同じデータベース、テーブル、そしてデータがコピーされました。

2. ローカル環境のパッケージを本番環境で再現

ローカル環境の Python 関連パッケージを本番環境でも再現するため、ローカル環境で requirements.txt ファイルを作成し、それを元に本番環境でパッケージインストールをさせます。

requirements.txt の作成

ローカル環境の Python 仮想環境へ移り、コマンド「pip freeze > requirements.txt」を実行します。

% pip freeze > requirements.txt

requirements.txt を本番環境へコピー

コマンド「scp requirements.txt 本番環境のユーザー名@本番環境のホスト名(もしくは IP アドレス):保存先のディレクトリ」を実行します。

だいぶ長いですが下記の例だとすると。。。

  • 本番環境のユーザー名: vpsadmin
  • 本番環境のホスト名: xx1-234-56789.vs.sakura.ne.jp
  • 保存先のディレクトリ: /var/www/example.com/html

下記の様になります。

scp requirements.txt vpsadmin@xx1-234-56789.vs.sakura.ne.jp:/var/www/example.com/html

無事本番環境に requirements.txt がコピーされました。

$ ls
pythonvenv  requirements.txt

本番環境で Python 仮想環境を作成

本番環境のディレクトリへ移動し、Python の仮想環境を作成します。

$ python3.9 -m venv pythonvenv
$ ls
pythonvenv

requirements.txt によるパッケージインストール

本番環境の Python 仮想環境に入った状態で、コマンド「pip install -r requirements.txt」を実行します。

(pythonvenv) $ pip install -r requirements.txt

すると requirements.txt の内容を元に Django を含めローカル環境で使っていたものと同じパッケージがインストールされます。

3. gunicorn のインストール

本番環境でのみ必要となるものとして、アプリケーションサーバーがあります。今回は gunicorn を使います。

Python 仮想環境内でアプリケーションサーバーの gunicorn をインストールします。

(pythonvenv) $ pip install gunicorn

4. settings.py の編集

ファイルを分割する必要性

settings.py は本番環境と開発環境で内容が異なる部分が出てくるので、下記の様にファイルを分ける必要があります。(ファイル名は任意)

  • settings_common.py:開発環境と本番環境で共通の部分を記述
  • settings.py:本番環境でのみ適用する部分を記述
  • settings_dev.py:開発環境でのみ適用する部分を記述

settings.py と settings_dev.py それぞれに「from .settings_common import *」と記述し、共通部分を settings_common.py から読み込む様設定します。

開発環境の runserver 実行時に settings_dev.py を指定

runserver 実行時、デフォルトでは settings.py が設定ファイルとして読み込まれますが、今後開発環境(ローカル環境)では settings_dev.py を使う必要があります。

そのため、今後開発環境で runserver を実行する際は settings_dev.py を「runserver --settings=プロジェクトディレクトリ名.settings_dev」の形式で渡して実行します。

(inmybag) % python manage.py runserver --settings=some_project.settings_dev

settings.py(本番環境用)の編集

DEBUG の変更

False に変更

DEBUG = False

ALLOWED_HOSTS の変更

ドメイン名を設定。

ALLOWED_HOSTS = ['example.com']

Web サーバーで www.example.com から example.com のリダイレクトを行っていれば example.com のみを設定するだけで大丈夫。

静的ファイルの本番環境での配置場所

STATIC_ROOT = '/var/www/examlpe.com/html/static'

5. Django ソースコードを本番環境に配置

本番環境への git のインストール

本番環境でコマンド「sudo apt update」を実行しパッケージリストを更新、その後「sudo apt install git」で git をインストールします。

$ sudo apt update
$ sudo apt install git
Reading package lists... Done
Building dependency tree       
Reading state information... Done
git is already the newest version (1:2.25.1-1ubuntu3.1).
git set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 18 not upgraded.

リモートリポジトリから本番環境へファイルをコピー

プロジェクトフォルダをリポジトリに設定しているので、プロジェクトフォルダを配置したい場所へ移動した上で git clone を実行します。

$ git clone https://github.com/ユーザー名/リポジトリ名.git

これで本番環境にもプロジェクトフォルダがコピーされました。

今後作業する際は何かにつけて「pkill gunicorn」で gunicorn を終わらせた方が良いです。エラーが起きた時にいくらコードを修正しても治らないまま数時間経って、「pkill gunicorn」一発で治ったこともありました。

6. データベースのログイン情報をサーバーの環境変数に記述

MySQL のデータベースを使用していて、settings.py ではユーザー名とパスワードを環境変数から取る様に設定しています。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'データベース名',
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': '',
        'PORT': '',
    }
}

そのため、サーバーの環境変数として記述します。ホームディレクトリの .bashrc ファイルの最下部に下記を追加しました。

export DB_USER='ユーザー名'
export DB_PASSWORD='パスワード'

7. 静的ファイルの配置

コマンド「python manage.py collectstatic」を実行し、settings.py で STATIC_ROOT に設定したパスに静的ファイルを集約します。

$ python manage.py collectstatic

これでとりあえず本番環境でも動くと思います。

さくらインターネットの DNS で設定するゾーン情報を理解したい

さくらインターネットのドメイン管理画面でドメインのゾーン情報をヘルプページを見ながらなんとか設定しました。

ただ、それぞれの項目が何を意味しているのかわからなかったので調べたことをまとめます。さくらインターネットの管理画面で設定した内容は下記の画像の通り。ドメイン名「meatthezoo.com」に対して設定しました。

設定内容

簡単ですがそれぞれの設定の意味は下記の通り。

エントリ名タイプデータ説明
@NSns1.dns.ne.jp.「meatthezoo.com」に対してさくらインターネット運営の権威DNSサーバー「ns1.dns.ne.jp.」を指定。
@NSns2.dns.ne.jp.「meatthezoo.com」に対してさくらインターネット運営の権威DNSサーバー「ns2.dns.ne.jp.」を指定。
@A123.456.78.90「meatthezoo.com」を IP アドレス「123.456.78.90」で使用する。
@MX10 @「meatthezoo.com」をメールサーバーに使用する。優先度を 10 に設定。
wwwCNAME@サブドメイン「www」を使用した場合にホスト「meatthezoo.com」と同じ設定を適用する。
mailCNAME@サブドメイン「mail」を使用した場合にホスト「meatthezoo.com」と同じ設定を適用する。
ftpCNAME@サブドメイン「ftp」を使用した場合にホスト「meatthezoo.com」と同じ設定を適用する。

たびたび出てくる「@」は設定対象のドメイン自身(今回の場合 meatthezoo.com)を表すそうです。

タイプとは

「タイプ」項目に登場した文字列の意味は下記の通りです。他にも種類がある様ですがとりあえず今回のゾーン情報の設定に出てきたものだけまとめます。

タイプ意味
NSゾーン情報を管理するネームサーバーのサーバー名を定義するレコード。ホスト(FQDN)をAレコードとして設定されていることが必要。
AIPv4でホスト名とIPアドレスの関連づけを定義するレコード。「www」などのホスト名を入力し、VALUEにグローバルIPアドレスを入力することによって、サーバーへの名前解決が行われる。
CNAME正規ホスト名に対する別名を定義するレコード。ホスト(FQDN)をAレコードとして設定されていることが必要。
MX対象ドメイン宛のメールの配送先(メールサーバ)のホスト名を定義するレコード。ホスト(FQDN)をAレコードとして設定されていることが必要。

Django のフォームで投稿した内容を Postfix でメール送信する方法

Django で作ったサイトのフォームで受け付けた情報を自分の Gmail アカウントへ送信する様に設定します。受信については特に考慮していません。

サーバーの OS は Ubuntu 20.04 となっています。

Postfix の設定

コマンド「sudo apt install postfix」を実行し、Postfix をインストールします。

すると下記の様な画面が表示されます。

「General type of mail configuration」の文言の後にいくつか選択肢が表示されますが、No configuration を選択します。

/etc/postfix/main.cfの編集

インストールが完了したらコマンド「sudo cp /usr/share/postfix/main.cf.debian /etc/postfix/main.cf」を実行し、postconf コマンドで main.cf ファイルを編集していきます。hostname、mydomain、myorigin の3つを確認、設定します。

hostname の設定

DNS の MX レコードで指定されているホスト名を指定します。

$ sudo postconf -e "myhostname = mail.example.com"

コマンド「vi /etc/postfix/main.cf」で main.cf を確認すると「myhostname = mail.example.com」が追記されているはずです。

mydomain の設定

mydomain は hostname の値によって自動的に決まります。コマンド「postconf mydomain」を実行して確認できます。hostname からサブドメインが除外された値になっているはずです。

$ postconf mydomain
mydomain = example.com

もし上記の様な値が返ってこない場合はコマンド「sudo postconf -e "mydomain = example.com"」で明示的に main.cf に設定します。

myorigin の設定

myorigin は デフォルトでは $myhostname を参照しています。

$ postconf myorigin
myorigin = $myhostname

代わりに $mydomain を参照する様変更する必要があります。

コマンド「sudo postconf -e "myorigin = $mydomain"」だとなぜかうまく反映されなかったので「sudo vi /etc/postfix/main.cf」でファイルを開いて直接「myorigin = $mydomain」を記述しました。

$ postconf myorigin
myorigin = $mydomain

Postfix の再起動

コマンド「sudo systemctl restart postfix.service」で Postfix を再起動します。

$ sudo systemctl restart postfix.service
$ 

main.cf には下記の2行が追記されていれば Postfix の設定は完了です。

myhostname = mail.example.com
myorigin = $mydomain

Django の settings.py の編集

Django プロジェクトの settings.py に下記を設定します。

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
DEFAULT_FROM_EMAIL = 'Sender <admin@example.com>'

動作確認

Django サイトのフォームで試しに投稿したところ、一応指定した G メールアカウントには届きました。

この時点で一応最低限の目的は達成されましたが、メールの暗号化とメールの認証について気になったので下記にまとめます。

メールの暗号化

Postfix で Gmail アカウント宛に送信したメールの詳細を見てみると「このメールは sakura.ne.jp で暗号化されませんでした」と表示があります。

これを解決するには、送信先がTLS(Transport Layer Security)に対応する場合はTLSで暗号化して送信する設定を Postfix 側で適用する必要があります。

下記のコマンドで main.cf に「smtp_tls_security_level = may」と追記し、 Postfix を再起動します。

$ sudo postconf -e "smtp_tls_security_level = may"
$ sudo systemctl restart postfix.service
$ 

再度メールを送って同じ部分を確認してみると「標準的な暗号化(TLS)」という表示に変わりました。

これでメールの暗号化は完了です。

メールの認証

Gメールで受信したメールの送信者のアイコンにカーソルを合わせると「Gメールでは、このメールが(スパム発信者からではなく)本当に example.com から送信されたメールであることを確認できませんでした。」という文言も表示されます。

この点に関しては手間がかかりそうな気がするので追々対応した際に追記します。

【ログ】Ubuntu 20.04: sudo apt install postfix

  • 実行コマンド:sudo apt install postfix
  • 実行日:2021/05/07
  • 実行環境:Ubuntu 20.04
$ sudo apt install postfix
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Suggested packages:
  procmail postfix-mysql postfix-pgsql postfix-ldap postfix-pcre postfix-lmdb postfix-sqlite sasl2-bin | dovecot-common resolvconf postfix-cdb mail-reader
  postfix-doc
The following NEW packages will be installed:
  postfix
0 upgraded, 1 newly installed, 0 to remove and 29 not upgraded.
Need to get 1198 kB of archives.
After this operation, 4540 kB of additional disk space will be used.
Get:1 http://jp.archive.ubuntu.com/ubuntu focal-updates/main amd64 postfix amd64 3.4.13-0ubuntu1 [1198 kB]
Fetched 1198 kB in 0s (4892 kB/s)
Preconfiguring packages ...
Selecting previously unselected package postfix.
(Reading database ... 151877 files and directories currently installed.)
Preparing to unpack .../postfix_3.4.13-0ubuntu1_amd64.deb ...
Unpacking postfix (3.4.13-0ubuntu1) ...
Setting up postfix (3.4.13-0ubuntu1) ...
Adding group `postfix' (GID 121) ...
Done.
Adding system user `postfix' (UID 114) ...
Adding new user `postfix' (UID 114) with group `postfix' ...
Not creating home directory `/var/spool/postfix'.
Creating /etc/postfix/dynamicmaps.cf
Adding group `postdrop' (GID 122) ...
Done.
/etc/aliases does not exist, creating it.

Postfix (main.cf) was not set up.  Start with
  cp /usr/share/postfix/main.cf.debian /etc/postfix/main.cf
.  If you need to make changes, edit /etc/postfix/main.cf (and others) as 
needed.  To view Postfix configuration values, see postconf(1).

After modifying main.cf, be sure to run 'systemctl reload postfix'.

Created symlink /etc/systemd/system/multi-user.target.wants/postfix.service → /lib/systemd/system/postfix.service.
Processing triggers for ufw (0.36-6) ...
Processing triggers for systemd (245.4-4ubuntu3.6) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for rsyslog (8.2001.0-1ubuntu1.1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...

Django の クラスベースビューで URL のパラメータを使う

まず URL ディレクトリの文字列を使う場合の復習

Django の ListView などでテンプレートに返すデータをフィルタリングする際、urls.py で設定した URL ディレクトリの文字列を取得してそれを元にすることがあると思います。

下記の様な感じで get_queryset 関数で self.kwargs から値を取り出す感じですね。

# urls.py
urlpatterns = [
    path('<str:some_code>/', views.SomeData.as_view(), name="some_data"),
]
# views.py
class SomeData(generic.ListView):
    ### 一部省略 ###
    def get_queryset(self):
        code = self.kwargs['some_code']
        return SomeDataModel.objects.filter(some_code_column=code)

ただ、今回はそうではなく URL のパラメータを「ドメイン名.com/?キー=値&キー=値」の形式で取得してそれをデータ取得に使いたいと思います。

URL のパラメータを使いたい

self.request.GET.get(パラメータキー) で取得

get_queryset 関数をオーバーライドする際に self.request.GET.get(パラメータのキー) で取得できます。

例えば「http://127.0.0.1:8000/devicelist/?brand_nm=apple&category=laptop,phone」の様な URL の場合。

「?brand_nm=apple&category=laptop,phone」の部分をビューの処理に使いたいとします。

# views.py 内 get_queryset 関数
def get_queryset(self):
    brand = self.request.GET.get('brand_nm')
    return SomeDataModel.objects.filter(brand_nm=brand)

値が一つだけの場合

値が一つだけの場合(brand_nm=apple)は「self.request.GET.get(キー)」でそのまま値が一つ取得できます。

print(self.request.GET.get('brand_nm'))
# apple

値が複数の場合

複数の値を「,」で繋げて URL に渡した場合(category=laptop,phone)は、「,」が含まれただけの一つの文字列になっています。

print(self.request.GET.get('category'))
# laptop, phone

なので一旦 .split(',') を通してリストにしてあげる必要があります。

print(self.request.GET.get('category').split(','))
# ['laptop', 'phone']
print(self.request.GET.get('category').split(',')[0])
# laptop
print(self.request.GET.get('category').split(',')[1])
# phone

値を指定していない場合

URL で渡していないキーを指定すると None が返ってきます。

print(self.request.GET.get('product_type'))
# None

Django の ModelForm で select option をテーブルから参照する

やりたいこと:Django の ModelForm を作るときに、ドロップダウンメニューの選択肢(select option)をデータベースのテーブルから持ってきたい。

結論から言いますと Foreign Key を使って別のテーブルのユニークキーをフォームの選択肢として利用します。

models.py でドロップダウンにしたいカラムに models.ForeignKey を適用

まず、models.py でドロップダウン表示にしたい項目に models.ForeignKey を適用します。

別テーブルでユニークになっている値(つまりドロップダウンの候補になる値)が入るという設定をします。

# models.py

class IgMstProduct(models.Model):
    id = models.AutoField(primary_key=True)
    product_nm = models.CharField(max_length=60, blank=True, null=True)
    brand_cd = models.ForeignKey('IgMstBrand',on_delete=models.SET_NULL, null=True, db_column='brand_cd')
    product_url = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'ig_mst_product'

上記の設定時、「db_column」で DB 側で実際に情報を受け取るカラム名を指定しないと、フォーム Submit 時に「1054, "Unknown column '〜_id' in 'field list'"」というエラーが返ってくると思います。

詳しくは調べていませんがどうやら Django が自動的に「〜_id」のカラム名で処理をしようとするらしいです。

forms.py で ModelChoiceField を設定

下記の様に対象の項目に対して forms.ModelChoiceField(queryset=モデル名.objects.all()) を設定してみると、なんとなくそれっぽくドロップダウンが表示されます。

# forms.py

class IgProductForm(forms.ModelForm):
    brand_cd = forms.ModelChoiceField(queryset=IgMstBrand.objects.all())

    class Meta:
        model = IgMstProduct
        fields = ('product_nm', 'product_category', 'brand_cd', 'product_url',)

が、このままだとドロップダウンの表示名が下記の様に「モデル名 object (1)」とかになるので変更します。

<select name="brand_cd" required id="id_brand_cd">
  <option value="" selected>---------</option>
  <option value="1">モデル名 object (1)</option>
  <option value="2">モデル名 object (2)</option>
  <option value="3">モデル名 object (3)</option>
  <option value="4">モデル名 object (4)</option>
  <option value="5">モデル名 object (5)</option>
  <option value="6">モデル名 object (6)</option>
</select>

ModelChoiceField を継承する別クラスを作成し、そこで label_from_instance 関数をオーバーライドし、return obj.表示したいカラム名 とすれば表示したいカラム名が表示名が変わります。

# forms.py

class CustomModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj): # label_from_instance 関数をオーバーライド
         return obj.brand_nm # 表示したいカラム名を return


class IgProductForm(forms.ModelForm):
    brand_cd = CustomModelChoiceField(queryset=IgMstBrand.objects.all()) # 上記のクラスを参照する様変更

    class Meta:
        model = IgMstProduct
        fields = ('product_nm', 'product_category', 'brand_cd', 'product_url',)
<select name="brand_cd" required id="id_brand_cd">
  <option value="" selected>---------</option>
  <option value="1">Nikon</option>
  <option value="2">Canon</option>
  <option value="3">Sony</option>
  <option value="4">Fujifilm</option>
  <option value="5">Leica</option>
  <option value="6">Olympus</option>
</select>

Django の REST framework で JSON を返す API を作る方法

Python 仮想環境内に作ったプロジェクトに API 用の独自のアプリケーションを作り、その中に View を作ります。

ここで紹介するのは単純にテーブル内のデータを全て GET で抽出してそのまま JSON 形式で返すだけのものです。POST や DELETE などは触れていません。

  1. 下準備
    • API 用 Django アプリケーションの作成
    • djangorestframework のインストール
    • urls.py の設定
    • models.py にモデルを記述
  2. シリアライザの作成
  3. ビューの作成
    • class based view の場合
    • function based view の場合
  4. 動作確認

下準備

API 用 Django アプリケーションの作成

API 用にアプリケーション「api」を作成します。

% python manage.py startapp api

settings.py の INSTALLED_APPS に追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig', # 追記
]

djangorestframework のインストール

コマンド「pip install djangorestframework」を実行します。

% pip install djangorestframework
Collecting djangorestframework
  Downloading djangorestframework-3.12.4-py3-none-any.whl (957 kB)
     |████████████████████████████████| 957 kB 4.1 MB/s 
Requirement already satisfied: django>=2.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from djangorestframework) (3.2)
Requirement already satisfied: pytz in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (2021.1)
Requirement already satisfied: sqlparse>=0.2.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (0.4.1)
Requirement already satisfied: asgiref<4,>=3.3.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (3.3.4)
Installing collected packages: djangorestframework
Successfully installed djangorestframework-3.12.4
%

settings.py の INSTALLED_APPS に追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig',
    'rest_framework', # 追記
]

urls.py の設定

アプリケーション「api」ディレクトリに url.py を作成した上で、プロジェクトレベルの url.py から参照します。

from django.contrib import admin
from django.urls import path, include # 追記

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')), # 追記
]

models.py にモデルを記述

API で使用したいモデルを models.py に記述します。

今回すでにデータベース上にテーブルを用意してあるのでコマンド「python manage.py inspectdb テーブル名」でモデル情報を抽出します。

% python manage.py inspectdb yt_analysis_07
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models


class YtAnalysis07(models.Model):
    channel_id = models.CharField(max_length=40, blank=True, null=True)
    channel_name = models.TextField(blank=True, null=True)
    view_count = models.BigIntegerField(blank=True, null=True)
    like_count = models.IntegerField(blank=True, null=True)
    dislike_count = models.IntegerField(blank=True, null=True)
    favorite_count = models.IntegerField(blank=True, null=True)
    comment_count = models.IntegerField(blank=True, null=True)
    video_count = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'yt_analysis_07'
% 

クラス文を models.py にコピーしますが、その際に 1 つ「primary_key=True」のフィールドを持つ必要があるそうです。

シリアライザの作成

Python のリスト・辞書形式のデータを JSON に変換するためのシリアライザを作成します。

アプリケーションフォルダ(今回は api/ )に「serializers.py」というファイルを作成します。

from rest_framework import serializers
from .models import YtAnalysis07 # モデルをインポート

class APISerializer(serializers.ModelSerializer):
    class Meta:
        model = YtAnalysis07 # 使用するモデル
        fields = '__all__' # 処理対象にするフィールド(今回は全項目)

ビューの作成

API のビューを作成します。ざっくり言うとモデルからデータを抽出し、シリアライザに渡して JSON に変換し、その JSON データをレスポンスとして返します。

class based view の場合

from rest_framework import viewsets
from .serializers import APISerializer
from .models import YtAnalysis07

class DataListView(viewsets.ModelViewSet):
    queryset = YtAnalysis07.objects.all() # モデルからデータを抽出するクエリセット
    serializer_class = APISerializer # 使用するシリアライザ

urls.py の設定は下記の様にします。

from django.urls import path
from . import views

app_name = 'api'
urlpatterns = [
    path('data-list/', views.DataListView.as_view({'get': 'list'}), name="data-list"),
]

function based view の場合

from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import APISerializer
from .models import YtAnalysis07

@api_view(['GET']) # GET のみに対応
def dataList(request):
    api_data = YtAnalysis07.objects.all() # モデルからデータを抽出する
    serializer = APISerializer(api_data, many=True) # シリアライザにデータを渡す
    return Response(serializer.data) シリアル可されたデータを return で返す

urls.py の設定は下記の様にします。

from django.urls import path
from . import views

app_name = 'api'
urlpatterns = [
    path('data-list/', views.dataList, name="data-list"),
]

動作確認

設定した URL をブラウザに打ち込むと下記の様な画面が表示されます。JSON データも見えます。

ブラウザで URL を叩くと上記の様な画面で表示されますが、例えばターミナルで URL を requests.get すると下記の様に JSON 形式のデータだけが返ってきます。

>>> import requests
>>> r = requests.get('http://127.0.0.1:8000/api/data-list/')
>>> r.text
'[{"channel_id":"UCLkAepWjdylmXSltofFvsYQ","channel_name":"BANGTANTV","view_count":22423409,"like_count":7325674,"dislike_count":20936,"favorite_count":0,"comment_count":381315,"video_count":9},{"channel_id":"UCE_M8A5yxnLfW0KghEeajjw","channel_name":"Apple","view_count":19044060,"like_count":600159,"dislike_count":21023,"favorite_count":0,"comment_count":0,"video_count":10},

これを Django のテンプレートから JavaScript で呼び出すなどして活用します。

【ログ】macOS Big Sur 11.2.2: brew install php

  • 実行コマンド:brew install php
  • 実行日:2021/04/13
  • 実行環境:macOS Big Sur 11.2.2
% brew install php
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
==> Updated Casks
Updated 1 cask.

==> Downloading https://ghcr.io/v2/homebrew/core/apr/manifests/1.7.0_2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/apr/blobs/sha256:d9a9554a726ec60e124055a55747e6e
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:d9a9554a7
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/apr-util/manifests/1.6.1_3
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/apr-util/blobs/sha256:34dd598e189eefff7e09be3ee9
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:34dd598e1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/argon2/manifests/20190702_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/argon2/blobs/sha256:a9dd363964a2a633ace13aff04e4
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:a9dd36396
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/aspell/manifests/0.60.8-1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/aspell/blobs/sha256:abf04f9f474e21d070e22667204c
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:abf04f9f4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/m4/manifests/1.4.18-1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/m4/blobs/sha256:0df9083b268f76a3cda0c9f0d2ce84b5
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:0df9083b2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/autoconf/manifests/2.71
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/autoconf/blobs/sha256:0aa64f171bac19ce6ac0c0ca69
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:0aa64f171
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/brotli/manifests/1.0.9
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/brotli/blobs/sha256:9d3009fd246d0f6cf9fd11d0a3bd
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:9d3009fd2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libmetalink/manifests/0.1.3
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libmetalink/blobs/sha256:ec4a4a8f898432cccfa2198
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:ec4a4a8f8
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libssh2/manifests/1.9.0_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libssh2/blobs/sha256:f9a31faed068d80fff508f2a08d
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:f9a31faed
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/c-ares/manifests/1.17.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/c-ares/blobs/sha256:514de64e48f4d2c6e448547a30ba
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:514de64e4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/jemalloc/manifests/5.2.1_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/jemalloc/blobs/sha256:7797788be2da677a8343ac6199
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:7797788be
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libev/manifests/4.33
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libev/blobs/sha256:95ddf4b85924a6a10d4a88b6eb526
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:95ddf4b85
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/nghttp2/manifests/1.43.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/nghttp2/blobs/sha256:e6112c4ce4b08b60edbb3d7fca3
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:e6112c4ce
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/openldap/manifests/2.4.58
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/openldap/blobs/sha256:a80cfbc1ab79fd40e646d0160c
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:a80cfbc1a
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/rtmpdump/manifests/2.4.20151223_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/rtmpdump/blobs/sha256:b9e42bf8023a8634a741402f7f
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:b9e42bf80
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/zstd/manifests/1.4.9
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/zstd/blobs/sha256:34a6c2cc25d1a7bca6e2294ec3d024
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:34a6c2cc2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/curl/manifests/7.76.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/curl/blobs/sha256:75d8508af0a6f1751b945b275b2cd1
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:75d8508af
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libtool/manifests/2.4.6_3
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libtool/blobs/sha256:a70ed5b9d74ec3b06bfc202ab36
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:a70ed5b9d
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/unixodbc/manifests/2.3.9
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/unixodbc/blobs/sha256:1b7672ec7e627941ab8e36dbe9
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:1b7672ec7
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/freetds/manifests/1.2.18
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/freetds/blobs/sha256:e1915b8ec9a59b5146e50310e77
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:e1915b8ec
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/manifests/1.6.37
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libpng/blobs/sha256:a8f1c35f9f004c4f7878c30027e3
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:a8f1c35f9
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/freetype/manifests/2.10.4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/freetype/blobs/sha256:01b464b98584ba5777d8fc4605
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:01b464b98
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/manifests/2.13.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/fontconfig/blobs/sha256:ee5961891c9e943c8bea6ad2
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:ee5961891
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/jpeg/manifests/9d
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/jpeg/blobs/sha256:c565929a4901365a3408b57275802f
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:c565929a4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libtiff/manifests/4.2.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libtiff/blobs/sha256:31dc53e161b68394309dfe7743f
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:31dc53e16
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/webp/manifests/1.2.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/webp/blobs/sha256:1099da9d890c863542eb14e0de9f82
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:1099da9d8
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gd/manifests/2.3.2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gd/blobs/sha256:2c746f463d1b0ceaa2a9986b9ace87da
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:2c746f463
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libffi/manifests/3.3_3
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libffi/blobs/sha256:8a7a02cffb368dfdeaeb1176a7a7
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:8a7a02cff
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pcre/manifests/8.44
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pcre/blobs/sha256:a67dd6141e117f849bbb7d3bde92ff
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:a67dd6141
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gdbm/manifests/1.19
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gdbm/blobs/sha256:3581501b051db1c0d1acccc710fe04
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:3581501b0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/mpdecimal/manifests/2.5.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/mpdecimal/blobs/sha256:255b6226cdcfaf0d401670125
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:255b6226c
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/sqlite/manifests/3.35.4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/sqlite/blobs/sha256:861dc044ea531c39a2105010107f
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:861dc044e
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/xz/manifests/5.2.5
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/xz/blobs/sha256:4fbd4a9e3eb49c27e83bd125b0e76d38
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:4fbd4a9e3
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/python/3.9/manifests/3.9.4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/python/3.9/blobs/sha256:77ba90d10acfc70e57781aae
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:77ba90d10
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/glib/manifests/2.68.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/glib/blobs/sha256:7d671e3104d1a3e8d620ef99b4a1c9
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:7d671e310
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gmp/manifests/6.2.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gmp/blobs/sha256:6a44705536f25c4b9f8547d44d129ae
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:6a4470553
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libpq/manifests/13.2
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libpq/blobs/sha256:eae0a60decded85f7b0af6c880f81
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:eae0a60de
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libsodium/manifests/1.0.18_1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libsodium/blobs/sha256:5afc5678e30a174c1e46f1e90
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:5afc5678e
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libzip/manifests/1.7.3
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/libzip/blobs/sha256:261afbcf4c391242a760158dd337
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:261afbcf4
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/oniguruma/manifests/6.9.6
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/oniguruma/blobs/sha256:505599ad17e21360a58a89db2
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:505599ad1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/manifests/10.36
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/pcre2/blobs/sha256:b2edbffaf229fc490843e83b43c4e
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:b2edbffaf
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/tidy-html5/manifests/5.6.0
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/tidy-html5/blobs/sha256:9c4ed7860ed418e2a018690e
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:9c4ed7860
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/php/manifests/8.0.3-1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/php/blobs/sha256:747463615874613ec5ea0e07f36e2ed
==> Downloading from https://pkg-containers-az.githubusercontent.com/ghcr1/blobs/sha256:747463615
######################################################################## 100.0%
==> Installing dependencies for php: apr, apr-util, argon2, aspell, m4, autoconf, brotli, libmetalink, libssh2, c-ares, jemalloc, libev, nghttp2, openldap, rtmpdump, zstd, curl, libtool, unixodbc, freetds, libpng, freetype, fontconfig, jpeg, libtiff, webp, gd, libffi, pcre, gdbm, mpdecimal, sqlite, xz, python@3.9, glib, gmp, libpq, libsodium, libzip, oniguruma, pcre2 and tidy-html5
==> Installing php dependency: apr
==> Pouring apr--1.7.0_2.big_sur.bottle.tar.gz
==> Caveats
apr is keg-only, which means it was not symlinked into /usr/local,
because Apple's CLT provides apr.

If you need to have apr first in your PATH, run:
  echo 'export PATH="/usr/local/opt/apr/bin:$PATH"' >> ~/.zshrc

For compilers to find apr you may need to set:
  export LDFLAGS="-L/usr/local/opt/apr/lib"
  export CPPFLAGS="-I/usr/local/opt/apr/include"

==> Summary
🍺  /usr/local/Cellar/apr/1.7.0_2: 104 files, 1.4MB
==> Installing php dependency: apr-util
==> Pouring apr-util--1.6.1_3.big_sur.bottle.tar.gz
==> Caveats
apr-util is keg-only, which means it was not symlinked into /usr/local,
because Apple's CLT provides apr (but not apr-util).

If you need to have apr-util first in your PATH, run:
  echo 'export PATH="/usr/local/opt/apr-util/bin:$PATH"' >> ~/.zshrc

==> Summary
🍺  /usr/local/Cellar/apr-util/1.6.1_3: 54 files, 878.3KB
==> Installing php dependency: argon2
==> Pouring argon2--20190702_1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/argon2/20190702_1: 12 files, 667.5KB
==> Installing php dependency: aspell
==> Pouring aspell--0.60.8.big_sur.bottle.1.tar.gz
🍺  /usr/local/Cellar/aspell/0.60.8: 767 files, 322.7MB
==> Installing php dependency: m4
==> Pouring m4--1.4.18.big_sur.bottle.1.tar.gz
==> Caveats
m4 is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have m4 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/m4/bin:$PATH"' >> ~/.zshrc

==> Summary
🍺  /usr/local/Cellar/m4/1.4.18: 13 files, 672.3KB
==> Installing php dependency: autoconf
==> Pouring autoconf--2.71.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/autoconf/2.71: 71 files, 3.2MB
==> Installing php dependency: brotli
==> Pouring brotli--1.0.9.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/brotli/1.0.9: 25 files, 2.4MB
==> Installing php dependency: libmetalink
==> Pouring libmetalink--0.1.3.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libmetalink/0.1.3: 31 files, 215.3KB
==> Installing php dependency: libssh2
==> Pouring libssh2--1.9.0_1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libssh2/1.9.0_1: 184 files, 970.1KB
==> Installing php dependency: c-ares
==> Pouring c-ares--1.17.1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/c-ares/1.17.1: 85 files, 672.5KB
==> Installing php dependency: jemalloc
==> Pouring jemalloc--5.2.1_1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/jemalloc/5.2.1_1: 16 files, 2MB
==> Installing php dependency: libev
==> Pouring libev--4.33.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libev/4.33: 12 files, 484.0KB
==> Installing php dependency: nghttp2
==> Pouring nghttp2--1.43.0.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/nghttp2/1.43.0: 24 files, 2.8MB
==> Installing php dependency: openldap
==> Pouring openldap--2.4.58.big_sur.bottle.tar.gz
==> Caveats
openldap is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have openldap first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openldap/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/openldap/sbin:$PATH"' >> ~/.zshrc

For compilers to find openldap you may need to set:
  export LDFLAGS="-L/usr/local/opt/openldap/lib"
  export CPPFLAGS="-I/usr/local/opt/openldap/include"

==> Summary
🍺  /usr/local/Cellar/openldap/2.4.58: 329 files, 7.1MB
==> Installing php dependency: rtmpdump
==> Pouring rtmpdump--2.4+20151223_1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/rtmpdump/2.4+20151223_1: 20 files, 603.7KB
==> Installing php dependency: zstd
==> Pouring zstd--1.4.9.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/zstd/1.4.9: 26 files, 3.4MB
==> Installing php dependency: curl
==> Pouring curl--7.76.0.big_sur.bottle.tar.gz
==> Caveats
curl is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have curl first in your PATH, run:
  echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.zshrc

For compilers to find curl you may need to set:
  export LDFLAGS="-L/usr/local/opt/curl/lib"
  export CPPFLAGS="-I/usr/local/opt/curl/include"


zsh completions have been installed to:
  /usr/local/opt/curl/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/curl/7.76.0: 484 files, 3.8MB
==> Installing php dependency: libtool
==> Pouring libtool--2.4.6_3.big_sur.bottle.tar.gz
==> Caveats
In order to prevent conflicts with Apple's own libtool we have prepended a "g"
so, you have instead: glibtool and glibtoolize.
==> Summary
🍺  /usr/local/Cellar/libtool/2.4.6_3: 71 files, 3.7MB
==> Installing php dependency: unixodbc
==> Pouring unixodbc--2.3.9.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/unixodbc/2.3.9: 46 files, 2.2MB
==> Installing php dependency: freetds
==> Pouring freetds--1.2.18.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/freetds/1.2.18: 1,259 files, 13.8MB
==> Installing php dependency: libpng
==> Pouring libpng--1.6.37.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libpng/1.6.37: 27 files, 1.3MB
==> Installing php dependency: freetype
==> Pouring freetype--2.10.4.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/freetype/2.10.4: 64 files, 2.3MB
==> Installing php dependency: fontconfig
==> Pouring fontconfig--2.13.1.big_sur.bottle.tar.gz
==> Regenerating font cache, this may take a while
==> /usr/local/Cellar/fontconfig/2.13.1/bin/fc-cache -frv
🍺  /usr/local/Cellar/fontconfig/2.13.1: 531 files, 3.6MB
==> Installing php dependency: jpeg
==> Pouring jpeg--9d.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/jpeg/9d: 21 files, 954.0KB
==> Installing php dependency: libtiff
==> Pouring libtiff--4.2.0.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libtiff/4.2.0: 248 files, 4.4MB
==> Installing php dependency: webp
==> Pouring webp--1.2.0.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/webp/1.2.0: 39 files, 2.4MB
==> Installing php dependency: gd
==> Pouring gd--2.3.2.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/gd/2.3.2: 35 files, 1.4MB
==> Installing php dependency: libffi
==> Pouring libffi--3.3_3.big_sur.bottle.tar.gz
==> Caveats
libffi is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

For compilers to find libffi you may need to set:
  export LDFLAGS="-L/usr/local/opt/libffi/lib"
  export CPPFLAGS="-I/usr/local/opt/libffi/include"

==> Summary
🍺  /usr/local/Cellar/libffi/3.3_3: 17 files, 540.5KB
==> Installing php dependency: pcre
==> Pouring pcre--8.44.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/pcre/8.44: 204 files, 5.8MB
==> Installing php dependency: gdbm
==> Pouring gdbm--1.19.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/gdbm/1.19: 24 files, 791.3KB
==> Installing php dependency: mpdecimal
==> Pouring mpdecimal--2.5.1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/mpdecimal/2.5.1: 71 files, 2.1MB
==> Installing php dependency: sqlite
==> Pouring sqlite--3.35.4.big_sur.bottle.tar.gz
==> Caveats
sqlite is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have sqlite first in your PATH, run:
  echo 'export PATH="/usr/local/opt/sqlite/bin:$PATH"' >> ~/.zshrc

For compilers to find sqlite you may need to set:
  export LDFLAGS="-L/usr/local/opt/sqlite/lib"
  export CPPFLAGS="-I/usr/local/opt/sqlite/include"

==> Summary
🍺  /usr/local/Cellar/sqlite/3.35.4: 11 files, 4.2MB
==> Installing php dependency: xz
==> Pouring xz--5.2.5.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/xz/5.2.5: 95 files, 1.4MB
==> Installing php dependency: python@3.9
==> Pouring python@3.9--3.9.4.big_sur.bottle.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/2to3
Target /usr/local/bin/2to3
already exists. You may want to remove it:
  rm '/usr/local/bin/2to3'

To force the link and overwrite all conflicting files:
  brew link --overwrite python@3.9

To list all files that would be deleted:
  brew link --overwrite --dry-run python@3.9

Possible conflicting files are:
/usr/local/bin/2to3 -> /Library/Frameworks/Python.framework/Versions/3.8/bin/2to3
/usr/local/bin/idle3 -> /Library/Frameworks/Python.framework/Versions/3.8/bin/idle3
/usr/local/bin/pydoc3 -> /Library/Frameworks/Python.framework/Versions/3.8/bin/pydoc3
/usr/local/bin/python3 -> /Library/Frameworks/Python.framework/Versions/3.8/bin/python3
/usr/local/bin/python3-config -> /Library/Frameworks/Python.framework/Versions/3.8/bin/python3-config
==> /usr/local/Cellar/python@3.9/3.9.4/bin/python3 -m ensurepip
==> /usr/local/Cellar/python@3.9/3.9.4/bin/python3 -m pip install -v --no-deps --no-index --upgra
==> Caveats
Python has been installed as
  /usr/local/bin/python3

Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to
`python3`, `python3-config`, `pip3` etc., respectively, have been installed into
  /usr/local/opt/python@3.9/libexec/bin

You can install Python packages with
  pip3 install <package>
They will install into the site-package directory
  /usr/local/lib/python3.9/site-packages

tkinter is no longer included with this formula, but it is available separately:
  brew install python-tk@3.9

See: https://docs.brew.sh/Homebrew-and-Python
==> Summary
🍺  /usr/local/Cellar/python@3.9/3.9.4: 3,047 files, 54.2MB
==> Installing php dependency: glib
==> Pouring glib--2.68.0.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/glib/2.68.0: 442 files, 21MB
==> Installing php dependency: gmp
==> Pouring gmp--6.2.1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/gmp/6.2.1: 21 files, 3.3MB
==> Installing php dependency: libpq
==> Pouring libpq--13.2.big_sur.bottle.tar.gz
==> Caveats
libpq is keg-only, which means it was not symlinked into /usr/local,
because conflicts with postgres formula.

If you need to have libpq first in your PATH, run:
  echo 'export PATH="/usr/local/opt/libpq/bin:$PATH"' >> ~/.zshrc

For compilers to find libpq you may need to set:
  export LDFLAGS="-L/usr/local/opt/libpq/lib"
  export CPPFLAGS="-I/usr/local/opt/libpq/include"

==> Summary
🍺  /usr/local/Cellar/libpq/13.2: 2,270 files, 26.5MB
==> Installing php dependency: libsodium
==> Pouring libsodium--1.0.18_1.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libsodium/1.0.18_1: 73 files, 1MB
==> Installing php dependency: libzip
==> Pouring libzip--1.7.3.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/libzip/1.7.3: 142 files, 757.8KB
==> Installing php dependency: oniguruma
==> Pouring oniguruma--6.9.6.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/oniguruma/6.9.6: 16 files, 1.4MB
==> Installing php dependency: pcre2
==> Pouring pcre2--10.36.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/pcre2/10.36: 230 files, 6.2MB
==> Installing php dependency: tidy-html5
==> Pouring tidy-html5--5.6.0.big_sur.bottle.tar.gz
🍺  /usr/local/Cellar/tidy-html5/5.6.0: 14 files, 2.6MB
==> Installing php
==> Pouring php--8.0.3.big_sur.bottle.1.tar.gz
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set php_ini /usr/local/etc/php/8.0/php.ini system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set php_dir /usr/local/share/pear system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set doc_dir /usr/local/share/pear/doc system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set ext_dir /usr/local/lib/php/pecl/20200930 syst
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set bin_dir /usr/local/opt/php/bin system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set data_dir /usr/local/share/pear/data system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set cfg_dir /usr/local/share/pear/cfg system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set www_dir /usr/local/share/pear/htdocs system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set man_dir /usr/local/share/man system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set test_dir /usr/local/share/pear/test system
==> /usr/local/Cellar/php/8.0.3/bin/pear config-set php_bin /usr/local/opt/php/bin/php system
==> /usr/local/Cellar/php/8.0.3/bin/pear update-channels
==> Caveats
To enable PHP in Apache add the following to httpd.conf and restart Apache:
    LoadModule php_module /usr/local/opt/php/lib/httpd/modules/libphp.so

    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>

Finally, check DirectoryIndex includes index.php
    DirectoryIndex index.php index.html

The php.ini and php-fpm.ini file can be found in:
    /usr/local/etc/php/8.0/

To have launchd start php now and restart at login:
  brew services start php
Or, if you don't want/need a background service you can just run:
  php-fpm
==> Summary
🍺  /usr/local/Cellar/php/8.0.3: 499 files, 77.8MB
==> Caveats
==> apr
apr is keg-only, which means it was not symlinked into /usr/local,
because Apple's CLT provides apr.

If you need to have apr first in your PATH, run:
  echo 'export PATH="/usr/local/opt/apr/bin:$PATH"' >> ~/.zshrc

For compilers to find apr you may need to set:
  export LDFLAGS="-L/usr/local/opt/apr/lib"
  export CPPFLAGS="-I/usr/local/opt/apr/include"

==> apr-util
apr-util is keg-only, which means it was not symlinked into /usr/local,
because Apple's CLT provides apr (but not apr-util).

If you need to have apr-util first in your PATH, run:
  echo 'export PATH="/usr/local/opt/apr-util/bin:$PATH"' >> ~/.zshrc

==> m4
m4 is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have m4 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/m4/bin:$PATH"' >> ~/.zshrc

==> openldap
openldap is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have openldap first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openldap/bin:$PATH"' >> ~/.zshrc
  echo 'export PATH="/usr/local/opt/openldap/sbin:$PATH"' >> ~/.zshrc

For compilers to find openldap you may need to set:
  export LDFLAGS="-L/usr/local/opt/openldap/lib"
  export CPPFLAGS="-I/usr/local/opt/openldap/include"

==> curl
curl is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have curl first in your PATH, run:
  echo 'export PATH="/usr/local/opt/curl/bin:$PATH"' >> ~/.zshrc

For compilers to find curl you may need to set:
  export LDFLAGS="-L/usr/local/opt/curl/lib"
  export CPPFLAGS="-I/usr/local/opt/curl/include"


zsh completions have been installed to:
  /usr/local/opt/curl/share/zsh/site-functions
==> libtool
In order to prevent conflicts with Apple's own libtool we have prepended a "g"
so, you have instead: glibtool and glibtoolize.
==> libffi
libffi is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

For compilers to find libffi you may need to set:
  export LDFLAGS="-L/usr/local/opt/libffi/lib"
  export CPPFLAGS="-I/usr/local/opt/libffi/include"

==> sqlite
sqlite is keg-only, which means it was not symlinked into /usr/local,
because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have sqlite first in your PATH, run:
  echo 'export PATH="/usr/local/opt/sqlite/bin:$PATH"' >> ~/.zshrc

For compilers to find sqlite you may need to set:
  export LDFLAGS="-L/usr/local/opt/sqlite/lib"
  export CPPFLAGS="-I/usr/local/opt/sqlite/include"

==> python@3.9
Python has been installed as
  /usr/local/bin/python3

Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to
`python3`, `python3-config`, `pip3` etc., respectively, have been installed into
  /usr/local/opt/python@3.9/libexec/bin

You can install Python packages with
  pip3 install <package>
They will install into the site-package directory
  /usr/local/lib/python3.9/site-packages

tkinter is no longer included with this formula, but it is available separately:
  brew install python-tk@3.9

See: https://docs.brew.sh/Homebrew-and-Python
==> libpq
libpq is keg-only, which means it was not symlinked into /usr/local,
because conflicts with postgres formula.

If you need to have libpq first in your PATH, run:
  echo 'export PATH="/usr/local/opt/libpq/bin:$PATH"' >> ~/.zshrc

For compilers to find libpq you may need to set:
  export LDFLAGS="-L/usr/local/opt/libpq/lib"
  export CPPFLAGS="-I/usr/local/opt/libpq/include"

==> php
To enable PHP in Apache add the following to httpd.conf and restart Apache:
    LoadModule php_module /usr/local/opt/php/lib/httpd/modules/libphp.so

    <FilesMatch \.php$>
        SetHandler application/x-httpd-php
    </FilesMatch>

Finally, check DirectoryIndex includes index.php
    DirectoryIndex index.php index.html

The php.ini and php-fpm.ini file can be found in:
    /usr/local/etc/php/8.0/

To have launchd start php now and restart at login:
  brew services start php
Or, if you don't want/need a background service you can just run:
  php-fpm
%