From fde0d4b6b053c5026dde0f49a9241a7b272c7696 Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Thu, 19 Feb 2026 10:19:03 +0900 Subject: [PATCH 1/4] feat: Add utility targets for updating DNS and TLS certificate --- Makefile | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 531513b..1f71807 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ MAKEFILE_DIR=$(abspath $(dir $(lastword $(MAKEFILE_LIST)))) -export BASE_SITE_PATH:=${MAKEFILE_DIR}/site export DOCKER:=docker export DOCKER_COMPOSE:=${shell ${DOCKER} compose >/dev/null 2>&1 && echo 'docker compose' || echo 'docker-compose'} +AWS_CLI:=docker run --rm amazon/aws-cli + +export BASE_SITE_PATH:=${MAKEFILE_DIR}/site export DOCKER_COMPOSE_YAML_MIDDLEWARES:=-f ./mt/mysql.yml -f ./mt/memcached.yml export UP_ARGS:=-d export MT_HOME_PATH:=${MAKEFILE_DIR}/../movabletype @@ -57,6 +59,7 @@ export MT_UID export MAILPIT_EXPOSE_PORT export PLACKUP export CMD +export EDGE_FQDN # mt-watcher container export DISABLE_MT_WATCHER @@ -268,3 +271,48 @@ code-cpanm-install: code-init code-open-workspace: code-cpanm-install code-generate-workspace code ${CODE_CODE_WORKSPACE_FILE} + +# utilities +update-site-dns: + @if [ -z "${EDGE_FQDN}" ]; then \ + echo "EDGE_FQDN is not set. Skipping DNS update."; \ + exit 0; \ + fi; + + @zone_name=$$(echo ${EDGE_FQDN} | perl -pe 's/^[^.]+\.//'); \ + zone_id=$$(${AWS_CLI} route53 list-hosted-zones-by-name --dns-name $$zone_name --query 'HostedZones[0].Id' --output text); \ + echo "EDGE_FQDN: ${EDGE_FQDN}"; \ + echo "zone_id: $$zone_id"; \ + printf "Are you sure you want to proceed? yes/no: "; \ + read answer; \ + if [ "$$answer" != "yes" ]; then \ + echo "Canceled DNS update."; \ + exit 0; \ + fi; \ + public_ip=$$(curl -s http://checkip.amazonaws.com | tr -d '\n'); \ + change_batch=$$(printf '{"Changes":[{"Action":"UPSERT","ResourceRecordSet":{"Name":"%s","Type":"A","TTL":300,"ResourceRecords":[{"Value":"%s"}]}}]}' "${EDGE_FQDN}" "$$public_ip"); \ + change_id=$$(${AWS_CLI} route53 change-resource-record-sets --hosted-zone-id $$zone_id --change-batch "$$change_batch" --query 'ChangeInfo.Id' --output text); \ + status=$$(${AWS_CLI} route53 get-change --id $$change_id --query 'ChangeInfo.Status' --output text); \ + while [ "$$status" = "PENDING" ]; do \ + echo "Route53 change is $$status: $$change_id"; \ + sleep 5; \ + status=$$(${AWS_CLI} route53 get-change --id $$change_id --query 'ChangeInfo.Status' --output text); \ + done; \ + echo "Route53 change status is $$status: $$change_id" + +update-site-certificate: down + @if [ -z "${LETSENCRYPT_EMAIL}" -o -z "${EDGE_FQDN}" ]; then \ + echo "LETSENCRYPT_EMAIL or EDGE_FQDN is not set. Skipping certificate update."; \ + exit 0; \ + fi; + + @cert_dir="${MAKEFILE_DIR}/ssl/certificates"; \ + lego_cmd="docker run --rm -v ${MAKEFILE_DIR}/ssl:/etc/lego -u `id -u`:`id -g` -p 80:80 xenolf/lego --path /etc/lego --accept-tos -m ${LETSENCRYPT_EMAIL} -d ${EDGE_FQDN} --http"; \ + if [ -f "$$cert_dir/${EDGE_FQDN}.crt" ]; then \ + $$lego_cmd renew --days 30; \ + else \ + $$lego_cmd run; \ + fi; \ + cp "$$cert_dir/${EDGE_FQDN}.key" "$$cert_dir/server.key"; \ + cp "$$cert_dir/${EDGE_FQDN}.issuer.crt" "$$cert_dir/chain.crt"; \ + cat "$$cert_dir/${EDGE_FQDN}.crt" "$$cert_dir/${EDGE_FQDN}.issuer.crt" > "$$cert_dir/server.crt" From 6c1b71c5f31d29d920a1a8986298b196fbecfeea Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Thu, 19 Feb 2026 10:29:33 +0900 Subject: [PATCH 2/4] feat: Run TLS termination proxy in mt-dev if EDGE_FQDN is set --- Makefile | 25 ++++++++++++++++++++----- mt/edge.conf | 20 ++++++++++++++++++++ mt/edge.yml | 11 +++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 mt/edge.conf create mode 100644 mt/edge.yml diff --git a/Makefile b/Makefile index 1f71807..a0f26ee 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ export UP_ARGS:=-d export MT_HOME_PATH:=${MAKEFILE_DIR}/../movabletype export HTTPD_HOST_NAME:=localhost export HTTPD_EXPOSE_PORT:=80 +export EDGE_EXPOSE_PORT:=443 export UPDATE_BRANCH:=yes export UPDATE_DOCKER_IMAGE:=yes export CREATE_DATABASE_IF_NOT_EXISTS:=yes @@ -46,6 +47,7 @@ export DOCKER_NODEJS_IMAGE export DOCKER_HTTPD_BUILD_CONTEXT export DOCKER_HTTPD_DOCKERFILE export DOCKER_HTTPD_IMAGE +export DOCKER_EDGE_IMAGE export DOCKER_MYSQL_IMAGE export DOCKER_MYSQL_COMMAND export DOCKER_MEMCACHED_IMAGE @@ -59,7 +61,8 @@ export MT_UID export MAILPIT_EXPOSE_PORT export PLACKUP export CMD -export EDGE_FQDN +export EDGE_CERT_FILE +export EDGE_KEY_FILE # mt-watcher container export DISABLE_MT_WATCHER @@ -84,7 +87,20 @@ ifeq ($(wildcard ${MT_CONFIG_CGI_SRC_PATH}),) $(error You should create ${MT_CONFIG_CGI_SRC_PATH} first.) endif -_DC=${DOCKER_COMPOSE} -f ./mt/common.yml ${DOCKER_COMPOSE_YAML_MIDDLEWARES} ${_DC_YAML_OVERRIDE} ${DOCKER_COMPOSE_YAML_EXPOSE} ${DOCKER_COMPOSE_USER_YAML} +ifneq (${EDGE_FQDN},) +EDGE_CERT_FILE=ssl/certificates/server.crt +EDGE_KEY_FILE=ssl/certificates/server.key +endif + +ifneq (${EDGE_CERT_FILE},) +ifneq (${EDGE_KEY_FILE},) +export DOCKER_COMPOSE_YAML_EDGE=-f ./mt/edge.yml +export EDGE_CERT_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_CERT_FILE}" =~ m{/} ? "${EDGE_CERT_FILE}" : "${MAKEFILE_DIR}/${EDGE_CERT_FILE}")' } +export EDGE_KEY_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_KEY_FILE}" =~ m{/} ? "${EDGE_KEY_FILE}" : "${MAKEFILE_DIR}/${EDGE_KEY_FILE}")' } +endif +endif + +_DC=${DOCKER_COMPOSE} -f ./mt/common.yml ${DOCKER_COMPOSE_YAML_MIDDLEWARES} ${DOCKER_COMPOSE_YAML_EDGE} ${_DC_YAML_OVERRIDE} ${DOCKER_COMPOSE_YAML_EXPOSE} ${DOCKER_COMPOSE_USER_YAML} _DATABASE=${shell perl -ne 'print $$1 if /^Database\s+([\w-]+)/' < ${MT_CONFIG_CGI_SRC_PATH}} .PHONY: db up down @@ -313,6 +329,5 @@ update-site-certificate: down else \ $$lego_cmd run; \ fi; \ - cp "$$cert_dir/${EDGE_FQDN}.key" "$$cert_dir/server.key"; \ - cp "$$cert_dir/${EDGE_FQDN}.issuer.crt" "$$cert_dir/chain.crt"; \ - cat "$$cert_dir/${EDGE_FQDN}.crt" "$$cert_dir/${EDGE_FQDN}.issuer.crt" > "$$cert_dir/server.crt" + cp "$$cert_dir/${EDGE_FQDN}.key" "${EDGE_KEY_FILE_SRC_PATH}"; \ + cat "$$cert_dir/${EDGE_FQDN}.crt" "$$cert_dir/${EDGE_FQDN}.issuer.crt" > "${EDGE_CERT_FILE_SRC_PATH}" diff --git a/mt/edge.conf b/mt/edge.conf new file mode 100644 index 0000000..d05d36e --- /dev/null +++ b/mt/edge.conf @@ -0,0 +1,20 @@ +server { + listen 443 ssl; + server_name _; + ssl_certificate /etc/nginx/certificates/server.crt; + ssl_certificate_key /etc/nginx/certificates/server.key; + client_max_body_size 0; + + location / { + proxy_pass http://httpd:80; + proxy_connect_timeout 300s; + proxy_send_timeout 3600s; + proxy_read_timeout 3600s; + proxy_request_buffering off; + proxy_buffering off; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } +} diff --git a/mt/edge.yml b/mt/edge.yml new file mode 100644 index 0000000..f1b7fae --- /dev/null +++ b/mt/edge.yml @@ -0,0 +1,11 @@ +# TLS termination proxy for mt and httpd +services: + edge: + image: ${DOCKER_EDGE_IMAGE:-nginx:latest} + restart: always + ports: + - "${EDGE_EXPOSE_PORT:-443}:443" + volumes: + - "./edge/default.conf:/etc/nginx/conf.d/default.conf:ro" + - "${EDGE_CERT_FILE_SRC_PATH}:/etc/nginx/certificates/server.crt:ro" + - "${EDGE_KEY_FILE_SRC_PATH}:/etc/nginx/certificates/server.key:ro" From 4e22711dc7565b79810aa808e98fc05c677d4378 Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Thu, 19 Feb 2026 11:47:36 +0900 Subject: [PATCH 3/4] feat: Enable to apply basic auth to edge proxy --- Makefile | 5 +++++ mt/edge.yml | 2 ++ mt/edge/auth-user.conf | 2 ++ mt/{edge.conf => edge/default.conf} | 2 ++ 4 files changed, 11 insertions(+) create mode 100644 mt/edge/auth-user.conf rename mt/{edge.conf => edge/default.conf} (93%) diff --git a/Makefile b/Makefile index a0f26ee..08f301c 100644 --- a/Makefile +++ b/Makefile @@ -100,6 +100,11 @@ export EDGE_KEY_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_KEY_FILE}" =~ m{/} endif endif +ifneq (${EDGE_AUTH_USER_FILE},) +export EDGE_AUTH_USER_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_AUTH_USER_FILE}" =~ m{/} ? "${EDGE_AUTH_USER_FILE}" : "${MAKEFILE_DIR}/${EDGE_AUTH_USER_FILE}")' } +export EDGE_AUTH_USER_CONF_DEST_PATH=/etc/nginx/server-conf.d/auth-user.conf +endif + _DC=${DOCKER_COMPOSE} -f ./mt/common.yml ${DOCKER_COMPOSE_YAML_MIDDLEWARES} ${DOCKER_COMPOSE_YAML_EDGE} ${_DC_YAML_OVERRIDE} ${DOCKER_COMPOSE_YAML_EXPOSE} ${DOCKER_COMPOSE_USER_YAML} _DATABASE=${shell perl -ne 'print $$1 if /^Database\s+([\w-]+)/' < ${MT_CONFIG_CGI_SRC_PATH}} diff --git a/mt/edge.yml b/mt/edge.yml index f1b7fae..b1e14de 100644 --- a/mt/edge.yml +++ b/mt/edge.yml @@ -9,3 +9,5 @@ services: - "./edge/default.conf:/etc/nginx/conf.d/default.conf:ro" - "${EDGE_CERT_FILE_SRC_PATH}:/etc/nginx/certificates/server.crt:ro" - "${EDGE_KEY_FILE_SRC_PATH}:/etc/nginx/certificates/server.key:ro" + - "${EDGE_AUTH_USER_FILE_SRC_PATH:-/dev/null}:/etc/nginx/.htpasswd:ro" + - "./edge/auth-user.conf:${EDGE_AUTH_USER_CONF_DEST_PATH:-/tmp/no-edge-auth}:ro" diff --git a/mt/edge/auth-user.conf b/mt/edge/auth-user.conf new file mode 100644 index 0000000..edcd297 --- /dev/null +++ b/mt/edge/auth-user.conf @@ -0,0 +1,2 @@ +auth_basic "Restricted"; +auth_basic_user_file /etc/nginx/.htpasswd; diff --git a/mt/edge.conf b/mt/edge/default.conf similarity index 93% rename from mt/edge.conf rename to mt/edge/default.conf index d05d36e..be21fcd 100644 --- a/mt/edge.conf +++ b/mt/edge/default.conf @@ -5,6 +5,8 @@ server { ssl_certificate_key /etc/nginx/certificates/server.key; client_max_body_size 0; + include /etc/nginx/server-conf.d/*.conf; + location / { proxy_pass http://httpd:80; proxy_connect_timeout 300s; From 83b936fde0a8c7f019fa1cc5163e8559f2752df1 Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Thu, 19 Feb 2026 17:54:32 +0900 Subject: [PATCH 4/4] fix: review path normalization routines --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 08f301c..4229447 100644 --- a/Makefile +++ b/Makefile @@ -76,7 +76,7 @@ ENV_FILE=.env # setup internal variables -MT_CONFIG_CGI_SRC_PATH=${shell perl -e 'print("${MT_CONFIG_CGI}" =~ m{/} ? "${MT_CONFIG_CGI}" : "${MAKEFILE_DIR}/${MT_CONFIG_CGI}")' } +MT_CONFIG_CGI_SRC_PATH=${shell perl -e 'print("${MT_CONFIG_CGI}" =~ m{^/} ? "${MT_CONFIG_CGI}" : "${MAKEFILE_DIR}/${MT_CONFIG_CGI}")' } export MT_CONFIG_CGI_SRC_PATH ifneq (${WITHOUT_MT_CONFIG_CGI},) @@ -95,13 +95,13 @@ endif ifneq (${EDGE_CERT_FILE},) ifneq (${EDGE_KEY_FILE},) export DOCKER_COMPOSE_YAML_EDGE=-f ./mt/edge.yml -export EDGE_CERT_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_CERT_FILE}" =~ m{/} ? "${EDGE_CERT_FILE}" : "${MAKEFILE_DIR}/${EDGE_CERT_FILE}")' } -export EDGE_KEY_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_KEY_FILE}" =~ m{/} ? "${EDGE_KEY_FILE}" : "${MAKEFILE_DIR}/${EDGE_KEY_FILE}")' } +export EDGE_CERT_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_CERT_FILE}" =~ m{^/} ? "${EDGE_CERT_FILE}" : "${MAKEFILE_DIR}/${EDGE_CERT_FILE}")' } +export EDGE_KEY_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_KEY_FILE}" =~ m{^/} ? "${EDGE_KEY_FILE}" : "${MAKEFILE_DIR}/${EDGE_KEY_FILE}")' } endif endif ifneq (${EDGE_AUTH_USER_FILE},) -export EDGE_AUTH_USER_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_AUTH_USER_FILE}" =~ m{/} ? "${EDGE_AUTH_USER_FILE}" : "${MAKEFILE_DIR}/${EDGE_AUTH_USER_FILE}")' } +export EDGE_AUTH_USER_FILE_SRC_PATH=${shell perl -e 'print("${EDGE_AUTH_USER_FILE}" =~ m{^/} ? "${EDGE_AUTH_USER_FILE}" : "${MAKEFILE_DIR}/${EDGE_AUTH_USER_FILE}")' } export EDGE_AUTH_USER_CONF_DEST_PATH=/etc/nginx/server-conf.d/auth-user.conf endif