Skip to content

Commit 5524443

Browse files
ppawlowskihardillb
andauthored
feat!: Run Device Agent in container as unpriviledged user (#565)
Co-authored-by: Ben Hardill <ben@flowforge.com>
1 parent 329e6aa commit 5524443

3 files changed

Lines changed: 50 additions & 5 deletions

File tree

.github/workflows/build.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ on:
66
paths-ignore:
77
- '.github/workflows/installer-build.yaml'
88
- 'installer/**'
9+
- 'docker/**'
10+
- '.github/workflows/docker-build.yaml'
911
pull_request:
1012
branches: [ main ]
1113
paths-ignore:
1214
- '.github/workflows/installer-build.yaml'
1315
- 'installer/**'
16+
- 'docker/**'
17+
- '.github/workflows/docker-build.yaml'
1418

1519
jobs:
1620
build:

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,38 @@ When running with the container you will need to mount the `device.yml` obtained
4444
docker run --mount type=bind,src=/path/to/device.yml,target=/opt/flowfuse-device/device.yml -p 1880:1880 flowfuse/device-agent:latest
4545
```
4646

47+
Alternatively, you can mount the entire configuration directory:
48+
49+
```bash
50+
docker run --mount type=bind,src=/path/to/config/dir,target=/opt/flowfuse-device -p 1880:1880 flowfuse/device-agent:latest
51+
```
52+
53+
> [!IMPORTANT]
54+
> **Breaking change in 4.0.0 — the container now runs as a non-root user.**
55+
>
56+
> From `4.0.0` the image runs as the unprivileged `flowfuse` user (`UID 2000` /
57+
> `GID 2000`) instead of `root`. If you bind-mount a host directory for state
58+
> (e.g. at `/opt/flowfuse-device` to persist `device.yml`, the `project/`
59+
> directory and the module cache), that directory must be **writable by UID
60+
> 2000**, otherwise the agent will fail to start with a permissions error.
61+
>
62+
> Before upgrading, change the ownership of the mounted directory on the host:
63+
>
64+
> ```bash
65+
> sudo chown -R 2000:2000 /path/to/config/dir
66+
> ```
67+
>
68+
> Alternatively, run the container as a UID that already owns the host
69+
> directory (the agent only requires the state directory to be writable by the
70+
> runtime user):
71+
>
72+
> ```bash
73+
> docker run --user $(id -u):$(id -g) ... flowfuse/device-agent:latest
74+
> ```
75+
>
76+
> If you build the image yourself, the user and group IDs can be customised with
77+
> the `FF_UID` and `FF_GID` build arguments.
78+
4779
## Configuration
4880
4981
The agent configuration is provided by a `device.yml` file within its working

docker/Dockerfile

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@ ARG NODE_VERSION=20
22
FROM node:${NODE_VERSION}-alpine
33

44
ARG VERSION=latest
5+
ARG FF_UID=2000
6+
ARG FF_GID=2000
57

68
RUN apk add --no-cache --virtual buildtools build-base linux-headers udev python3 openssl
79

8-
RUN npm install -g npm
10+
RUN addgroup -g ${FF_GID} -S flowfuse \
11+
&& adduser -u ${FF_UID} -S -G flowfuse -h /opt/flowfuse-device flowfuse \
12+
&& mkdir -p /opt/flowfuse-device \
13+
&& chown -R "${FF_UID}":"${FF_GID}" /opt/flowfuse-device
914

10-
RUN mkdir -m 777 -p /opt/flowfuse-device
11-
RUN npm config set cache /opt/flowfuse-device/.npm --global
12-
RUN npm install -g @flowfuse/device-agent@${VERSION} --omit=dev
13-
RUN chmod -R 777 /opt/flowfuse-device/.npm
15+
RUN npm install -g npm \
16+
&& npm config set cache /opt/flowfuse-device/.npm --global \
17+
&& npm install -g @flowfuse/device-agent@${VERSION} --omit=dev \
18+
&& chown -R ${FF_UID}:${FF_GID} /opt/flowfuse-device
1419

1520
EXPOSE 1880
1621

@@ -23,4 +28,8 @@ LABEL org.label-schema.name="FlowFuse Device Agent" \
2328
authors="FlowFuse Inc."
2429

2530

31+
ENV HOME=/opt/flowfuse-device
32+
33+
USER flowfuse
34+
2635
CMD ["flowfuse-device-agent"]

0 commit comments

Comments
 (0)