CentOS7.5 + Apache + PHP + MySQL サーバを構築し、WordPressサイトを引っ越す(2018/11/20)

昔の記事が消えてしまっていたようなので復活させます。

概要

記事数1,500超とそこそこデータのあるテスト用のWordPressのサイトを引っ越しした際のメモです。

サーバを一から建てたのでその部分のメモも含みます。

また、いくつかの点については後日得た情報で加筆修正しています。

作業内容

以下、作業内容を書いていきます。サーバはCentOS7.5を建てます(当時)。

1. 初期設定

nmtuiでIPとホスト名を設定し、passwdでパスワード設定。

1.1. Update

# sudo yum update

## 略

1.2. Upgrade

# sudo yum upgrade

## 略

2. セキュリティ

2.1. SELINUX

鎮まり給え。

# vi /etc/sysconfig/selinux

#SELINUX=enforcing
SELINUX=disabled

2.2. firewalld

80, 443を許可

# firewall-cmd --add-port=80/tcp --permanent
success
# firewall-cmd --add-port=443/tcp --permanent
success

リロード

# firewall-cmd --reload
success

確認

# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens32
  sources:
  services: ssh dhcpv6-client
  ports: 80/tcp 443/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

3. chronyインストール

# yum install chrony

## 略

# systemctl enable chronyd

# firewall-cmd --add-port=123/tcp --permanent
success
# firewall-cmd --add-port=123/udp --permanent
success
# firewall-cmd --reload
success

自動起動するようにして、ポート123を開けておきます。

4. リポジトリ追加

4.1. epel

# yum -y install epel-release
# yum -y update

## 略

4.2. remi

# rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
http://rpms.famillecollet.com/enterprise/remi-release-7.rpm を取得中
警告: /var/tmp/rpm-tmp.vZFq3z: ヘッダー V4 DSA/SHA1 Signature、鍵 ID XXXXXXXX: NOKEY
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:remi-release-7.5-2.el7.remi      ################################# [100%]
# rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi

4.3. リポジトリ有効化

# vi /etc/yum.repos.d/remi.repo

[remi]
enabled=1

remi。

# vi /etc/yum.repos.d/remi-php72.repo

[remi-php72]
enabled=1

php。

5. vsftpd

5.1. インストール

# yum -y install vsftpd

5.2. 設定

# vi /etc/vsftpd/vsftpd.conf

## 匿名ユーザ無効化

#anonymous_enable=YES
anonymous_enable=NO

## タイムアウト時間変更

#idle_session_timeout=600
idle_session_timeout=600

#data_connection_timeout=120
data_connection_timeout=60

## ASCIIモード有効

#ascii_upload_enable=YES
ascii_upload_enable=YES

#ascii_download_enable=YES
ascii_download_enable=YES

## ホームディレクトリより上へのアクセス制限

#chroot_local_user=YES
chroot_local_user=YES

#chroot_list_enable=YES
chroot_list_enable=YES

#chroot_list_file=/etc/vsftpd/chroot_list
chroot_list_file=/etc/vsftpd/chroot_list

## IPv4有効

#listen=NO
listen=YES

## IPv6無効化

#listen_ipv6=YES
listen_ipv6=NO

## アクセスユーザ制御

userlist_deny=NO

## ユーザごとの設定ファイルを指定

user_config_dir=/etc/vsftpd/user_conf

## ローカル時間有効

use_localtime=YES

## パッシブモード有効

pasv_promiscuous=YES
pasv_min_port=50000
pasv_max_port=50030

## .htaccessをFTPソフトから見られるようにする

force_dot_files=YES

色々設定。

# firewall-cmd --add-service=ftp --permanent
success
# firewall-cmd --reload
success

ポートを開けます。

5.3. ユーザ設定

# vi /etc/vsftpd/chroot_list

## 空ファイル作成

## root以外参照できないように権限変更

# ls -al /etc/vsftpd/chroot_list
-rw-r--r-- 1 root root 0 MM月 dd hh:ii /etc/vsftpd/chroot_list
# chmod 600 /etc/vsftpd/chroot_list
# ls -al /etc/vsftpd/chroot_list
-rw------- 1 root root 0 MM月 dd hh:ii /etc/vsftpd/chroot_list

5.4. ユーザ作成・設定

# useradd ftpuser

ユーザ追加。

# vi /etc/vsftpd/user_list

ftpuser

/etc/vsftpd/user_listに追加。/etc/vsftpd/chroot_listは上に遡らせないようにするため、記載しない。

# vi /etc/vsftpd/user_conf/ftpuser

local_root=/var/www/example/

FTPユーザのルートディレクトリを指定します( /var/www/example/ は 12.2. 仮想サイト作成 でディレクトリを掘っています)。

# passwd ftpuser

パスワード設定。

# systemctl start vsftpd.service
# systemctl enable vsftpd.service
Created symlink from /etc/systemd/system/multi-user.target.wants/vsftpd.service to /usr/lib/systemd/system/vsftpd.service.

起動&自動起動設定。

6. Apache

6.1. Apache(2.4.6-80)

# yum -y install httpd-devel

## 略

完了しました!

インストール。

# mv -i /etc/httpd/conf.d/autoindex.conf /etc/httpd/conf.d/autoindex.conf.org
# mv -i /etc/httpd/conf.d/userdir.conf /etc/httpd/conf.d/userdir.conf.org
# mv -i /etc/httpd/conf.d/welcome.conf /etc/httpd/conf.d/welcome.conf.org

いらない設定を読み込まないように。

# systemctl start httpd
# systemctl enable httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service.

起動&自動起動設定。

6.2. mode_ssl(2.4.6-80)

# yum -y install mod_ssl

## 略

完了しました!

7. PHP(7.2.12-1)

# yum -y install php php-devel php-pdo php-mysqlnd php-mbstring php-gd php-pear php-pecl-apc-devel zlib-devel php-xml php-mcrypt

WordPressに必要そうなモジュールも込みでインストール。php-xmlはプラグインで要求されることが多いので。

# mkdir /var/log/php
# chown apache /var/log/php
# chmod 755 /var/log/php

続いてエラーログディレクトリ作成&権限設定。

# vi /etc/php.ini

;expose_php = On
expose_php = Off

;date.timezone =
date.timezone = 'Asia/Tokyo'

;error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_reporting = E_ALL & ~E_DEPRECATED

;error_log = syslog
error_log = "/var/log/php/php_errors.log"

設定変更。

# vi /etc/httpd/conf.d/php.conf

    #php_value session.save_handler "files"
    #php_value session.save_path    "/var/lib/php/session"

8. memcached(1.5.12-1)

# yum -y install memcached-devel php-pecl-memcache

インストール。

# vi /etc/php.d/40-memcache.ini

;session.save_handler=memcache
session.save_handler=memcache

;session.save_path="tcp://localhost:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
session.save_path="tcp://localhost:11211"

設定。

# systemctl start memcached
# systemctl reload httpd
# systemctl enable memcached
Created symlink from /etc/systemd/system/multi-user.target.wants/memcached.service to /usr/lib/systemd/system/memcached.service.

セッションだけならばメモリキャッシュしても大丈夫でしょう、という判断。

9. MySQL(8.0.13-1)

# rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm を取得中
警告: /var/tmp/rpm-tmp.RrLyDn: ヘッダー V3 DSA/SHA1 Signature、鍵 ID XXXXXXXX: NOKEY
準備しています...              ################################# [100%]
更新中 / インストール中...
   1:mysql80-community-release-el7-1  ################################# [100%]

ダウンロード。

# yum -y install mysql-community-devel mysql-community-server

インストール。

# mkdir /var/log/mysql
# chown -R mysql:mysql /var/log/mysql

ログディレクトリ作成。

# vi /etc/my.cnf

[mysqld]

## 略

slow_query_log=ON
slow_query_log_file=/var/log/mysql/slow_query.log
long_query_time=1.0

## 略

log_timestamps=SYSTEM
skip-character-set-client-handshake

追記。

# systemctl start mysqld
# systemctl enable mysqld

起動&自動起動設定。

# less /var/log/mysqld.log

A temporary password is generated for root@localhost: XXXXXXXXXXXX

初期パスワードを見付け出します。

# mysql_secure_installation --use-default

Securing the MySQL server deployment.

Enter password for user root: XXXXXXXXXXXX

The existing password for the user account root has expired. Please set a new password.

New password: ZZZZZZZZZZZZ

Re-enter new password: ZZZZZZZZZZZZ
The 'validate_password' component is installed on the server.
The subsequent steps will run with the existing configuration
of the component.
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No) :  y
Success.


Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) :  y
Success.

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.


Remove test database and access to it? (Press y|Y for Yes, any other key for No) :  y
 - Dropping test database...
Success.

 - Removing privileges on test database...
Success.

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) :  y
Success.

All done!

rootのパスワードを変更。

10. Postfix

# less /etc/postfix/main.cf

mydestination = $myhostname, localhost.$mydomain, localhost

$mydomainがないことを確認。

11. Webmin

11.1. perl-Net-SSLeay(1.55-6)

# yum -y install perl-Net-SSLeay

必要なライブラリをインストール。

11.2. Webmin(1.900-1)

# yum -y install http://download.webmin.com/download/yum/webmin-1.900-1.noarch.rpm

本体をダウンロード&インストール。

# vi /etc/webmin/miniserv.conf

## 末尾に追加

allow=127.0.0.1 XXX.XXX.XXX.XXX/24

# /etc/rc.d/init.d/webmin restart

再起動。

# firewall-cmd --add-port=10000/tcp --permanent
success
# firewall-cmd --reload
success

ポートを開けます。

11.3. 設定

GUIで

  • Webmin
    • Webmin configurations
      • Language and Locale

Japanese(JA_JP.UTF-8)を選択。

12. Apache仮想サイト

12.1. ダミーサイトの作成

Apacheで存在しない仮想サイトを指定すると意図しないサイトが表示されるのでダミーを作っておきます。

# mkdir /var/www/dummy/
# mkdir /var/www/dummy/web
# chown hoge:hoge /var/www/dummy/web/

適当に仮想サイトのドキュメントルートにするディレクトリを掘って、以降Webminから設定。

  • 仮想ホストの作成
    • アドレス: 全てのアドレス
    • ポート: 80
    • ドキュメントのルート: /var/www/dummy/web
    • サーバ名: dummy.example.jp
    • 仮想サーバの追加: 選択したファイル: /etc/httpd/conf.d/1.conf
    • ディレクティブのコピー元: どこにもない

# vi /etc/httpd/conf.d/1.conf

#Options None ##コメントアウト

## 以下を追加

AllowOverride All
Options FollowSymLinks

.htaccess有効化のため。

12.2. 仮想サイト作成

今度は本当に使用する仮想サイトを作成。

# mkdir /var/www/example
# mkdir /var/www/example/web

以降、Webminから設定。

  • 仮想ホストの作成
    • アドレス: 特定のアドレス(IP)
    • ポート: デフォルト
    • ドキュメントのルート: /var/www/example/web
    • サーバ名: example.jp
    • 仮想サーバの追加: 選択したファイル/etc/httpd/conf.d/example.conf
    • ディレクティブのコピー元: どこにもない

作成後、ディレクティブの編集。

DocumentRoot "/var/www/example/web"
ServerName www.example.jp
ServerAlias example.jp
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.jp$
RewriteRule ^(.*)$       http://www.example.jp/$1 [R=301,L]
<Directory "/var/www/example/web">
allow from all
AllowOverride All
Options FollowSymLinks
Require all granted
</Directory>

www ありなしを統一するために

  • ServerAliaswww なしでもこの仮想サイトで応答する
  • RewriteEngine 以下3行で www なしのアクセスを www ありにリダイレクト

を追記しています( 13. Let’s Encrypt の作業後に 443 ポートの仮想サイトにも同様の設定を行う)。

また、 .htaccess 有効化のため AllowOverrideOptions を変更します。

これでApacheを再起動。

13. Let’s Encrypt

13.1. インストール

# sudo yum install epel-release

## 略

パッケージ epel-release-7-11.noarch はインストール済みか最新バージョンです
何もしません

必要なパッケージのインストール(いらなかった)。

# sudo yum install certbot python-certbot-apache

## 略

完了しました!

本体インストール。

13.2. 設定

# certbot
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator apache, Installer apache
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): hoge@example.jp
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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: Y
Starting new HTTPS connection (1): supporters.eff.org

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: dummy.example.jp
2: example.jp
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 2
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for example.jp
Waiting for verification...
Cleaning up challenges
Created an SSL vhost at /etc/httpd/conf.d/example-le-ssl.conf
Deploying Certificate to VirtualHost /etc/httpd/conf.d/example-le-ssl.conf

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 vhost in /etc/httpd/conf.d/example.conf to ssl vhost in /etc/httpd/conf.d/example-le-ssl.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://example.jp

You should test your configuration at:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.jp/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.jp/privkey.pem
   Your cert will expire on 2019-02-18. 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

完了。

13.3. 自動更新設定

# vi /etc/crontab

23 1 * * * root /usr/bin/certbot renew --post-hook "sudo systemctl reload httpd"

cronで自動実行するように設定。

14. WordPress

14.1. MySQL設定

  • DB作成: example_wpdb
    • 文字コード: utf8mb4_0900_ai_ci
    • 照合順序: utf8mb4_ja_0900_as_cs_ks
  • ユーザ作成: example_wpdb_user
    • 許可なし。example_wpdbに対しての許可だけ与える

これでDBインポート。

14.2. wp-config.php

wp-config.phpを変更。

/** WordPress のためのデータベース名 */
define('DB_NAME', 'old_db');

/** MySQL データベースのユーザー名 */
define('DB_USER', 'old_user');

/** MySQL データベースのパスワード */
define('DB_PASSWORD', 'old_password');

/** MySQL のホスト名 */
define('DB_HOST', 'localhost');

/** データベースのテーブルを作成する際のデータベースのキャラクターセット */
define('DB_CHARSET', 'utf8');

/** データベースの照合順序 (ほとんどの場合変更する必要はありません) */
define('DB_COLLATE', '');

から

/** WordPress のためのデータベース名 */
define('DB_NAME', 'example_wpdb');

/** MySQL データベースのユーザー名 */
define('DB_USER', 'example_wpdb_user');

/** MySQL データベースのパスワード */
define('DB_PASSWORD', 'new_password');

/** MySQL のホスト名 */
define('DB_HOST', 'localhost');

/** データベースのテーブルを作成する際のデータベースのキャラクターセット */
define('DB_CHARSET', 'utf8mb4_0900_ai_ci');

/** データベースの照合順序 (ほとんどの場合変更する必要はありません) */
define('DB_COLLATE', 'utf8mb4_ja_0900_as_cs_ks');

と変更。

14.3. FTPアップロード

旧サイトからダウンロードしたWordPressのファイル群と上述wp-config.phpをアップロード。

14.4. 権限設定

# usermod -aG wheel,apache ftpuser

WordPress管理画面からはApache権限の操作になるのでその関連の設定。まずユーザをApacheグループに追加。

# chown -R apache:apache /var/www/example/web
# find /var/www/example/web/ -type f -exec chmod 664 {} \;
# find /var/www/example/web/ -type d -exec chmod 775 {} \;

再帰的に所有者と権限を変更。ちなみに/var/www/example/root:rootとしておきます。

# chmod 400 /var/www/example/web/wp-config.php

wp-config.phpは特に厳重に。

15. WP-CLI

# cd ~
# curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 5241k  100 5241k    0     0   768k      0  0:00:06  0:00:06 --:--:--  806k
# chmod +x wp-cli.phar
# mv wp-cli.phar /usr/local/bin/wp

インストール。

# wp search-replace --recurse-objects 'example.com' 'example.jp' --allow-root
+------------------+-----------------------+--------------+------+
| Table            | Column                | Replacements | Type |
+------------------+-----------------------+--------------+------+
| wp_commentmeta   | meta_key              | 0            | SQL  |
| wp_commentmeta   | meta_value            | 0            | SQL  |
| wp_comments      | comment_author        | 0            | SQL  |
| wp_comments      | comment_author_email  | 0            | SQL  |
| wp_comments      | comment_author_url    | 0            | SQL  |
| wp_comments      | comment_author_IP     | 0            | SQL  |
| wp_comments      | comment_content       | 0            | SQL  |
| wp_comments      | comment_approved      | 0            | SQL  |
| wp_comments      | comment_agent         | 0            | SQL  |
| wp_comments      | comment_type          | 0            | SQL  |
| wp_links         | link_url              | 0            | SQL  |
| wp_links         | link_name             | 0            | SQL  |
| wp_links         | link_image            | 0            | SQL  |
| wp_links         | link_target           | 0            | SQL  |
| wp_links         | link_description      | 0            | SQL  |
| wp_links         | link_visible          | 0            | SQL  |
| wp_links         | link_rel              | 0            | SQL  |
| wp_links         | link_notes            | 0            | SQL  |
| wp_links         | link_rss              | 0            | SQL  |
| wp_options       | option_name           | 0            | SQL  |
| wp_options       | option_value          | 16           | PHP  |
| wp_options       | autoload              | 0            | SQL  |
| wp_postmeta      | meta_key              | 0            | SQL  |
| wp_postmeta      | meta_value            | 17           | PHP  |
| wp_posts         | post_content          | 165          | SQL  |
| wp_posts         | post_title            | 0            | SQL  |
| wp_posts         | post_excerpt          | 0            | SQL  |
| wp_posts         | post_status           | 0            | SQL  |
| wp_posts         | comment_status        | 0            | SQL  |
| wp_posts         | ping_status           | 0            | SQL  |
| wp_posts         | post_password         | 0            | SQL  |
| wp_posts         | post_name             | 0            | SQL  |
| wp_posts         | to_ping               | 0            | SQL  |
| wp_posts         | pinged                | 0            | SQL  |
| wp_posts         | post_content_filtered | 15           | PHP  |
| wp_posts         | guid                  | 1986         | SQL  |
| wp_posts         | post_type             | 0            | SQL  |
| wp_posts         | post_mime_type        | 0            | SQL  |
| wp_term_taxonomy | taxonomy              | 0            | SQL  |
| wp_term_taxonomy | description           | 0            | SQL  |
| wp_termmeta      | meta_key              | 0            | SQL  |
| wp_termmeta      | meta_value            | 0            | SQL  |
| wp_terms         | name                  | 0            | SQL  |
| wp_terms         | slug                  | 0            | SQL  |
| wp_usermeta      | meta_key              | 0            | SQL  |
| wp_usermeta      | meta_value            | 0            | PHP  |
| wp_users         | user_login            | 0            | SQL  |
| wp_users         | user_nicename         | 0            | SQL  |
| wp_users         | user_email            | 0            | SQL  |
| wp_users         | user_url              | 0            | SQL  |
| wp_users         | user_activation_key   | 0            | SQL  |
| wp_users         | display_name          | 0            | SQL  |
+------------------+-----------------------+--------------+------+
Success: Made 2199 replacements.

旧ドメイン(example.com)から新ドメイン(example.jp)に置換。

  • トップ、2ページ目、固定ページが表示されることを確認
  • ログイン正常
  • アップデート適用
  • 記事をアップ
  • メディアの追加・削除

以上のことができることを確認。

16. SSH

# vi /etc/ssh/sshd_config


#PermitRootLogin yes
PermitRootLogin no

#PermitEmptyPasswords no
PermitEmptyPasswords no

SSH での root ログイン禁止と空パスワード禁止に設定を変更。

# systemctl reload sshd
#

リロード。OK。

引っかかりポイント

途中何度も引っかかったので、引っかかったポイントを列挙しておきます。

参考

CentOS7.5

Webmin

vsftpd

Apache

ディレクティブ

Memcached

MySQL

Postfix

Let’s Encrypt

WordPress

SSH

この記事を書いた人

アバター

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。