2025/12/10 Updated by

Docker Image を自作する (4c)

ubuntu 24.04LTS + ユーザ作成 + sshd + httpd + cert + fail2ban + syslog


[Up] Japanese English
このページ内での表記:
「ホストOSの対話環境」は背景色を黄色(lightyellow)で表す。
「Conainer 内の root 権限の対話環境」は背景色を水色(azure)であらわす。
「Conainer 内の一般ユーザ権限の対話環境」は背景色を赤色(#ffeeee)であらわす。
「他のPCの対話環境」は紫色(#eeeeff)で表す。

sshd, httpd (https), fail2ban を自動起動する ubuntu24.04LTS の docker Image を生成する

方針

作成手順

  1. 作業用フォルダを作成する
  2.   $ mkdir -p ~/doc/docker/ubuntu24_sshd_https_fail2ban
      $ cd ~/doc/docker/ubuntu24_ssd_https3
    
  3. 作業用フォルダの中に Dockerfile を作成する。
  4. Dockerfile
    # ゲストOS: Ubuntu 24.04 LTS
    
    FROM ubuntu:24.04
    
    
    # Change Your Own UNAME, UID, GID, PASS
    
    ENV UNAME=guest
    ENV UID=1000
    ENV GID=1000
    ENV PASS=password
    
    ENV SSHD_PORT=22
    
    # 必要なパッケージのインストール
    
    RUN apt-get update && \
        DEBIAN_FRONTEND=noninteractive apt-get install -y \
        sudo \
        bash tcsh \
        ## sshd \
        openssh-server \
        supervisor \
        net-tools iputils-tracepath traceroute iputils-ping curl iproute2 \
        ufw \
        ## fail2ban \
        locales tzdata \
        rsyslog fail2ban \
        ## https \
        apache2 \
        libapache2-mod-php \
        php-fpm \
        cron certbot \
        ## others \
        && rm -rf /var/lib/apt/lists/*
    
    ## SSH 設定: パスワード認証を有効化
    
    RUN sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
        sed -i "s/^#Port.*/Port ${SSHD_PORT}/" /etc/ssh/sshd_config && \
        mkdir /var/run/sshd
    
    ## Apache 設定: ServerName エラー防止
    
    RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
    
    ## PHP 設定
    RUN sed -i 's/^;date\.timezone =.*/date\.timezone = "Asia\/Tokyo"/' /etc/php/8.3/apache2/php.ini
    
    # PHP-FPM によるPHPの高速化
    RUN sed -i \
        '/<\/VirtualHost>/i <FilesMatch "\\.php$">\n  SetHandler "proxy:unix:/var/run/php/php8.3-fpm.sock|fcgi://localhost/"\n</FilesMatch>' \
        /etc/apache2/sites-available/default-ssl.conf
    
    RUN a2enmod proxy_fcgi setenvif
    RUN a2enconf php8.3-fpm
    
    
    # supervisord の設定ファイルを設置する (Daemon 起動用)
    
    RUN mkdir -p /var/log/supervisor/conf.d
    COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
    
    
    ## fail2bin: ネットワーク攻撃対策
    
    # locale 設定
    RUN locale-gen ja_JP.UTF-8 && \
        update-locale LANG=ja_JP.UTF-8
    ENV LANG=ja_JP.UTF-8
    ENV LC_ALL=ja_JP.UTF-8
    
    
    # timezone 設定
    RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
    RUN echo 'Asia/Tokyo' > /etc/timezone
    
    # fail2bin
    COPY jail.local /etc/fail2ban
    
    
    # ポート開放
    
    EXPOSE 22 80 443
    
    
    # Copy Shell Script "entrypoint.sh"
    
    COPY entrypoint.sh /entrypoint.sh
    RUN chmod +x /entrypoint.sh
    
    ENTRYPOINT ["/entrypoint.sh"]
    
    CMD []
    
  5. 作業用フォルダの中に entrypoint.sh を作成する
  6. entrypoint.sh
    #!/bin/bash
    set -euo pipefail
    
    if [ ! -f /var/app/.initialized ]; then
        ######## First Time ########
    
        echo "First run. Setting up ..."
        mkdir -p /var/app
        touch /var/app/.initialized
    
        if ! getent passwd "$UNAME" &>/dev/null; then    # 同じユーザ名のユーザが存在しなければ
    
            UNAME_TARGET="$(getent passwd "$UID" | cut -d: -f1 || true)"    # 同じ UID のユーザがいるか調べる
    
            if [ -n "${UNAME_TARGET}" ]; then    # 既存のユーザのユーザ名を変更する
    
    	    echo "Renaming user ${UNAME_TARGET} to $UNAME UID=${UID}"
    	    
    	    usermod -l "$UNAME" "$UNAME_TARGET"    #ユーザ名を変更する
    	    groupmod -n "$UNAME" "$UNAME_TARGET"    # グループ名を変更する (GIDは既存の値のまま)
    	    usermod -d "/home/$UNAME" -m "$UNAME"    # ホームディレクトリ名を変更する
    	    if [ -d "/home/$UNAME_TARGET" ] && [ ! -d "/home/$UNAME" ]; then
    	        mv "/home/$UNAME_TARGET" "$/home/$UNAME"
    	    fi
    
            else    # 新規ユーザを作成する
    
    	    echo "Creating user ${UNAME} with UID=${UID}, GID=${GID}"
    	    
    	    if ! getent group "${UNAME}" &>/dev/null; then    # 同名グループが無ければ作成
                    echo "Creating group ${UNAME} with GID=${GID}"
                    groupadd -g ${GID} ${UNAME}
    	    fi
    	    useradd -m -u ${UID} -g ${GID} -s /bin/bash ${UNAME}    # 新規ユーザを作成する
    	    echo "${UNAME}:${PASS}" | chpasswd    # パスワードを設定する
                usermod -aG sudo ${UNAME}       # sudo グループに加える
    	fi
    
    
        fi
    
        # ホームディレクトリの Owner が root:root になることがあるので明示的に変更する。
        chown -v ${UNAME}:${UNAME}  /home/${UNAME}
    
        # SSHD のポート番号を変更する
        sed -i "s/^Port.*/Port ${SSHD_PORT}/" /etc/ssh/sshd_config
    
        
    else
        ######## Second Time or Later ########
        
        echo "Starting for the second time or later ..."
    
    fi
    
    
    # firewall
    /usr/sbin/ufw enable
    #/usr/sbin/ufw allow from 0.0.0.0/0 to any port ${SSHD_PORT} proto tcp
    /usr/sbin/ufw default deny incoming
    
    # supervisord start (background)
    /usr/bin/supervisord -c /etc/supervisor/supervisord.conf &
    
    
    # Execute Commands in CMD
    
    if [ "$#" -gt 0 ]; then
        exec "$@"
    else
        echo "No command provided. Starting bash ..."
        exec bash
    fi
    
  7. 作業用フォルダの中に supervisord.conf を作成する
  8. supervisord.conf
    # supervisord の追加`設定ファイル
    # /etc/supervisor/conf.d/supervisord.conf
    
    [supervisord]
    nodaemon=true
    
    
    [program:rsyslog]
    command=/usr/sbin/rsyslogd -n
    autostart=true
    autorestart=true
    priority=5
    
    
    [program:sshd]
    # syslog に送る。
    command=/bin/sh -c "/usr/sbin/sshd -D -e 2>&1 | logger -t sshd"
    autostart=true
    autorestart=true
    
    
    [program:php-fpm]
    command=/usr/sbin/php-fpm8.3 -F
    autostart=true
    autorestart=true
    stdout_logfile=/var/log/php-fpm.log
    stderr_logfile=/var/log/php-fpm.err
    
    
    [program:apache2]
    command=/usr/sbin/apachectl -D FOREGROUND
    autostart=true
    autorestart=true
    stopasgroup=true
    killasgroup=true
    stdout_logfile=/var/log/apache2_stdout.log
    stderr_logfile=/var/log/apache2_stderr.log
    
    
    [program:cron]
    command=/usr/sbin/cron -f
    autostart=true
    autorestart=true
    
    
    [program:fail2ban]
    command=/usr/bin/fail2ban-server -xf start
    autorestart=true
    stderr_logfile=/var/log/fail2ban.err.log
    stdout_logfile=/var/log/fail2ban.out.log
    priority=10
    
  9. 作業用フォルダの中に fail2ban の設定ファイル jail.local を作成する
  10. jail.local
    # fail2ban settings
    # /etc/supervisor/conf.d/jail.local
    
    [DEFAULT]
    banaction = nftables-multiport
    
    
    [sshd]
    enabled = true
    port    = ssh
    filter  = sshd
    backend = polling
    logpath = /var/log/syslog
    maxretry = 5
    findtime = 10m
    bantime = 1h
    
  11. image を build する。
  12.   $ docker build -t ubuntu24_sshd_https_fail2ban .
      ...
    成功
    
  13. 生成した Image を確認する
  14. $ docker image ls
    REPOSITORY            TAG       IMAGE ID       CREATED         SIZE
    ubuntu24_sshd_https_fail2ban   latest    d12fc3012451   2 hours ago    329MB
    ...
    
  15. (注意) 上で用意した supervisod.conf は、Container の /etc/supervisor/conf.d/supervisord.conf としてコピーする。 supervisord の設定ファイルは /etc/supervisor/supervisord.conf であるが、このファイルの中で /etc/supervisor/conf.d/*.conf をインクルードする。

Container 用の永続的なファイルシステムを作成する

コンテナに永続的なファイルシステムを提供するために、1777 のパーミッションでフォルダを作っておく。 skicky bit が on (1777) のフォルダには、 「誰でもファイルを作成できるが、作成した本人だけがファイルを変更したり消したりできる」 という特徴がある。

$ sudo mkdir -p /home/docker         ← ディレクトリを作成する
$ sudo chmod 1777 /home/docker       ← 誰でもファイルを作成できるが、作成した本人にしか消去できないモードに設定する
$ ls -ld /home/docker                ← ディレクトリのsticky bit が on になっていることを確認する。
drwxrwxrwt 3 root root 4096  4月 26 15:47 /home/docker

Docker Network を生成する

「アクセスしてきたクライアントの正しいIPアドレスがContainer 上の httpdサーバ (apache2) に伝わる」ように macvlan を使って「Container に物理 NIC と同じネットワークの独立した IP アドレスを与える」ことにする。

前提条件と環境

  1. ホストOSの接続しているネットワークを調べる。
  2. $ netstat -nr
    カーネルIP経路テーブル
    受信先サイト    ゲートウェイ    ネットマスク   フラグ   MSS Window  irtt インタフェース
    0.0.0.0         192.168.12.1    0.0.0.0         UG        0 0          0 eno1
    172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 docker0
    192.168.12.0    0.0.0.0         255.255.255.0   U         0 0          0 eno1
    
  3. ホストOSの IP アドレスを調べる。
  4. $ ifconfig 
    	...
    eno1: flags=4163  mtu 1500
            inet 192.168.12.3  netmask 255.255.255.0  broadcast 192.168.12.255
            inet6 2409:11:3920:6400:5a47:caff:fe71:3b7d  prefixlen 64  scopeid 0x0
            inet6 2409:11:3920:6400:4c1a:ff8c:eab1:41c9  prefixlen 64  scopeid 0x0
            inet6 fe80::5a47:caff:fe71:3b7d  prefixlen 64  scopeid 0x20
            ether 58:47:ca:71:3b:7d  txqueuelen 1000  (イーサネット)
    ...
    
  5. docker のネットワーク一覧を表示して、macvlan_net が存在するかどうかを調べる。
  6. $ docker network ls
    NETWORK ID     NAME          DRIVER    SCOPE
    ebbd998b2086   bridge        bridge    local
    17420af9f271   host          host      local
    557533733a33   macvlan_net   macvlan   local
    a3538f29efc6   none          null      local
    
  7. (macvlan ネットワークが存在しない場合は ) macvlan ネットワークを作成する。
  8. $ docker network create -d macvlan \
        --subnet=192.168.12.0/24 \
        --gateway=192.168.12.1 \
        -o parent=eno1 \
        --ip-range=192.168.12.192/28 \
        macvlan_net
    
    
  9. docker のネットワーク一覧を表示する。macvlan_net が作成されていることがわかる。
  10. $ docker network ls
    NETWORK ID     NAME          DRIVER    SCOPE
    ebbd998b2086   bridge        bridge    local
    17420af9f271   host          host      local
    557533733a33   macvlan_net   macvlan   local
    a3538f29efc6   none          null      local
    
    $ docker network ls --no-trunc
    NETWORK ID                                                         NAME          DRIVER    SCOPE
    ebbd998b20868aea17c1e9f3cd85edb3c7c0ce9181edfe9b308284604275e136   bridge        bridge    local
    17420af9f27199ef5081c56e85910d913c73ae8f3885e48e4ed0b09a06d48016   host          host      local
    557533733a33e84ca9eb665736f6a273414778f30a3e744411596008728b0b2b   macvlan_net   macvlan   local
    a3538f29efc60166d3f639d42894eff9f902649036619190011c3a66b262a06a   none          null      local
    
  11. macvlan ネットワークの詳細をみる
  12.   $ docker network inspect macvlan_net
      [
        {
            "Name": "macvlan_net",
            "Id": "557533733a33e84ca9eb665736f6a273414778f30a3e744411596008728b0b2b",
            "Created": "2025-05-18T13:38:38.53151226+09:00",
            "Scope": "local",
            "Driver": "macvlan",
            "EnableIPv4": true,
            "EnableIPv6": false,
            "IPAM": {
                "Driver": "default",
                "Options": {},
                "Config": [
                    {
                        "Subnet": "192.168.12.0/24",
                        "IPRange": "192.168.12.192/28",
                        "Gateway": "192.168.12.1"
                    }
                ]
            },
            "Internal": false,
            "Attachable": false,
            "Ingress": false,
            "ConfigFrom": {
                "Network": ""
            },
            "ConfigOnly": false,
            "Containers": {
                "65cf25b6ca3756fd9babc1b29d9b1a30d493c9ee85a713b530a91e999f9c35de": {
                    "Name": "ubuntu24-sshd-httpd-vlan193",
                    "EndpointID": "f8525f08c56d699552c023cdd7a589c2dd177ed575085d15b44eea960f83df3e",
                    "MacAddress": "a6:a6:4d:50:7a:0d",
                    "IPv4Address": "192.168.12.193/24",
                    "IPv6Address": ""
                }
            },
            "Options": {
                "parent": "eno1"
            },
            "Labels": {}
        }
    ]
    

Docker Contaner を生成する

Image ubuntu24_sshd_https_fail2ban を用いて、 macvlan_net ネットワークに接続する、 新しい Container ubuntu24-sshd-https-vlan193 を生成する。

Container を作成+実行する

  1. image から container を生成して起動する。 下の実行例はユーザ名を www とした場合である。 デフォルトの一般ユーザと同じ名前なので新たにユーザが作成されることはないし、 UID, GID, パスワードは -e オプションで指定しても変更されることはない。
  2.   $ docker run --name ubuntu24-sshd-https-fail2ban193 --restart always \
        --hostname https193 \
        -e UNAME=www \
        --network macvlan_net \
        --ip 192.168.12.193 \
        --cap-add=NET_ADMIN \
        -v /home/docker/https193:/mnt/hostos \
        -it ubuntu24_sshd_https_fail2ban
    
    起動オプション
  3. Container を起動した対話環境が、そのままContainer 内で動作する bash との対話環境になる。root権限でloginした状態である。
  4. First run. Setting up ...
    Renaming user ubuntu to www UID=1000
    ownership of '/home/www' retained as www:www
    Firewall is active and enabled on system startup
    Default incoming policy changed to 'deny'
    (be sure to update your rules accordingly)
    No command provided. Starting bash ...
    root@https193:/# 2025-12-15 20:11:58,711 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  If you intend to run as root, you can set user=root in the config file to avoid this message.
    2025-12-15 20:11:58,711 INFO Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing
    2025-12-15 20:11:58,714 INFO RPC interface 'supervisor' initialized
    2025-12-15 20:11:58,714 CRIT Server 'unix_http_server' running without any HTTP authentication checking
    2025-12-15 20:11:58,714 INFO supervisord started with pid 618
    2025-12-15 20:11:59,718 INFO spawned: 'rsyslog' with pid 621
    2025-12-15 20:11:59,720 INFO spawned: 'fail2ban' with pid 622
    2025-12-15 20:11:59,722 INFO spawned: 'apache2' with pid 623
    2025-12-15 20:11:59,723 INFO spawned: 'cron' with pid 624
    2025-12-15 20:11:59,725 INFO spawned: 'php-fpm' with pid 625
    2025-12-15 20:11:59,726 INFO spawned: 'sshd' with pid 629
    2025-12-15 20:12:00,803 INFO success: rsyslog entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    2025-12-15 20:12:00,803 INFO success: fail2ban entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    2025-12-15 20:12:00,803 INFO success: apache2 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    2025-12-15 20:12:00,803 INFO success: cron entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    2025-12-15 20:12:00,803 INFO success: php-fpm entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    2025-12-15 20:12:00,803 INFO success: sshd entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    #                ← Container 内の対話環境 (root 権限の bash) が動く
    
  5. 直ちに ユーザ www のパスワードを変更する。
  6. # passwd www
    New password: 新しいパスワード        ← 新しいパスワードを入力する(エコーバックされない)
    Retype new password: 新しいパスワード ← もう一度新しいパスワードを入力する(エコーバックされない)
    
  7. netstat コマンドを用いて、ルーティング情報を調べる。 → Container が接続しているネットワークは 192.168.12.0/24で、 デフォルトのルーティング先が 192.168.12.1 であることがわかる
  8. $ netstat -nr
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
    0.0.0.0         192.168.12.1    0.0.0.0         UG        0 0          0 eth0
    192.168.12.0    0.0.0.0         255.255.255.0   U         0 0          0 eth0
    
  9. ifconfig でContainer のIPアドレスを調べる。 → 192.168.12.193 であることがわかる。
  10. $ ifconfig
    eth0: flags=4163  mtu 1500
            inet 192.168.12.193  netmask 255.255.255.0  broadcast 192.168.12.255
            ether 8a:9e:8a:00:aa:16  txqueuelen 0  (Ethernet)
            RX packets 5434  bytes 30400112 (30.4 MB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 4498  bytes 300984 (300.9 KB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10
            loop  txqueuelen 1000  (Local Loopback)
            RX packets 8  bytes 1058 (1.0 KB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 8  bytes 1058 (1.0 KB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
  11. firewall の状態を調べて、ssh (=22), http (=80), https (=443) のポートを開ける。
  12. # ufw status
    Status: active
    # ufw allow from 0.0.0.0/0 to any port 22 proto tcp
    Rule added
    # ufw allow from 0.0.0.0/0 to any port 80 proto tcp
    Rule added
    # ufw allow from 0.0.0.0/0 to any port 443 proto tcp
    Rule added
    
    ファイアウォールの設定状況を見る
    # ufw status
    Status: active
    
    To                         Action      From
    --                         ------      ----
    22/tcp                     ALLOW       Anywhere
    80/tcp                     ALLOW       Anywhere
    443/tcp                    ALLOW       Anywhere
    
  13. ネットワーク上の他のマシンから、ssh接続できることを確認する。
  14. sshで
    $ ssh www@192.168.12.193
    
    [注意] パスワードを迅速に変更しておくこと。
  15. ネットワーク上の他のマシンから httpd 接続できることを確認する。
  16. ブラウザで http://192.168.12.193/ にアクセスする

httpsを使えるように設定する

証明書を発行する

  1. ルータを使って外部ネットワークと切り分けている場合は、ルータのポートフォワーディング機能を用いて 80番ポートと 443番ポートへのアクセスが、apache2 サーバに転送されるように設定しておく。
  2. certbot をインストールする ← これは Dockerfile の中でやってあるはず。
  3. # apt -y install certbot 
    
  4. certbot のパラメータ
  5.   --webroot でWebサーバの公開ディレクトリ配下を認証用に一時領域に使う
      -w DocumentRoot
      -d 証明書を取得する対象の FQDN (= Fully Qualified Domain Name)
    
  6. certbot を使って、証明書を発行する。下の例は、自分のWWWサーバに対して example.com というドメインが登録してあり、WWWの管理者が root@example.com の場合である。適切な名前に変更すること。
  7. # certbot certonly --webroot -w /var/www/html -d example.com  
    Saving debug log to /var/log/letsencrypt/letsencrypt.log
    Enter email address (used for urgent renewal and security notices)
     (Enter 'c' to cancel): root@example.com 
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Please read the Terms of Service at
    https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
    agree in order to register with the ACME server. Do you agree?
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    (Y)es/(N)o: y 
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Would you be willing, once your first certificate is successfully issued, 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: n 
    Account registered.
    Requesting a certificate for example.com
    
    Successfully received certificate.
    Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
    Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem
    This certificate expires on 2023-09-01.
    These files will be updated when the certificate renews.
    Certbot has set up a scheduled task to automatically renew this certificate in the background.
    
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    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
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    
  8. 証明書を自動的に更新する設定を行う。 証明書の更新手順が通常とは異なるので注意すること。
  9. docker container ではsystemd が動作していないので systemctl が使えない。 そのため、cron を使って certbot を定期的に実行する。

  10. cron はインストールされているはず。
  11. # which cron 
    /usr/sbin/cron
    
    # ps aux | grep cron 
    root          44  0.0  0.0   4192  2340 pts/0    S    04:10   0:00 /usr/sbin/cron -f
    root        1223  0.0  0.0   3528  1740 pts/0    S+   04:19   0:00 grep --color=auto cron
    
    
  12. [Optional] Editor をインストールして環境変数を設定する。
  13. # apt install -y vim 
    $ export EDITOR=vi 
    
  14. certbot renew を crontab に登録する
  15. $ crontab -e
  16. 以下を追加する。毎日 2:00 に更新をチェックする。証明書が更新されたときは apache2 を再起動する。
  17. この Container では apache2 を supervisord 経由で起動しているので、 apache2 の再起動に systemctl や apachectl は使えない。 supervisorctl を使う。
    0 2 * * * certbot renew --quiet --deploy-hook "supervisorctl restart php-fpm apache2"
    

apache2 の設定を変更する

  1. apache2 にsslモジュールを追加する
  2. # a2enmod ssl
    # a2enmod ssl 
    Considering dependency mime for ssl:
    Module mime already enabled
    Considering dependency socache_shmcb for ssl:
    Enabling module socache_shmcb.
    Enabling module ssl.
    See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
    To activate the new configuration, you need to run:
      service apache2 restart
    
  3. /etc/apache2/sites-available/default-ssl.conf が生成されるので編集する。
  4. /etc/apache2/sites-available/default-ssl.confの変更点
    *** default-ssl.conf.ORG        Sun May 25 05:46:24 2025
    --- default-ssl.conf    Sun May 25 05:48:02 2025
    ***************
    *** 1,5 ****
      <VirtualHost *:443>
    !       ServerAdmin webmaster@localhost
    
            DocumentRoot /var/www/html
    
    --- 1,2 ----
      <VirtualHost *:443>
    !       ServerAdmin root@example.com
    
            DocumentRoot /var/www/html
    
    ***************
    *** 28,35 ****
            #   /usr/share/doc/apache2/README.Debian.gz for more info.
            #   If both key and certificate are stored in the same file, only the
            #   SSLCertificateFile directive is needed.
    !       SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
    !       SSLCertificateKeyFile   /etc/ssl/private/ssl-cert-snakeoil.key
    
            #   Server Certificate Chain:
            #   Point SSLCertificateChainFile at a file containing the
    --- 28,35 ----
            #   /usr/share/doc/apache2/README.Debian.gz for more info.
            #   If both key and certificate are stored in the same file, only the
            #   SSLCertificateFile directive is needed.
    !       SSLCertificateFile      /etc/letsencrypt/live/example.com/cert.pem
    !       SSLCertificateKeyFile   /etc/letsencrypt/live/example.com/privkey.pem
    
            #   Server Certificate Chain:
            #   Point SSLCertificateChainFile at a file containing the
    ***************
    *** 38,44 ****
            #   the referenced file can be the same as SSLCertificateFile
            #   when the CA certificates are directly appended to the server
            #   certificate for convinience.
    !       #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
    
            #   Certificate Authority (CA):
            #   Set the CA certificate verification path where to find CA
    --- 38,44 ----
            #   the referenced file can be the same as SSLCertificateFile
            #   when the CA certificates are directly appended to the server
            #   certificate for convinience.
    !       SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
    
            #   Certificate Authority (CA):
            #   Set the CA certificate verification path where to find CA
    
  5. SSLを有効化する
  6. /etc/apache2/sites-enabled/default-ssl.conf から /etc/apache2/sites-available/default-ssl.conf への シンボリックリンクを張る。
    # a2ensite default-ssl 
    Enabling site default-ssl.
    To activate the new configuration, you need to run:
      service apache2 reload
    
  7. SSLを有効化する
  8. mod_ssl を有効化する。具体的には /etc/apache/mods-enabled/ssl.{load, conf} から/etc/apache/mods-available/ssl.{load,conf} へのシンボリックリンクを張る。
    # a2enmod ssl 
    Considering dependency mime for ssl:
    Module mime already enabled
    Considering dependency socache_shmcb for ssl:
    Module socache_shmcb already enabled
    Module ssl already enabled
    
  9. apache2 を再起動する
  10. supervisorctl を使って再起動する。
    # supervisorctl restart apache2 
    2025-06-06 15:26:04,195 INFO waiting for apache2 to stop
    2025-06-06 15:26:04,204 WARN stopped: apache2 (terminated by SIGTERM)
    apache2: stopped
    2025-06-06 15:26:04,214 INFO spawned: 'apache2' with pid 1418
    2025-06-06 15:26:04,257 WARN exited: apache2 (exit status 0; not expected)
    2025-06-06 15:26:05,261 INFO spawned: 'apache2' with pid 1421
    2025-06-06 15:26:07,227 INFO success: apache2 entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
    apache2: started
    
  11. ネットワーク上の他のマシンからブラウザで https 接続してみる。
  12. URL: https://example.com


Redirect

  1. rewrite モジュールをインストールする
  2.   sudo a2enmod rewrite
    
  3. https でのアクセスを https に転送する
  4. /etc/apache2/sites-available/000-default.conf の中の の間に次の記述を追加する
            Redirect permanent / https://ynitta.net/
    
    以下の記述も変更しておくとよい。
    ServerAdmin y7anitta@gmail.com
    
  5. https://ynitta.net/class/ のアクセスを https://ynitta.com/class/ に転送する
  6. /etc/apache2/sites-available/default-ssl.conf の中の の間に次の記述を追加する
            Redirect temp /class https://ynitta.com/class
    
    以下の記述も変更しておくとよい。
    ServerAdmin y7anitta@gmail.com
    

アクセス制限

.htaccess によるアクセス制限が効くように /etc/apache2/apache2.conf に次の記述を加える。
/etc/apache2/apache2.conf に追加する設定
<Directory /var/www/html>
    Options Indexes FollowSymLinks MultiViews Includes ExecCGI
    AllowOverride FileInfo AuthConfig Indexes Options Limit
    Require all granted
</Directory>

文字コード

デフォルトの文字コードを utf-8 にする
  1. 設定ファイルを作成する。
  2. /etc/apache2/conf-available/charset.conf
    AddDefaultCharset UTF-8
    
  3. 設定を有効化する
  4.   sudo a2enconf charset
    
    これにより、 /etc/apache2/conf-available/charset.conf から /etc/apache2/conf-enabled/charset.conf にシンボリックリングを張る。
  5. apache2 を再起動する
  6. ls  supervisorctl restart apache2
    

その他

ソフトウェアのインストール

  sudo apt update
  sudo apt install -y emacs-lucid
  sudo apt install -y rsync
  sudo apt install -y less

ssh のpublic_key

一般ユーザで
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
これで ~/.ssh/id_ed25519{,.pub} ができる。 他のマシンから ssh でアクセスするには public_key を登録した ~/.ssh/authorized_keys を用意する。

fail2ban にapache2 を追加する

iptables と nftables が必要だが、これは既にインストール済みである。 もしインストールしてなければ次のようにインストールする。
  sudo apt update
  sudo apt install -y iptables nftables
apache2 のログは以下にある。
/etc/log/apache2/access.log
/etc/log/apache2/error.log
filter は /etc/fail2ban/filter.d/apache* に存在する。
  ls /etc/fail2ban/filter.d/apache*
apache2 のlogをsyslog に渡して、/var/log/syslog に取るように設定する。
/etc/fail2ban/jail.d/jail-apache.local
[apache-auth]
enabled  = true
port     = http,https
filter   = apache-auth
logpath  = /var/log/apache2/error.log
backend  = polling
maxretry = 5
findtime = 10m
bantime  = 1h

[apache-badbots]
enabled  = true
port     = http,https
filter   = apache-badbots
logpath  = /var/log/apache2/access.log
backend  = polling
maxretry = 2
findtime = 10m
bantime  = 12h

[apache-noscript]
enabled  = true
port     = http,https
filter   = apache-noscript
logpath  = /var/log/apache2/access.log
backend  = polling
maxretry = 3
findtime = 10m
bantime  = 6h

/etc/fail2ban/jail.local に次を追加した方が安全とのことだが。
[DEFAULT]
banaction = nftables-multiport
supervisord の設定ファイルを変更した場合は、次の操作を行っておくこと。
sudo /bin/bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart fail2ban
確認する
sudo fail2ban-client status apache2

一時的にfail2ban から apache2 に関する設定を取り除く。 /etc/fail2ban/jail.d/jail-apache.local を /mnt/hostos/www に移動しておく。


sshdの安全な設定について

sshd で Pass phrase による設定ができたら、/etc/ssh/sshd_config を次のように 変更して、パスワードによるアクセスを禁止した方がよい。
  1. アクセスする外部のマシンで公開暗号鍵を作成する。
  2.   sudo ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "USER@MACHINE"
    
  3. 外部のマシンの~/.ssh/id_ed25519.pub の内容を、このマシンの ~/.ssh/authorization_keys に追加する。
  4. sshdサーバへのパスワードによるログインを禁止する設定。
  5. /etc/ssh/sshd_config の変更
    *** sshd_config.ORG	2025-05-20 00:31:41.248567113 +0900
    --- sshd_config	2025-05-20 00:32:27.233803321 +0900
    ***************
    *** 31,41 ****
    --- 31,43 ----
      
      #LoginGraceTime 2m
      #PermitRootLogin prohibit-password
    + PermitRootLogin prohibit-password
      #StrictModes yes
      #MaxAuthTries 6
      #MaxSessions 10
      
      #PubkeyAuthentication yes
    + PubkeyAuthentication yes
      
      # Expect .ssh/authorized_keys2 to be disregarded by default in future.
      #AuthorizedKeysFile	.ssh/authorized_keys .ssh/authorized_keys2
    ***************
    *** 55,60 ****
    --- 57,63 ----
      
      # To disable tunneled clear text passwords, change to no here!
      #PasswordAuthentication yes
    + PasswordAuthentication no
      #PermitEmptyPasswords no
      
      # Change to yes to enable challenge-response passwords (beware issues with
    
  6. sshd サーバを再起動する。
  7.   sudo supervisorctl restart sshd
    
  8. 他のマシンからパスフレーズを用いて ssh アクセスする。
  9.     ssh www@192.168.12.139
    

java

apt からインストール可能な java (OpenJDK) のバージョンを確認する方法
  $ apt search openjdk-
  ...
  openjdk-8-jdk-headless/noble-updates,noble-security 8u472-ga-1~24.04 amd64
    OpenJDK Development Kit (JDK) (headless)
  ...
  openjdk-11-jre-headless/noble-updates,noble-security 11.0.29+7-1ubuntu1~24.04 amd64
    OpenJDK Java runtime, using Hotspot JIT (headless)
  ...
  openjdk-17-jdk-headless/noble-updates,noble-security 17.0.17+10-1~24.04 amd64
    OpenJDK Development Kit (JDK) (headless)
  ...
  openjdk-21-jdk-headless/noble-updates,noble-security 21.0.9+10-1~24.04 amd64
    OpenJDK Development Kit (JDK) (headless)
  ...
  openjdk-25-jdk-headless/noble-updates,noble-security 25.0.1+8-1~24.04 amd64
    OpenJDK Development Kit (JDK) (headless)
   ...
apt でインストールできる最新の LTS は Java 25 であるのでこれをインストールする。
  $ sudo apt install openjdk-25-jdk-headless
  $ java -version
  openjdk version "25.0.1" 2025-10-21
  OpenJDK Runtime Environment (build 25.0.1+8-Ubuntu-124.04)
  OpenJDK 64-Bit Server VM (build 25.0.1+8-Ubuntu-124.04, mixed mode, sharing)
  $ javac -version
  javac 25.0.1
java/javac のバージョンを切り替えるには Ubuntu では update-alternatives を使う。
  $ sudo update-alternatives --list javac
  $ sudo update-alternatives --config java
  $ sudo update-alternatives --config javac
  $ sudo update-alternatives --config java

Container を再起動したら apache2 が起動しない

/run/apache2/apache2.pid が残っているために、apache2が起動できないことがある。
  sudo rm -f /run/apache2/apache2.pid
  sudo supervisorctl restart apache2