サブスクリプション管理サービス「PreBill」を作りました

はじめに

FJORD BOOT CAMP(フィヨルドブートキャンプ)というプログラミングスクールに通っていまして、最近卒業しました。

こちらのスクールの最終課題で自作サービスを作りましたので、紹介させていただきます。 今回作成したのは、個人で利用しているサブスクリプションサービスを一元管理できるサービスです。

サブスクリプション管理アプリ「PreBill」

PreBill

github.com

作った経緯

サブスク、利用している方も多いと思うのですが、自分がどれだけサービスを利用していていくら消費しているのか、またそれぞれのサービスの更新がいつなのかを把握するのは意外と面倒だったりします。サブスクリプション型のサービスも増えており、様々なサービスを利用していると気づかぬうちに月々の出費がかさんでいることもあるかもしれません。また、サービスの更新日を忘れていたために解約しようかどうか迷っていたサービスが自動更新されていたという経験がある方も少なくないのではないでしょうか。

通常ならば料金や更新日を確認するにはサービスの管理画面やメールなどで確認すると思うのですが、それをまとめて確認できて、通知もしてくれると便利かも!と思い作成することにしました。

フィヨルドブートキャンプでは、自作サービス開発を始める前にどんなサービスを作るかについて、サービスの内容を説明するエレベーターピッチを作成し、レビューを受けます。いくつか提案をしている中で、自分が抱える不満を解決するサービスを作ると良いというアドバイスをいただきました。単に「こういったサービスがあると面白そう」といった視点だけでは、誰にも利用されないサービスになってしまう可能性も大いにあります。自分の抱える不満を解決できるサービスならば、最低でも自分という利用者がいるので誰にも利用されないサービスにはならずに済みます。

このアドバイスをいただいてから自分が面倒に感じていることは無いだろうか?ということを考え、思いついたのがサブスクリプションの管理アプリです。

できること

自分が利用しているサービスの料金や更新日を一覧できます。それぞれのサービスに通知を設定することもできるので、設定された日付になったらメールで通知を受け取ることができます。

また、トップページには登録されているサービスの合計金額(年額合計/月平均合計額)が表示されるので、自分がいくらサブスクリプションサービスに課金しているのかが一目瞭然になります。

レスポンシブなので、PC、スマホタブレットからでも利用することができます。

PC

f:id:shoynoi:20200527163903p:plain

スマホ

f:id:shoynoi:20200527164156p:plain

できないこと

サブスクリプションサービスにいくら課金しているのか、次の更新がいつなのかを管理するサービスであり、「これまでにいくら支払ったのか」という実績は記録されません。

利用しているサービスの登録については利用者自身で行う必要があります。サービス登録の自動化、もしくはより簡潔に登録ができる方法を実現したかったのですが、良い案が思い浮かびませんでした。代わりに、フィヨルドブートキャンプのメンターの方とペアプロをした際に、サービス名を入力したときにサービス名や料金などを補完する機能を実装しました。

f:id:shoynoi:20200527162206g:plain

これで少しは登録の面倒さは減るのではないかなーと思っています。 そこでペアプロを初めて体験したのですが、一人で開発しているときには思いつかなかったアイデアや、アドバイスなどをいただけて非常に勉強になりました。

これからやりたいこと・課題

現在、サービスのプランとして登録できるのは、月額/年額払いのみになっています。サブスクリプションサービスによっては3ヶ月毎に更新のようなサービスもあるようなので、登録できるプランは柔軟に設定できるようにしたいと考えています。

また、トップページにアイコンが表示できると視認性もよくなるかなーと思いますので、一覧ページにアイコンが表示されるようにしたいです。今後も引き続き開発を続けて、より便利にしていきたいです。

まとめ

サブスクリプションサービスの利用が増えている方は是非一度登録して利用してみていただけたらと思います。不満点や要望などありましたら、@shoynoiにDM等お願いします。

1年ちょっとフィヨルドブートキャンプで学習し、自分でサービスを考えてリリースできたのはひとえにメンターである@komagataさんと@machidaさんのおかげです。本当にありがとうございました。

PostgreSQLのリモート接続設定

デフォルトではlocalでの接続しか許可されていない。 別のホスト(端末)からでもデータベースに接続できるように設定を変更する

設定方法

環境

設定項目(データベースを持つ側)

  1. listen_addressesの修正
  2. データベース(PostgreSQL)のポート変更
  3. 接続を許可するIPを追記

listen_addressesの修正

listen_addressesはクライアントアプリケーションからの接続を監視するTCP/IPアドレスを指定する。この項目で、どのインターフェースが接続を試みるかを制御する。安全でないネットワークインターフェース上において繰り返して行われる接続要求の防止に役立つ(19.3. 接続と認証)

postgresql.confを開き、listen_addressesの項目を編集する

$ sudo vim /etc/postgresql/11/main/postgresql.conf

60行目付近の以下の項目を探す

#listen_addresses = 'localhost'

接続を受け付けるホストのIPアドレスを記述する。すべてのIPアドレスからの接続を受け付ける場合は'*'と指定する。

listen_addresses = '*'

データベースのポート変更

postgresql.conf内の60行目付近にport番号を指定する項目がある この項目に以下を指定する

port = 5432

接続を許可するIPを追記

次に、pg_hba.confを編集して接続を許可するIPアドレスを設定する。 この設定で誰がサーバーにアクセス可能かをきめ細かく制御できる。

$ sudo vim /etc/postgresql/11/main/pg_hba.conf

93行目付近に#IPv4 local connections:と記述されている項目がある。 その中に以下を追記する

host all all 192.168.x.xxx/0 md5

書式は、 接続形式 database user IP-address auth-method
となっている。

上記の設定は、TCP/IPを使用した接続で、192.168.x.xxx/0の範囲内のホストに対してMD5認証を行い、すべてのユーザー、すべてのデータベースへの接続を許可する。ということになる。

設定を反映させる

PostgreSQLを再起動して変更した設定を反映させる

sudo /etc/init.d/postgresql restart

接続の確認

ローカルのシェルからさくらのVPS上のデータベースサーバに接続を試みて接続できるか確かめる。

psql -h os3-xxx-xxxxx.vs.sakura.ne.jp -U akira -d mydb

接続ができた。

SSHの基礎を押さえる

SSHとは

Secure Shell。

暗号や認証の技術を利用してリモートサーバーと安全に通信を行うためのプロトコル

SSHはクライアントとサーバー間の通信を暗号化する。そのため、安全にリモートサーバーにログインしたり、リモートサーバー上でコマンドを実行できるようになる。

SSHを利用した通信をするには専用のソフトが必要となる。現在はOpenSSHがよく利用されている。

もう少し詳しく

クライアントがリモートサーバーと安全に通信を行うには、

  1. 接続しようとしているサーバーが本当に目的のサーバーなのか?(ホスト認証)
  2. サーバーに接続しようとしているクライアント(ユーザー)は正しいユーザーなのか?(ユーザー認証)

ということを検証する。

この認証には公開鍵認証方式が活用されている。

公開鍵認証方式

公開鍵と秘密鍵の2つの鍵を使ってデータの暗号化、復号を行う公開鍵暗号を利用した認証方式。公開鍵で暗号化されたデータは対となる秘密鍵でしか復号できない仕組みになっている。この性質を利用して、クライアント/サーバーが正規のものかどうかを確認する。

例えば、

ユーザー認証で公開鍵認証方式を利用する場合

  1. クライアントは暗号化用の公開鍵と復号用の秘密鍵を生成する
  2. サーバーに公開鍵を登録する
  3. クライアントが接続要求をすると、サーバーは乱数を公開鍵で暗号化してクライアントに渡す
  4. クライアントは渡された乱数を秘密鍵で復号してハッシュ値を求め、サーバーに渡す
  5. サーバーはクライアントが送り返してきたハッシュ値と元のハッシュ値を比較して一致したら認証する

以上の流れでサーバーはユーザーが正しいユーザーかどうかを判断する。

ポイントはパスワードないし秘密鍵等の重要な情報はネットワーク上に流れないという点である。 暗号化されたデータを盗み見られたとしても、元のデータはわからないし、(秘密鍵が漏洩しない限り)秘密鍵無しでは暗号化されたデータは復号がほぼ不可能であるため、安全にデータのやり取りを行うことができる。

ホスト認証

例えば、悪意のある第三者が同一のIPアドレスでサーバを偽装していて、クライアントがそれに気づかずに正しいパスワードを入力してしまった場合、正規のサーバーに不正ログインされる恐れがある。このようななりすましを防止するための仕組み。ホスト認証にも公開鍵認証が利用されている。

  1. クライアントはサーバーのホストキーの公開鍵を受け取る
  2. クライアントはホストキーの公開鍵で乱数を暗号化してサーバーに渡す
  3. サーバーは渡された乱数をホストキーの秘密鍵で復号してハッシュ値を求め、クライアントに渡す
  4. クライアントはサーバーから受け取ったハッシュ値と元のハッシュ値を比較して一致したら認証する

初回アクセス時はクライアントはサーバーのホストキーの公開鍵を保有していないので、サーバーへの接続を続行するかどうかの確認とともに、指紋(fingerprint)を提示する。

$ ssh -p 50010 hoge@xxxxxxxxxx.vs.sakura.ne.jp
The authenticity of host '[xxxxxxxxxx.vs.sakura.ne.jp]:50010 ([xxx.xxx.xx.xx]:50010)' can't be established.
ECDSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxx/x/xxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[xxxxxxxxxx.vs.sakura.ne.jp]:50010,[xxx.xxx.xx.xx]:50010' (ECDSA) to the list of known hosts.
Linux xxxxxxxxxx 4.9.0-8-amd64 #1 SMP Debian 4.9.130-2 (2018-10-27) x86_64

このfingerprintを接続前に予めサーバー上で確認しておき、上記で提示されたfingerprintと比較して一致しているかどうか判断する。確認方法は以下。

$ ssh-keygen -l
Enter file in which the key is (/home/hoge/.ssh/id_rsa): /etc/ssh/ssh_host_ecdsa_key.pub
256 SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxx/x/xxxxxxxxxxxxxx. root@xxxxxxxxxx (ECDSA)

初回アクセス以外は基本的に接続要求した時点で自動で認証が行われる。 警告が表示される場合はfingerprintが異なるため、接続を中止し、原因を探る必要がある。

ユーザー認証

サーバーに接続要求するクライアントが正しいユーザーであるかを確認する。 ユーザ認証は主に以下の2通りの認証方式がある。

  1. パスワード認証

    UNIXのユーザーアカウントにログインする時のパスワードをクライアントが入力することでそのクライアントが正しいユーザーであることを認証する。この認証方式は(暗号化されているとはいえ)パスワードをサーバーに送るため、リスクが高い。

  2. 公開鍵認証

    先程の例に書いたように、公開鍵認証はパスワードや秘密鍵などの知られたらアカウントにログインされてしまうような情報はネットワークに流れないため、セキュリティを考慮するとこちらの認証方式を設定することが強く推奨される。

インストールと設定方法

今回はローカル(Mac)の端末からさくらのVPS(Debian9(stretch))にSSHで接続する。

DebianにOpenSSHをインストール

$ sudo apt update

$ sudo apt install ssh

sshをインストールすることで、OpenSSHクライアントとOpenSSHサーバーがインストールされる。

OpenSSHの設定

OpenSSHの設定ファイルsshd_configに設定を記述

念の為、バックアップを取っておく

# cp /etc/ssh/sshd_config /etc/ssh/sshd_config.org

rootでのログインを禁止する

SSH接続でrootにログインできてしまうとすべての操作を実行することができてしまい、セキュリティ上問題があるため、rootでのログインを禁止するための設定をする。

設定方法はsshd_configのPermitRootLoginをnoに変更する。

PermitRootLogin no

これでSSH接続した端末でrootへのログインは禁止され、エラーが出力される。

ポート番号を変更する

SSHサーバーではデフォルトで22番ポートを使用するように設定されている。

このポート番号はSSH接続でよく使用されるポート番号で、これを利用してサーバーに対して攻撃を行うボットが存在している。ポート番号を変更することでこの攻撃の(簡単な)対策が行える。

sshd_configに記述されているPort 22の部分を別の番号に書き換える。

0-65535の間で任意の番号を指定する(ウェルノウンポートは避けたほうが良い。)

Port 50010

sshを再起動して設定を反映させる。

設定を記述しただけでは設定内容が反映されていないため、sshの再起動を行う。

$ sudo /etc/init.d/ssh restart

再起動が完了したら、設定が反映される。

クライアント側の設定

キーペアの作成

まだキーペア(公開鍵と秘密鍵)を作成していなければ、新しく生成する。

$ ssh-keygen -t rsa

コマンドを実行すると、パスフレーズの入力が求められる。

パスフレーズ秘密鍵を使用する時のパスワードに相当する。万が一秘密鍵が漏洩した場合でも正しいパスフレーズを入力しなければ秘密鍵は使用できないようになっている。

キーペアの生成が完了すると、~/.ssh/ディレクトリの中に、id_rsa.pub(公開鍵)とid_rsa(秘密鍵)がそれぞれ作成されている。

このうち、公開鍵であるid_rsa.pubをリモートサーバーに登録する。

公開鍵をサーバーに登録(ssh-copy-idコマンドを使う)

ssh-copy-idコマンドを使って公開鍵をリモートサーバーに登録する。

$ ssh-copy-id -i ~/.ssh/id_rsa.pub サーバーのユーザー名@サーバーのホスト名

このコマンドを使うと、サーバ側へのauthrorized_keysの作成やパーミッションの設定などを自動で行ってくれ、非常に便利。

sshを使ってログインをする

設定が終了したら、実際にログインできるか確認する。

$ ssh -p 50010 サーバーのユーザー名@サーバーのホスト名

-pオプションには先程設定したPort番号を指定する。

パスワードログインを禁止する

ログインできたら、今後はSSH接続のみを許可するために、パスワードログインを禁止する設定をする。

sshd_configのPasswordAuthenticationをnoに変更して、SSH接続している端末でのパスワードログインを禁止する。

PasswordAuthentication no

$ sudo /etc/init.d/ssh restartSSHを再起動。

これで、SSH接続ができるようになる。

Homebrewのインストールと使い方

FJORD BOOT CAMPのプラクティスの一つである黒い画面入門の中で、Homebrewに関する解説があります。HomebrewはMac用のパッケージマネージャーです。Homebrewを使うことによって便利なコマンドやソフトウェアをインストールすることができ、さらにインストールされたソフトの依存関係まで管理してくれるようになります。

このHomebrewについてすでに多くの記事が存在するのですが、自分の備忘録も兼ねてまとめていきたいと思います。

【目次】

インストール方法

Homebrewの公式ページを参照しながら進めていきます。

Homebrewをインストールするために必要な要件が以下のように記載されています。(2019年1月11日時点)

  • An 64-bit Intel CPU
  • macOS 10.12 or higher
  • Command Line Tools (CLT) for Xcode: xcode-select --install, developer.apple.com/downloads or Xcode
  • A Bourne-compatible shell for installation (e.g. bash or zsh)

Homebrewの利用にはXcodeが必要になるようです。 App StoreからXcodeをインストールしましょう。 インストールが終了したらTerminalで以下のコードを実行します。

xcode-select --install

これでHomebrewのインストールに必要なソフトがインストールされたので、次はHomebrewをインストールします。 公式サイトに記載されているスクリプトをTerminalにコピペすれば完了です。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

これでHomebrewのインストールが完了しました。 HomebrewをインストールしたことでHomebrewのコマンドが利用できるようになります。

Homebrewのコマンド

ドキュメントに詳細が記載されていますが、使用頻度の高そうなコマンドをまとめておきます。

パッケージの検索

$ brew search <text>

<text>の部分はその文字を含むパッケージを検索します。正規表現による検索も可能。

パッケージのインストール

$ brew install (パッケージ名)

パッケージのアンインストール

$ brew uninstall (パッケージ名)

インストール済みパッケージの表示

$ brew list

インストール済みのパッケージの一斉更新

$ brew update

treeをインストールしてみる

実際にパッケージをインストールしてみます。 treeと呼ばれるパッケージをインストールしてみましょう。 brew searchでtreeを検索します。

treeという文字を含んだパッケージの一覧が表示されました。 この中からtreeをインストールします。

インストールが完了しました。

brew listで確認します。

きちんとインストールされているのが確認できます。

treeはディレクトリ配下のファイル構造をツリー上に表示するパッケージのようですね。

環境変数PATHを確認/追加する方法

現在、FjordBootcampにてプログラミングを学習中のshoynoiです。

今回はFjordBootcampのカリキュラムの中の一つである黒い画面(Terminal)の基本について。 Webデザイナーの為の「本当は怖くない」“黒い画面”入門 - FJORD,LLCを読み進め、その中で学習したPATHという機能についてまとめていきます。

PATHを確認して通してみる

普段ターミナルで使用するコマンドは様々なディレクトリに格納されています。コマンドを打ち込むと、該当するコマンドの実行ファイルがあればそれを読み込み、結果がターミナル上に表示されます。 例えばlsコマンドは/bin/にありますが、このコマンドを実行する場合はTerminalに$ /bin/lsと記述することでプログラムが実行されます。

f:id:shoynoi:20190111124013p:plain

しかし、コマンドを使用するときに毎回$ /bin/lsのように記述するのはとても面倒です。そこで、Shellに予め実行ファイルがある道(PATH)を教えてあげることができます。すると、実行ファイルまでのパスを省略してファイル名(コマンド)のみで実行できるようになります。

PATHを確認する

PATHは環境変数の1つとして定義されています。 環境変数はローカル環境内で設定・参照できるようにした特別な変数のことをいいます。 Terminalにenvと打ち込むと現在設定されている環境変数の一覧が羅列されます。 一部を抜粋します。

$ env
...
USER=akira
...
PATH=/usr/local/opt/mysql@5.7/bin:/Users/akira/.rbenv/shims:/Users/akira/.rbenv/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
...
HOME=/Users/akira
...

環境変数名と値がイコールで結ばれています。 PATHについてみてみましょう。スラッシュやコロンがたくさん並んでいて複雑に見えます。 PATHは、それぞれのPATHを:(コロン)で区切って並べます。 先程の/bin/lsのPATHはすでに:/bin:として設定されていることがわかります。 このPATHの機能のおかげでコマンド(プログラム)の場所を意識することなくPCに直接指示を与えるようにコマンドを使用することができます。

f:id:shoynoi:20190111124010p:plain

ちなみに、各環境変数echo $環境変数名でその中身を表示することができます。

f:id:shoynoi:20190111123931p:plain

PATHを設定する

PATHは予め設定されているものもありますが、独自にPATHを設定することができます。 例えば

export PATH="$PATH:/Users/akira/bin"

環境変数$PATHに対して:(コロン)で区切り、新しくパスを追加しているのがわかると思います。 このようにexportコマンドを使って環境変数PATHに追加したいパスを記述することでそのディレクトリ内のプログラムを直接実行できるようになります。

これを「パスを通す」といいます。