猫のCentos7のウェブサーバー環境構築メモ

# メモの理由：壊れたOne Noteの代わりに、Centos7サーバー構築のメモ

Microsoftがデスクトップ版 One Note を廃止してくれたおかげで、UWPのアプリに変わり、そのせいでタブが壊れて、クイックノートに編集した記事がリポジトリのように残りまくり...使いづらくなったので、必要項目をどこかにメモとして残しておこうと。自分のブログだと、ふっとばして残らないいことが多いので。

## SSHのポート変更

sshの標準ポートは 22 だけど、そのままだと攻撃の的になるので...

```config:/etc/ssh/sshd_config
Port [番号]
```

Firewalld のはずなので（カゴヤVPSのOpenVZのときはiptableだった）

```bash
firewall-cmd --add-port=[変更番号]/tcp --permanent
firewall-cmd --remove-service=ssh --permanent
firewall-cmd --reload
```

順番間違えるとアボンするから注意が必要。

【追記】
--permanent は、永久保存コマンド。そのため、--reload するまでは反映されない。
即時反映する場合は --permanent を抜けばいい。

```bash
firewall-cmd --add-port=[変更番号]/tcp
```
当然、--permanent の設定をしていない場合、再起動で設定が吹っ飛ぶので、SSHの設定の場合は上の方がいいと思う（入れなくなってしまいますからね）


## sudo でパスワード不要にする

centos7 は、標準でsudo 入っていないので `yum -y install sudo` が必要。

```config:visudo
[ユーザー名] ALL=(ALL) NOPASSWD:ALL
```

NOPASSWD:[コマンドのパス] の指定で、対象の限定も可能

猫は最近、デプロイ用（systemctl resatart ほげほげ)）用のために使ってる。
ASP.NET Core だと、デプロイしたあとに、再起動させないと反映しませんからね。
webから叩く。PHPとかで `shell_exec( 'sudo systemctl restart ほげほげ' );` みたいに。
あとは、管理用のウェブプログラムでシステムコマンドが必要な場合とかとか？

## ユーザー作成関係

```bash
useradd [ユーザー名]
usermod -g [グループ名] [ユーザー名]
passwd [ユーザー名]
groupadd [グループ名]
userdel -r [ユーザー名]
```

上から作成、グループ変更、パスワード変更、グループ追加、ユーザー削除(-rでホームディレクトリも死ぬ)

## ホスト名変更

```bash
hostnamectl set-hostname [ホスト名]
```

上の設定だけだと、VPSによって、変更してもリブートすると戻ってしまう。(猫が借りているカゴヤVPSのKVM版だと戻る）

```config:/etc/cloud/cloud.cfg
preserve_hostname: true
```

これでリブートしても元に戻らない。

## レガシーコマンドを入れとく

意外に使う、wget, nslookup, ifconfig...。新しいコマンドあるけど、覚えるのがね。

```bash
yum -y install wget net-tools bind-utils
```

## 新しいパッケージの導入

epel-release は標準。PHPの最新版を入れるなら、remi が必須（独自コンパイルしないなら）

```bash
yum -y install epel-release
```

remi は、パッケージ版(rpm)もあるけども、/etc/yum.repos.d/ を汚染しまくるので、ファイルのみにしてる。

```bash
wget http://rpms.famillecollet.com/enterprise/remi.repo > /etc/yum.repos.d/remi.repo
```

最新版のPHPが出ても直ぐに反映されないけど、rpm自体はすでに用意されていたりすることが多い。そのため

```config:/etc/yum.repo.d/remi.repo
[remi-php73]
name=Remi's PHP 7.3 RPM repository for Enterprise Linux $releasever - $basearch
#baseurl=http://rpms.remirepo.net/enterprise/$releasever/php73/$basearch/
mirrorlist=http://cdn.remirepo.net/enterprise/$releasever/php73/mirror
# WARNING: Only available for RHEL/CentOS >= 6
enabled=1
gpgcheck=1
gpgkey=http://rpms.remirepo.net/RPM-GPG-KEY-remi
```

この上の部分を php73 の部分を、対象のPHPバージョンに書き直せばなんとかなる。

## PHPの導入

remi.repo の enabled=1 にしとけば、--enablerepo=remi-php73 を入れなくても、その対象にはなる。ちなみに、Centos7の標準だとPHP5.6が入ってしまう。

```bash
yum --enablerepo=remi-php73 install php php-opcache php-fpm php-gd php-pdo php-dom php-mbstring　php-mysqlnd php-openssl php-json php-pecl-apcu php-pdo_sqlite php-pdo_mysql php-pecl-memcached
```

PHPの設定編集は `/etc/php.ini` になるが、PHP-FPMを使う場合は `/etc/php-fpm.d/` の配下にあるファイルになる。PHP-FPMのプロセス・ユーザーやグループをそれぞれ作ることも可能。www.conf を元手に

```ini:/etc/php-fpm.d/test.conf
; Start a new pool named 'www'.
; the variable $pool can be used in any directive and will be replaced by the
; pool name ('www' here)
[www]

...
```

の [www] を、[test] や、他の名前に変えてあげれば良い。

PHPの実行時権限としての割り当ては、

```ini:/etc/php-fpm.d/www.conf
user = toryuneko
; RPM: Keep a group allowed to write in log dir.
group = web_groups
```

のここで割り当てる（FTP等の権限をユーザーに割り当てる場合。NginxやApacheのままなら、そのようにする）

PHP-FPM などをNginxから読み書きできるよう権限を割り当てる場合＋PHP-FPMをUnixソケットで割り当てる場合は次のようにしておく。

```ini:/etc/php-fpm.d/www.conf
listen = /var/run/php-fpm.www.sock

listen.owner = nginx
listen.group = nginx
listen.mode = 0660
```

PHP-FPM のサービス登録は

```bash
systemctl start php-fpm
systemctl enable php-fpm
```

## 複数のPHPを導入する

PHP7.2, PHP7.3 対応のサーバーを作るなど。なお、上の remi.repo ファイルに、導入したいPHPのバージョン設定を用意しておく必要がある。

```bash
for v in 72 73 ; do yum -y install php$v-php-{opcache,fpm,gd,pdo,dom,mbstring,mysqlnd,openssl,json,pecl-apcu,pdo_sqlite,pdo_mysql,pecl-memcached,xdebug} ; done
```

この方法で入れると、PHPのファイル名が変わる。PHPの設定ファイルも`/etc/opt/remi/php[バージョン]/php.ini`になる。また、php-fpmの実行も、`system start php72-php-fpm` と、頭にPHPのバージョン指定が必要になり、ちょいとややこしいので注意が必要。PHP5シリーズがなくなったから、普通のサイト構築では複数導入は不要だけど、開発環境ならアリかもね。

## Nginxの導入

猫は最近、モジュールを入れるためコンパイルして導入しているのですが、systemdのファイル作るの面倒なので、パッケージ導入後、コンパイルしてます。モジュール用意しないサイトならば、そのまま突っ込む。なお、現時点のNginx最新版はTLSv1.3に対応していないので対応するならばコンパイルしていれないとだめ。

```vim:/etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
```
mainlineじゃなくてstable 外衣場合は、2階層目のURLを変更すればOK。

```bash
yum install nginx
systemctl start nginx
systemctl enable nginx
```

設定ファイルは `/etc/nginx/` 配下にある。

既定の nginx.conf は、独自にかなり書き直してるので、参考までに
あと、よくわかってない部分もあるので、そこはご教授いただけると幸いでする。

```conf:/etc/nginx/nginx.conf
# 基本設定（猫仕様）

## == user setting ====
user  nginx;

## == worker setting ====
# auto 自動で割り当て
# 数値 プロセス数手動割り当て
worker_processes  auto;
# worker毎のファイルディスクリプタ上限数
#   /proc/sys/fs/file-max で数を確認
#   worker_connectionの3～4倍が目安
worker_rlimit_nofile 4096;
# cpuのワーカープロセス割り当てを2進数で設定
#   物理プロセスが 2 以上のみ有効
#   未設定の場合はOSスケジューラにより割り当て依存する
worker_cpu_affinity auto;


## == error log ====
error_log  /var/log/nginx/error.log warn;

## == process id ====
pid        /var/run/nginx.pid;

## == event block ====
events {
    # 1つのworkerが処理できる接続数
    worker_connections  1024;

    # 複数の接続をすべて一度に受ける
    multi_accept on;

    # Linuxは固定(Linux=epoll, Unix=kqueue)
    use epoll;
}

## == http block ====
http {
    ## mime type 設定ファイル
    include       /etc/nginx/mime.types;

    ## 規定MIMEタイプ
    default_type  application/octet-stream;

    ## Serverバージョン表示(Off推奨)
    server_tokens off;

    ## Logの基本設定を読み込み
    include /etc/nginx/conf.d/log.conf;

    ## ファイル転送モード時にシステムコールを利用する
    sendfile        on;

    ## tcp転送を向上
    tcp_nopush     on;

    ## etag off
    etag off;

    ## 常時接続維持時間
    keepalive_timeout  30;

    ## 常時接続時の接続数制限
    keepalive_requests 200;

    ## バーチャルホストのドメイン名の調整用
    server_names_hash_bucket_size 128;

    ## アップロード制限
    client_max_body_size 100M;

    ## クライアントヘッダサイズ
    client_header_buffer_size 16k;
    client_body_buffer_size 32k;

    ## limit 設定
    include /etc/nginx/conf.d/limit.conf;

    ## ロードバランス調整
    include /etc/nginx/conf.d/loadbalancing.conf;

    ## gzip圧縮の有無
    include /etc/nginx/conf.d/gzip.conf;

    ## file cacheの有無
    include /etc/nginx/conf.d/cache.conf;

    ## fastcgi cache
    include /etc/nginx/conf.d/fastcgi/cache.conf;

    ## proxy setting
    include /etc/nginx/conf.d/proxy/proxy.conf;

    ## proxy cache
    include /etc/nginx/conf.d/proxy/cache.conf;

    ## upstream set
    include /etc/nginx/conf.d/upstream.conf;

    ## Server設定 読み込み
    include /etc/nginx/server.d/*.conf;
}
```


猫は、それぞれNginxの環境を個別に分けていろいろ設定している。特にSSLの設定はシンドイ。OneDriveやブルーレイ、USBメモリなどにバックアップしてるけど、ファイルが飛んでしまうとSSLの設定だけが一番シンドイので、メモとして残しとく（それ以外はたいしたことない）

ちなみに、以下の設定は、 server ディレクティブ中で利用する

```vim:/etc/nginx/conf.d/ssl.conf
#
# SSL共通設定 config
#
# 別途SSL証明書の設定が必要
#  ssl_certificate [public+agent.crt];
#  ssl_certificate_key [private.crt];
#
# MEMO:
#  DH鍵交換生成
#  $ openssl dhparam 2048 -out /etc/nginx/ssl/dhparam.pem
#
## DH鍵設定
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

## SSLキャッシュ時間
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_buffer_size 4k;

## SSL通信方式
ssl_protocols TLSv1.2 TLSv1.3;

## 共通鍵暗号方式
ssl_prefer_server_ciphers on;
ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA512:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:ECDH+AESGCM:ECDH+AES256:DH+AESGCM:DH+AES256:!aNULL:!eNULL:!LOW:!RC4:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS;
resolver 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844];

## HSTSヘッダの追加
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
```

TLSv1.3対応なので、そこだけ注意がいる。


## FTPサーバー構築

こいつは、そのまま放り込む。`yum -y install vsftpd` としてあとは `systemctl start vsftpd` と `systemctl enable vsftpd` をしとく。

```config:/etc/vsftpd/vsftpd.conf
# 匿名ユーザーの禁止有無
anonymous_enable=NO

# ログの有効化
xferlog_file=/var/log/xferlog

# ASCIIの転送（アップ、ダウンロード）を許可
ascii_upload_enable=YES
ascii_download_enable=YES

# FTPのバージョンを表示させない
ftpd_banner=Whelcom to blah FTP service.

# ユーザー階層以下にいけないようにする
# chroot_list_fileに指定したユーザーのみ、配下にいける
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list

# ディレクトリごと削除できるようにする
ls_recurse_enable=YES

# pasvモードを有効にする
pasv_enable=YES
pasv_min_port=10000
pasv_max_port=10010

# sslモードの有効
ssl_enable=YES
allow_anon_ssl=NO
ssl_tlsv1_2=YES
ssl_tlsv1_1=NO
ssl_tlsv1=NO
ssl_sslv2=NO
ssl_sslv3=NO
require_ssl_reuse=NO
ssl_ciphers=HIGH
rsa_cert_file=/etc/letsencrypt/live/hoehoge.com/fullchain.pem
rsa_private_key_file=/etc/letsencrypt/live/hogehoge.com/privkey.pem
force_local_logins_ssl=YES
force_local_data_ssl=YES

# ユーザーの接続許可設定
# ユーザー接続許可設定(YES=禁止,NO=許可)
userlist_deny=NO　　
userlist_file=/etc/vsftpd/user_list　# 設定ファイルの位置

# ユーザーのルートフォルダ位置
user_config_dir=/etc/vsftpd/user_conf.d/
allow_writeable_chroot=YES
```
Letsencrypt用意するまで、SSL使えないので、そのときはコメントアウトで封印しとく。SSLの時、Pasvにしないとエラーで入れないのだけど、そういう仕様なのだろうか、ということでPASVモードの設定が入れてあるだけど、このあたりはドキュメント解読不足。

```bash
touch /etc/vsftpd/chroot_list
mkdir /etc/vsftpd/user_conf.d/

firewall-cmd --add-service=ftp --permanent
firewall-cmd --add-port=10000-10010/tcp --permanent
firewall-cmd --reload
```

/etc/vsftpd/user_conf.d/ は、ユーザー名ファイルを作り、その中に`local_root=[パス]`の情報を入れれば、FTPで接続した時のルートがそこになる。それぞれのユーザーで生成できるので便利。

user_list の設定を逆転させているので、許可するユーザーを指定するようにしている。ユーザー増えるとホワイトリスト方式のが楽ですしね。

## sambaの導入

開発環境、特にWindowsの場合はHyper-Vという最強のツールがあり、これを利用する方が開発効率がいい。ちまたでは、Mac OSが最強だとかいうのがいるけど、猫はそう思わない。両方使っているけど、そういう面を見るとWindowsのがやりやすいと感じてる。特に共有フォルダ関係を組み合わせると最強だから（Macの共有フォルダは直ぐ落ちる...）。

```bash
yum -y install samba samba-client samba-common
systemctl start smb nmb
systemctl enable smb nmb
firewall-cmd --add-service=samba --permanent
firewall-cmd --reload
```
インストール時は samba だけど、サービス実行は、smb となる。名前が変わるのでややこしい。

```config:/etc/samba/smb.conf
[global]
        unix charset = UTF-8
        dos charset = CP932

        workgroup = WORKGROUP
        security = user

        passdb backend = tdbsam

        printing = cups
        printcap name = cups
        load printers = yes
        disable spoolss = yes
        cups options = raw

[develop web site]
        comment = develop web site
        path = /var/www
        browseable = yes
        writable = yes
        public = yes
        valid users = develop
        create mask = 0664
        directory mask = 0775
```

ユーザー生成（割り当て)

```bash
smbpasswd -a [ユーザー]
```

運用環境に導入はやめた方がいいけど、Hyper-Vなりに突っ込んで開発するには、FTP使うよりこれが一番楽である。ファイル多くなるときついけどね（特にGit使ってると）。

## Letsencryptの導入

ドメインがいるのと、公開してる必要があるのと、いろいろ面倒。よく失敗する（ぁ

```bash
yum -y install epel-release
yum -y install certbot
```

猫は主にNginxを使って環境構築するので、その構築をしておく。ただ、せっかくSSL化してるのにHTTPアクセスも許可しないといけないのが煩わしい。基本的にはリダイレクトさせてるけど、そのためにserver ディレクティブは別途用意してる。

```nginx:/etc/nginx/conf.d/letsencrypt.conf
## == server redirect (HTTPS Redirect) and letsencrypt settings ====
server {
    listen 80;
    listen [::]:80;

    server_name nekochaya.jp;
    server_name www.nekochaya.jp;
    server_name blog.nekochaya.jp;

    location ^~ /.well-known/acme-challenge/ {
        allow all;
        root /var/www/letsencrypt/public_html/;
        default_type text/plain;
        access_log off;
        log_not_found off;
    }

    location / {
        return 301 https://$server_name$request_uri;
    }
}
```

ちなみに、定期的にcronで自動更新を動かすため、80ポートは空けておかないといけないので注意が必要。

```bash
certbot certonly --webroot -w /var/www/letsencrypt/public_html -d nekochaya.jp -d www.nekochaya.jp --agree-tos --email [email]
```

今後、ワイドカードに対応するそうですが、今のところはサブドメインも指定しないといけないので、1つの証明書に複数のドメインを割り当てる場合は -d を複数指定すればOK。なお、ちゃんとドメインの設定（Aレコード、CNAMEレコード）は必要。また、別途のドメインを個々で指定したい場合はもう一度同じコマンドを通してやればいい。nginx の letsencrypt.conf に、server_name を追加するのも忘れず。

自動更新のために、cronに入れるのだけど、centos7の標準cronは、anacronが入ってる。ちょっとスパンをおいたりするので、猫は入れ替えてる。

```bash
yum -y install cronie-noanacron
yum -y remove cronie-anacron
```

クローンの設定では、renewされたときにNginxを再起動するようにしている

```config:/etc/cron.d/letsencrypt
0 0 * * * root /bin/certbot renew --max-log-backups 7 --post-hook "/usr/sbin/nginx -s reload"
```

それぞれの項目は以下の通り 

* renew 更新
* --max-log-backups [ログローテート回数] 
* --post-hook "[コマンド]" 成功時の実行コマンド

ちなみに、--force-renewal を使うと、毎回更新処理が走ってしまう。renewだと、期限切れの結構前ぐらいから証明書を更新してくれるらしいので、今はこれで様子見をしている。
ただいま実験中：`--post-hook "/usr/sbin/nginx -s reload && /bin/systemctl restart vsftpd"`
FTPもLetsencryptの証明書使ってるので、リロードしないと反映してくれないことに気がつく。ただ、上のコマンドが動くのかわからないので、今は実験中という形

## MariaDB の導入

最後は、データベース導入。MySQLではなく、最近はMariaDBにしてる。

```bash
rpm --import https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
```

```vim:/etc/yum.repos.d/mariadb.repo
[mariadb]
name=mariadb repo
baseurl=https://yum.mariadb.org/10.3/centos/7/$basearch/
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
enabled=1
```

```bash
yum -y install mariadb-server mariadb-client
systemctl start mariadb
systemctl enable mariadb
mysql_secure_installation
```

あとは、設定なりを突っ込んだりして終わり。
このあたりはチューニングがいるので、参考程度までに

```conf:/etc/my.cnf.d/server.cnf
[mysqld]
skip-name-resolve

max_connections = 100
thread_cache_size = 25

# グローバルバッファ
key_buffer_size = 64M
max_heap_table_size = 32M
max_allowed_packet = 16M
tmp_table_size = 32M
query_cache_size = 64M
read_rnd_buffer_size = 1M
sort_buffer_size = 2M
read_buffer_size = 512K
join_buffer_size = 512K
lower_case_table_names = 1

# バイナリログの保存期間
expire_logs_days = 7

# 文字コード設定
character-set-filesystem = binary
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci

# innodb 設定
innodb_buffer_pool_size = 256M
innodb_log_buffer_size = 16M
innodb_file_per_table = 1

# error log 設定
log_error = "/var/log/mysql/mysqld.log"
log_warnings = 1

# query log 設定
general_log = ON
general_log_file = "/var/log/mysql/sql.log"

# slow query log 設定
slow_query_log = 1
slow_query_log_file = "/var/log/mysql/slow.log"
long_query_time = 3

# デフォルトDBストレージ
default_storage_engine = InnoDB

# 自動インクリメントのロック
innodb_autoinc_lock_mode = 2

# ログの出力方式
innodb_flush_log_at_trx_commit = 0
```

## 終わりに

未だ、メールサーバーの構築が難しすぎて手を入れることが出来ません。Postfix難しすぎです。一応、OneNoteにメモはあるのですが、毎回失敗してるので、何か間違っているのでしょう。というか、Postfix関連のクイックノートが30ぐらいあるので、書き直しした物がぐっちゃぐちゃになっていて、どれが正しいのかわからなくなってしまってます。なので、もう一度調べ直しがいります。

今回は、ウェブ環境構築のためのもの限定でメモりました。一番良く構築する環境なので。他にもノートがいっぱい残ってるので、ちょっと纏めて書いて残しておこうと思います。OneNote捨てられるように...