Skip to content

Apache

Apache HTTP Server chart for Kubernetes using the official docker.io/library/httpd image. The chart is designed for static sites, reverse-proxy front doors, and internal web endpoints that need a small, hardened web server with clear Kubernetes integration points.

Key Features

  • Official httpd image pinned to Apache HTTP Server 2.4.68
  • Non-root runtime on port 8080 with a read-only root filesystem
  • Generated Apache configuration for security headers, health checks, logging, and static content
  • Inline content, existing ConfigMap content, and extra virtual host snippets
  • Ingress and Gateway API routing with separate value contracts
  • Optional Basic Auth from an existing Secret or External Secrets Operator
  • Apache exporter sidecar, ServiceMonitor, HPA, PDB, NetworkPolicy, and dual-stack Services
  • Helm tests that verify the /healthz endpoint through the Service

Installation

Install from the HelmForge HTTPS repository:

helm repo add helmforge https://repo.helmforge.dev
helm repo update
helm install apache helmforge/apache --namespace apache --create-namespace

Install from OCI:

helm install apache oci://ghcr.io/helmforgedev/helm/apache \
  --namespace apache \
  --create-namespace

Architecture

The chart runs Apache HTTP Server as a Deployment. Apache listens on a non-root container port, serves content from a ConfigMap-backed document root, writes logs to stdout and stderr, and exposes /healthz for probes and Helm tests.

Typical traffic flow:

  1. Client traffic enters through Ingress, Gateway API, or the cluster Service.
  2. The Service forwards traffic to Apache pods on port 8080.
  3. Apache serves chart-managed static content, a user-managed ConfigMap, or custom virtual host snippets.
  4. Optional Basic Auth reads htpasswd material from a Secret.
  5. Optional metrics scrape the exporter sidecar, which reads Apache mod_status.

The chart intentionally does not install a certificate manager, ingress controller, Gateway implementation, WAF, content build system, PHP runtime, or external synchronization agent.

Differentiators

The Apache chart is useful when you need a secure web server primitive rather than a full application platform:

  • It uses the official Apache image without wrapping it in a custom runtime.
  • It defaults to a non-root, read-only filesystem posture while keeping the required Apache write paths explicit.
  • It treats static content as a deployable artifact through ConfigMap names, which fits GitOps rollouts.
  • It can expose the same workload through Ingress or Gateway API without changing application pods.
  • It keeps Basic Auth as a Kubernetes Secret concern and integrates with External Secrets Operator for provider-backed secrets.
  • It includes NetworkPolicy and Service dual-stack fields for platform teams that enforce network boundaries centrally.

Quick Start

Deploy a small static page from inline values:

content:
  files:
    index.html: |
      <!doctype html>
      <html lang="en">
      <body>
        <h1>Hello from Apache</h1>
      </body>
      </html>

Validate the deployment:

helm test apache -n apache
kubectl port-forward svc/apache -n apache 8080:80
curl -fsS http://localhost:8080/healthz

Production Pattern

For production, keep web content in an immutable ConfigMap that is created by your release pipeline. Roll the Helm release by changing the ConfigMap name.

replicaCount: 3

content:
  existingConfigMap: apache-site-content-20260613

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 1
    memory: 512Mi

pdb:
  enabled: true
  minAvailable: 1

networkPolicy:
  enabled: true
  ingress:
    enabled: false
  egress:
    enabled: true
    allowDns: true
    allowInternet: false
    extraEgress:
      - to:
          - ipBlock:
              cidr: 10.0.0.0/8
        ports:
          - protocol: TCP
            port: 443

Use immutable content names instead of mutating a live ConfigMap. That keeps rollbacks deterministic and avoids confusing pod checksums.

Routing

Ingress

Ingress uses the HelmForge-standard ingress.ingressClassName key:

ingress:
  enabled: true
  ingressClassName: nginx
  hosts:
    - host: apache.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: apache-tls
      hosts:
        - apache.example.com

Gateway API

Gateway API renders an HTTPRoute. The chart points route backends to the Apache Service automatically.

gateway:
  enabled: true
  parentRefs:
    - name: public-gateway
      namespace: gateway-system
  hostnames:
    - apache.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /

Gateway API requires Gateway API CRDs and a compatible controller in the cluster. See the official Gateway API documentation.

Dual-Stack Services

Dual-stack fields are optional and map directly to Kubernetes Service fields:

service:
  ipFamilyPolicy: PreferDualStack
  ipFamilies:
    - IPv4
    - IPv6

Use SingleStack with one family when validating on IPv4-only local clusters.

Authentication And External Secrets

Basic Auth expects an htpasswd file from a Secret:

basicAuth:
  enabled: true
  existingSecret: apache-basicauth
  htpasswdKey: htpasswd

For GitOps installations, let External Secrets Operator reconcile that Secret:

basicAuth:
  enabled: true
  existingSecret: apache-basicauth

externalSecrets:
  enabled: true
  secretStoreRef:
    name: cluster-secrets
    kind: ClusterSecretStore
  data:
    - secretKey: htpasswd
      remoteRef:
        key: apache/basicauth
        property: htpasswd

The chart fails template rendering when ExternalSecret is enabled without data or dataFrom. See the official External Secrets Operator documentation.

Observability

Enable the exporter only when Apache mod_status is explicitly allowed for the scrape path:

metrics:
  enabled: true
  serviceMonitor:
    enabled: true
    labels:
      release: prometheus

serverStatus:
  enabled: true
  require: 'local'

In production, keep mod_status local to the pod and let the exporter scrape it from the sidecar path. Do not expose the status endpoint to general client traffic.

Network Policy

NetworkPolicy is opt-in because enforcement depends on the cluster CNI:

networkPolicy:
  enabled: true
  ingress:
    enabled: true
    namespaceSelector:
      kubernetes.io/metadata.name: ingress-nginx
  egress:
    enabled: true
    allowDns: true
    allowInternet: false

Set networkPolicy.egress.allowInternet=true only when Apache needs outbound access for reverse proxy targets or remote content integrations. Use networkPolicy.egress.extraEgress for complete additional egress rules with to and ports.

Configuration Reference

Core

Parameter Default Description
replicaCount 2 Apache pod count when HPA is disabled.
nameOverride "" Chart name override.
fullnameOverride "" Full release name override.
commonLabels {} Labels added to chart resources.
serverName localhost Apache ServerName value.
image.repository docker.io/library/httpd Official Apache HTTP Server image.
image.tag 2.4.68 Apache image tag.
image.pullPolicy IfNotPresent Image pull policy.
imagePullSecrets [] Image pull secrets.
containerPorts.http 8080 Non-root Apache listener port.
containerPorts.metrics 9117 Exporter sidecar port.

Apache Configuration

Parameter Default Description
httpd.serverTokens Prod Apache ServerTokens value.
httpd.serverSignature Off Apache ServerSignature value.
httpd.traceEnable Off Apache TraceEnable value.
httpd.logLevel warn Apache log level.
httpd.allowOverride None Directory AllowOverride setting.
httpd.options -Indexes +FollowSymLinks Directory Options setting.
httpd.extraConfig "" Extra snippets appended to httpd.conf.
httpd.extraVhosts {} Additional virtual host snippets.

Content

Parameter Default Description
content.existingConfigMap "" Existing ConfigMap containing web root files.
content.files sample index.html Files rendered into the chart-managed content ConfigMap.

Authentication And Secrets

Parameter Default Description
basicAuth.enabled false Enable Basic Auth using htpasswd data.
basicAuth.existingSecret "" Secret containing htpasswd data.
basicAuth.htpasswdKey htpasswd Secret key for the htpasswd file.
externalSecrets.enabled false Render an ExternalSecret for Basic Auth material.
externalSecrets.refreshInterval 0 ExternalSecret refresh interval.
externalSecrets.secretStoreRef.name "" SecretStore or ClusterSecretStore name.
externalSecrets.secretStoreRef.kind SecretStore Secret store kind.
externalSecrets.target.creationPolicy Owner ExternalSecret target creation policy.
externalSecrets.data [] Individual provider key mappings.
externalSecrets.dataFrom [] Provider extraction blocks.

Service And Routing

Parameter Default Description
service.type ClusterIP Kubernetes Service type.
service.annotations {} Service annotations.
service.port 80 Public HTTP Service port.
service.metricsPort 9117 Metrics Service port.
service.ipFamilyPolicy null Optional Service IP family policy.
service.ipFamilies [] Optional Service IP families.
ingress.enabled false Render an Ingress.
ingress.ingressClassName "" IngressClass name.
ingress.annotations {} Ingress annotations.
ingress.hosts apache.local Ingress host and path rules.
ingress.tls [] Ingress TLS entries.
gateway.enabled false Render a Gateway API HTTPRoute.
gateway.apiVersion gateway.networking.k8s.io/v1 HTTPRoute API version.
gateway.parentRefs [] Gateway parent references.
gateway.hostnames [] HTTPRoute hostnames.
gateway.rules path prefix / HTTPRoute match rules.

Network Policy

Parameter Default Description
networkPolicy.enabled false Render NetworkPolicy resources.
networkPolicy.ingress.enabled true Restrict inbound traffic when policy is enabled.
networkPolicy.ingress.namespaceSelector {} Allowed namespace selector.
networkPolicy.ingress.podSelector {} Allowed pod selector.
networkPolicy.egress.enabled true Restrict outbound traffic when policy is enabled.
networkPolicy.egress.allowDns true Allow DNS egress.
networkPolicy.egress.allowInternet true Allow IPv4 and IPv6 internet egress.
networkPolicy.egress.extraRules [] Legacy additional egress rules.
networkPolicy.egress.extraEgress [] Additional complete egress rule objects.

Probes, Resources, And Scheduling

Parameter Default Description
livenessProbe.* see values Apache liveness probe timings.
readinessProbe.* see values Apache readiness probe timings.
startupProbe.* see values Apache startup probe timings.
resources.requests.cpu 50m Apache CPU request.
resources.requests.memory 64Mi Apache memory request.
resources.limits.cpu 500m Apache CPU limit.
resources.limits.memory 256Mi Apache memory limit.
podSecurityContext non-root fsGroup + seccomp Pod-level security context.
securityContext non-root, no privilege escalation Container-level security context.
nodeSelector {} Node selector.
tolerations [] Pod tolerations.
affinity {} Pod affinity.
topologySpreadConstraints [] Pod topology spread constraints.
priorityClassName "" PriorityClass name.
terminationGracePeriodSeconds 30 Pod termination grace period.

Availability And Metrics

Parameter Default Description
pdb.enabled false Render a PodDisruptionBudget.
pdb.minAvailable 1 Minimum available pods.
autoscaling.enabled false Render an HPA.
autoscaling.minReplicas 2 HPA minimum replicas.
autoscaling.maxReplicas 10 HPA maximum replicas.
autoscaling.targetCPUUtilizationPercentage 80 HPA CPU target.
metrics.enabled false Enable Apache exporter sidecar.
metrics.image.repository docker.io/lusotycoon/apache-exporter Exporter image repository.
metrics.image.tag v1.0.11 Exporter image tag.
metrics.resources small defaults Exporter resources.
metrics.serviceMonitor.enabled false Render a ServiceMonitor.
metrics.serviceMonitor.interval 30s Scrape interval.
metrics.serviceMonitor.labels {} ServiceMonitor labels.
serverStatus.enabled false Enable Apache mod_status config.
serverStatus.path /server-status Status endpoint path.
serverStatus.require local Apache Require expression for status access.

Extension Points

Parameter Default Description
serviceAccount.create true Create a dedicated ServiceAccount.
serviceAccount.name "" ServiceAccount name override.
serviceAccount.annotations {} ServiceAccount annotations.
podLabels {} Additional pod labels.
podAnnotations {} Additional pod annotations.
annotations {} Additional resource annotations.
extraEnv [] Additional Apache container environment variables.
extraVolumes [] Additional pod volumes.
extraVolumeMounts [] Additional Apache volume mounts.
extraManifests [] Additional manifests rendered verbatim.

Examples

Common Issues

Symptom Likely Cause Fix
/healthz returns 404 Custom Apache config no longer serves the generated health file Preserve the generated health alias or update probe paths.
403 from /server-status serverStatus.require blocks the exporter Permit the exporter path or disable metrics.
Basic Auth is ignored Secret key does not match basicAuth.htpasswdKey Check Secret data keys and ExternalSecret target keys.
Gateway route has no traffic parentRefs or listener hostnames do not match the Gateway Check Gateway readiness and HTTPRoute attachment status.
NetworkPolicy blocks traffic Namespace or pod selectors do not match callers Adjust selectors or disable the policy until the CNI rules are verified.
Content does not change Existing ConfigMap name did not change Publish a new immutable ConfigMap and update content.existingConfigMap.

Validation

After deployment:

helm test apache -n apache
kubectl get pods -n apache -l app.kubernetes.io/name=apache
kubectl rollout status deployment/apache -n apache
kubectl logs -n apache deploy/apache --all-containers --since=10m
kubectl get events -n apache --sort-by=.lastTimestamp