2025/12/10 Updated by
Docker Image を自作する (4c)
ubuntu 24.04LTS + ユーザ作成 + sshd + httpd + cert + fail2ban + syslog
[Up]
このページ内での表記:
「ホストOSの対話環境」は背景色を黄色(lightyellow)で表す。
「Conainer 内の root 権限の対話環境」は背景色を水色(azure)であらわす。
「Conainer 内の一般ユーザ権限の対話環境」は背景色を赤色(#ffeeee)であらわす。
「他のPCの対話環境」は紫色(#eeeeff)で表す。
sshd, httpd (https), fail2ban を自動起動する ubuntu24.04LTS の docker Image を生成する
方針
作成手順
作業用フォルダを作成する
$ mkdir -p ~/doc/docker/ubuntu24_sshd_https_fail2ban
$ cd ~/doc/docker/ubuntu24_ssd_https3
作業用フォルダの中に Dockerfile を作成する。
Dockerfile中の パスワード (D_PASS, PASS)の部分は、推測されにくい文字列に必ず変更すること。
OpenSSH サーバをインストールする。
Apache2 サーバをインストールする。
PHPをインストールする。
subervisor デーモンをインストールする。これは Container を起動するたびに各サーバを自動起動する役目を担う。
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 []
作業用フォルダの中に entrypoint.sh を作成する
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
作業用フォルダの中に supervisord.conf を作成する
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
作業用フォルダの中に fail2ban の設定ファイル jail.local を作成する
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
image を build する。
$ docker build -t ubuntu24_sshd_https_fail2ban .
...
成功
生成した Image を確認する
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu24_sshd_https_fail2ban latest d12fc3012451 2 hours ago 329MB
...
(注意) 上で用意した supervisod.conf は、Container の
/etc/supervisor/conf.d/supervisord.conf
としてコピーする。
supervisord の設定ファイルは
/etc/supervisor/supervisord.conf
であるが、このファイルの中で /etc/supervisor/conf.d/*.conf をインクルードする。
Container 用の永続的なファイルシステムを作成する
コンテナに永続的なファイルシステムを提供するために、1777 のパーミッションでフォルダを作っておく。
skicky bit が on (1 777) のフォルダには、
「誰でもファイルを作成できるが、作成した本人だけがファイルを変更したり消したりできる」
という特徴がある。
$ 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 アドレスを与える」ことにする。
前提条件と環境
ホストOSのネットワーク: 192.168.12.0/24
ホストOSのネットワークのゲートウェイ: 192.168.12.1
物理 NIC インタフェース名: eno01
ホストOSのIPアドレス: 192.168.12.3
Containerに割り当てるIPアドレス: 192.168.12.192/28 すなわち 192.168.12.[192-207]
[注意] macvlan_net に接続した Container には、ホストOSから直接はネットワーク通信できなくなる(他のマシンを経由すると可能)。
ホストOSの接続しているネットワークを調べる。
ネットワークアドレス: → 192.168.12.0/24
ゲートウェイ: 192.168.12.1
物理NICインタフェース: eno1
Intel のCPUを持つPCに Ubuntu 24.04LTS をインストールした場合は eno1 となる。
Raspberry PI (ARM64) に Ubuntu 24.04LTS をインストールした場合は eth0 となる。
ifconfig コマンドで調べること。
$ 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
ホストOSの IP アドレスを調べる。
ホストOSのIPアドレス: 192.168.12.3
$ 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 (イーサネット)
...
docker のネットワーク一覧を表示して、macvlan_net が存在するかどうかを調べる。
$ 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
(macvlan ネットワークが存在しない場合は ) macvlan ネットワークを作成する。
$ 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
docker のネットワーク一覧を表示する。macvlan_net が作成されていることがわかる。
$ 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
macvlan ネットワークの詳細をみる
$ 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 の起動オプションに --network macvlan_net オプションを追加することにより、
この Container はホストOSのネットワークを共有する。
Container の起動オプションで -p オプションは指定しない。
ホストOSのネットワークを共有した場合、port forwarding はできないため。
Conatiner のIPアドレスを -ip オプションで指定する。
Conatiner が接続するネットワークを --network (ネットワーク名) で指定する。
Container を作成+実行する
image から container を生成して起動する。
下の実行例はユーザ名を www とした場合である。
デフォルトの一般ユーザと同じ名前なので新たにユーザが作成されることはないし、
UID, GID, パスワードは -e オプションで指定しても変更されることはない。
$ 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
起動オプション
--name : 生成するcontainer の名前は ubuntu24-sshd-https-fail2ban193
--hostname : ホスト名は https193
--restart always : docker が起動すると、このコンテナも自動起動する。
--network macvlan_net : Container は macvlan_net にアクセスする。
--ip IPv4 アドレス: Container の IP アドレスを指定する。
--cap-add=NET_ADMIN : ネットワークに関する特権をこの Container に与える(セキュリティ上の問題になる可能性があるので注意が必要)。コンテナ内でファイアウォール (ufw) が使えるようになる。
-e : run 時に実行されるシェルスクリプト (entrypoint.sh) 中の環境変数を設定する。
環境変数名 値
UNAME www
UID 2000
GID 2000
-v : ホストOSの /home/docker/httpd193 が Container の /mnt/hostos にマウントされる。
マウントポイント
ホストOS ゲストOS
/home/docker/hhtpd /mnt/hostos
使用する Docker Image は ubuntu24_sshd_https
Container を起動した対話環境が、そのままContainer 内で動作する bash との対話環境になる。root権限でloginした状態である。
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) が動く
直ちに ユーザ www のパスワードを変更する。
# passwd www
New password: 新しいパスワード ← 新しいパスワードを入力する(エコーバックされない)
Retype new password: 新しいパスワード ← もう一度新しいパスワードを入力する(エコーバックされない)
netstat コマンドを用いて、ルーティング情報を調べる。
→
Container が接続しているネットワークは 192.168.12.0/24で、
デフォルトのルーティング先が 192.168.12.1 であることがわかる
$ 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
ifconfig でContainer のIPアドレスを調べる。
→ 192.168.12.193 であることがわかる。
$ 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
firewall の状態を調べて、ssh (=22), http (=80), https (=443) のポートを開ける。
# 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
ネットワーク上の他のマシンから、ssh接続できることを確認する。
sshで
$ ssh www@192.168.12.193
[注意] パスワードを迅速に変更しておくこと。
ネットワーク上の他のマシンから httpd 接続できることを確認する。
ブラウザで http://192.168.12.193/ にアクセスする
httpsを使えるように設定する
証明書を発行する
ルータを使って外部ネットワークと切り分けている場合は、ルータのポートフォワーディング機能を用いて
80番ポートと 443番ポートへのアクセスが、apache2 サーバに転送されるように設定しておく。
certbot をインストールする ← これは Dockerfile の中でやってあるはず。
# apt -y install certbot
certbot のパラメータ
--webroot でWebサーバの公開ディレクトリ配下を認証用に一時領域に使う
-w DocumentRoot
-d 証明書を取得する対象の FQDN (= Fully Qualified Domain Name)
certbot を使って、証明書を発行する。下の例は、自分のWWWサーバに対して example.com というドメインが登録してあり、WWWの管理者が root@example.com の場合である。適切な名前に変更すること。
# 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
証明書を自動的に更新する設定を行う。
証明書の更新手順が通常とは異なるので注意すること。
docker container ではsystemd が動作していないので systemctl が使えない。
そのため、cron を使って certbot を定期的に実行する。
cron はインストールされているはず。
# 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
[Optional] Editor をインストールして環境変数を設定する。
# apt install -y vim
$ export EDITOR=vi
certbot renew を crontab に登録する
$ crontab -e
以下を追加する。毎日 2:00 に更新をチェックする。証明書が更新されたときは apache2 を再起動する。
この Container では apache2 を supervisord 経由で起動しているので、
apache2 の再起動に systemctl や apachectl は使えない。
supervisorctl を使う。
0 2 * * * certbot renew --quiet --deploy-hook "supervisorctl restart php-fpm apache2"
apache2 の設定を変更する
apache2 にsslモジュールを追加する
# 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
/etc/apache2/sites-available/default-ssl.conf が生成されるので編集する。
/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
SSLを有効化する
/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
SSLを有効化する
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
apache2 を再起動する
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
ネットワーク上の他のマシンからブラウザで https 接続してみる。
URL: https://example.com
Redirect
rewrite モジュールをインストールする
sudo a2enmod rewrite
https でのアクセスを https に転送する
/etc/apache2/sites-available/000-default.conf
の中の
の間に次の記述を追加する
Redirect permanent / https://ynitta.net/
以下の記述も変更しておくとよい。
ServerAdmin y7anitta@gmail.com
https://ynitta.net/class/ のアクセスを https://ynitta.com/class/ に転送する
/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 にする
設定ファイルを作成する。
/etc/apache2/conf-available/charset.conf
AddDefaultCharset UTF-8
設定を有効化する
sudo a2enconf charset
これにより、
/etc/apache2/conf-available/charset.conf から
/etc/apache2/conf-enabled/charset.conf にシンボリックリングを張る。
apache2 を再起動する
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 を次のように
変更して、パスワードによるアクセスを禁止した方がよい。
アクセスする外部のマシンで公開暗号鍵を作成する。
sudo ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -C "USER@MACHINE"
外部のマシンの~/.ssh/id_ed25519.pub の内容を、このマシンの ~/.ssh/authorization_keys に追加する。
sshdサーバへのパスワードによるログインを禁止する設定。
/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
sshd サーバを再起動する。
sudo supervisorctl restart sshd
他のマシンからパスフレーズを用いて ssh アクセスする。
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