Gateway NE132-F14PにUbuntu 22.0.4.5 LTSを導入し、Webサーバを構築する

# Gateway NE132-F14PにUbuntu 22.0.4.5 LTSを導入し、Webサーバを構築する

作成期間: 2024/11/25 - 2024/12/01

これからサーバーを構築しようとする、ある程度興味はある人向けの内容です。最終的にDocker container上でapache2によるサーバーを動かし、そこで自身が作成したウェブサイトを表示させるところまで行います。その途中で、公開鍵暗号とパスワードを利用した2段階認証を使うSSH接続、Linuxの基礎知識やコマンド、vi(vim)の使い方などを学習します。

## 0. 準備物

- [Gateway NE132-F14P](https://acerjapan.com/gateway/notebook/mobile/ne/NE132-F14P)（以下、「ノートパソコン」、「パソコン」などと呼称します）
- 4GBほど空き容量がある中身が削除されてもいいUSBメモリ（以下、「USBメモリ」と呼称します）
- SSH接続するためのパソコン

## 1. インストールするためのISOファイルの作成

1. 初期化されたGateway NE132-F14PはWindows 10 Homeが入っています。そこでローカルアカウントを作成してください[^1]。

2. [Rufus](https://rufus.ie/ja/)をダウンロードしてください。タイプは標準、プラットフォームはWindows x64のものを選んでください。

3. [Ubuntu Desktop 日本語 Remix](https://www.ubuntulinux.jp/download/ja-remix)をダウンロードしてください。ミラーサイトは好きなもので構いません。

4. Gateway NE132-F14PにUSBメモリをさしてRufusを起動してください。

5. デバイスをさしたUSBメモリに指定してください。

6. 選択でダウンロードしたISOファイルを選択してください。

7. パーティション構成をMBRからGPTに変更してください。

8. ターゲットシステムをUEFU(CSM無効)にしてください。

9. スタートを押してください。

10. ISOイメージ（ファイル コピー）モードで書き込む（推奨）を選択してください。

11. USBメモリの中身がすべて削除されることを了承してください。

12. 完了したら、Rufusを閉じるで終了して、USBメモリを抜いてください。

13. パソコンをシャットダウンしてください。

## 2. Ubuntuのインストール[^2]

4-6は使用するパソコンがeMMCだと特に必要です。

1. パソコンを起動してください。このとき、F2を連打してUEFI BIOSに入ってください。

2. set supervisor passwordで簡単なsupervisor passwordを一時的に設定してください。

3. Boot欄からboot priority orderのUSB HDDを1にしてください。F6で設定できます。

4. Security欄のSelect an UEFI files as trusted for executingを選択してください。

5. HDD0 -> EFI -> ubuntu -> shimx64.efiを順番に選択してください。

6. set supervisor passwordで2で決めたsupervisor passwordを入力し、空入力(Enter)、空入力(Enter)でsupervisor passwordを空白にしてください。

7. F10で設定を保存し、パソコンをシャットダウンしてください。

8. パソコンにUSBメモリをさしてください。

9. パソコンを起動してください。

10. ブートデバイス選択画面で、try or install ubuntuを選択してください。

11. Ubuntuをインストールを選択してください。

12. キーボードはJapaneseのJapanese(OADG109A)を選択してください。

13. とりあえず無線ネットワークには接続しない(I don't want to connect to a Wi-Fi network right now)を選択してください。

14. アップデートと他のソフトウェアの、「あらかじめどのアプリケーションをインストールしますか？」に対しては、通常のインストールを選択してください。

15. 今回は「ディスクを削除してUbuntuをインストール」を選択してください。

16. 「ディスクに変更を書き込みますか？」というタイトルのダイアログボックスは続けるをクリックしてください。

17. 「どこに住んでいますか？」はTokyoを選択してください。

18. 名前を入力してください。***短いほうがいいです***[^3]。

19. コンピューターの名前も入力してください。

20. パスワードも入力してください。忘れないでください。

21. インストールが終わったらUSBメモリを抜いてください。

22. パソコンをシャットダウンしてください。

## 3. Linuxについて

1. パソコンを起動してください。

2. ユーザーを選択して、パスワードを入力してください。

3. Wi-Fiに接続します。右上のボタンから設定画面に遷移して、CA証明書は必要ありませんにチェックを入れ、ユーザー名とパスワードを入力してください。

4. Windowsキーを押して、`terminal`と検索して端末を起動してください。ubuntu bashが起動します。

    もし日本語入力が出来なくて、したいのであれば、[このページなどを見て、mozcとfcitx5を入れてください。](https://ryonakagami.github.io/2023/08/12/ubuntu-japanese-input-mozc/)

5. ここからしばらくLinuxについて学びます。知っている人は飛ばしてください。

6. LinuxとはOSです。Linus Torvaldsを中心としてカーネルというシステムの中核部分(プロセス管理、メモリ管理、ファイルシステムなど)が開発されています。カーネルはGPLでソースが公開されています。このカーネルに、シェル（カーネルとユーザーを仲介するソフトウェア）やUI、インストーラーなどを一緒にして、簡単に使えるようにしたのがLinuxディストリビューションです。[大きくDebian系とRed Hat系があり、UbuntuはDebian系です。](https://www.mtioutput.com/entry/differ-redhat-debian)

7. Linuxでは、拡張子は単にファイル名の一部として認識されます。種類として、

    - 通常ファイル（テキストファイルとバイナリファイル）、
    - リンクファイル（Windowsでいうショートカット）、
    - 特殊ファイル（デバイスファイル[^4]やWindowsでいう隠しファイル）、
    - ディレクトリ（Windowsでいうフォルダ）

    の4つがあります。

8. Linuxのファイルシステムはディレクトリの中にディレクトリがあって(ファイルもあって)、更にその中にディレクトリがあって(ファイルもあって)...というような木構造をしています。この一番上のファイルをルート(`root`)ディレクトリと言って、`/`で表します。また、現在のユーザーのファイル(`/home/`のどのディレクトリかということ)を`~`で表します。

9. ディレクトリやフォルダを一意に指定するのにパスというのを使います。例えば

    ```bash
    /home/user/desktop/hello
    ```

    というのはルートディレクトリの`home`ディレクトリの`user`ディレクトリの`desktop`ディレクトリの`hello`というファイルを指すということです。このように`/`から始めるパスのことを絶対パスといいます。

    そうではなくて今いるディレクトリ（カレントディレクトリ）からのパスを相対パスといいます。

    例えば今`user`ディレクトリにいるとして、

    ```bash
    ./../user2/picture/apple.jpg
    ```

    というのは`user`ディレクトリの親ディレクトリにある`user2`ディレクトリの`picture`ディレクトリの`apple.jpg`というファイルを指すということです。カレントディレクトリは`./`で、親ディレクトリは`../`で表します。通常`./`は省いても構いません。

## 4. シェルについて

1.  ~~シェルとはカーネルとユーザーを仲介するソフトウェアです。~~(2024/12/03追記: 違うらしいです https://qiita.com/ko1nksm/items/935be63e940f00e4c228) Ubuntuでは標準でbashというシェルが入っています。シェルのコマンドについてとりあえず最低限必要なものを紹介します。オプションはコマンドの後に空白を入れてつけてください。また、一番初めに`sudo`をつけると管理者権限で実行できます。強制終了は`Ctrl`+`C`です。他にもあるので都度インターネットなどで調べるなどしてください[^8]。

    ```bash
    ls 
    ```

    ディレクトリにあるファイルを表示します。`-a`オプションで隠しファイルなどもすべて表示します。

    ```bash
    cd (ディレクトリ名) 
    ```

    カレントディレクトリにあるディレクトリに移動します。`foo/bar/baz`のようにして深い位置に一度でに移動できます。

    ```bash
    mkdir (ディレクトリ名) 
    ```

    カレントディレクトリに新しいディレクトリを生成します。`foo/bar/baz`のように深い位置に移動せずに生成できます。

    ```bash
    rm (ファイル名) 
    ```

    カレントディレクトリにあるファイルを削除します。`foo/bar/baz`のようにして深い位置に移動せずに削除できます。

    ```bash
    rmdir (ディレクトリ名) 
    ```

    カレントディレクトリにあるディレクトリを削除します。削除するディレクトリは空でないといけません。`foo/bar/baz`のようにして深い位置に移動せずに削除できます。

    ```bash
    cp (ファイルもしくはディレクトリ名) (新しいファイルもしくはディレクトリ名)
    ```

    カレントディレクトリにあるファイルもしくはディレクトリをコピーして新しいファイルもしくはディレクトリを生成します。ただしディレクトリに中身がある場合は`-r`オプションを付けて中身もコピーする必要があります。

    ```bash
    touch (新しいファイル名) 
    ```

    カレントディレクトリに新しいファイルを生成します。

    ```bash
    vi (ファイル名) 
    ```

    カレントディレクトリのファイルをテキストエディタvimで開きます。ファイルがない場合は勝手に作成して開きます。

    （Vimはviの派生ソフトウェアです。）

    >VimはGUIを必要とせずCUIでも動くため、Unix系OSに標準のエディタとして搭載されていることが多い。コンピュータの大容量化と高速化にともない、2000年以降のOSでは viに代わってより高機能な Vim、あるいはその機能劣化版が標準装備されるようになってきている。このため、コマンドライン上でviを実行すると代わりにVimが起動するディストリビューションが一般的となった。
    >[Vim - Wikipedia](https://ja.wikipedia.org/wiki/Vim)

    ```bash
    cat (ファイル名) 
    ```

    ファイルの中身を表示します。

    また、シェルにはパイプというものがあります。パイプを使用すると、あるコマンドの出力を別のコマンドの入力として渡すことができます。パイプは `|` という記号で表されます。

    例えば、`ls` コマンドでディレクトリの内容を表示し、その結果を `grep` コマンドでフィルタリングする場合、以下のようにパイプを使用します：

    ```bash
    ls | grep "pattern"
    ```

    この例では、`ls` コマンドの出力が `grep` コマンドの入力として渡され、指定したパターンに一致する行だけが表示されます。

## 5. vimについて

1. vimについて最低限必要な知識を紹介します。vimにはモードがあります。通常`vi`コマンドで起動したときはノーマルモードで、ファイルの保存やvimの終了、カーソル移動などができます。ノーマルモードで`i`を押すと挿入モードに移行し、文字の入力ができます。挿入モードで`ESC`を押すとノーマルモードに移行します。

    ノーマルモードでよく使う動作を以下に示します。他にもあるので都度インターネットなどで調べるなどしてください。[^9]

    ```vi
    :wq 
    ```

    保存して終了します

    ```vi
    h 
    j 
    k 
    l 
    ```

    上から順に、左、下、上、右に移動します

    ```vi
    dd 
    ```

    行を削除します

    ```vi
    x 
    ```

    ハイライトのかかった文字を削除します

    ```vi
    i 
    ```

    挿入モードに移行します

## 6. シェルとvimの演習

1. 以下の演習を通して体験してみてください。後で使います。4-1や5-1を見てもわからない場合は生成AIなどに聞いてもいいでしょう。

- `/home/sandbox/test/hello`というファイルを作成し、vimで起動して挿入モードに移行し`Hello, World!`と書いて保存して閉じてください。
- `/home/(ユーザー名)`に移動して管理者権限で`.vimrc`というファイルを作成してください(すでにある場合は一旦それを別名にして、新しく作ってください)。
- `.vimrc`を開いて入力モードに移行し、

    ```.vimrc
    set showmode
    set number
    set expandtab
    set shiftwidth=4
    set smartindent
    ```

    と入力し[^10]、保存して閉じてください。
- `/home/sandbox/test/hello2`というファイルを作成し、中身に「Hello, World!?」と書いて保存して閉じてください（初めから.`.vimrc`がなかった場合、見た目が変わって現在のモードや行番号が表示されているに気が付きましたか？これは`.vimrc`によるものです[^5]。初めからあった場合は名前を変えたのを戻してそれを使ってください）。
- 1回のコマンドで`test`をコピーして`test2`を作成してください。
- `/home/sandbox/test2/`の中身を確認してください。そこにあったファイルの中身も確認してください。
- `test2`を1回のコマンドで削除してください。

## 7. 権限について

1. [^11]ファイルやディレクトリの権限について、`ls -l`で確認できます。作った人が所有者になります。権限には、r: 読み取り、w: 書き込み、x:実行の3種類があリます。ls -lの1文字目はファイルの種類(ファイル:-、ディレクトリ:d)で、2-4文字目は所有者の権限、5-7文字目は所有グループの権限、8-10文字目はどちらでもないユーザーの権限です。これを変更するのに`chmod`コマンド(`chmod` (アクセス権) (ファイルもしくはディレクトリ名))を利用できます。記号を用いた方法では、以下のような方法を使います。

    |対象|操作|権限|
    |-|-|-|
    |u: 所有者|+: 権限の追加|r: 読み取り|
    |g: 所有グループ|-: 権限の削除|w: 書き込み|
    |o: その他ユーザー|=: 権限の指定|x: 実行|
    |a: 全ユーザー|||

    例えば`hello`を全ユーザーが読めるようにしたいときには

    ```bash
    chmod a+r sandbox
    ```

    とすれば良いです。実行して`ls -l`で確認してみてください。

    数字を用いた方法では、以下のような方法を使います。

    r, w, xをそれぞれニ進数の桁に見立て、r=4, w=2, x=1として権限がある場合にその桁を1、ない場合は0とします。それを10進数として見たしたものを使います。例えば読み書きが出来て実行できないならrは1、wも1、xは0ですからこれは10進数で6です。読みだけ出来てそれ以外が出来ないならrだけが1なので4です。仮に`hello2`を所有者が読み書きできて所有グループは読みのみ、どちらでもないユーザーは何も出来ないという権限にしたい場合は

    ```bash
    chmod 640 hello2
    ```

    とすればいいわけです。これも実行して`ls -l`で確認してみてください。

2. [^12]権限をより管理者レベルの高いユーザーに移譲したいときは`chown`コマンドを使います。なお`sudo`（管理者権限）が必要です。

    ```bash
    sudo chown (ユーザー名) (ファイルもしくはディレクトリ名)
    ```

    所有グループの変更は`chgrp`コマンドで行います。

    ```bash
    sudo chgrp (グループ名) (ファイルもしくはディレクトリ名)
    ```

## 8. 環境変数について

1. ここで環境変数というのはシェルの状態や設定値のことです。例えばあるプログラムをあるファイルに適用するときに毎回そのプログラムまでのパスを指定するのが面倒くさいのでそのパスを省略したりするのに使います(これまで使ってきたコマンドがまさにそうです)。

    環境変数は`echo`コマンドで確認できます[^13]。***環境変数名の先頭には$を付けてください。***

    ```bash
    echo $(環境変数名)
    ```

    なお、`echo`コマンドは本来指定した文字列をそのまま表示するだけのコマンドです。

    環境変数名には以下のようなものがあります:
    - PATH : コマンドが実行される際に検索されるディレクトリのリスト
    - USER : 現在のユーザー名
    - LANG : 使用する言語とロケール（場所）の設定
    - HOME : 現在のユーザーのホームディレクトリ
    - HISTSIZE : 保存されるコマンド履歴の最大数
    - HISTFILE : コマンド履歴が保存されるファイルのパス
    - EDITOR : デフォルトのテキストエディタ
    - SHELL : 現在使用しているシェルのパス

    環境変数の値を一時的に変更するには`export`コマンドを使います[^14]。***この場合は環境変数名の先頭に$をつけません。***

    ```bash
    export (環境変数名)=(設定値)
    ```

    例えばコマンド履歴を保存する場所を`sandbox/.bash_history`にしたい場合は

    ```bash
    export HISTFILE=/home/(ユーザー名)/sandbox/.bash_history
    ```

    を実行すると良いです。これでこのターミナルが終了するまでは`sandbox/.bash_history/`にコマンド履歴が保存されます。

    ターミナルが一度終了して次に起動しても、永続的に設定を保持していたい場合は`~/.bashrc`もしくは`.bash_profile`を編集してください。

## 9. ネットワークについて

1. インターネットやLANではTCP/IPというネットワークプロトコルを利用してIPアドレスというものでネットワーク上の機器を管理識別しています[^15]。IPv4アドレスは8ビット×4の形式で構成され、各ブロックは10進数表記で0から255までを割り当てる事ができます。

    ```IP Address
    11000000.10101000.00000001.00000010
         192.     168.       1.       2
    ```

    IPアドレスはネットワーク部とホスト部が合体したもので、その境界をサブネットマスクというもので管理します[^16]。サブネットマスクはIPアドレスと同じく8ビット×4の形式ですが、特定の場所まではすべて1で特定の場所からはすべて0という形式になっています。この1と0の境界が対応するIPアドレスのネットワーク部とホスト部の境界です。

    ```Subnet Mask
    11111111.11111111.11111111.00000000
         255.     255.     255.       0
    ```

    例えばこの場合上24桁目までがネットワーク部です。

    このIPアドレスとサブネットマスクの表記法としてCIDR（サイダー: Classless Inter-Domain Routing[^6]）表記というのがあります。これはサブネットマスクのネットワーク部の長さをそのまま10進数にしたもので、上2つの例では

    ```CIDR
    192.168.1.2/24
    ```

    というふうになります。

2. IPアドレスはA, B, Cという3つのクラスがあります。CIDR表記で示すとクラスAは.../8, Bは.../16, Cは.../24となるもののことです。

3. ネットワークアドレスとはホスト部がすべて0に置き換えられたIPアドレスのことで、ネットワークそのものを指します。

    ブロードキャストアドレスとはホスト部がすべて1に置き換えられたIPアドレスのことで、ネットワーク全体に通信を行うときに使います。

    ネットワークアドレスとブロードキャストアドレスは機器に割り当てることができません。

    プライベートIPアドレスとはLANで特定の範囲内で自由に割当できるIPアドレスです。

    グローバルIPアドレスとは世界中で一意に指定できるIPアドレスのことです。

4. 複数のアプリケーションが一つのコンピューターで動作している場合に、それぞれに対する別の通信が来ると、IPアドレス1つで指定するとかぶるので、ポートという概念を利用します[^17]。よく使われるサービスにはあらかじめポートが割り当てられており、これはwell-knownポートと呼ばれ、

    ```bash
    cat /etc/services
    ```

    で見ることが出来ます。

5. IPアドレスは数字です。これはコンピューターにとっては理解しやすいですが人間にとっては理解しにくいので、数字以外のアルファベットなどを使って管理します[^7]。IPアドレスに対応する名前をホスト名として、DNS（Domain Name System）で管理します[^18] [^19]。ホスト名とドメイン名を組み合わせてFQDN（Fully Qualified Domain Name: 完全修飾ドメイン名）といいます。例えば

    ```URL
    www.ct.omu.ac.jp
    ```

    はjp（日本）ネットワークのac（高等教育機関）ネットワークのomu（大阪公立大学）ネットワークの（高専）ctネットワークのwwwサーバーを指すということです。

6. ネットワークとの接点をネットワークインターフェースと呼び、Linuxでは「eth0(Ethernetの0番[^21])」などの名前で表されます。これは

    ```bash
    ip addr show
    ```

    で確認できます。

7. 普通コンピューターをネットワークに接続するとDHCP（Dynamic Host Configuration Protocol）で自動的にIPアドレスが割り当てられます[^20]。これは時間経過で勝手にIPアドレスが変わります。しかし、外部にサーバーを公開する場合などは時間経過でIPアドレスが変化されると困ります。なのでサーバーを運用する場合などはIPアドレスを固定する必要があります。Ubuntuではnetplanを利用してIPアドレスを固定します。これは設定ファイルを`/etc/netplan/(ファイル名).yaml`を作って、

    ```bash
    sudo netplan apply
    ```

    というコマンドを実行することで可能です。[設定ファイルの作り方はこのページを参考にしてください。](https://ja.linux-console.net/?p=29495)

## 10. ユーザー管理について

1. ターミナルで`$`が出た場合は一般ユーザー、`#`が出た場合はrootユーザーです[^22]。rootユーザーは管理者権限が必要なときのみ使いますが、一般ユーザーが`sudo`を使うことでもそのコマンドのみで管理者権限を与えられます。Ubuntuインストール直後はrootユーザーのパスワードがないので、

    ```bash
    sudo passwd root
    ```

    で設定する必要があります。実際のところセキュリティ上rootユーザーを使うことはほとんどなく、`sudo`で済ましてしまいます。

2. ユーザーを追加するときは

    ```bash
    sudo adduser (ユーザー名)
    ```

    を実行します[^23]。途中で

    ```bash
    New password: 
    ```

    という状態になるので入力して、もう一度確認のために同じパスワードを入力します。

    追加されたのを確認するには

    ```bash
    tail /etc/passwd
    ```

    を実行します。

3. ユーザーをグループへ追加するときは

    ```bash
    sudo usermod -aG (グループ名) (ユーザー名)
    ```

    を実行します。あるユーザーが`sudo`を使いたいときは、そのユーザーが`sudo`グループに追加されている必要があります[^23]。

4. ユーザーをグループから削除するときは

    ```bash
    sudo gpasswd -d (ユーザー名) (グループ名)
    ```

    を実行します。

5. ユーザーを削除するときは

    ```bash
    sudo userdel (ユーザー名)
    ```

    を実行します。

6. ユーザーを切り替えるときは

    ```bash
    su (切り替え先のユーザー名)
    ```

    を実行します。-オプションをつけると切り替え後そのユーザーのディレクトリに移動します。なお、rootユーザーは

    ```bash
    su 
    ```

    を実行します[^23]。-オプションを付けると切り替え後ルートディレクトリに移動します。

## 11. サーバー管理

1. サーバーの稼働時間と負荷を確認するには、

    ```bash
    uptime
    ```

    を実行します[^24]。このコマンドで末尾に表示される`load average`で、左から順に1分間での負荷、5分間での負荷、15分間での負荷が表示されます。これらの負荷がサーバーのCPUコア数を下回っていれば、サーバーのスペックが十分であると判断できます。逆に、上回っていれば、スペック増強を考えないといけません。

2. ディスクの使用状況を確認するには

    ```bash
    df
    ```

    を実行します[^25]。-hオプションで単位をつけてくれるのでわかりやすいです。`Size`はそのファイルシステムの最大容量、`Use`は現在使用している容量、`Avail`は空き容量、`Use%`は最大容量に対する現在使用している割合、`Mounted on`はどこに接続されているかを表します。

3. メモリやスワップ領域（メモリに載せきることができず、仮想メモリとしてSSDやHDDなどが利用されている領域）の利用状況を確認するには、

    ```bash
    free
    ```

    を実行します[^26]。`-h`オプションで単位を付けてくれるのでわかりやすいです。`total`は使用可能な最大メモリ領域、`used`は現在利用されているメモリ領域、`free`は現在利用されていないメモリ領域（からキャッシュやバッファに使用されているメモリを除いたもの）、`shared`は複数プロセス間で共有されているメモリの領域、`buff/cache`はバッファとキャッシュに使用されているメモリの領域、`avialble`は現在利用されていないメモリ領域です。

4. プロセスという実行中のプログラムを確認するには、

    ```bash
    ps
    ```

    を実行します[^27]。`aux`オプションですべてのプロセスを確認できます。`USER`はプロセスを所有しているユーザー名、`PID`は各プロセスに割り当てられた一意の識別子、`%CPU`はプロセスが使用しているCPU時間の割合、`VSZ`はプロセスが利用している仮想メモリの総量、`RSS`はプロセスが利用している実際の物理メモリの量、`TTY`はプロセスが関連付けられている端末、`STAT`はプロセスの状態、`START`はプロセスが開始された時刻または日付、`TIME`はプロセスが使用したCPU時間の累計、`COMMAND`は実行されたコマンド名とその引数です。

5. `uptime`や`free`、`ps`コマンドを定期的に行ってリアルタイムに確認する場合は

    ```bash
    top
    ```

    を実行します[^28]。3秒ごとに更新されます。

6. サービスとは特定の役割や機能を持ったサブシステムのことです。`systemd`とは、Linuxの一般的な初期化システムで、各種サービスを起動時に立ち上げる役割を持ちます[^29]。これを制御管理するのが`systemctl`ですが、`systemd`以外にも

    ```bash
    systemctl (サブコマンド) (サービス名)
    ```

    のように実行すればサービスを管理できます。以下はサブコマンドです[^30]:
    - `start` サービスの開始
    - `stop` サービスの停止
    - `reload` サービスの再読み込み
    - `restart` サービスの再起動
    - `enable` サービスの自動起動オン(システム起動時)
    - `disable` サービスの自動起動オフ(システム起動時)
    - `status` サービスの状態表示
    - `daemon-reload` 設定ファイルの再読み込み

7. 定期的にコマンドを実行するには

    ```bash
    crontab (オプション)
    ```

    を実行します[^31]。`-l`オプションでスケジュール設定を表示、`-r`オプションでスケジュール設定をすべて削除、`-e`オプションでスケジュール設定を編集します。

    編集する際は、

    ```cron
    (分) (時) (日) (月) (曜日) (実行コマンド)
    ```

    のように記述します。分、時、日、月、曜日にはすべてを意味する*(ワイルドカード)を指定できます。すべてワイルドカードにした場合は1分毎に実行されます。

    例として、毎週土曜日20時50分に[AtCoder](https://atcoder.jp)を開くコードを以下に示します:

    ```cron
    50 20 * * 6 xdg-open https://atcoder.jp
    ```

    なお、実行コマンドにはシェルスクリプトなども指定できます。`sudo`などもつけることができます。また、`/etc`の`cron`と名のつくファイルにそれぞれ設定を書けばスケジュールから設定を記述することもできます。

8. 時間管理をするには、

    ```bash
    timedatectl
    ```

    を実行します。現在の場所の時間などが表示されます。

    自動で設定したい場合は、インターネットを使って時刻を同期させるNTP(Network Time Protocol)という仕組みを使います。

    ```bash
    sudo timedatectl set-ntp true
    ```

    を実行し、もう一度`timedatectl`を実行してNTP synchronized: yesと表示されればOKです[^32]。

    タイムゾーンを設定する場合は

    ```bash
    sudo timedatectl set-timezone (タイムゾーン)
    ```

    で設定します。

## 12. Apache HTTP Serverの導入

1. （3-4でmozcとfcitx5を入れた人はもう知っているかもしれませんが）Debian系でソフトウェアをインストールするにはaptコマンド

    ```bash
    sudo apt install (パッケージ名)
    ```

    を実行してインストールできます。

2. ここではApache HTTP Serverを利用してWebサーバーを構築します。インストールするにはまず

    ```bash
    sudo apt update
    ```

    を実行し、パッケージリストを更新（パッケージリポジトリから最新のパッケージのバージョンなどを入手する）[^33]してから

    ```bash
    sudo apt -y install apache2
    ```

    を実行します[^34]。`-y`オプションは途中で聞かれるyes/noで答える質問に全部yesで答えるというオプションです。インストールできたら

    ```bash
    sudo systemctl start apache2
    ```

    で起動し、

    ```bash
    sudo systemctl enable apache2
    ```

    で自動起動を有効化、

    ```bash
    sudo systemctl status apache2
    ```

    で状況を確認します。正しく起動できていれば`Active`欄が`active (running) `と表示されます。

    正しく起動できていることを確認したらブラウザで `http://(サーバーのIPアドレス) `に接続してApache2 Ubuntu Default Pageというページが表示されたらOK。サーバーのIPアドレスは`ip addr show`で確認できます。

3. Apache HTTP Serverの設定ファイルは`/etc/apache2/apache2.conf`や`/etc/apache2/sites-available/000-defualt.conf`です。

    `apache2.conf`はサーバー全体の設定を行うファイルで、Apacheの基本的な動作や全体に適用される設定を記述します。

    `000-default.conf`は特定の仮想ホスト（この場合はデフォルトのホスト）の設定を行うファイルで、特定のサイトやドメインに対する設定を記述します。

    Webページに関する変更は基本的に`000-default.conf`を変更するか新しい設定ファイルを作成します。

    設定ファイルで記述可能な設定項目をディレクティブといい、主要なものを以下に示します[^35]。

    - `ServerRoot`: 設定ファイル等を配置するトップディレクトリ（例：/etc/apache2）
    - `Listen`: Apacheが受け付けるIPアドレス(省略可能)とポート番号（例：80）
    - `User`: Apacheの実行ユーザー（例：User #-1）
    - `Group`: Apacheの実行グループ（例：Group #-1）
    - `ServerAdmin`: Apacheの管理者（例：webmaster@localhost）
    - `ServerName`: Webサーバー名、クライアントに返す様々なエラーメッセージ中に記述する、問い合わせアドレス（例：www.example.com）
    - `DocumentRoot`: Webページを配置するディレクトリ（例：/var/www/html）
    - `DirectoryIndex`: サーバー名でアクセスしたときに表示するファイル（例：index.html）

4. 今ある仮想ホストを残して仮想ホストを新しく作るために、

    ```bash
    sudo touch /etc/apache2/sites-available/(ファイル名).conf
    ```

    を実行します。そこに

    ```(ファイル名).conf
    <VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot (ディレクトリパス)
    DirectoryIndex (ファイル名)
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    <Directory "var/www/practice1">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
    </Directory>
    </VirtualHost>
    ```

    を記述してください。ディレクトリパスには例えば`/var/www/html2`などWebページを配置するディレクトリを、ファイル名には例えば`index.html`などを記述してください。

    ディレクトリパス（今回は`/var/www/html2`とします）に指定したディレクトリとファイル名（今回は`index.html`とします）に指定したファイルを作ります。

    ```bash
    sudo mkdir -p /var/www/html2
    sudo touch /var/www/html2/index.html
    sudo vi /var/www/html2/index.html
    ```

    を実行して、適当にHTMLファイルをなにか書いてください。例えば

    ```vim
    <!DOCTYPE html>
    <html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>デモページ</title>
    </head>
    <body>
        <h1>ようこそ、デモページへ！</h1>
        <p>これはサンプルのHTMLページです。</p>
        <p>Apache HTTP Serverを使用してこのページを表示しています。</p>
    </body>
    </html>
    ```

    のように。

    そして、もともと起動していた仮想ホストを無効化し、この新しく作った仮想ホストを有効化するために

    ```bash
    sudo a2dissite 000-default.conf # 無効化
    sudo a2ensite ファイル名.conf # 有効化
    sudo systemctl reload apache2
    ```

    を実行します。

    これでまた http://(サーバーのIPアドレス) に接続して自分で記述した内容のページが表示されたらOK。サーバーのIPアドレスは`ip addr show`で確認できます。

5. Ubuntuではファイアフォールの設定に`ufw`コマンドを利用します[^36]。

    ```bash
    sudo ufw enable
    sudo ufw allow 'Apache'
    sudo ufw status
    ```

    `enable`でファイアフォールを有効化し、`allow 'Apache'`でwell-knownである80番ポートを開放しています。正しく実行できていれば

    ```bash
    Apache ALLOW Anywhere
    Apache(v6) ALLOW Anywhere(v6)
    ```

    のように表示されます。

6. Webページにパスワードをかけて特定の人のみに閲覧させたいときは、BASIC認証を使用します。

    ```bash
    sudo apt install apache2-utils
    ```

    を実行して基本認証を利用するパッケージをインストールします。次に、

    ```bash
    sudo htpasswd -c /etc/apache2/.htpasswd (ユーザー名)
    ```

    でユーザー登録を行います[^37]。初回ではないなら`-c`オプションは不要です。

    次に設定ファイル(`/etc/apache2/sites-available/(ファイル名).conf`)に以下のディレクティブを追加します:

    ```(ファイル名).conf
    <Directory "(認証を利用するディレクトリパス)">
    AuthType Basic
    AuthName "Restricted Content"
    AuthUserFile /etc/apache2/.htpasswd
    Require valid-user
    </Directory>
    ```

    (認証を利用するディレクトリパス)に記述されるディレクトリには、パスワード認証をしたいファイルが入り、そのディレクトリにあるすべてのファイルに対して有効になります。

    `AuthType`には認証の種類を記述します。今回はBasic認証です。Digest認証などもあります。

    `AuthName`には、認証ダイアログに表示取れるメッセージを記述します。今回はRestricted Content（制限されたコンテンツ）です。

    `AuthUserFile`には認証に使用するユーザー名とパスワードが格納されているファイルのパスを記述します。

    `Require`には認証に成功したユーザーに対するアクセス制御を指定します。`valid-user`で認証したすべてのユーザーにアクセスを許可します。

    変更を保存したら、

    ```bash
    sudo systemctl reload apache2
    ```

    でApache HTTP Serverを再起動します。

7. Apache HTTP Serverのアクセスログは/var/log/apache2/access.logに保存されます。

    ```bash
    cat /var/log/apache2/access.log
    ```

    で覗くと、

    - どのIPアドレスから接続してきたか
    - 接続元のユーザー名
    - アクセス日時
    - リクエストされたページ
    - ステータスコード
    - リソースに対する転送量
    - アクセス元のURL
    - アクセスしたWebブラウザ

    などを見ることができます[^38]。

    ステータスコードとはHTTPリクエストが正常に終了したかどうかを示すコードで、

    - **200 OK**: リクエストが成功し、サーバーがリクエストされたリソースを正常に返したことを示します。
    - **401 Unauthorized**: 認証が必要なリソースに対して認証が行われていない、または認証に失敗したことを示します。
    - **403 Forbidden**: サーバーがリクエストを理解したが、アクセスを拒否していることを示します。認証があってもアクセスが許可されない場合に使用されます。
    - **404 Not Found**: リクエストされたリソースがサーバー上に存在しないことを示します。
    - **500 Internal Server Error**: サーバー内部で予期しないエラーが発生し、リクエストを処理できなかったことを示します。

    などがあります[^39]。

8. Apache HTTP Serverのエラーログは`/var/log/apache2/error.log`に保存されます。

    ```bash
    cat /var/log/apache2/error.log
    ```

    で覗くと、

    - エラーがおきた日時
    - エラーを発生させたモジュールとエラーレベル
    - プロセスID
    - クライアント情報(IPアドレスとポート番号)
    - エラーメッセージ

    などが表示されます[^40]。

## 13. SSH接続

1. よくサーバーにSSHで接続して作業をするということがあるので、公開鍵認証とパスワード認証の2段階認証を使ってSSH接続をするための設定を行います。

    ```bash
    sudo apt install opnessh-server
    ```

    でOpenSSHをインストールし、

    ```bash
    sudo systemctl start ssh
    sudo systemctl enable ssh
    ```

    で起動、

    ```bash
    sudo systemctl status ssh
    ```

    で起動しているかを確認します[^41]。起動していたらActiveの欄active (running) になっています。

2. セキュリティ向上のため、デフォルトの設定を（ポートをwell-knownのものからwell-knownではないものに）変更します。しかしその前に元の設定のバックアップを

    ```bash
    sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config_backup
    ```

    でとっておきましょう。

    そして

    ```bash
    sudo vi /etc/ssh/sshd_config
    ```

    で#Port22とある行を探し、#をとってコメントアウトを解除、今回は10022に変更して保存してください。終わったら

    ```bash
    sudo ufw allow 10022/tcp
    sudo sytemctl reload ssh
    ```

    でポートを開放し、SSHを再起動します。

    外部からはrootユーザーでログインされると危険なので、それを禁止するために

    ```bash
    PermitRootLogin no
    ```

    を実行します[^42]。特定のユーザーにのみログインを許可する場合は

    ```bash
    AloowUsers (ユーザー名)
    ```

    を実行します[^43]。それぞれ行ったあとは`systemctl`で再起動を忘れないでください。

3. SSH接続をするためのパソコンでシェルを開き、

    ```shell
    ssh (ユーザー名)@(ホスト名もしくはIPアドレス) -p (ポート番号)
    ```

    を実行します。今回はポート番号は10022です。初回接続のときは"Are you sure you want to continue connectinf (yes/no/[fingerprint])?と聞かれるので、正しく接続できているならyesを選択します。

4. SSH接続をするためのパソコンのシェルで、

    ```shell
    ssh-keygen -t ed25519 -f ./.ssh/id_ed25519
    ```

    を実行します[^44]。実行するとパスフレーズを入力せよと言われるので入力して（しなくてもいい）、Enterを押してください。

    `ed25519`[^45]は暗号化アルゴリズムで、現在(2024年11月)主流のものです。

    ファイル名で指定したファイルに鍵が隠されています。このファイルはユーザーディレクトリの`.ssh`というディレクトリにあることが多いです。

    正常に実行されていると`.ssh`に`id_ed25519`という秘密鍵と`id_ed25519.pub`という公開鍵の2つのファイルが生成されます。

5. 公開鍵を登録するために、

    ```shell
    $ cat $HOME\.ssh\(公開鍵のファイル名) | ssh (ユーザ名@ホスト名もしくは IP アドレス）-p (ポート番号) "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
    ```

    を実行します。今回の場合は公開鍵のファイル名は`id_ed25519.pub`です。

    公開鍵の内容を`cat`で取得、それを`ssh`コマンドで接続した先にファイルを作って入れ、所有者以外は権限を与えないようにしています。

    また、2段階認証を有効化するために、

    ```bash
    sudo vi /etc/ssh/sshd_config
    ```

    で設定ファイルを開き[^46]、

    ```sshd_config
    AuthenticationMethods publickey, password
    ```

    を記述して保存したら、`systemctl`で再起動してください。

    これでSSH接続をするためのパソコンで

    ```shell
    ssh (ユーザー名)@(ホスト名もしくはIPアドレス) -p (ポート番号)
    ```

    を実行して接続できれば完了です。

## 14. Docker導入

1. Dockerは、アプリケーションをコンテナとしてパッケージ化し、どこでも一貫して動作させるためのツールです。コンテナと呼ばれる実行環境は軽量で、仮想マシンよりも効率的です[^47]。また、Dockerイメージという環境を再現するためのアーカイブファイルで簡単に環境を作ることができます。

2. まず、適当なところに

    ```docker_install.sh
    # Add Docker's official GPG key:
    sudo apt-get update
    sudo apt-get install ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc

    # Add the repository to Apt sources:
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

    sudo apt-get update
    sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    ```

    を、`docker_install.sh`として保存し、名前をそのまま入力して実行してください[^48]。必要なら、`chmod +x docker_install.sh`で実行権限をつけてください。

    インストール出来たら、

    ```bash
    sudo docker --version
    sudo systemctl status docker
    ```

    でDockerのバージョンと起動状態を確認してください。もし起動していなければ、`systemctl`コマンドで起動してください。今後、dockerコマンドをユーザーで実行したい場合は、

    ```bash
    sudo usermod -aG docker $USER
    newgrp docker
    ```

    を実行してdockerグループにユーザーを追加してください。

3. 11-6で書いたように、OSはまず初めにPID1(`Systemd`)を実行し、そのプログラムがどんどん他のサービスを起動させます。プロセスには依存関係があるので、PID1を停止させると、それが呼んでいたサービスもすべて停止します。逆に、それ停止させると全プロセスをすべて停止させるようなプロセスをPID1と呼びます。コンテナを停止しても全プロセスの停止にもなります。

4. Dockerイメージは[Docker Hub](https://hub.docker.com)に上がっていればインストールできるので、とりあえず`hello-world`を実行します。

    ```bash
    docker container run hello-world
    docker run -it ubuntu bash
    ```

    下のコマンドはコンテナ内でubuntu bashを開くためのコマンドです。`exit`で脱出できます。

    ```bash
    docker container ls -a
    ```

    でコンテナの一覧を確認できます。そこでは

    - コンテナID: 各コンテナに割り当てられる一意の識別子です。通常、12文字の短縮形式で表示されます。

    - イメージ: コンテナの実行環境を定義するテンプレートです。アプリケーションやその依存関係を含みます。

    - ステータス: コンテナの現在の状態を示します。例：running（実行中）、exited（停止）、paused（一時停止）など。

    - コンテナ名: コンテナに割り当てられた名前です。指定しない場合は自動的に生成されますが、--name オプションで指定することもできます。

    などが表示されます[^49]。

5. `hello-world`を停止するには

    ```bash
    docker container stop hello-world
    ```

    を実行します。`hello-world`の部分は`docker container ls -a`で調べたときに出てきています。

6. `hello-world`を削除するには

    ```bash
    docker container rm hello-world
    ```

    を実行します。停止→削除と行うときには`-f`オプションを付けます。

7. 何故か名前で指定でないときは、

    ```bash
    docker ps -q
    ```

    でコンテナのIDが表示されるので、これを指定してください[^50]。

## 15. Docker上でApache HTTP Serverを動かす

1. [httpdがApache HTTP ServerのDocker Hubでの名前なので](https://hub.docker.com/_/httpd)、

    ```bash
    mkdir -p ~/(ディレクトリ名)/htdocs ~/ディレクトリ名/conf
    ```

    で管理ディレクトリを作ってから、

    ```bash
    cd ~/(ディレクトリ名)
    docker run -dit --name my-apahe-app -p 8080:80 -v ./htdcos:/usr/local/apache2/htdocs/ -v ./conf:/usr/apache2/conf httpd:2.4
    ```

    で起動させます[^51]。

    `-dit`は`-d`、`-i`、`-t`コマンドの組み合わせで、コンテナをバックグラウンドで実行し、標準入力を開いたまま疑似ターミナルを割り当てるというオプションです。

    `-p`オプションでホストの8080番ポートにアクセスすると、コンテナ内の80番ポートにリクエストが転送されるようになっています。

    `-v`オプションでホストの `./htdocs` ディレクトリをコンテナの `/usr/local/apache2/htdocs/` ディレクトリに接続します。これにより、ホスト上のファイルがコンテナ内で利用可能になります。

    `httpd:2.4`は使用するDockerイメージの名前です。

    この状態で、`./htdocs`に`index.html`を入れるとコンテナ上のApache HTTP Serverで読み込まれて内容がインターネットに公開されます。

[^1]: ここではそれてしまうので詳しくは書きませんが、[例えばこういうサイトが参考になります](https://www.pc-cafe.jp/windows11_local_account_setup/)

[^2]: [こちらのページを参考にしました](https://blog.bleuazur.org/2020/09/25/ubuntu%E3%81%A7pc%E3%82%92%E5%86%8D%E7%94%9F%EF%BC%81%E3%81%A7%E3%82%82%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%AA%E3%81%84%EF%BC%81%EF%BD%9E%E3%81%9D%E3%82%93%E3%81%AA%E6%99%82%E3%81%AE%E4%B8%80%E4%BE%8B/)

[^3]: なぜならターミナルの先頭に表示される名前だからです。長いと領域を取られて邪魔です。

[^4]: コンピューターに接続されているキーボードやマウス、ディスプレイやスピーカーなど外部デバイスを制御するためのファイル。

[^5]: 私が行った限りでは、何故か標準でtiny vimがインストールされるということになっていました。なので、ここで作成しています。

[^6]: [こちらのページを参考にしました](https://wa3.i-3-i.info/word11990.html)

[^7]: [こちらのページを参考にしました](https://wa3.i-3-i.info/word16226.html)

[^8]: [こちらのページを参考にしました](https://qiita.com/nakatie/items/ed22a6b5398bc8768e68)

[^9]: [こちらのページを参考にしました](https://qiita.com/ktoyod/items/0a8491cdb6c0191ab0cc)

[^10]: それぞれ、以下のような意味です。`set showmode` 現在のモードを表示する。`set number` 行を表示する。`set expandtab` tabを半角スペースで代用。`set shiftwidth=4` インデントの幅を4に。`set smartindent` 改行したときに勝手にインデント。プログラムの構造も考慮。[こちらのページを参考にしました](https://qiita.com/reireias/items/230c77b3ff5575832654)

[^11]: [こちらのページを参考にしました](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)

[^12]: [こちらのページを参考にしました](https://www.kakiro-web.com/chown-command/)

[^13]: [こちらのページを参考にしました](https://atmarkit.itmedia.co.jp/ait/articles/1705/26/news013.html)

[^14]: [こちらのページを参考にしました](https://linuxcommand.net/export/)

[^15]: [こちらのページを参考にしました](https://www.cman.jp/network/term/ip/)

[^16]: [こちらのページを参考にしました](https://www.cman.jp/network/term/subnet/)

[^17]: [こちらのページを参考にしました](https://www.cman.jp/network/term/port/)

[^18]: [こちらのページを参考にしました](https://www.cman.jp/network/term/dns/)

[^19]: [こちらのページを参考にしました](https://www.cman.jp/network/term/domain/)

[^20]: [こちらのページを参考にしました](https://wa3.i-3-i.info/word1959.html)

[^21]: [こちらのページを参考にしました](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1136425906)

[^22]: [こちらのページを参考にしました](https://learning.zealseeds.com/contents/text/IPA/technology/openSourceSoftware/os/linux/index.html)

[^23]: [こちらのページを参考にしました](https://qiita.com/010Ri/items/249c7e5326ced6468142)

[^24]: [こちらのページを参考にしました](https://ja.linux-console.net/?p=30299)

[^25]: [こちらのページを参考にしました](https://ja.linux-console.net/?p=14972)

[^26]: [こちらのページを参考にしました](https://qiita.com/yasushi-jp/items/9fa169251998b642aec9)

[^27]: [こちらのページを参考にしました](https://linux.joho.info/command/ps/)

[^28]: [こちらのページを参考にしました](https://qiita.com/tetoralynx/items/9bffce2c4d5dff10239d)

[^29]: [こちらのページを参考にしました](https://qiita.com/gogonosmarty/items/140526ac7bb4ba956877)

[^30]: [こちらのページを参考にしました](https://office54.net/iot/linux/linux-systemd-systemctl)

[^31]: [こちらのページを参考にしました](https://office54.net/iot/linux/ubuntu-cron-crontab)

[^32]: [こちらのページを参考にしました](https://self-development.info/%E3%80%90ubuntu%E3%80%91ntpdate%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8Ftimedatectl%E3%81%AB%E3%82%88%E3%82%8B%E6%99%82%E5%88%BB%E5%90%88%E3%82%8F%E3%81%9B/)

[^33]: [こちらのページを参考にしました](https://qiita.com/masoo/items/8ebc51a6a9f32417d4a3)

[^34]: [こちらのページを参考にしました](https://ja.linux-console.net/?p=998)

[^35]: [こちらのページを参考にしました](https://httpd.apache.org/docs/2.4/ja/mod/directives.html)

[^36]: [こちらのページを参考にしました](https://qiita.com/RyoMa_0923/items/681f86196997bea236f0)

[^37]: [こちらのページを参考にしました](https://www.server-world.info/query?os=Ubuntu_20.04&p=httpd&f=8)

[^38]: [こちらのページを参考にしました](https://beyondjapan.com/blog/2020/02/access-log/)

[^39]: [こちらのページを参考にしました](https://developer.mozilla.org/ja/docs/Web/HTTP/Status)

[^40]: [こちらのページを参考にしました](https://httpd.apache.org/docs/2.4/ja/logs.html)

[^41]: [こちらのページを参考にしました](https://codechacha.com/ja/ubuntu-install-openssh/)

[^42]: [こちらのページを参考にしました](https://syutaku.blog/linux-sshd-config-permitrootlogin/)

[^43]: [こちらのページを参考にしました](https://qiita.com/Xmimi_soft/items/1a806b3dfe8673671b25)

[^44]: [こちらのページを参考にしました](https://qiita.com/to3izo/items/9b5b80430e43cd3c4e3c)

[^45]: [こちらのページを参考にしました](https://qiita.com/aktsmm/items/5764682c0c5cd063e511)

[^46]: [こちらのページを参考にしました](https://orebibou.com/ja/home/201701/20170122_001/)

[^47]: [こちらのページを参考にしました](https://qiita.com/SatoshiSobue/items/a612ebbb3a9242c09db5)

[^48]: [こちらのページを参考にしました](https://docs.docker.com/engine/install/ubuntu/)

[^49]: [こちらのページを参考にしました](https://qiita.com/JK447/items/bed378680eee49c5f600)

[^50]: [こちらのページを参考にしました](https://docs.docker.jp/engine/reference/commandline/ps.html)

[^51]: [こちらのページを参考にしました](https://qiita.com/sugurutakahashi12345/items/dc23dab2613b0e6103e8)