fix(paperless-ngx): egress names the Tika/Gotenberg POD ports, not the Service port
The rule allowed outbound 80, the port the apache-tika and gotenberg Services listen on, and justified it in a comment: an egress rule names the port on the destination as the client dials it, and the client dials the Service. That is wrong. kube-proxy does a ClusterIP Service's destination NAT BEFORE the egress policy is evaluated at the pod's network interface, so the policy sees podIP:targetPort and never clusterIP:port - and those two charts forward 80 to 9998 and 3000. Deployed as 14.0.0+up3.3.1 it cut Paperless off from both services on 2026-10-15: mail import, EML, HTML and Office documents stopped, plain PDFs and images kept working, and the error was httpx.ConnectTimeout with no mention of a NetworkPolicy. The rule now names 9998, 3000 and 80. The 80 stays because it costs nothing and covers a foreign Tika that really does listen on 80. The refuted sentence is quoted rather than deleted: it reads perfectly, which is how it survived review, and the timeout-not-refused symptom is written down with it. No policy switch of its own: the rule stays gated on paperless.files.tikaGotenberg.enabled, because a second value that can drift from the feature re-arms this very outage. New networkPolicy.egress.mailImport opens IMAPS 993, off by default - paperless' mail accounts are rows in its database, so the chart cannot derive the rule. Plain IMAP (143) and POP3 stay in extraPorts, and 993 is noted as a real destination port, because a mail server outside the cluster has no DNAT in the path. Minor: one additive value, and a fix that widens a rule. Nothing breaks, no value becomes required, appVersion unchanged. Part of #136
This commit is contained in:
5 files changed
+168
-43
No files matched your search
+48
-14
@@ -549,13 +549,28 @@ valkey:
|
||||
networkPolicy:
|
||||
# WHAT THIS POLICY ALLOWS: inbound 8000 only, and outbound DNS plus TCP 5432
|
||||
# (Postgres), 6379 (Redis/Valkey), 443, and - only while
|
||||
# paperless.files.tikaGotenberg.enabled is true - 80 for the Tika and
|
||||
# Gotenberg Services.
|
||||
# paperless.files.tikaGotenberg.enabled is true - 9998, 3000 and 80 for Tika
|
||||
# and Gotenberg.
|
||||
#
|
||||
# NOTE WHY THAT RULE SAYS 80 AND NOT 9998/3000: an egress rule names the port
|
||||
# on the DESTINATION as the client dials it, and paperless dials those
|
||||
# charts' SERVICES, which listen on 80 and forward to the containers' own
|
||||
# ports.
|
||||
# WHY THAT RULE NAMES 9998/3000 AND NOT JUST THE SERVICES' 80 (Gitea #136, an
|
||||
# outage on 2026-10-15). The note that used to stand here said:
|
||||
#
|
||||
# "an egress rule names the port on the DESTINATION as the client dials it,
|
||||
# and paperless dials those charts' SERVICES, which listen on 80 and
|
||||
# forward to the containers' own ports."
|
||||
#
|
||||
# That is wrong, and it is kept as a quotation because it sounds right - which
|
||||
# is why it was never checked. kube-proxy does the ClusterIP Service's
|
||||
# destination NAT BEFORE the egress policy is evaluated at the pod's network
|
||||
# interface, so the policy sees podIP:targetPort, never clusterIP:port. An
|
||||
# egress rule therefore names the POD port: 9998 for apache-tika, 3000 for
|
||||
# gotenberg, both read from those charts' containerPorts. The 80 stays because
|
||||
# it costs nothing and covers a foreign Tika that really does listen on 80.
|
||||
#
|
||||
# AND THE FAILURE MODE IS A TIMEOUT, NOT "connection refused": a missing
|
||||
# service refuses, a dropped packet runs into the timeout. 5432, 6379 and 443
|
||||
# were unaffected only because their Service port and pod port are the same
|
||||
# number.
|
||||
#
|
||||
# THREE THINGS IT DOES NOT COVER:
|
||||
# - The VALKEY SUBCHART'S POD. It carries its own labels, so this policy
|
||||
@@ -566,10 +581,10 @@ networkPolicy:
|
||||
# only because the job moves files between mounted volumes and the SMB
|
||||
# share arrives as a CSI volume mounted by the NODE - the pod opens no
|
||||
# connection of its own. If that changes, the CronJob needs labels first.
|
||||
# - MAIL FETCHING. Paperless' mail accounts are rows in its database,
|
||||
# configured in the web UI, so this chart cannot see them. A release that
|
||||
# fetches mail needs IMAP in egress.extraPorts, or a mail rule silently
|
||||
# stops importing.
|
||||
# - MAIL FETCHING, unless egress.mailImport is switched on. Paperless' mail
|
||||
# accounts are rows in its database, configured in the web UI, so this
|
||||
# chart cannot see them and cannot derive the rule. Left off on a release
|
||||
# that does fetch mail, a mail rule silently stops importing.
|
||||
#
|
||||
# And the usual two: 5432 and 6379 are the STANDARD ports rather than the
|
||||
# configured ones, and a policy is only a boundary where the CNI enforces
|
||||
@@ -622,6 +637,21 @@ networkPolicy:
|
||||
podLabels:
|
||||
app.kubernetes.io/name: rke2-traefik
|
||||
egress:
|
||||
# Outbound IMAPS (993) for paperless' mail import. OFF, and it has to be a
|
||||
# value rather than something the chart derives: the mail accounts are ROWS
|
||||
# IN THE DATABASE, entered in the web UI, so nothing in these values says
|
||||
# whether a release fetches mail. Switching this on is the operator saying
|
||||
# that it does.
|
||||
#
|
||||
# 993 ONLY, deliberately. Plain IMAP (143) and POP3 (110, 995) are not
|
||||
# covered - a value named mailImport that opened four ports would be wider
|
||||
# than its name - and belong in extraPorts below.
|
||||
#
|
||||
# NOTE THE DIFFERENCE FROM THE TIKA RULE: 993 is the real destination port,
|
||||
# because a mail server outside the cluster is reached with no Service and
|
||||
# so no destination NAT in the path. What decides whether an egress rule
|
||||
# needs the Service port or the pod port is that NAT, and nothing else.
|
||||
mailImport: false
|
||||
# Additional outbound TCP ports. DNS (UDP and TCP 53) is always allowed and
|
||||
# has no switch - a knob whose only other setting breaks every name lookup
|
||||
# in the pod is a trap, not a feature.
|
||||
@@ -632,8 +662,12 @@ networkPolicy:
|
||||
# permits its port to ANY destination. What the cap still buys is real: a
|
||||
# compromised pod cannot open arbitrary outbound connections.
|
||||
#
|
||||
# IMAP (993, or 143 for the plaintext case) is the entry this chart needs
|
||||
# most, for mail accounts configured in the web UI. Also a Postgres or
|
||||
# Redis on a non-standard port, or a Tika/Gotenberg addressed on its
|
||||
# container port (9998 / 3000) instead of through its Service.
|
||||
# PLAIN IMAP (143) and POP3 (110, 995) go here - IMAPS 993 has its own
|
||||
# switch above. Also a Postgres or Redis on a non-standard port, and a Tika
|
||||
# or Gotenberg that listens on neither its chart's container port nor 80.
|
||||
#
|
||||
# These are POD ports for anything inside the cluster, for the reason given
|
||||
# at the top of this block: a ClusterIP Service's port is translated away
|
||||
# before the policy sees the packet. For a destination outside the cluster
|
||||
# there is no translation and the port is simply the one being dialled.
|
||||
extraPorts: []
|
||||
Reference in new issue
Block a user