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
16 changes: 12 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM eclipse-temurin:11.0.22_7-jdk-jammy AS builder
FROM eclipse-temurin:21-jdk-jammy AS builder
COPY . /usr/src/openas2
WORKDIR /usr/src/openas2
# To test Locally builder environment:
# docker run --rm -it -v $(pwd):/usr/src/openas2 openjdk:11 bash
# docker run --rm -it -v $(pwd):/usr/src/openas2 eclipse-temurin:21-jdk-jammy bash
RUN apt update
RUN apt-get install -y unzip
RUN rm -f Server/dist/*
Expand All @@ -18,14 +18,22 @@ RUN cd /usr/src/openas2/Runtime/bin && \
mv config config_template


FROM eclipse-temurin:11.0.22_7-jre-jammy
FROM eclipse-temurin:21-jre-jammy
ENV OPENAS2_BASE=/opt/openas2
ENV OPENAS2_HOME=/opt/openas2
ENV OPENAS2_TMPDIR=/opt/openas2/temp
COPY --from=builder /usr/src/openas2/Runtime/bin ${OPENAS2_BASE}/bin
COPY --from=builder /usr/src/openas2/Runtime/lib ${OPENAS2_BASE}/lib
COPY --from=builder /usr/src/openas2/Runtime/resources ${OPENAS2_BASE}/resources
COPY --from=builder /usr/src/openas2/Runtime/config_template ${OPENAS2_HOME}/config_template
RUN mkdir ${OPENAS2_BASE}/config
# Run as an unprivileged user rather than root, since the server is usually exposed to the internet.
# The user is in group 0 and everything it writes is group writable, so platforms that run the
# container under an arbitrary user ID in group 0 work as well. The ID is numeric in USER so that
# Kubernetes can verify runAsNonRoot.
RUN useradd --uid 1000 --gid 0 --home-dir ${OPENAS2_HOME} --no-create-home --shell /usr/sbin/nologin openas2 \
&& mkdir -p ${OPENAS2_BASE}/config ${OPENAS2_BASE}/data ${OPENAS2_BASE}/logs ${OPENAS2_TMPDIR} \
&& chown -R 1000:0 ${OPENAS2_BASE} \
&& chmod -R g=u ${OPENAS2_BASE}
USER 1000
WORKDIR $OPENAS2_HOME
ENTRYPOINT ["/opt/openas2/bin/start-container.sh"]
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,26 @@ You can then go to `http://localhost:4080` or `http://host-ip:4080` in a browser

The default OpenAS2 environment in the image is:

OPENAS2_BASE: /usr/local/tomcat
OPENAS2_HOME: /usr/local/tomcat
OPENAS2_TMPDIR: /usr/local/tomcat/temp
JAVA_HOME: /usr/local/openjdk-11
OPENAS2_BASE: /opt/openas2
OPENAS2_HOME: /opt/openas2
OPENAS2_TMPDIR: /opt/openas2/temp
JAVA_HOME: /opt/java/openjdk (Java 21)

### Running as a non-root user

The image runs OpenAS2 as user `openas2` (UID `1000`) in group `0`, not as root. Anything mounted into the
container that OpenAS2 writes to, normally `/opt/openas2/config` and `/opt/openas2/data`, must be writable by that
user, or the server fails to start with `Permission denied`. A directory created by Docker for a bind mount is owned
by root, so give it to the container user:

```console
$ sudo chown -R 1000:0 ./config ./data
```

A named Docker volume is initialised from the image the first time it is used, so it already has the right owner.

To keep running as root instead, for example while existing volumes are migrated, override the user with
`docker run --user 0`, or `user: "0"` in docker-compose.yml.

The configuration files are available in `/opt/openas2/config/`.

Expand Down
17 changes: 17 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ The release download file is: OpenAS2Server-4.13.0.zip
The zip file contains a PDF document (OpenAS2HowTo.pdf) providing information on installing and using the application.
## NOTE: Testing covers Java 17 to 21.

Version UNRELEASED
===========================

This is a minor enhancement and bugfix release.
1. Fix the Docker image failing to build, and run OpenAS2 in it as an unprivileged user instead of root (issue #367).
The image built on Java 11 but the project compiles for Java 17, so "docker build" failed with "invalid target
release: 17". Both stages now use Java 21. The server now runs as the user "openas2" (UID 1000, group 0), since it
is usually exposed to the internet. Volumes mounted for the config and data folders must be writable by that user:
see the upgrade notes in RELEASE-NOTES.md and the README.

Version 4.14.0 2026-10-13
===========================

Expand Down Expand Up @@ -41,6 +51,13 @@ This is a minor enhancement and bugfix release.

**You must review all notes for the relevant intermediate versions from your version to this release version.**

### Upgrading to a version after 4.14.0 if you run the OpenAS2 Docker image:
1. The image now runs OpenAS2 as the unprivileged user "openas2" (UID 1000, group 0) instead of root. Volumes
mounted for /opt/openas2/config and /opt/openas2/data must be writable by that user or the server will fail to
start with "Permission denied". Change their ownership (for example "chown -R 1000:0 ./config ./data"), set
fsGroup in a Kubernetes pod securityContext, or keep running as root with "docker run --user 0" while the
volumes are migrated. See the README for details.

### Upgrading to 4.6.1 or newer from any older version if using parallel processing mode:
1. Ensure you change the property for enabling parallel mode by removing the 3rd consecutive "l" from "process_files_in_paralllel".

Expand Down
10 changes: 10 additions & 0 deletions changes.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
**IMPORTANT NOTE**: Please review upgrade notes in the RELEASE-NOTES.md if you are upgrading

Version UNRELEASED
===========================

This is a minor enhancement and bugfix release.
1. Fix the Docker image failing to build, and run OpenAS2 in it as an unprivileged user instead of root (issue #367).
The image built on Java 11 but the project compiles for Java 17, so "docker build" failed with "invalid target
release: 17". Both stages now use Java 21. The server now runs as the user "openas2" (UID 1000, group 0), since it
is usually exposed to the internet. Volumes mounted for the config and data folders must be writable by that user:
see the upgrade notes in RELEASE-NOTES.md and the README.

Version 4.14.0 2026-10-13
===========================

Expand Down
8 changes: 8 additions & 0 deletions k8s-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ spec:
labels:
app: openas2
spec:
# The image runs as the unprivileged UID 1000. fsGroup makes block storage volumes writable by it;
# Azure Files and other SMB or NFS volumes ignore fsGroup, so set their ownership or permissions
# in the storage class mount options instead (for example uid=1000,gid=0).
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 0
fsGroup: 1000
containers:
- name: openas2
image: myrepo/openas2app:latest
Expand Down
Loading