Featured image of post お名前メールとGMOクラウドのVPSの設定の備忘録

お名前メールとGMOクラウドのVPSの設定の備忘録

目次

背景

とある仕事でお名前メールとGMOクラウドのVPSのセットアップが必要だったので、その時のセットアップのメモ

構成

ローカル:

  • 環境: WSL1
  • IDE: VSCode

FW:

  • APサーバー: Django
  • Webサーバー: Nginx
  • RDB: Postgres
  • 証明書: Let’s encrypt

サーバー:

  • ドメイン: お名前.com
  • メールサーバー: お名前メール
  • メールクライアント: ThunderBird
  • サーバー: GMO Cloud VPS

メールの設定

Eメールの仕組み

  • Emailの仕組みは簡単に言うと、郵便の仕組みとおなじ
  • 郵便で送信者を偽装できるようにEmailでも同じことができる
  • 故に、SPFとDKIMとDMARC認証SPFが必要になる

ネームサーバー

レンタルサーバーRS、お名前メールを利用している場合は次のNSになり、MMレコードなどもデフォルトで設定される。

  • プライマリ: ns-rs1.gmoserver.jp
  • セカンダリ: ns-rs2.gmoserver.jp

セキュリティ

SPF(Sender Policy Framework)

SPFの目的は、送信者のドメインがそのメールサーバーからのメール送信を許可しているかを確認する。

  • 仕組み
    • ドメインのDNSにSPFレコードを設定し、そのドメインがどのIPアドレスやメールサーバーから送信を許可しているかをリスト化する
  • 動作
    • 受信サーバーがメールを受け取った際に、送信元のIPアドレスをSPFレコードと照合する
    • 許可されているサーバーからのメールであれば「合格」と判定し、それ以外は「不合格」とする

=> メール送信者の偽装チェック

1
2
3
4
5
6
- type:
  - TXT
- host:
  - dendroid.net
- value:
  - 600v=spf1 include:_spf.onamae.ne.jp ~all

なお、includeは指定されたドメインの SPF レコードを取り込み、その内容を評価に含めることを意味する。

この先は次のようになっている。

1
2
3
$ dig +short TXT _spf.onamae.ne.jp

"v=spf1 include:_netblocks1.onamae.ne.jp include:_netblocks2.onamae.ne.jp include:spf.protection.outlook.com include:_spf.maildeliver.jp +ip4:157.7.183.0/24 +ip4:210.157.19.64/26 +ip4:157.7.151.0/24 +ip4:163.44.89.0/24 +ip4:150.95.48.0/24 ~all"

ここにあるip4で指定されたIPアドレスが許可されたメールサーバーとなる。

DKIM(DomainKeys Identified Mail)

DKIMの目的は、メールが送信されてから内容が改ざんされていないことを確認するためのデジタル署名を提供する事。

  • 仕組み
    • ドメインのDNSに公開鍵を含むDKIMレコードを設定し、メール送信時に署名(電子署名)を付加する
    • この署名は送信ドメインとメールの内容に基づいて生成される
  • 動作
    • 受信サーバーはDKIM署名を検証し、送信元のDNSに公開鍵を問い合わせる
    • 署名と公開鍵が一致する場合、メールが正当なものであり、改ざんされていないと判断される

=> メール内容の改ざん検出

1
2
3
4
5
6
- type:
  - TXT 
- host:
  - default._domainkey.xxx.net
- value:
  - v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2jhFvt8dN5ZKiiZtBqZkp7GXMna+7JXl4Q4dnPAhlEILQrLSrWeJCqtJ42YTSzMO4Z6PygeJfisMJMuEg9aib4kAn3zGbSfK/NAsamgLAMFJgrNK5S18S3mvNWWMBV4YfiMmmJu0kqkGSKELyKHPeTKPdu9j2xGxuku/SsgFQYpejqvrcFDxvd1RdIhK+Yupqx8UBNRiQxRfzjgq+Ceo+X7lqZTH1GcjvI+lFYU0Xau3B2MGP//slIV36bIduYIYV7PSgYVFY6i45WlIsldmkVoDhPCe1yQH7SWta/jUHnmGLMZT7MeD/RSyh6tp23GdiF3RGQM1rzfgEdmiUqglywIDAQAB	

これはDKIMのバージョンDKIM1でRSA暗号されている公開鍵(base64エンコード化)の意味

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ echo "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2jhFvt8dN5ZKiiZtBqZkp7GXMna+7JXl4Q4dnPAhlEILQrLSrWeJCqtJ42YTSzMO4Z6PygeJfisMJMuEg9aib4kAn3zGbSfK/NAsamgLAMFJgrNK5S18S3mvNWWMBV4YfiMmmJu0kqkGSKELyKHPeTKPdu9j2xGxuku/SsgFQYpejqvrcFDxvd1RdIhK+Yupqx8UBNRiQxRfzjgq+Ceo+X7lqZTH1GcjvI+lFYU0Xau3B2MGP//slIV36bIduYIYV7PSgYVFY6i45WlIsldmkVoDhPCe1yQH7SWta/jUHnmGLMZT7MeD/RSyh6tp23GdiF3RGQM1rzfgEdmiUqglywIDAQAB" | base64 -d > dkim_pubkey.der
$ openssl rsa -inform DER -in dkim_pubkey.der -pubin -outform PEM -out dkim_pubkey.pem
$ openssl rsa -in dkim_pubkey.pem -pubin -text -noout

Public-Key: (2048 bit)
Modulus:
    00:da:38:45:be:df:1d:37:96:4a:8a:26:6d:06:a6:
    64:a7:b1:97:32:76:be:ec:95:e5:e1:0e:1d:9c:f0:
    21:94:42:0b:42:b2:d2:ad:67:89:0a:ab:49:e3:66:
    13:4b:33:0e:e1:9e:8f:ca:07:89:7e:2b:0c:24:cb:
    84:83:d6:a2:6f:89:00:9f:7c:c6:6d:27:ca:fc:d0:
    2c:6a:68:0b:00:c1:49:82:b3:4a:e5:2d:7c:4b:79:
    af:35:65:8c:05:5e:18:7e:23:26:98:9b:b4:92:a9:
    06:48:a1:0b:c8:a1:cf:79:32:8f:76:ef:63:db:11:
    b1:ba:4b:bf:4a:c8:05:41:8a:5e:8e:ab:eb:70:50:
    f1:bd:dd:51:74:88:4a:f9:8b:a9:ab:1f:14:04:d4:
    62:43:14:5f:ce:38:2a:f8:27:a8:f9:7e:e5:a9:94:
    c7:d4:67:23:bc:8f:a5:15:85:34:5d:ab:b7:07:63:
    06:3f:ff:ec:94:85:77:e9:b2:1d:b9:82:18:57:b3:
    d2:81:85:45:63:a8:b8:e5:69:48:b2:57:66:91:5a:
    03:84:f0:9e:d7:24:07:ed:25:ad:6b:f8:d4:1e:79:
    86:2c:c6:53:ec:c7:83:fd:14:b2:87:ab:69:db:71:
    9d:88:5d:d1:19:03:35:af:37:e0:11:d9:a2:52:a8:
    25:cb
Exponent: 65537 (0x10001)

この公開鍵は、受信者がメールのデジタル署名を検証するために使用される。

DMARC(Domain-based Message Authentication, Reporting, and Conformance)

DMARCの目的はSPFとDKIMの結果に基づいて、メールを受信する側がどのように扱うかを指示し、レポートを受け取る仕組み。

  • 仕組み
    • ドメインのDNSにDMARCポリシーを設定する
    • DMARCポリシーは、SPFとDKIMの認証結果を基に、メールを受信側が「許可」「隔離」「拒否」するかを指示する
  • 動作
    • 受信サーバーはSPFとDKIMを検証し、DMARCポリシーに従って適切な処理を行う
    • また、DMARCポリシーに基づいて、結果をドメイン所有者にレポートする

=> SPFやDKIMで認証に失敗したメールをどう扱うかの制御が可能で、不正メールの状況が分かる。

1
2
3
4
5
6
- type:
  - TXT
- host:
  - _dmarc.xxx.net
- value:
  - v=DMARC1; p=reject

このp=rejectはpolicy違反のメールはrejectするという意味 お名前.comでGmailだと、なぜか通らなかったので、次の設定にした。

_dmarc.dendroid.net 600 v=DMARC1; p=none

Thunderbirdの設定

Thunderbirdの設定

ローカルの初期セットアップ

WSLを使ってローカルで鍵生成

WSL上でWindows用のファイルを生成する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 任意のキー名を変数として定義
$ KEY_NAME="gmo"
$ SSH_DIR="/mnt/c/Users/xxx/.ssh"

# ディレクトリ作成と移動
$ mkdir -p $SSH_DIR
$ cd $SSH_DIR

# SSH鍵を生成
$ echo "y" | ssh-keygen -q -t rsa -N '' -f ${SSH_DIR}/id_${KEY_NAME}_rsa >/dev/null 2>&1


# 権限設定
$ chmod -R 700 $SSH_DIR
$ chmod 600 $SSH_DIR/id_${KEY_NAME}_rsa

# configファイルに設定を追加
$ cat >> config <<EOF
Host gmo
    User                myuser 
    Port                4649 
    HostName            sub0000551573.hmk-temp.com
    IdentityFile        C:/Users/xxx/.ssh/id_${KEY_NAME}_rsa

EOF

$ cat $SSH_DIR/id_${KEY_NAME}_rsa.pub

なお、userとportの設定は後でVPSの中でするので、最初はコメントアウトでOK。
また、表示された公開鍵は後でVPSで追加する。

Windows側での非公開鍵の権限変更

WSL側でマウントしているWindowsのファイルのパーミッションの変更は厳しいので、PowerShellを利用する。

まずは現在の権限の確認。

1
2
3
4
5
6
PS C:\Users\xxx> icacls "C:\Users\xxx\.ssh\id_gmo_rsa"
C:\Users\xxx\.ssh\id_gmo_rsa NT AUTHORITY\SYSTEM:(F)
                               BUILTIN\Administrators:(F)
                               DESKTOP-017FR51\xxx:(F)

Successfully processed 1 files; Failed processing 0 files

つまり、次となっている。

  • NT AUTHORITY\SYSTEM: フルコントロール ((F))
  • BUILTIN\Administrators: フルコントロール ((F))
  • DESKTOP-017FR51\xxx: フルコントロール ((F))

(念のため、id_gmo_rsaのバックアップをとって) SYSTEMとAdminの権限を抜く。

1
2
3
PS C:\Users\xxx> icacls "C:\Users\xxx\.ssh\id_gmo_rsa" /remove "NT AUTHORITY\SYSTEM" "BUILTIN\Administrators"
processed file: C:\Users\xxx\.ssh\id_gmo_rsa
Successfully processed 1 files; Failed processing 0 files

継承されたアクセスを無効化する。

1
2
3
4
PS C:\Users\xxx> icacls "C:\Users\xxx\.ssh\id_gmo_rsa" /inheritance:r

processed file: C:\Users\xxx\.ssh\id_gmo_rsa
Successfully processed 1 files; Failed processing 0 files

再度、権限の確認。

1
2
3
4
PS C:\Users\xxx> icacls "C:\Users\xxx\.ssh\id_gmo_rsa"
C:\Users\xxx\.ssh\id_gmo_rsa DESKTOP-017FR51\xxx:(F)

Successfully processed 1 files; Failed processing 0 files

接続テスト。

1
PS C:\Users\xxx\.ssh> ssh gmo

WindowsからのSSHの接続テスト

/mnt/c/Users/xxx/.ssh/configの設定を使ったVSCocdeのリモートエクスプロラーのSSHで接続する。

VPSの初期セットアップ

最初の接続

GMOから来たID、PWで接続する。

1
$ ssh root@subXXXXXX.hmk-temp.com

user追加

作業用ユーザーの追加。

1
2
# adduser myuser
# usermod -aG sudo myuser

userのswitch

今後はmyuserで操作する。

1
# su myuser

以後rootは使わない。

myuserの初期設定

editorの設定

.bashrcに次を追加。

1
EDITOR=vim

もしくは、vim.basic(basicの方が軽い)。

1
$ sudo update-alternatives --set editor /usr/bin/vim.basic

公開鍵の追加

次の手順でインスタンスに公開鍵を追加する。

1
2
3
4
$ mkdir -p ~/.ssh
$ chmod 700 ~/.ssh
$ echo "ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" >> ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

これ以降は非公開鍵で認証してSSHをする。

定番

パッケージの更新

システムの全更新。

1
$ apt update && sudo apt upgrade -y

タイムゾーン

タイムゾーンの設定。

1
2
3
$ sudo dpkg-reconfigure tzdata
$ cat /etc/timezone
Asia/Tokyo

システム情報確認

ディスク

/dev/vda1がディスクパーテーションなので、それを確認すればOK。

1
2
3
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        50G  6.0G   41G  13% /

メモリ

1
2
3
4
$ free -h
              total        used        free      shared  buff/cache   available
Mem:          961Mi       459Mi        72Mi       2.0Mi       429Mi       345Mi
Swap:         1.0Gi       7.0Mi       1.0Gi

CPU

CPUの構成(2コア、2.1GHz)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ lscpu | head -n 10
Architecture:                       x86_64
CPU op-mode(s):                     32-bit, 64-bit
Byte Order:                         Little Endian
Address sizes:                      40 bits physical, 48 bits virtual
CPU(s):                             2
On-line CPU(s) list:                0,1
Thread(s) per core:                 1
Core(s) per socket:                 1
Socket(s):                          2
NUMA node(s):                       1

使用率

1
2
$ top -bn1 | grep 'Cpu(s)' 
%Cpu(s):  2.9 us,  5.9 sy,  0.0 ni, 91.2 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

それぞれのCPU時間の意味:

  • 高いとCPU使用率が高い
    • us: ユーザー
    • sy: システム
  • 高いとCPU使用率が低い
    • ni: ナイス値が変更されたユーザー
    • id: アイドル
    • wa: I/O 待ち時間
    • hi: ハードウェア割り込み
    • si: ソフトウェア割り込み
    • st: ステール時間

NOTE: ナイス値(Nice Value)は、プロセスの優先度を調整するためのパラメータ

セキュリティ対策

ポートの確認

空いているポートの確認。

53(DNSリゾルバ)、22(SSH)と、40983のエフェメラルポートが空いている。

1
2
3
4
5
6
7
$ sudo ss -tuln
Netid    State      Recv-Q     Send-Q         Local Address:Port          Peer Address:Port    Process
udp      UNCONN     0          0              127.0.0.53%lo:53                 0.0.0.0:*
tcp      LISTEN     0          4096           127.0.0.53%lo:53                 0.0.0.0:*
tcp      LISTEN     0          128                  0.0.0.0:22                 0.0.0.0:*
tcp      LISTEN     0          1024               127.0.0.1:40983              0.0.0.0:*
tcp      LISTEN     0          128                     [::]:22                    [::]:*

ちなみに、40983はcode-384fというCOMMANDだった。

1
2
3
4
5
6
7
$ sudo lsof -i :40983

COMMAND    PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd      8838 myuser   10u  IPv4 161552      0t0  TCP localhost:57754->localhost:40983 (ESTABLISHED)
code-384f 8857 myuser   10u  IPv4 161546      0t0  TCP localhost:40983 (LISTEN)
code-384f 8857 myuser   11u  IPv4 162577      0t0  TCP localhost:40983->localhost:57754 (ESTABLISHED)

その詳細は、インスタンス内のvscodeのプロセスだった。
(SSHをVSCode経由でつないでいる)

1
2
3
$ ps -p 8857 -o comm,cmd
COMMAND         CMD
code-384ff7382d /home/myuser/.vscode-server/code-384ff7382de624fb94dbaf6da11977bba1ecd427 command-shell --

ファイアウォールの設定

ファイアウォールの設定。

1
2
3
$ sudo ufw allow OpenSSH
$ sudo ufw allow 80/tcp  # HTTP
$ sudo ufw allow 443/tcp  # HTTPS

有効化

1
$ sudo ufw enable

状態確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

SSHの認証を強化

1
$ sudoedit /etc/ssh/sshd_config

次の変更を行う。

  • SSHポートの変更: デフォルトの22から他のポートに変更する
  • rootの直接ログインを禁止
  • パスワード認証を無効にし、公開鍵認証に切り替える
1
2
3
4
5
Port 4649
PermitRootLogin no

# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no

その後4649を公開。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$ sudo ufw allow 4649
$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere                  
80/tcp                     ALLOW       Anywhere                  
443/tcp                    ALLOW       Anywhere                  
4649                       ALLOW       Anywhere                  
OpenSSH (v6)               ALLOW       Anywhere (v6)             
80/tcp (v6)                ALLOW       Anywhere (v6)             
443/tcp (v6)               ALLOW       Anywhere (v6)             
4649 (v6)                  ALLOW       Anywhere (v6)             

再起動して4649から接続テスト。

1
$ systemctl restart sshd

22を無効化してリロード。

1
2
$ sudo ufw deny 22
$ sudo ufw reload

今後は4649から接続する。

また、jail.localを更新する。

1
2
$ sudo systemctl restart fail2ban
$ sudo ufw reload

fail2ban

不正アクセス対策にfail2banでインストールする。

1
2
$ sudo apt install fail2ban
$ sudo systemctl enable fail2ban

jail.localにUFW用の設定を追加する。

1
$ sudoedit /etc/fail2ban/jail.local

設定の中味。

1
2
3
4
5
6
[DEFAULT]
banaction = ufw

[sshd]
enabled = true
port = 4649

再起動。

1
$ sudo systemctl restart fail2ban

チェック

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ sudo systemctl status fail2ban
● fail2ban.service - Fail2Ban Service
     Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2024-10-28 20:51:40 JST; 11min ago
       Docs: man:fail2ban(1)
    Process: 51516 ExecStartPre=/bin/mkdir -p /run/fail2ban (code=exited, status=0/SUCCESS)
   Main PID: 51517 (f2b/server)
      Tasks: 5 (limit: 1044)
     Memory: 12.0M
     CGroup: /system.slice/fail2ban.service
             └─51517 /usr/bin/python3 /usr/bin/fail2ban-server -xf start

Oct 28 20:51:40 sub0000551573.hmk-temp.com systemd[1]: Starting Fail2Ban Service...
Oct 28 20:51:40 sub0000551573.hmk-temp.com systemd[1]: Started Fail2Ban Service.
Oct 28 20:51:40 sub0000551573.hmk-temp.com fail2ban-server[51517]: Server ready
1
2
3
4
$ sudo fail2ban-client status
Status
|- Number of jail:      1
`- Jail list:   sshd

Docker設定

Dockerのセットアップ

念のため、古いDockerの削除。

1
$ sudo apt-get remove docker docker-engine docker.io containerd runc

Dockerのインスコ。

1
$ sudo apt-get install apt-transport-https ca-certificates curl software-properties-common

Dockerの公式GPGキーを追加

1
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Dockerのリポジトリを設定

1
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker Engineをインストール

1
2
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io

正常にDockerがインスコされた事を確認。

1
2
$ sudo docker --version
Docker version 27.3.1, build ce12230

Docker Composeのインスコ

最新バージョンのDocker Composeをダウンロードしてインストール

1
$ sudo curl -SL https://github.com/docker/compose/releases/download/v2.30.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose

実行権限の追加

1
$ sudo chmod +x /usr/local/bin/docker-compose

インスコの確認

1
2
$ docker-compose --version
Docker Compose version v2.30.1

非rootユーザーでの実行設定

1
$ sudo usermod -aG docker ${USER}

一旦グループを変更(もしくは再起動)

1
$ newgrp docker

チェック

1
2
$ docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE

Githubの設定

前提

VPSからコードをDlするにはいくつかの方法がある。

  • UserのSSH Keyの設定
  • RepositoryのDeploy keyの設定
  • Github Appsの設定

今回はDeploy Keyを使用する。

VPS内でSSHの設定

1
2
3
$ wget https://gist.githubusercontent.com/3265/54d0339408e8cd1898af6694b983736f/raw/1338df8b11fb851e429c65bf8e721451ed795e40/github.sh
$ sudo chmod +x github.sh
$ ./github.sh myrepo

Repository > Deploy keysから公開鍵を追加する。

1
2
$ ssh -T git@myrepo
Hi xxx/xxx! You've successfully authenticated, but GitHub does not provide shell access.

これで接続ができたので、クローンする。

1
$ git clone git@dendroid:xxx/xxx.git

Pythonの環境

依存パッケージをインストール

1
2
3
$ sudo apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev libffi-dev liblzma-dev python-openssl git

Pyenvのインストール

1
$ curl https://pyenv.run | bash

bashrcの更新

1
2
3
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

再度読み込み

1
$ source ~/.bashrc

チェック

1
2
$ pyenv --version
pyenv 2.4.17

Poetryのインストール

1
$ curl -sSL https://install.python-poetry.org | python3 -

.bashrcでパスを通す。

1
export PATH="$HOME/.local/bin:$PATH"

有効化

1
$ source ~/.bashrc

チェック

1
2
$ poetry --version
Poetry (version 1.8.4)

Pythonのインストール

使うPythonのインストール。

1
2
$ pyenv install 3.6.0
$ pyenv install 3.11.0

確認

1
2
3
4
$ pyenv versions
* system (set by /home/myuser/.pyenv/version)
  3.6.0
  3.11.0

globalを変更(開発時はローカルを変更する)

1
2
3
4
5
6
7
$ pyenv global 3.11.0

$ which python
/home/myuser/.pyenv/shims/python

$ python --version
Python 3.11.0

pip-toolsのインストール

globalのpythonを3.11.0に変更したので、それでインストールする。

1
2
3
4
$ pip install pip-tools

$ which pip-compile 
/home/myuser/.pyenv/shims/pip-compile

Postgresの設定

psqlのインストール

1
$ sudo apt-get install postgresql-client

cliのインストール

1
$ pip install pgcli

参考文献

Built with Hugo
テーマ StackJimmy によって設計されています。