30歳からのプログラミング

30歳無職から独学でプログラミングを開始した人間の記録。

ウェブエンジニアがサーバーを管理していくための初歩

インフラについて調べていたので、その備忘録。
調べていく上で重視したのは、概念や概要を知ること。細かい知識はあとでいくらでも調べることが出来るが、土台となるものがなければ調べることすら出来ない。
「公式ガイドやハウツー記事に従って設定したけど、俺は今、一体何をしているんだ?」という状態から抜け出したかった。
具体的なコマンドよりも、そもそも何をしているのか、そしてそれは何のために行っているのかを、把握できるようになりたかった。

そもそもサーバーってなんだ

一口にサーバーといっても、多義的。
まずこれを区別していないのが、混乱の元だった。
初学者は「サーバー」と言っている時に具体的に何を指しているのか、意識したほうがいい。

まず最初に存在するのが、ハードウェアとしてのサーバー。
これはただのコンピュータであり、中身が入っていなければただの箱である。
VPSクラウドなどで、本当に物理的にコンピュータが存在するのかなどは、取り敢えず措いておく。
VPSクラウドでも、サーバーというコンピュータ(に相当するもの)が存在するのは同じだから。

我々が使っているコンピュータと一緒で、サーバー(コンピュータ)にもOSが必要である。
サーバーでは、WindowsMacではなく、Linuxが使われていることが多い。
LinuxにはCentOSなど様々な種類がある。
この記事では、サーバーのOSはCentOS7である前提で進めていくが、基本的な考え方は、他のOSでもほとんど変わらないと思う。

OS以外にサーバー(コンピュータ)に必要なものとして、IPアドレスがある。これは、ネットワーク上でこのコンピュータを識別するための仕組み。

VPSサービスなどを契約すると、IPアドレスは最初から割り当てられており、あなたが契約しているサーバー(コンピュータ)のIPアドレスはこれですよとメールなどで送られてくる。
また、OSを簡単にインストールするための仕組みも、VPSサービスなどには用意されていると思う。

しかし、コンピュータを動かすためのOSをインストールし、ネットワーク上で識別するためのIPアドレスを用意しても、それだけでは自分のような初心者ウェブエンジニアが思い浮かべる「サーバー」の動きにはならない。

OSだけでは不十分で、様々なアプリケーションを起動させたり、管理したりする必要がある。
自分が普段使っているパソコンと一緒で、用途に応じてインストールやら設定やらが必要になる。

手元のパソコンでインターネットを利用するためには、ウェブクライアントとしてブラウザを用意しなければならない。
そうすることで、このパソコンはウェブクライアントとして機能するようになる。

そして、ウェブクライアントとHTTP通信を行い、リクエストに応じてレスポンスを返すコンピュータをウェブサーバーと呼ぶ。
手元のパソコンにブラウザを用意するように、サーバー(コンピュータ)にはウェブサーバーソフトウェア(後述)を用意して、そのサーバー(コンピュータ)をウェブサーバーとして利用できるようにする必要があるのだ。
ウェブプログラミングの文脈で単に「サーバー」というときは、「ウェブサーバー」を指していることが多いと思う。

つまり、サーバー(コンピュータ)をウェブサーバーとして利用、運用していくために、サーバー(コンピュータ)の適切な管理が必要になる。
そしてコンピュータを操作するために使うのが、SSHyumである。

参考資料

デーモン

SSHyumの前に、デーモンについて説明しておく。

デーモンとは、UNIX系のOSにおいて、常駐しているソフトウェアのこと。
これが起動しているから常に、必要に応じて処理を行うことが出来る。

ウェブサーバーとHTTP通信できるのも、そのためのデーモンがサーバー(コンピュータ)上で動いているから。
だから、24時間いつでも、HTTPでリクエストを送ればちゃんとレスポンスが返ってくる。

参考資料

SSH

一般的に、サーバー(コンピュータ)として使っているコンピュータは手元にはないことが多いはず。
そのため、離れた場所にあるコンピュータにアクセスする必要がある。
そのための方法が、SSHである。

SSHとは、HTTPと同じ、アプリケーション層のプロトコル
そして、これもHTTPと同じだが、SSH通信を行うためにはそのためのソフトが必要になる。

まず手元のパソコンに、SSHクライアントソフトウェアが入っている必要がある。
Macの場合は最初から入っているため、ターミナルでsshというコマンドを使うことでSSH通信ができる。

そしてサーバー(コンピュータ)にSSHサーバーソフトウェアを入れ、それを起動させれば、そのサーバー(コンピュータ)をSSHサーバーとして使えるようになる。
そうすると、SSHクライアントからのアクセスを受け取ってそれを処理できるようになる。
この状態は、SSHのデーモン(sshd)が動いているとも表現できる。

具体的なソフトウェアとしては、OpenSSHというものを使うことが多い。
クライアントとしてもサーバー(SSHサーバー)としても使うことができ、最初からMacに入っているのもこれ。

Macのターミナルで以下のコマンドを打つと、SSH通信を行える。

$ ssh ユーザー名(後述)@サーバー(コンピュータ)のIP

SSHでログインすれば、サーバー(コンピュータ)にログインした状態になるので、様々な操作を行うことが出来る。

前述のようにサーバー(コンピュータ)のOSはLinuxを使うことが多いが、MacUnix系のOSなので、多くのコマンドは共通している。
そのため、普段ターミナルで使っているlscdなどはそのまま使うことが出来る。

例えば、以下のコマンドで/etc/ssh/sshd_configというファイルを編集できる。

# cd /etc/ssh
# vim sshd_config

このファイルは、sshdの設定ファイル。セキュリティ対策などでSSHの設定を変える際は、このファイルを編集することになる。
ちなみに、編集した設定を有効にするには# systemctl restart sshd.serviceというコマンドでsshdの再起動させる必要がある。

SSH通信を終えるには、exitコマンドでサーバー(コンピュータ)からログアウトする。

参考資料

yum

SSHによってサーバー(コンピュータ)を操作できるようになった。

そこでよく行うものの一つが、yumである。
これは、パッケージ管理システム。
フロントエンドのnpmMacbrewが、役割として近いと思う。

yumを使ってソフトウェア(パッケージ)をインストールしたり、アップデートしたり出来る。

# yum list installedで、既にインストールされているパッケージを確認できる。
# yum install パッケージ名で、パッケージをインストール。
# yum search パッケージ名で、パッケージを検索。

ところで、インストールや検索と言うが、一体どこからインストールしているのだろうか。
どこを対象にして検索をかけているのだろうか。
それは、「リポジトリ」からである。

リポジトリという、パッケージの配布元がある。
そして、リポジトリというのは一つではなく、世の中にたくさん存在するのだが、yumを実行したときに対象となるのは、そのサーバー(コンピュータ)に登録済みかつ有効になっているリポジトリのみである。

登録してあるリポジトリは、# yum repolist allで確認できるし、有効かどうかもこれで確認できる。
ここに登録されており、かつ有効なリポジトリから、インストールしたり、アップデートしたり、検索したりする。

/etc/yum.repos.d/以下にファイルを作ることで、任意のリポジトリを追加することも出来る。
詳しくはこちらの記事を参照。
yum|yum リポジトリの設定と追加

ユーザーとパーミッション

SSH通信によってサーバー(コンピュータ)にアクセスし、yumなどの操作を行っていくわけだが、それは必ず何らかの「ユーザー」によって行われる。 最初にSSHでログインするときは恐らく、rootというユーザーだと思う。

だがroot以外にもユーザーは存在し、# cat /etc/passwdでユーザー一覧を見ることが出来る。

また、自分でユーザーを追加することも出来る。

# adduser ユーザー名 // ユーザーの追加
# passwd ユーザー名 // ユーザーのパスワードを設定

ユーザーが複数存在することは分かったが、では、ユーザーによって何が違うのかというと、そのコンピュータ内で何が出来るのかという権限が異なる。

例えば、ファイルを読み書きするのには、そのファイルに対して権限を持っている必要がある。 # ls -lというコマンドで、そのディレクトリ内のファイルやディレクトリの権限などの情報を見ることが出来る。

これらを変更するには、chmodchownといったコマンドを使う。

参考資料

ファイアウォールとポート

ここからようやく、具体的な設定や操作の話になる。
まずはファイアウォールから。

サーバー(コンピュータ)はネットワークにつながっているため、どうしても外部からの攻撃の危険に晒されることになる。

ファイアウォールは外部からの攻撃を防ぐための仕組みであり、そのための代表的な機能が、パケットフィルタリングである。

サーバー(コンピュータ)とクライアントがデータをやり取りする際、データをパケットという単位に分割して送受信する。
そしてパケットには様々な情報が含まれており、ファイアウォールはこの情報を見て、許可されている通信かどうかを判断し、そうでない通信は拒絶するようにする。
これがパケットフィルタリングである。

よく使われるのが、特定のポートでの通信だけを許可する、という設定である。

ポートとは通信の出入り口のことで、パケットは必ずこのポートを通って、やり取りされる。
ポートは複数存在し、それぞれを識別するために番号が振られている。
これがポート番号。
通信に使うプロトコルにはTCPUDPの2種類があるが、それぞれにポート番号が存在する。

そして、これが重要なのだが、各サービス毎に、使用するポートは決っている。
例えばSSH通信の場合は、デフォルトではTCPの22というポートで通信が行われる。HTTP通信はTCPの80である。

ウェブサーバーとして利用する場合、そのサーバー(コンピュータ)が使用するポートは、かなり限られている。
ファイアウォールのパケットフィルタリングの機能を使い、使用していないポートでの通信は許可しないようにするのが、セキュリティの基本である。
そうすることで、必要な通信以外は発生させないようにして、攻撃に晒されるリスクを減らすことが出来るからだ。

CentOS7でのファイアウォールの設定は、firewalldというツールを使って行う。

参考資料

systemctl

firewalldの操作に先立って、CentOS7の基本的な操作を確認しておく。

ソフトウェアの起動や停止などは、systemctlというコマンドで行う。

上から順に、起動、停止、再起動。

# systemctl start ソフトウェア名
# systemctl stop ソフトウェア名
# systemctl restart ソフトウェア名

ファイアウォールSSHサーバーソフトウェア、ウェブサーバーソフトウェアを停止することはあまりないと思うが、設定を変更した際にそれを反映させるために再起動を行うことは多い。

また、これらのソフトウェアは、自動起動を有効にしておくのが基本。
これを有効にしておくことで、OSが起動した際にそのソフトウェアも自動的に起動してくれる。
この設定を有効にしておかないと、何らかの理由でサーバー(コンピュータ)が再起動した際に、ファイアウォールなどの個別のソフトウェアも手動で起動させないといけなくなってしまう。

自動起動が有効になっているかは、# systemctl list-unit-files -t serviceで確認し、対象のソフトウェアがenabledとなっていれば有効になっている。
だがこれだと大量のソフトウェアが出てきて見づらいので、grepを合わせて使うとよい。

# systemctl list-unit-files -t service | grep firewalld
firewalld.service                             enabled 

無効(disable)になっていた場合、# systemctl enable ソフトウェア名で有効にできる。

firewalld

firewalldを使っていくには、ゾーンという概念とサービスという概念を理解する必要がある。

ゾーンとは、各種設定をひとまとめにした設定集のようなもの。
デフォルトで9つのゾーンが用意されているが、この中から一つを選んで、適用することになる。
そうするとそのゾーンで行っている設定が有効になる。

以下のコマンドで、現在適用されているゾーンを確認できる。

# firewall-cmd --get-active-zones
public
  interfaces: eth0

上記の場合、publicというゾーンが使われていることを意味している。
デフォルトではこの設定になっているはずで、他のゾーンに変更したり、自分でゾーンを作成したりすることも出来るのだが、最初のうちは不要だと思う。
publicをそのまま使いながら、必要に応じてpublicの設定を変えていけばよい。

もう一つ重要なのが、サービスという概念。
サービスを、ゾーンに追加したり削除したりすることで、そのサービスが使っているポートを開けたり閉じたりできる。

例えば、HTTP通信を許可したい場合は、現在有効になっているゾーン、つまりpublicに、httpを追加すればよい。

以下が、そのための具体的な方法。

先程既に出てきたが、firewalldを操作するためのコマンドはfirewall-cmdなので、それを使う。

まず、現在使われているサービスは何なのかを把握する必要がある。

# firewall-cmd --list-all --zone=ゾーン名

いくつか項目が出てくるが、servicesの欄を見て、そこに書かれているものが、そのゾーンで有効になっているサービスである。

services: dhcpv6-client ssh

これを見るとhttpがないので、追加する。

追加のコマンドは# firewall-cmd --zone=ゾーン名 --add-service=サービス名
今回はpublichttpを追加するので# firewall-cmd --zone=public --add-service=httpになる。

削除する場合は--add-serviceではなく--remove-serviceを使う。

# firewall-cmd --list-all --zone=ゾーン名でもう一度確認すると、追加されていることが分かる。

services: dhcpv6-client ssh http

だがこの方法で行った設定は一時的なもので、firewalldが再起動されると元に戻ってしまう。

一時的ではなく恒久的な設定にしたい場合は、--permanentオプションをつける。

# firewall-cmd --zone=ゾーン名 --add-service=サービス名 --permanent

だがこの変更は即座には反映されず# firewall-cmd --reloadを実行しないと反映されない。

こうするとこの設定は恒久的なものになり、再起動しても元に戻ることはない。

恒久的な設定について確認する場合も、--permanentオプションをつければよい。

# firewall-cmd --list-all --zone=ゾーン名 --permanent

設定できるサービスはhttp以外にも存在し、# firewall-cmd --get-servicesで一覧を見ることが出来る。
各サービスの情報を得るのは# firewall-cmd --info-service=サービス名

各サービスの設定ファイルは/usr/lib/firewalld/services/に入っている。
例えば以下は、httpの設定ファイル。使っているポートの情報などが書かれていることが分かる。

# cat /usr/lib/firewalld/services/http.xml
<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>WWW (HTTP)</short>
  <description>HTTP is the protocol used to serve Web pages. If you plan to make your Web server publicly available, enable this option. This option is not required for viewing pages locally or developing Web pages.</description>
  <port protocol="tcp" port="80"/>
</service>

これを編集して# firewall-cmd --reloadを実行すれば、そのサービスに対応するポート番号などを変更できる。
注意点は、これはあくまでもファイアウォールの設定の話であり、それとは別に各ソフトウェア(OpenSSHやnginxなど)側でポート番号の変更を行う必要がある。

参考資料

ウェブサーバーソフトウェア

ファイアウォールの設定も終わったので、次はいよいよ、ウェブサーバーソフトウェア。
これをインストールして起動することで、サーバ(コンピュータ)がウェブサーバーとして機能するようになり、HTTP通信が可能になる。
この場合、サーバ(コンピュータ)は、ウェブサーバーであり、かつSSHサーバーでもある、という状態になる。

ウェブサーバーソフトウェアを起動することでそれがHTTP通信を処理するデーモンとなり、HTTPリクエストを24時間受け付けることが可能になる。
ウェブサーバーとして動作しているデーモンをhttpdと表現することがある。
ただCentOSにおいては、httpdとは、デフォルトのウェブサーバーソフトウェアであるApacheのことを指す。
そのため、単にhttpdといってしまうと、Apacheという具体的なソフトウェアを指しているのか、それともウェブサーバーソフトウェアという総称のことを意味しているのか、分かりにくい。
だから基本的にはhttpdという表現は避けたほうがいいのかもしれない。

Apacheの他に、nginxというウェブサーバーソフトウェアもある。

ここではnginxを使う。バージョンは1.12.2

まずはここまでに書いた内容を使って、yumでnginxをインストールし、起動、そして自動起動を有効にする。
そうすると、HTTP通信が可能になる。
試しにhttp://IPアドレスにアクセスすると、nginxが用意しているデフォルトのコンテンツが表示される。

このコンテンツは、サーバー(コンピュータ)の/usr/share/nginx/htmlに入っている。
つまり、ここのディレクトリの内容が、HTTP通信でルートURLにアクセスしたときに返されている。
このディレクトリを、ドキュメントルートと呼ぶ。

そのためドキュメントルートの内容を差し替えることで、表示されるコンテンツが変えることが出来る。

nginxの設定ファイルは/etc/nginx/nginx.confで、ドキュメントルートもここに書かれている。

また、HTTPリクエストを受け取る度に、そのログが自動的に記録されていく。
ログファイルは/var/log/nginxに入っている。

参考資料

まとめ

DNSの設定など、ここでやってないことも多いが、取り敢えずこれで、スタティックなページをウェブ上に公開することは出来るようになった。

ものすごく大雑把にまとめてしまうと、SSHでサーバー(コンピュータ)にログインし、yumで必要なパッケージ(ソフトウェア)を用意し、ファイアウォールでTCP80のポートを開け、ウェブサーバーソフトウェアを起動してドキュメントルートにコンテンツを置けば、そのコンテンツをウェブで公開することが出来る。

『はじめよう! プロセス設計 ~要件定義のその前に』を読んだ

同僚に借りて読んだ。
三部作の二番目のようだが、前作を知らなくても特に問題なく読めた。

「設計」や「要件定義」という言葉がタイトルに入っているが、本書の内容はシステム設計などに限定されるものではなく、もっと普遍的なことを扱っている。
仕事とは何か、ということを解きほぐしていき、それをよりよいものにするためにはどうすればいいのかを考えていく。

プログラマやプロジェクトマネージャー以外にもオススメできる。

gihyo.jp

まず、文書が平易で読みやすい。難しい専門用語は使われておらず、予備知識が何もなくても読み進めることが出来る。

それから、随所に載っているイラストが分かりやすく、理解を促してくれる。
この手の書籍のイラストは、ただ「柔らかい雰囲気」や「手に取りやすい雰囲気」を出すだけのもので、ほとんど意味がないことが多い、と個人的には思っている。 ただ単に本文の内容を繰り返しているだけだったり。
だが本書のイラストは、本文の内容を別の角度で表現したり、分かりやすく図解したり、ちゃんと意味のあるものになっている。
イラストレーターの略歴を見ると、著者が経営している会社の設立にも参加しているらしく、単なる外注先ではなくビジネスパートナーのような存在らしい。
だから、著者の主張を理解して、本文の内容を上手く補完するようなイラストを描けるのだろう。

タイトルにもある通り、プロセスというものが、本書のメインテーマになっている。

プロセスとは、仕事を達成するための過程や手順であり、その仕組みのこと。
そして、仕事は連鎖していくものであり、その連鎖のこともプロセスであると言える。

連鎖とはどういうことか。
仕事を行うためには、材料や道具が必要になる。
材料や道具を使って何らかの活動を行い、成果を生み出すのが、仕事。

例えば料理をするという仕事を行うためには、食材や調理器具が必要となる。だから、料理をする前にまず、食材を買う、調理器具を準備する、といった仕事が必要になる。それらの仕事の成果として食材や調理器具が手に入り、それを使って「料理をする」という仕事を行う。その成果が「完成した料理」だが、さらにそれを材料として、「料理をテーブルに運ぶ」という仕事を行う。

このようにして、仕事はつながっていく。
この連鎖が上手くいかないと、滞留が発生したり、仕事が非効率になったりしていく。

こういったことは、多くの人が考えていることだとは思う。
段取り、と呼ばれたりするもの。ゴールを達成するために、仕事を分解し、まず何から手をつけるか考える。
そういう意味では、目新しくて斬新な話というわけではない。
本書でも、仕事で何らかの成果を出している以上、プロセスは既に存在していると書いている。
問題なのは、プロセスを意識的、計画的に行っていないことだという。

多くのプロセスは、なし崩し的、自然発生的に生まれたものであり、あまり深く考えずにそれを踏襲し習慣になってしまっている。
仕事が上手く進まない原因がここにある。
プロセスをよく見直して、良質なプロセスに変えていく必要がある。

では、良質なプロセスとはなんだろうか。
良質なプロセスであるためには、価値ある成果を生み出すものでなければならない。

プロセスや業務の見直しというと、どうしても、単なる効率化ということに目が向いてしまう。
だがそれでは意味がない。
不必要な業務や的外れな施策を効率化していては本末転倒だ。
価値を生む、ということを主軸にしないといけない。

そして、価値ある成果を生み出すプロセスとは、顧客が抱えている課題を解決するプロセスである。
ビジネスとは、顧客の問題解決を支援することである。だから、最終的に顧客の問題解決にたどり着かなければ、そのプロセスには価値はない。
本書の後半では、顧客が自身の課題を解決していくプロセスを「CX(カスタマーエクスペリエンス=顧客体験)」と呼び、CXを軸にして、プロセス設計の仕方を見ていく。

本書によれば、プロセスを設計する上で重要なのは、ゴールをしっかりと定義し(ビジョンや要件の明確化)、そのゴールから逆算して大まかな流れを考え(バックキャスティング)、そうやって描いた流れを細かいステップに分割して(ブレイクダウン)、粒度の細かなタスクに落とし込んでいくことだと言う。

ゴールを明確にすることやゴールから逆算して考えることも、よく言われることであり、目新しい話ではない。
こういう、当たり前のことを自覚的に、丁寧にやっていくことが、大切なのだろう。

冒頭で「システム設計に限定されるものではない」と書いたが、プロセス設計とはそもそも仕事に限定されるものではない。
本書で説明している考え方や設計は、生活全般に当てはめることが出来る。

本書の最後でビジョン、戦略、兵站といった話題についても少し触れられているが、「よりよい仕事の進め方」だけの本ではない。
もっと、応用範囲の広い話である。

この記事で紹介されている、「無理をするなら、ちゃんとした軍隊でなければ」というセリフを思い出した。
大学院中退、就職。そして1年後。 : ボルボラのブログ

しかし、結果と経験からいえば、心だけで「決意する」ことは、何の効用もなかった。努力するには準備が必要だという考え方がなかった。すべてのステップを飛ばして、いきなり「努力する」→「成果が出る」というプロセスを実行できるものだと信じていた。
(中略)
現実的には、努力するための体勢を整える作業なくして、努力できるということはない。もちろん広い世の中には例外もいるだろうが、自分がその例外だと考えるのは、たいていの場合悲しい結果にしかならない。

この引用の通りで、兵站やプロセスの連鎖というのは、人生においても重要になる。
ゴールに到達するためには「相当な努力をする」というプロセスが必要だとする。そして「相当な努力をする」というプロセスを実行するためには、大抵の場合、その材料として「健康な心身」が必要になる。だからまず、「努力をする」というプロセスに先立って、「睡眠」や「運動」といったプロセスを実行して、その成果として「健康な心身」を手に入れなければならない。

仕事にしろ私生活にしろ、何か達成したことがあるのならば、本書で紹介されているプロセス設計の考え方を実践していくことで、その実現可能性を高めていくことが出来るはずだと思う。