Building from source¶
Euro-Office builds entirely inside Docker via docker buildx bake. The only
host requirements are Docker with the buildx container driver, and Git with SSH
access to the repositories.
Prerequisites¶
Before building for the first time, complete the one-time setup described in
build/BUILD_REQUISITES.md:
- Docker CE installed (not
podman— RHEL-based systems default to podman) - Your build user added to the
dockergroup and re-logged in -
A buildx container driver created and bootstrapped:
-
SSH key added to your GitHub profile (for submodule access)
Clone the repository¶
If you already cloned without --recurse-submodules:
Build the Docker image¶
All build commands run from the build/ subdirectory:
This builds the standalone target (the default group) and loads the resulting
image into your local Docker daemon as ghcr.io/euro-office/documentserver:latest.
Why these flags:
| Flag | Reason |
|---|---|
BUILDX_BAKE_ENTITLEMENTS_FS=0 |
Newer BuildKit versions gate filesystem access behind entitlement checks. This disables the check since the access is explicitly granted below. |
--allow=fs.read=.. |
The build reads source files from the parent directory (context = ".." in docker-bake.hcl). BuildKit requires explicit permission for this. |
--load |
Imports the finished image into the local Docker daemon. Without this flag the image is built but not accessible via docker run. |
Verify the image was created:
Run and verify the image¶
Start the locally built image:
docker run -d \
--name euro-office-dev \
--restart=unless-stopped \
-p 8080:80 \
-e JWT_ENABLED=true \
-e JWT_SECRET=dev-secret \
ghcr.io/euro-office/documentserver:latest
Wait for the container to finish initialising, then check the health endpoint:
Expected output: true
To open the built-in example app in a browser:
docker run -d \
--name euro-office-dev \
--restart=unless-stopped \
-p 8080:80 \
-e JWT_ENABLED=true \
-e JWT_SECRET=dev-secret \
-e EXAMPLE_ENABLED=true \
ghcr.io/euro-office/documentserver:latest
Then open http://localhost:8080/example/ in your browser.
Stop and remove the container when done:
Build a branded image¶
The default build produces a Euro-Office image. To build for a different brand (e.g. Nextcloud Office), include the brand-specific HCL file alongside the main bake file:
cd DocumentServer/build
BUILDX_BAKE_ENTITLEMENTS_FS=0 docker buildx bake \
-f docker-bake.hcl \
-f brands/nextcloud-office-brand/brand-server.hcl \
--allow=fs.read=.. \
--allow=fs=./brands/nextcloud-office-brand/generated \
--load
The additional --allow=fs=./brands/nextcloud-office-brand/generated flag grants
BuildKit write access to the directory where the brand asset generation step
exports its output.
What changes in a branded build:
| Default (Euro-Office) | Branded (Nextcloud Office) | |
|---|---|---|
| Image tag | ghcr.io/euro-office/documentserver:latest |
ghcr.io/nextcloud-office/documentserver:latest |
| Install path inside image | /var/www/euro-office/ |
/var/www/nextcloud-office/ |
COMPANY_NAME env var |
Euro-Office |
Nextcloud Office |
| Visual assets | Built-in defaults | Generated from brands/nextcloud-office-brand/svg/ |
How the brand asset pipeline works:
Including a brand HCL overrides the dummy brand-icons target in docker-bake.hcl
with a real build step. That step runs build-icons.bake.Dockerfile — an Alpine
container with rsvg-convert — which renders the five source SVGs into PNGs, ICOs,
and correctly named SVG copies for each component (server admin panel, welcome page,
example app). The generated files are written to
brands/nextcloud-office-brand/generated/ and then injected into the server,
example, and packages build stages via COPY --from=brand-icons.
Customising the visual identity:
The visual output depends entirely on the five source SVGs in
brands/nextcloud-office-brand/svg/:
svg/
logo-dark.svg # square app icon, dark theme
logo-light.svg # square app icon, light theme
logo-large-dark.svg # wide logo, dark theme
logo-large-light.svg # wide logo, light theme
splash.svg # splash screen
Replace these files with your own artwork and rebuild. Everything in generated/
is derived from them — do not edit the generated files directly.
Note
The nextcloud-office-brand source SVGs currently contain the same artwork as
the Euro-Office defaults. A branded build will compile and run correctly, but
will look identical until different SVG files are placed in svg/.
Build targets¶
| Target / group | Command | Output |
|---|---|---|
standalone (default) |
docker buildx bake |
ghcr.io/euro-office/documentserver:latest |
develop |
docker buildx bake develop |
ghcr.io/euro-office/documentserver:latest-dev — includes build tools |
packages |
docker buildx bake packages |
.deb and .rpm files in build/deploy/packages/ |
cluster |
docker buildx bake cluster |
Orchestrated cluster images (cluster-docs, cluster-example, cluster-utils) |
Override the version¶
The version is read from the VERSION file at the repository root. Override it at
build time via environment variables:
PRODUCT_VERSION=9.3.1 BUILD_NUMBER=42 \
BUILDX_BAKE_ENTITLEMENTS_FS=0 \
docker buildx bake --allow=fs.read=.. --load
BUILD_NUMBER is appended to the version string (e.g. 9.3.1-42). It defaults
to dev.1 when not set.
Build distribution packages¶
cd DocumentServer/build
BUILDX_BAKE_ENTITLEMENTS_FS=0 docker buildx bake packages \
--allow=fs.read=.. \
--allow=fs=./deploy/packages
Packages are written to build/deploy/packages/. Both .deb and .rpm are
produced for each architecture in a single run:
deploy/packages/
euro-office-documentserver_9.3.1-dev.1_arm64.deb
euro-office-documentserver-9.3.1-dev.1.aarch64.rpm
The --allow=fs=./deploy/packages flag grants BuildKit write access to that
output directory.
Output directory is not cleared between runs
The deploy/packages/ directory accumulates packages across builds. Remove
old packages before building if you want only the current run's output:
Note
The packages target builds the full source first (same pipeline as standalone)
before producing the packages. Expect the same build time as a full image build
on a cold cache.
Override version and build number¶
PRODUCT_VERSION=9.3.1 BUILD_NUMBER=42 \
BUILDX_BAKE_ENTITLEMENTS_FS=0 \
docker buildx bake packages \
--allow=fs.read=.. \
--allow=fs=./deploy/packages
This produces euro-office-documentserver_9.3.1-42_<arch>.deb and the equivalent .rpm.
Troubleshooting¶
Cache layer lock errors¶
When building with a warm cache, multiple targets may attempt to write the same cache layer in parallel, producing errors like:
These are transient and BuildKit retries them automatically — the build completes successfully. If the errors cause an actual build failure, disable cache writes for that run:
BUILDX_BAKE_ENTITLEMENTS_FS=0 docker buildx bake \
--allow=fs.read=.. \
--load \
--set "*.cache-to="
Broken build cache¶
If a build stalls or fails with errors about missing paths inside the build cache
(e.g. cannot change to '/build-cache1/third_party/workdir/icu/icu'), prune the
BuildKit cache and retry: