Skip to content

Restore HTTP access logging on the minimal image's :443 vhost - #155

Merged
jsokol merged 1 commit into
masterfrom
FIX-apache-access-logging
Aug 13, 2026
Merged

Restore HTTP access logging on the minimal image's :443 vhost#155
jsokol merged 1 commit into
masterfrom
FIX-apache-access-logging

Conversation

@jsokol

@jsokol jsokol commented Aug 13, 2026

Copy link
Copy Markdown
Member

The bug

An Apache CustomLog inside a vhost replaces the one inherited from the server config. default-ssl.conf declared only ssl_request_log, so conf-enabled/other-vhosts-access-log.conf never applied to :443 — and since the ALB speaks only to :443, the :80 vhost's access.log stayed empty too.

Net effect: no HTTP access logging anywhere for a dedicated-hosting customer.

ssl_request_log was the only record of a request, and it's a poor one:

[13/Aug/2026:17:29:01 +0000] 10.120.0.74 TLSv1.3 TLS_AES_256_GCM_SHA384 "GET / HTTP/1.1" 1925

10.120.0.74 is the load balancer, not the caller. No status code, no referer, no user agent. And nothing ships it off the container — it's a real file on the ephemeral /var/log volume, so it dies with the task.

How it hid

Found while verifying demo's migration: a probe request couldn't be located in CloudWatch at all.

The log-tailer sidecar in simplerisk-customers-cdk appears to cover this — it tails /var/log/apache2/access.log. It can't. That path is a symlink to /dev/stdout in the php:apache base image, and /dev/stdout is a write end, so the tail reads nothing forever. The sidecar entry looked like coverage while providing none.

The fix

A combined-format CustomLog to access.log, which reaches the container's stdout and therefore the awslogs driver — the Docker-native path, needing no sidecar entry.

Client identity comes from X-Forwarded-For since %h is the load balancer. The whole header is logged deliberately: the ALB appends the true peer as the last element, so only the last one is trustworthy, and keeping the chain visible beats hiding a forged prefix behind a single value. (mod_remoteip would be the alternative, but it needs a trusted-proxy range that varies per region, and misconfiguring it makes spoofing win silently.)

ssl_request_log is kept for the TLS protocol/cipher detail the combined format doesn't carry.

Verification

Built the image and ran apache2ctl -tSyntax OK. Requests through the vhost emit on stdout:

203.0.113.9  - - [13/Aug/2026:17:35:15 +0000] "GET /?abuse-probe HTTP/1.1"      200 4031 "-" "curl/8.7.1"
198.51.100.4 - - [13/Aug/2026:17:35:15 +0000] "GET /nonexistent-page HTTP/1.1"  404  298 "-" "curl/8.7.1"

Including the 404 the previous configuration could not record at all.

An Apache CustomLog inside a vhost REPLACES the one inherited from the server
config. default-ssl.conf declared only ssl_request_log, so
conf-enabled/other-vhosts-access-log.conf never applied to :443 -- and since the
ALB speaks only to :443, the :80 vhost's access.log stayed empty too.

The result was no HTTP access logging anywhere for a dedicated-hosting customer.
ssl_request_log was the only record of a request, and it is a poor one: its %h is
the load balancer's private address rather than the caller, and its format carries
no status code, referer, or user agent. Nothing shipped it off the container
either -- it is a real file on the ephemeral /var/log volume, so it died with the
task.

Found while verifying demo's migration: a probe request could not be located in
CloudWatch at all. The log-tailer sidecar appears to cover this (it tails
/var/log/apache2/access.log) but cannot -- that path is a symlink to /dev/stdout
in the php:apache base image, and /dev/stdout is a write end, so the tail reads
nothing. The sidecar entry looked like coverage while providing none.

Adds a combined-format CustomLog to access.log, which reaches the container's
stdout and therefore the awslogs driver. Client identity comes from
X-Forwarded-For, since %h is the load balancer. The whole header is logged
deliberately: the ALB appends the true peer as the last element, so only the last
one is trustworthy, and keeping the chain visible beats hiding a forged prefix
behind a single value.

ssl_request_log is kept for the TLS protocol/cipher detail the combined format
does not carry.

Verified on a built image: `apache2ctl -t` reports Syntax OK, and requests through
the vhost emit, on stdout,

  203.0.113.9  ... "GET /?abuse-probe HTTP/1.1"     200 4031 "-" "curl/8.7.1"
  198.51.100.4 ... "GET /nonexistent-page HTTP/1.1" 404  298 "-" "curl/8.7.1"

including the 404 the previous configuration could not record.
@jsokol
jsokol merged commit b2adf5c into master Aug 13, 2026
5 checks passed
@jsokol
jsokol deleted the FIX-apache-access-logging branch August 13, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant