Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tiny-buckets-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#nops: Hard-set UID and GID when CHAINLINK_USER is non-root, and document container RootDir and safe volume mount conventions for operators.
7 changes: 6 additions & 1 deletion core/chainlink.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,12 @@ RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
&& apt-get update && apt-get install -y postgresql-client-17 \
&& rm -rf /var/lib/apt/lists/*

RUN if [ ${CHAINLINK_USER} != root ]; then useradd --uid 14933 --create-home ${CHAINLINK_USER}; fi
# Prod images (CHAINLINK_USER=chainlink) run as UID:GID 14933:14933 for deterministic
# ownership on bind mounts in Docker/Compose deployments without K8s securityContext overrides.
RUN if [ ${CHAINLINK_USER} != root ]; then \
groupadd --gid 14933 ${CHAINLINK_USER} && \
useradd --uid 14933 --gid 14933 --create-home ${CHAINLINK_USER}; \
fi
USER ${CHAINLINK_USER}

# Expose image metadata to the running node.
Expand Down
5 changes: 5 additions & 0 deletions core/config/docs/core.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ InsecureFastScrypt = false # Default
# Deprecated: no effect. Always enabled.
InsecurePPROFHeap = true # Default
# RootDir is the Chainlink node's root directory. This is the default directory for logging, database backups, cookies, and other misc Chainlink node files. Chainlink nodes will always ensure this directory has 700 permissions because it might contain sensitive data.
#
# Container deployments: official prod Docker images run as UID:GID 14933:14933 (user `chainlink`). Bind mounts must be owned 14933:14933, or use named volumes with an appropriate fsGroup in Kubernetes. A non-deterministic GID mismatch is a common cause of read/write errors on bind mounts in Docker/Compose.
# RootDir in containers: both '/home/chainlink' and '~/.chainlink' (which resolves to '/home/chainlink/.chainlink') are valid. Choose one and align any persistence mounts to that path. '/home/chainlink' is often preferred because '.chainlink' is hidden by default.
# Volume mounts: ensure you do not bind-mount over '/home/chainlink' — it replaces the entire home directory, hides image-created paths such as '.cache', and causes permission failures.
# Mount config and secrets at separate paths (e.g. '/run/secrets/config.toml', '/configs/...') and pass them via CLI flags ('-c', '-s', '-a', '-p'). Subdirectory mounts under home (e.g. '/home/chainlink/workflows') are acceptable when permissions match 14933:14933.
RootDir = '~/.chainlink' # Default
# ShutdownGracePeriod is the maximum time allowed to shut down gracefully. If exceeded, the node will terminate immediately to avoid being SIGKILLed.
ShutdownGracePeriod = '5s' # Default
Expand Down
8 changes: 8 additions & 0 deletions docs/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ RootDir = '~/.chainlink' # Default
```
RootDir is the Chainlink node's root directory. This is the default directory for logging, database backups, cookies, and other misc Chainlink node files. Chainlink nodes will always ensure this directory has 700 permissions because it might contain sensitive data.

Official prod Docker images run as UID:GID 14933:14933 (user `chainlink`). A non-deterministic GID mismatch is a common cause of read/write errors on bind mounts in Docker/Compose.

RootDir '/home/chainlink' and '~/.chainlink' (which resolves to
'/home/chainlink/.chainlink') are valid. Choose one and align any persistence mounts to that path. '/home/chainlink' is often preferred because '.chainlink' is hidden by default.

Do not bind-mount over '/home/chainlink' — it replaces the entire home directory and causes permission failures. Mount config and secrets at separate paths (e.g. '/run/secrets/config.toml', '/configs/...') and pass them via CLI flags
('-c', '-s', '-a', '-p').

### ShutdownGracePeriod
```toml
ShutdownGracePeriod = '5s' # Default
Expand Down
6 changes: 5 additions & 1 deletion plugins/chainlink.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ RUN curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc \
&& apt-get update && apt-get install -y postgresql-client-17 \
&& rm -rf /var/lib/apt/lists/*

RUN if [ ${CHAINLINK_USER} != root ]; then useradd --uid 14933 --create-home ${CHAINLINK_USER}; fi
# Prod images (CHAINLINK_USER=chainlink) run as UID:GID 14933:14933 for deterministic ownership.
RUN if [ ${CHAINLINK_USER} != root ]; then \
groupadd --gid 14933 ${CHAINLINK_USER} && \
useradd --uid 14933 --gid 14933 --create-home ${CHAINLINK_USER}; \
fi
USER ${CHAINLINK_USER}

# Expose image metadata to the running node.
Expand Down
Loading