Using xcaddy build to include a nodejs app

1. The problem I’m having:

I am taking a stab at building a small (read-only) UI for the caddy API.

So far I configured Caddy to expose the API and I have a standalone app that displays some data (like the config and limited metrics). As a next step, I want to wrap my UI into a module so I can install it with caddy (instead of running it as another container) — also to not have to expose the API (even if it’s “just” a local Docker network in the end).

This question is kind of broad — apologies — but how do you get started?

I know “how to” Go, as in, using the embed feature. But usually, this is a two step process. I build my JavaScript, then I move the build artefact to the go build, etc…

With xcaddy build --with etc (btw, kudos for creating that, it’s kinda wild to customise Caddy like this and get a binary) I am bit stuck on where to start.

Is it possible to use xcaddy with already compiled Go code? E.g., I would pre-compile my module and then include that somehow? Or do I have to write some Make to inject the build from JavaScript somehow? Or can I start npm run build somewhere?

I feel like, this is a noob question, but my Google fu is lacking.

2. Error messages and/or full log output:


3. Caddy version:

/srv # caddy version
v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

4. How I installed and ran Caddy:

I am using a multi-stage (Docker) build to build and essentially run Caddy:


FROM caddy:${CADDY_VERSION}-builder as builder

RUN xcaddy build \


ADD . .


COPY --from=builder /usr/bin/caddy /usr/bin/caddy

ENTRYPOINT [ "/usr/bin/caddy" ]
CMD ["docker-proxy", "--caddyfile-path=/opt/etc/caddy/Caddyfile", "--ingress-networks=public"]

a. System environment:

  • Docker for Mac (Docker Swarm)
  • Docker 20.x (Linux, OpenStack)

b. Command:


c. Docker

	docker run --rm -it \
		--name caddy-dev-local \
		-p 80:80 \
		-v $(CURDIR)/rootfs/etc/caddy:/opt/etc/caddy \

d. My complete Caddy config:

	admin localhost:2019
	log default {
		output stdout
		format console
		include http.log.access admin.api

# admin-ui host
	route {
		reverse_proxy localhost:2019 {
			header_up Host localhost:2019

5. Links to relevant resources:

No. You need to point xcaddy to your Go code. Typically that’ll be in a GitHub repo where the module name is essentially a reference to the repo (e.g. the caddy-docker-proxy module you’re adding up Caddy). There’s no dynamic linking here, it’s statically linked at compile time so go build needs access to the Go source code to include.

I don’t understand how Node comes into play here. If you’re writing Go code, why Node? I’m not sure what you mean.

The frontend app uses Svelte. And it’s is build with nodejs. My plan is to embed it into the Caddy module using embed. For this to work, I have to start a build process (such as “npm run build”) to create the artefact for the frontend code and then I have to place it into the tree for the Go-module (aka the Caddy Module).

I am just having trouble assembling it all into one I guess. And I am looking for an example.

(I edited my answer to provide more context.)

I think you can build it, push the built JS code to a github repo next to your Go module, then use --with to pull it into a Caddy build. I think that should work, right?

We are thinking about adding embed support in xcaddy itself, but we haven’t started on that yet Support for embedding static files at build-time · Issue #130 · caddyserver/xcaddy · GitHub

Yeah, thanks for responding again. I just figured out that I can use go generate and literally //go:generate npm ci to create the list of files to embed. I guess that will require npm when my module is used, but I’ll try that before I commit release artefacts to git. :slight_smile:

Alternatively you can make the npm build in Docker just before running xcaddy (separate stage?) then use the = form of --with to point to your module in a relative/absolute path instead of fetching it from GitHub. See the examples at GitHub - caddyserver/xcaddy: Build Caddy with plugins, specifically the ones with =../.. etc

Thanks, I’ll give that a … Go :wink: as well.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.