2024/12/25

EC2でAmazon Linux 2023の設定あれこれ

## 作業前確認
[Amazon Linux 2023 リリースノート](https://docs.aws.amazon.com/ja_jp/linux/al2023/release-notes/relnotes.html)  

### インスタンスのネットワーク設定
```
ip addr show
```

[ip コマンド チートシート](https://access.redhat.com/sites/default/files/attachments/rh_ip_command_cheatsheet_1214_jcs_print_ja4.pdf)  
### 外部アクセス
```
ping 8.8.8.8
curl https://www.example.com
```

## OS基本設定関連
### SELinux無効化
[AWS ユーザーガイド](https://docs.aws.amazon.com/ja_jp/linux/al2023/ug/disable-option-selinux.html)  
[Red Hat Documentatioin](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/8/html/using_selinux/enabling_and_disabling_selinux-disabling_selinux_changing-selinux-states-and-modes)  
```
# 設定確認
sestatus

# grubbyを確認
rpm -q grubby
# ブートローダーを設定して、カーネルコマンドラインに selinux=0 を追加
sudo grubby --update-kernel ALL --args selinux=0

# 再起動
sudo reboot

# Disabledを確認
getenforce
```
この方法で停止起動するとSELinuxが有効化されていたが、今はどうか..  

### ipv6設定
```
# コピーして編集後にdiff
diff /etc/sysconfig/network /etc/sysconfig/network.org
3d2
< NETWORKING_IPV6=no
```

### ファイルシステムを確認
```
df -h
```

### ホスト名を確認
```
# インスタンスIDを含まないIPベース。以前より短くなった気が
uname -n
```

#### ホスト名を変更したい場合
```
# ホスト名を変更
sudo hostnamectl set-hostname [new-hostname]
# 変更を確認
hostnamectl
```

### ユーザ設定関連
#### ユーザを追加する場合
```
# 追加
sudo adduser testuser

# パスワード設定
sudo passwd testuser

# wheelグループへ追加する場合
cat /etc/group | grep wheel
sudo usermod -aG wheel testuser
```

#### umaskを設定
```
# 対象ユーザのbash_profileを変更
diff .bash_profile .bash_profile.org
9,10d8
<
< umask 0002
source ~/.bash_profile
umask
```

### タイムゾーン設定
```
timedatectl status
sudo timedatectl set-timezone Asia/Tokyo
ls -l /etc/localtime
timedatectl status
```

### ロケール設定
```
localectl status
sudo localectl set-locale LANG=ja_JP.UTF-8
localectl status
ls -l /etc/locale.conf

# /etc/sysconfig/i18nの方はダミー
cat /etc/sysconfig/i18n
sudo sed -i "s/en_US\.UTF-8/ja_JP\.UTF-8/g" /etc/sysconfig/i18n
cat /etc/sysconfig/i18n

# 編集後に再起動
sudo reboot
```

### フォントを追加する場合
#### IPAフォントの例
```
# インストール可能なフォントを確認
dnf list | grep ipa- | grep fonts

# インストール
sudo dnf install -y ipa-gothic-fonts ipa-mincho-fonts ipa-pgothic-fonts ipa-pmincho-fonts

# 確認
ls -l /usr/share/fonts
fc-list | grep ipa
```
## デーモン設定関連
[YUM コマンド チートシート](https://access.redhat.com/sites/default/files/attachments/rh_yum_cheatsheet_1214_jcs_print-ja.pdf)  
[DNF コマンドリスト](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/managing_software_with_the_dnf_tool/assembly_yum-commands-list_managing-software-with-the-dnf-tool)  
[systemd チート シート](https://access.redhat.com/sites/default/files/attachments/rh_systemd_cheatsheet_1214_jcs_print_ja1.pdf)  

### パッケージ最新化
```
# 以下のAmazon Linux2と同様の方法ではアップデートされない。
sudo dnf update -y
```
```
# バージョンを指定する場合
sudo dnf upgrade --releasever=2023.4.20240401

# 最新化する場合
sudo dnf upgrade --releasever=latest
```

### sshデーモン設定
```
# コピーして編集後にdiff。ssh_configの方じゃないよ
diff /etc/ssh/sshd_config /etc/ssh/sshd_config.org
21c21
< Port 7071
---
> #Port 22
40c40
< PermitRootLogin forced-commands-only
---
> #PermitRootLogin prohibit-password

# 編集後はリロード
systemctl reload sshd
```

### cronie
```
# 未導入を確認
systemctl status crond
# 利用可能パッケージを確認
dnf info cronie
# インストール
sudo dnf -y install cronie
# 導入済みを確認
dnf info cronie
# サーバー起動時に起動する
sudo systemctl enable crond
# 起動
sudo systemctl start crond
# 起動確認
systemctl status crond
```

### rsyslog
```
# 未導入を確認
systemctl status rsyslog
# 利用可能パッケージを確認
dnf info rsyslog
# インストール
sudo dnf -y install rsyslog
# 導入済みを確認
dnf info rsyslog
# サーバー起動時に起動する
sudo systemctl enable rsyslog
# 起動
sudo systemctl start rsyslog
# 起動確認
systemctl status rsyslog
```

## CloudWatchAgent関連

### Update
CloudWatchAgentの設定ファイルはSSMパラメータストアで管理した方がいい。
AutoScaling構成で常に最新の設定を適用する場合、ユーザーデータでSSMパラメータストアから設定ファイルを取得する工夫が要る。
ちなみに、SSMを利用すれば、インストールから設定ファイル作成、起動はEC2に入らず設定が可能。

#### CloudWatchAgentインストール
SSMのディストリビューターから、「AmazonCloudWatchAgent」を選択して「1回限りのインストール」を実行。

#### collectdインストール
SSMのRun Commandから、「AWS-RunShellScript」を選択して、インストールコマンドを投入。
CLIの場合は以下
```
aws ssm send-command \
    --targets "Key=instanceIds,Values=インスタンスID" \
    --document-name "AWS-RunShellScript" \
    --comment "Install collectd" \
    --parameters 'commands=["sudo yum install -y collectd"]'
```

#### 設定ファイルの作成
SSMのパラメータストアに直接作成する。amazon-cloudwatch-agent-config-wizardから作成した場合は、「AmazonCloudWatch-linux」などの名前で作成される。

#### Run Commandから起動
Run Commandで「AmazonCloudWatch-ManageAgent」を実行。「Optional Configuration Location」にパラメータストアに設定した名前を指定する。

#### ユーザーデータの指定例
```
#!/bin/bash
# Retrieve the parameter from SSM Parameter Store
CONFIG_JSON=$(aws ssm get-parameter --name "/cloudwatch/agent-config" --query "Parameter.Value" --output text)

# Save the configuration to the CloudWatch Agent config file
echo "$CONFIG_JSON" > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

# Start the CloudWatch Agent
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
    -a fetch-config \
    -m ec2 \
    -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json \
    -s
```

以下は旧手順
### CloudWatch Agentインストール
```
# 未導入を確認
systemctl status amazon-cloudwatch-agent
# 利用可能パッケージを確認
dnf info amazon-cloudwatch-agent
# インストール
sudo dnf install -y amazon-cloudwatch-agent
# 導入済みを確認
dnf info amazon-cloudwatch-agent
# サーバー起動時に起動する
sudo systemctl enable amazon-cloudwatch-agent
# 起動
sudo systemctl start amazon-cloudwatch-agent
# 起動確認 ※まだ未設定だから起動はできないよ
systemctl status amazon-cloudwatch-agent
```

### collectdインストール
```
# 未導入を確認
systemctl status collectd
# 利用可能パッケージを確認
dnf info collectd
# インストール
sudo dnf install -y collectd
# 導入済みを確認
dnf info collectd

# 設定編集
diff collectd.conf collectd.conf.org
77,79c77,79
< <Plugin syslog>
<       LogLevel notice
< </Plugin>
---
> #<Plugin syslog>
> #     LogLevel info
> #</Plugin>

# サーバー起動時に起動する
sudo systemctl enable collectd
# 起動
sudo systemctl start collectd
# 起動確認
systemctl status collectd
```

#### EPEL(Extra Packages for Enterprise Linux)リポジトリを追加する場合
```
sudo amazon-linux-extras install epel
sudo yum install -y collectd
```

### CloudWatch Agentの設定ファイルを編集
```
sudo vi /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
cat /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
```

### 設定ファイル読み込み
```
# 設定ファイル読み込み後は自動的に/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_amazon-cloudwatch-agent.jsonに移動する

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
```

### 再起動
```
sudo systemctl restart amazon-cloudwatch-agent.service
```

### 状態確認
```
sudo systemctl status amazon-cloudwatch-agent.service

sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
```

### ログ確認
```
cat /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log

sudo journalctl -u amazon-cloudwatch-agent.service 
```

### マネジメントコンソールで確認
CloudWatchでメトリクスとログの連携を確認する

## Apache関連
### Apacheインストール
```
# 未導入を確認
systemctl status httpd
# 利用可能パッケージを確認
dnf info httpd
# インストール
sudo dnf install -y httpd
# 導入済みを確認
dnf info httpd
# サーバー起動時に起動する
sudo systemctl enable httpd
# 起動
sudo systemctl start httpd
# 起動確認
systemctl status httpd
```

#### 導入ディレクトリ確認
```
ls -la /etc/httpd
ls -la /etc/httpd/conf
ls -la /usr/sbin/httpd
```

#### バージョン確認
```
httpd -v
```

#### ドキュメントルートの設定例
```
sudo chown -R ec2-user:apache /var/www
sudo usermod -aG apache ec2-user
exitしてsh再起動
groups
sudo chmod 2775 /var/www && find /var/www -type d -exec sudo chmod 2775 {} \;
find /var/www -type f -exec sudo chmod 0664 {} \;
ls -la /var/www
sudo mv /var/www/html /var/www/myapp
sudo mkdir /var/www/myapp/public
ls -la /var/www
ls -la /var/www/myapp
ls -la /var/www/myapp/public
```
**OS設定のumask(0002)変更後に行うように**

#### ログファイル確認
```
sudo ls -la /var/log/httpd/
```

#### httpd.conf編集後の確認
```
cat /etc/httpd/conf/httpd.conf | grep DocumentRoot
cat /etc/httpd/conf/httpd.conf | grep -Pzo '(?s)<directory myapp="" public="" var="" www="">.*?</directory>'
cat /etc/httpd/conf/httpd.conf | grep ServerTokens
cat /etc/httpd/conf/httpd.conf | grep Header
cat /etc/httpd/conf/httpd.conf | grep ServerSignature
cat /etc/httpd/conf/httpd.conf | grep RequestHeader
cat /etc/httpd/conf/httpd.conf | grep TraceEnable
cat /etc/httpd/conf/httpd.conf | grep Timeout
cat /etc/httpd/conf/httpd.conf | grep KeepAlive
cat /etc/httpd/conf/httpd.conf | grep RemoteIP
cat /etc/httpd/conf/httpd.conf | grep LogFormat
cat /etc/httpd/conf/httpd.conf | grep SetEnv
cat /etc/httpd/conf/httpd.conf | grep CustomLog
diff -u httpd.conf httpd.conf.org | grep -E "^\+|^-"
```

### SSL設定関連
#### mod_sslインストール
```
# 利用可能パッケージを確認
dnf info mod_ssl

# インストール
sudo dnf install -y mod_ssl

# 導入済みを確認
dnf info mod_ssl
```

#### 秘密鍵を生成
```
openssl genrsa -out private.key 2048
```

#### CSRを生成
```
openssl req -new -key private.key -out certificate.csr
```

#### 自己署名証明書の作成
```
openssl x509 -req -days 3650 -in certificate.csr -signkey private.key -out certificate.crt
```

#### 証明書の検証
```
openssl x509 -in certificate.crt -text -noout
```

#### Apacheへ証明書をインストール
```
sudo mkdir -p /etc/ssl/private 
sudo mkdir -p /etc/ssl/certs 
sudo cp private.key /etc/ssl/private/ 
sudo cp certificate.crt /etc/ssl/certs/ 
sudo chmod 600 /etc/ssl/private/private.key 
sudo chmod 644 /etc/ssl/certs/certificate.crt 
```

#### httpd.conf編集
```
<virtualhost>
    ServerName localhost
    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/certificate.crt
    SSLCertificateKeyFile /etc/ssl/private/private.key
    DocumentRoot /var/www/myapp/public
    <directory myapp="" public="" var="" www="">
        AllowOverride All
        Require all granted
    </directory>
</virtualhost>
```

#### httpd.conf編集後の確認
```
cat /etc/httpd/conf/httpd.conf | grep -Pzo '(?s)<virtualhost>.*?</virtualhost>'
```

#### apache再起動
```
sudo systemctl restart httpd
```

### apacheアクセス確認
```
# HTTP
curl http://localhost/
curl -o /dev/null -s -w "%{http_code}\n" http://localhost/

# HTTPS
curl https://localhost/ -k
curl -o /dev/null -s -w "%{http_code}\n" https://localhost/ -k
```

### 証明書の接続確認
```
openssl s_client -connect localhost:443 | openssl x509 -noout -text
```

### モジュール確認
```
httpd -M
```

## PHP関連
### PHP本体をインストール
```
# 利用可能パッケージを確認
dnf info php8.3

# インストール
sudo dnf -y install php8.3

# 導入済みを確認
dnf info php8.3

# バージョン確認
php -v

# インストール済みのモジュール確認
php -m

# 依存関係で入ったモジュールの確認(php-commonの例)
rpm -ql php8.3-common
```

### 拡張モジュールをインストール
```
# 利用可能パッケージを確認
dnf list available | grep php8.3

# インストール
sudo dnf -y install php8.3-gd php8.3-mysqlnd php8.3-zip

# 導入済みを確認
dnf list installed | grep php
```

### モジュール一覧
```
php -m
```

### php-fpmを設定
```
# サーバー起動時に起動する
sudo systemctl enable php-fpm.service

# 起動
sudo systemctl start php-fpm.service

# 起動確認
systemctl status php-fpm.service
```

### PHP導入ディレクトリを確認
```
ls -la /etc/php.ini
ls -la /usr/bin/php
ls -la /usr/lib64/php8.3/modules/
```

### ログ設定の確認
```
cat /etc/php.ini | grep log_errors
cat /etc/php.ini | grep error_log
sudo ls -l /var/log/php-fpm/
```

### php.ini編集後の確認
```
cat /etc/php.ini | grep expose_php
cat /etc/php.ini | grep timezone
cat /etc/php.ini | grep log_errors
cat /etc/php.ini | grep short_open_tag
cat /etc/php.ini | grep memory_limit
cat /etc/php.ini | grep post_max_size
cat /etc/php.ini | grep upload_max_file
diff /etc/php.ini /etc/php.ini.org
```

### Apacheとphp-fpm再起動
```
sudo systemctl restart httpd
sudo systemctl restart php-fpm.service
```

### phpinfoで確認
```
echo "<?php phpinfo(); ?>" > /var/www/html/phptest.php
```

## その他モジュールインストール関連
### Composerインストール
```
# 利用可能パッケージを確認
dnf info composer

# インストール
sudo dnf -y install composer
rpm -qa | grep composer
dnf info composer
```

### Node.jsインストール
```
dnf info nodejs
sudo dnf -y install nodejs
rpm -qa | grep nodejs
dnf info nodejs
```

## loglotate設定関連
```
cat /etc/logrotate.d/httpd_access
cat /etc/logrotate.d/httpd_error
cat /etc/logrotate.d/syslog
cat /etc/logrotate.d/system_logs
cat /var/www/myapp/storage/logs/myapp_log
ls -la /etc/logrotate.d

# デバッグモードで実行
logrotate -d /etc/logrotate.d/httpd_access
```

## MySQL関連
### MySQLクライアントインストール
**依存性の欠如でリポジトリからインストールできずhttpでインストールする場合の方法**
```
# システムで有効なリポジトリーを表示
dnf repolist

# 対象サイトをリポジトリへ追加
sudo dnf -y localinstall https://dev.mysql.com/get/mysql80-community-release-el9-1.noarch.rpm

# リポジトリー追加を確認
dnf repolist

# 必要なGPGキーのインポート(インストールでエラーになったので)
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023

# インストール
sudo dnf -y install mysql-community-client

# 導入済みを確認
rpm -qa | grep mysql

# バージョンを確認
mysql --version
```

### 接続確認
```
mysql -h [RDSエンドポイント] -P 3306 -u [ユーザー名] -p
```

---
## rpmコマンドの使用例
```
# インストール済みのパッケージ一覧を表示
rpm -qa

# 特定のパッケージのインストール状況を確認
rpm -q パッケージ名

# パッケージの情報を表示
rpm -qi パッケージ名

# インストールされたRPMパッケージのディレクトリを表示
rpm -ql パッケージ名
```

## journalctlコマンドの使用例
```
# 直近(1000行)をページャで表示
journalctl -e  

# サービス名(sysmtemd unit)でフィルタ
journalctl -u [サービス名]

# 特定プライオリティ以上でフィルタ
journalctl -p [プライオリティ]

# カーネルログの表示
journalctl -k

# リアルタイムで表示
journalctl -f
```

## laravel動作確認時の最低限の設定
### aws-sdk
```
# S3他
composer require aws/aws-sdk-php
# SES
composer require aws/aws-sdk-php-laravel
```

### .htaccessファイルを有効化
```
diff httpd.conf httpd.conf.org
124,125c124
< #DocumentRoot "/var/www/html"
< DocumentRoot "/var/www/html/laravelapp/public"
---
> DocumentRoot "/var/www/html"
137,138c136
< #<directory html="" var="" www="">
< <directory html="" laravelapp="" public="" var="" www="">
---
> <directory html="" var="" www="">
151,152c149
<     #Options Indexes FollowSymLinks
<     Options FollowSymLinks
---
>     Options Indexes FollowSymLinks
159,160c156
<     #AllowOverride None
<     AllowOverride All
---
>     AllowOverride None
```

### EC2へ適用するインスタンスプロファイルでS3とSESの認可設定
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:Describe*",
            ],
            "Resource": "*"
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ses:SendRawEmail",
                "ses:SendEmail"
            ],
            "Resource": "*" 
        }
    ]
}
```

## PostgreSQL 16をソースからインストール
(Amazon Linux 2023で最新がPostgreSQL15だったため)  
[ソースコードからインストール](https://www.postgresql.jp/docs/16/install-requirements.html)
```
# ソースコードを入手
wget https://ftp.postgresql.org/pub/source/v16.0/postgresql-16.0.tar.gz

# 展開
tar zxf postgresql-9.6.19.tar.gz

# 必要なパッケージをインストール
sudo dnf -y install gcc
sudo dnf -y install readline-devel

# インストール
sudo mkdir /usr/local/postgresql
sudo ./configure --prefix=/usr/local/postgresql/ --with-pgport=5432 --without-icu --without-zlib
make
sudo make install
```

## プライベートサブネットのEC2への接続方法
### 踏み台サーバ経由で接続(ProxyCommandを使用)
```
# SSH
ssh -oProxyCommand='ssh -W %h:%p [bastion]' [target]

# SCP
scp -p -oProxyCommand='ssh -W %h:%p [bastion]' [コピー元] [コピー先]
```
> **-W host:portの指定**  
> %h:%pがtargetのホストとポートに置き換わり、クライアントの標準入力と出力をセキュアチャネルを介してホストのポートに転送するように要求します。

#### 接続例
* 踏み台IP: xx.xx.xx.xx(パブリックIP)  
* 踏み台SSHポート: 10022  
* 接続先IP: yy.yy.yy.yy(プライベートIP)  
* 接続先SSHポート: 10023  
```
# SSH
ssh -o ProxyCommand="ssh -i bastion-keypair.pem -p 10022 -W %h:%p ec2-user@xx.xx.xx.xx" -i target-keypair.pem -p 10023 ec2-user@yy.yy.yy.yy

# SCP(SCPのポート指定は-P)
scp -p -oProxyCommand='ssh -i bastion-keypair.pem -p 10022 -W %h:%p ec2-user@xx.xx.xx.xx' -i target-keypair.pem -P 10023 ./test.zip ec2-user@yy.yy.yy.yy:/tmp
```

#### プライベートサブネットのMySQLへ接続する例
* ローカルの任意のポート: 55555  
* DBサーバのListenポート: 3306  
```
ssh -o ProxyCommand="ssh -i bastion-keypair.pem -p 10022 -W %h:%p ec2-user@xx.xx.xx.xx" -i target-keypair.pem -p 10023 ec2-user@yy.yy.yy.yy -L 55555:test-rds.cjwn3xtq8mxn.ap-northeast-1.rds.amazonaws.com:3306
```

### ロードバランサー経由
任意のポートをターゲットEC2のSSHポートへ転送するリスナーを追加すれば可能。ALBはHTTP(S)用なので不可。

## インスタンスタイプ確認
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html  

### IMDSv1(旧バージョン)
```
curl http://169.254.169.254/latest/meta-data/
```
### IMDSv2
```
# トークンを発行
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`

# トークンを利用してメタデータを参照
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/

# ワンライナー
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"` \
&& curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
```

0 件のコメント:

コメントを投稿

人気の投稿