smallwebwaf (https://git.eeqj.de/sneak/smallwebwaf/src/branch/main/SPEC.md) deploys as a protective reverse proxy in a second container next to an app's container, with the app's traefik labels moved onto that second container so it receives the traffic and forwards to the app. Its SPEC notes upaas was never examined for whether it supports this shape.
Investigation only, no code in this unit. Answer on this issue, citing the relevant upaas code/config paths:
Can a repo's deploy produce two containers today, with the traefik labels on the second one instead of the app?
If not, what is the minimal feature that would allow it?
Definition of done: a definitive written answer here with citations; if the answer to (1) is no, a follow-up feature-request issue is filed in this repo describing the minimal feature and referencing this issue.
(model: claude-fable-5)
smallwebwaf (https://git.eeqj.de/sneak/smallwebwaf/src/branch/main/SPEC.md) deploys as a protective reverse proxy in a second container next to an app's container, with the app's traefik labels moved onto that second container so it receives the traffic and forwards to the app. Its SPEC notes upaas was never examined for whether it supports this shape.
Investigation only, no code in this unit. Answer on this issue, citing the relevant upaas code/config paths:
1. Can a repo's deploy produce two containers today, with the traefik labels on the second one instead of the app?
2. If not, what is the minimal feature that would allow it?
Definition of done: a definitive written answer here with citations; if the answer to (1) is no, a follow-up feature-request issue is filed in this repo describing the minimal feature and referencing this issue.
(model: claude-fable-5)
Q1: No. A deploy cannot today produce two long-lived containers with the
traefik labels on the second one. upaas deploys exactly one container per app
and attaches all labels to it.
(a) How many containers a deploy launches — one.
deployContainerWithTimeout (internal/service/deploy/deploy.go:565) removes
the single existing container (removeOldContainer, deploy.go:1034), then
calls createAndStartContainer (deploy.go:1061) once.
createAndStartContainer calls docker.CreateContainer then docker.StartContainer exactly once; the container is named "upaas-" + app.Name (deploy.go:1156).
CreateContainer is a single ContainerCreate call
(internal/docker/client.go:242, API call at client.go:254).
The lookup/replace path assumes one container: FindContainerByAppID returns containers[0] (client.go:431).
The only other container ever created is a throwaway alpine/git clone helper
during the build phase, always force-removed (client.go:706). README lists
"Multiple container orchestration" as a Non-Goal.
(b) Which container gets the traefik/ingress labels — always the app
container.
upaas has no traefik-specific code. Labels are a generic per-app key/value
list (internal/models/label.go), fetched by app.GetLabels and passed
through buildLabelMap (deploy.go:1168), which attaches every app label plus
the upaas.id label to the one app container (buildContainerOptions, deploy.go:1108 -> client.go:258).
traefik.* values appear only as user-entered examples in tests
(internal/service/app/app_test.go:492); there is no plumbing to send labels
anywhere but the app container.
So the smallwebwaf shape (a proxy sidecar carrying the traefik labels, app off
the ingress network) is not supported.
Q2: Minimal feature. Add an optional per-app sidecar container plus label
routing:
Data model: a sidecar spec (image, env/ports, internal network) and a marker
for which labels are "ingress" labels (internal/models/app.go plus a new
child table alongside the env/label/volume/port tables).
Deploy flow: create/start the app + sidecar set and remove the whole set on
redeploy/rollback (deploy.go:565, :1061, :1034; drop the containers[0] single-container assumption at client.go:431).
Label routing: send the ingress/traefik labels to the sidecar, keep upaas.id
on every container (deploy.go:1108 / :1168).
Networking: put the app on an internal-only network with the sidecar bridging
the ingress and internal networks (app already has one docker_network, app.go:48).
Disclosure: this investigation ran on opus-4-8 rather than fable because the
fable weekly quota is exhausted.
Model: opus-4-8
## Answer
**Q1: No.** A deploy cannot today produce two long-lived containers with the
traefik labels on the second one. upaas deploys exactly one container per app
and attaches all labels to it.
**(a) How many containers a deploy launches — one.**
- `deployContainerWithTimeout` (`internal/service/deploy/deploy.go:565`) removes
the single existing container (`removeOldContainer`, `deploy.go:1034`), then
calls `createAndStartContainer` (`deploy.go:1061`) once.
- `createAndStartContainer` calls `docker.CreateContainer` then
`docker.StartContainer` exactly once; the container is named
`"upaas-" + app.Name` (`deploy.go:1156`).
- `CreateContainer` is a single `ContainerCreate` call
(`internal/docker/client.go:242`, API call at `client.go:254`).
- The lookup/replace path assumes one container: `FindContainerByAppID` returns
`containers[0]` (`client.go:431`).
- The only other container ever created is a throwaway `alpine/git` clone helper
during the build phase, always force-removed (`client.go:706`). README lists
"Multiple container orchestration" as a Non-Goal.
**(b) Which container gets the traefik/ingress labels — always the app
container.**
- upaas has no traefik-specific code. Labels are a generic per-app key/value
list (`internal/models/label.go`), fetched by `app.GetLabels` and passed
through `buildLabelMap` (`deploy.go:1168`), which attaches every app label plus
the `upaas.id` label to the one app container (`buildContainerOptions`,
`deploy.go:1108` -> `client.go:258`).
- `traefik.*` values appear only as user-entered examples in tests
(`internal/service/app/app_test.go:492`); there is no plumbing to send labels
anywhere but the app container.
So the smallwebwaf shape (a proxy sidecar carrying the traefik labels, app off
the ingress network) is not supported.
**Q2: Minimal feature.** Add an optional per-app sidecar container plus label
routing:
- Data model: a sidecar spec (image, env/ports, internal network) and a marker
for which labels are "ingress" labels (`internal/models/app.go` plus a new
child table alongside the env/label/volume/port tables).
- Deploy flow: create/start the app + sidecar set and remove the whole set on
redeploy/rollback (`deploy.go:565`, `:1061`, `:1034`; drop the
`containers[0]` single-container assumption at `client.go:431`).
- Label routing: send the ingress/traefik labels to the sidecar, keep `upaas.id`
on every container (`deploy.go:1108` / `:1168`).
- Networking: put the app on an internal-only network with the sidecar bridging
the ingress and internal networks (app already has one `docker_network`,
`app.go:48`).
Filed as a feature request: https://git.eeqj.de/sneak/upaas/issues/206
Disclosure: this investigation ran on opus-4-8 rather than fable because the
fable weekly quota is exhausted.
Model: opus-4-8
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
smallwebwaf (https://git.eeqj.de/sneak/smallwebwaf/src/branch/main/SPEC.md) deploys as a protective reverse proxy in a second container next to an app's container, with the app's traefik labels moved onto that second container so it receives the traffic and forwards to the app. Its SPEC notes upaas was never examined for whether it supports this shape.
Investigation only, no code in this unit. Answer on this issue, citing the relevant upaas code/config paths:
Definition of done: a definitive written answer here with citations; if the answer to (1) is no, a follow-up feature-request issue is filed in this repo describing the minimal feature and referencing this issue.
(model: claude-fable-5)
Answer
Q1: No. A deploy cannot today produce two long-lived containers with the
traefik labels on the second one. upaas deploys exactly one container per app
and attaches all labels to it.
(a) How many containers a deploy launches — one.
deployContainerWithTimeout(internal/service/deploy/deploy.go:565) removesthe single existing container (
removeOldContainer,deploy.go:1034), thencalls
createAndStartContainer(deploy.go:1061) once.createAndStartContainercallsdocker.CreateContainerthendocker.StartContainerexactly once; the container is named"upaas-" + app.Name(deploy.go:1156).CreateContaineris a singleContainerCreatecall(
internal/docker/client.go:242, API call atclient.go:254).FindContainerByAppIDreturnscontainers[0](client.go:431).alpine/gitclone helperduring the build phase, always force-removed (
client.go:706). README lists"Multiple container orchestration" as a Non-Goal.
(b) Which container gets the traefik/ingress labels — always the app
container.
list (
internal/models/label.go), fetched byapp.GetLabelsand passedthrough
buildLabelMap(deploy.go:1168), which attaches every app label plusthe
upaas.idlabel to the one app container (buildContainerOptions,deploy.go:1108->client.go:258).traefik.*values appear only as user-entered examples in tests(
internal/service/app/app_test.go:492); there is no plumbing to send labelsanywhere but the app container.
So the smallwebwaf shape (a proxy sidecar carrying the traefik labels, app off
the ingress network) is not supported.
Q2: Minimal feature. Add an optional per-app sidecar container plus label
routing:
for which labels are "ingress" labels (
internal/models/app.goplus a newchild table alongside the env/label/volume/port tables).
redeploy/rollback (
deploy.go:565,:1061,:1034; drop thecontainers[0]single-container assumption atclient.go:431).upaas.idon every container (
deploy.go:1108/:1168).the ingress and internal networks (app already has one
docker_network,app.go:48).Filed as a feature request: #206
Disclosure: this investigation ran on opus-4-8 rather than fable because the
fable weekly quota is exhausted.
Model: opus-4-8