@ours.network/install 1.2.1-nightly.4 → 1.2.1-nightly.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GATEWAY_SETUP.md +178 -0
- package/README.md +471 -9
- package/ROOTLESS_PODMAN_VALIDATION.md +210 -0
- package/assets/Dockerfile +14 -12
- package/assets/Dockerfile.gateway +5 -0
- package/assets/docker-compose.yaml +8 -1
- package/assets/fleet-settings.example.json +48 -0
- package/assets/gateway-entrypoint.sh +37 -0
- package/assets/release-lock.json +1177 -4508
- package/assets/release.json +37 -19
- package/assets/scripts/build/build-common.mjs +2 -1
- package/assets/scripts/build/build-sdk.mjs +6 -1
- package/assets/scripts/maintenance/build-context.mjs +1 -1
- package/assets/scripts/maintenance/daemon-owner.mjs +15 -0
- package/assets/scripts/maintenance/docker-layout-conversion.mjs +7 -3
- package/assets/scripts/maintenance/recover-notifications.mjs +26 -0
- package/assets/scripts/maintenance/release-graph.mjs +18 -1
- package/assets/scripts/maintenance/state-operation.mjs +62 -5
- package/assets/scripts/runtime/README.md +7 -0
- package/assets/scripts/runtime/client-setup.mjs +80 -6
- package/assets/scripts/runtime/dependency-ready.mjs +13 -0
- package/assets/scripts/runtime/diagnostics.mjs +72 -0
- package/assets/scripts/runtime/entrypoint.sh +5 -1
- package/assets/scripts/runtime/health-messenger.mjs +7 -6
- package/assets/scripts/runtime/notifications-gateway.mjs +90 -0
- package/assets/scripts/runtime/recover.mjs +165 -0
- package/assets/scripts/runtime/start-cowork.sh +5 -0
- package/assets/scripts/runtime/start-messenger.sh +29 -4
- package/assets/scripts/runtime/start-telegram.sh +5 -0
- package/assets/scripts/runtime/supervise.mjs +35 -0
- package/assets/sources.json +54 -28
- package/install.mjs +7 -2
- package/lib/boot-readiness.mjs +43 -0
- package/lib/build-transition.mjs +16 -0
- package/lib/client-cli.mjs +127 -0
- package/lib/container-engine.mjs +127 -0
- package/lib/diagnostics.mjs +1 -0
- package/lib/docker-conversion-runtime.mjs +3 -2
- package/lib/docker-layout-installation.mjs +2 -1
- package/lib/docker-recovery.mjs +55 -0
- package/lib/docker-runtime-repair.mjs +160 -0
- package/lib/effects.mjs +357 -133
- package/lib/gateway-transition.mjs +87 -0
- package/lib/gateway.mjs +158 -0
- package/lib/legacy-migration.mjs +13 -2
- package/lib/orchestrate-uninstall.mjs +18 -6
- package/lib/orchestrate.mjs +193 -43
- package/lib/plan.mjs +27 -11
- package/lib/podman-preflight.mjs +40 -0
- package/lib/server-onboarding.mjs +164 -16
- package/lib/server-ports.mjs +17 -0
- package/lib/setup-options.mjs +99 -28
- package/lib/setup.mjs +35 -17
- package/lib/target.mjs +24 -8
- package/lib/uninstall.mjs +2 -2
- package/lib/usage.mjs +21 -7
- package/lib/workspace-setup.mjs +83 -0
- package/package.json +4 -2
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Rootless Podman integration validation
|
|
2
|
+
|
|
3
|
+
Status: implementation under review; **not a qualified server-support release**.
|
|
4
|
+
Validation date: 2026-09-25. No production deployment, migration, restart or merge.
|
|
5
|
+
|
|
6
|
+
## Scope and source baseline
|
|
7
|
+
|
|
8
|
+
The supplied `rootless-podman-support.zip` was inspected as design/evidence,
|
|
9
|
+
not executable authority. SHA-256:
|
|
10
|
+
`0eafc865566be71bcb87d432a98384da47e6d153e4395d9cfe721b4def168e96`.
|
|
11
|
+
It contains six substantive Markdown documents and no implementation patches.
|
|
12
|
+
Its historical ARM VM observations do not establish current Linux amd64 support.
|
|
13
|
+
|
|
14
|
+
All referenced repositories were fetched into isolated checkouts at these
|
|
15
|
+
`prerelease` commits. SDK, CLI and daemon share the SDK repository; the MCP
|
|
16
|
+
repository also supplies Codex and Claude Code integrations.
|
|
17
|
+
|
|
18
|
+
| Repository | Commit |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| ours-network | a9ae420d2878a304911e94d53d0cdd2cff06f299 |
|
|
21
|
+
| ours-sdk | 737e1028cabadcbb8837548923c7a92b49e9e575 |
|
|
22
|
+
| ours-cowork | 2d2ff8979756678068b8f6b85c619f6d811010ff |
|
|
23
|
+
| ours-messenger-server | 5e2ca2be5789a5300fcbed08a0dd26b9b59780ef |
|
|
24
|
+
| ours-tg-connector | 21f4bf92b52e1d61261987f298bcc76248cddb78 |
|
|
25
|
+
| ours-fleet | 717f6d8a09e6173b9b8a017fc5efb08d71927524 |
|
|
26
|
+
| ours-mcp | ce6e3e0298b83aec0257c4ae3773d785d8b38889 |
|
|
27
|
+
|
|
28
|
+
Runtime launch/build/maintenance and gateway packaging belong to ours-network;
|
|
29
|
+
no source changes were required in the other repositories. Host Fleet and harness
|
|
30
|
+
integrations continue using their existing client paths. Their unrelated feature
|
|
31
|
+
suites are not implied by the installer results below.
|
|
32
|
+
|
|
33
|
+
## Corrections established by testing
|
|
34
|
+
|
|
35
|
+
- This prerelease already checks authenticated gateway readiness during install.
|
|
36
|
+
The added lifecycle check covers full starts and preserves intentionally stopped
|
|
37
|
+
applications during partial runtime restoration.
|
|
38
|
+
- Podman 5.4.2 with Compose 5.5.1 exposes the whole named volume instead of the
|
|
39
|
+
requested subpath. Its vendor restart unit also lacks `should-start-on-boot`.
|
|
40
|
+
The new preflight rejects this combination rather than weakening isolation.
|
|
41
|
+
- Local and API Podman must select the same rootless store. Compose is passed an
|
|
42
|
+
explicit Unix socket; native builds use the retained root/runroot/driver.
|
|
43
|
+
Both report the same retained UID/GID mapping fingerprint.
|
|
44
|
+
- Podman image IDs need Docker-compatible `sha256:` normalization at the adapter
|
|
45
|
+
boundary. Missing-object detection must not reinterpret inspect error 125 as
|
|
46
|
+
permission to create or replace an object.
|
|
47
|
+
- Compose excludes maintenance profiles from ordinary configuration output and
|
|
48
|
+
implicitly builds absent administration images. Native build resolution enables
|
|
49
|
+
all profiles and builds the selected missing administration image first.
|
|
50
|
+
- Fresh schema-2 installations omit embedded `networkMcp`; the shared rebuild
|
|
51
|
+
validator previously required it. Validation now accepts absence and still
|
|
52
|
+
rejects malformed or conflicting embedded configuration, while retaining
|
|
53
|
+
standalone-profile, credential, provenance and strict legacy conversion checks.
|
|
54
|
+
- Gateway COPY destinations must remain accessible to UID 101 on both engines.
|
|
55
|
+
Runtime DNS comes from validated container nameservers, retaining nginx variables.
|
|
56
|
+
|
|
57
|
+
## Observed environment and results
|
|
58
|
+
|
|
59
|
+
Native Debian 13 Linux amd64, unprivileged UID 1000, subordinate UID/GID ranges,
|
|
60
|
+
SELinux disabled, standalone Docker Compose 5.5.1. Podman 6.1.2 was built from
|
|
61
|
+
upstream tag commit `04f3aa430e6df81bea059978bc5bafbc846ba3e7` with systemd and
|
|
62
|
+
seccomp support, using netavark/aardvark-dns 2.1.0. A separate task store and API
|
|
63
|
+
socket isolated all Podman tests from the installed 5.4.2 default backend.
|
|
64
|
+
|
|
65
|
+
- Behavioral preflight: PASS on 6.1.2, including UID-1000 private storage,
|
|
66
|
+
volume subpath isolation, DNS, Compose reset/wait/JSON status.
|
|
67
|
+
- Native synthetic secret/cache build: PASS; secret absent from command arguments,
|
|
68
|
+
build output, image inspect/history and final filesystem.
|
|
69
|
+
- Production runtime: native build of the shipped exact package/integrity policy,
|
|
70
|
+
runtime metadata and gateway artifact capability qualification PASS.
|
|
71
|
+
- Development runtime: native build from all exact prerelease commits above,
|
|
72
|
+
including private SDK/submodule acquisition through an environment build secret,
|
|
73
|
+
native compilation and gateway capability qualification PASS. The source-built
|
|
74
|
+
five-service lifecycle and authenticated gateway also PASS.
|
|
75
|
+
- Real runtime: prepare, access-init/access-issue, test Human identity, all five
|
|
76
|
+
services, authenticated gateway readiness, stop/status/start PASS.
|
|
77
|
+
- Maintenance: server backup/restore and Cowork backup/reset/restore PASS; all
|
|
78
|
+
services subsequently restarted with authenticated gateway readiness.
|
|
79
|
+
- Rebuild: the initial fresh-layout validator defect was reproduced and fixed;
|
|
80
|
+
retained transition recovery PASS after rebuilding the maintenance helper. A
|
|
81
|
+
second complete rebuild using final code and the real installation lock PASS,
|
|
82
|
+
including offline state validation and authenticated gateway readiness.
|
|
83
|
+
- Gateway runtime: Docker 2/2 and Podman 2/2 PASS for root/nested paths,
|
|
84
|
+
authentication, WebSockets and changed backend IPs. Combined Podman native
|
|
85
|
+
capability/build-secret and gateway tests: 4/4 PASS.
|
|
86
|
+
- Installer suite: 756 passed, 0 failed, 11 opt-in tests skipped; subsequent
|
|
87
|
+
adapter-only addition separately passed (13 adapter tests).
|
|
88
|
+
- Independent Critic reruns confirmed the behavioral/native-secret tests and
|
|
89
|
+
adapter regressions. Final review is recorded separately from these observations.
|
|
90
|
+
|
|
91
|
+
The runtime harness called actual installer effects against owned resources.
|
|
92
|
+
It deliberately did not claim a complete public install: the isolated custom
|
|
93
|
+
store/socket cannot satisfy standard vendor boot-unit selection, and the public
|
|
94
|
+
preflight rejects that configuration. A harness backup label collision was
|
|
95
|
+
correctly rejected; separate per-domain labels were used afterward.
|
|
96
|
+
|
|
97
|
+
## Reproduction and remaining release gates
|
|
98
|
+
|
|
99
|
+
From `packages/installer`, with installed package dependencies:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
umask 022
|
|
103
|
+
node --test
|
|
104
|
+
OURS_TEST_DOCKER=1 node --test test/gateway-docker.test.mjs
|
|
105
|
+
PODMAN_COMPOSE_PROVIDER=/absolute/path/to/docker-compose \
|
|
106
|
+
OURS_TEST_PODMAN=1 node --test test/podman-integration.test.mjs test/gateway-docker.test.mjs
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The gateway fixture covers root and nested base paths, discovery, service routing,
|
|
110
|
+
forged-host denial, Telegram authentication, WebSocket upgrade and backend IP
|
|
111
|
+
replacement without restarting nginx. Test projects and their resources are
|
|
112
|
+
uniquely named and cleaned up. The Podman tests require a functional matching API
|
|
113
|
+
socket; `OURS_PODMAN_SOCKET` can select an isolated harness socket.
|
|
114
|
+
|
|
115
|
+
Before advertising a supported engine/provider pair, run the full public installer
|
|
116
|
+
and update/rebuild/legacy-conversion matrix on a disposable native Linux amd64
|
|
117
|
+
host with SELinux Enforcing, standard vendor user units, logout/linger, reboot,
|
|
118
|
+
unexpected exit and explicit-stop behavior. Include Docker parity for the full
|
|
119
|
+
maintenance matrix. This shared host is not a safe reboot/SELinux test target.
|
|
120
|
+
No fallback to privileged containers, whole-volume service mounts, host chown,
|
|
121
|
+
keep-id, or globally disabled SELinux is permitted.
|
|
122
|
+
|
|
123
|
+
### Disposable VM handoff
|
|
124
|
+
|
|
125
|
+
Provision a dedicated x86_64 VM (at least 4 vCPU, 8 GiB RAM, 40 GiB free disk)
|
|
126
|
+
whose distribution supplies Podman 6.1.2, compatible netavark/aardvark, subordinate
|
|
127
|
+
UID/GID support and vendor `podman-restart.service` with
|
|
128
|
+
`--filter should-start-on-boot=true`. Use an unprivileged test account, cgroup v2,
|
|
129
|
+
standard HOME/XDG paths, SELinux **Enforcing**, Node.js 22+, npm, Python 3.9+
|
|
130
|
+
with `os.pidfd_open`/`signal.pidfd_send_signal` support, and standalone
|
|
131
|
+
Docker Compose 5.5.1. The Podman pass must have no Docker CLI/daemon dependency.
|
|
132
|
+
The VM owner must explicitly authorize reboots and terminate all sessions for the
|
|
133
|
+
logout test. These commands are for that disposable VM, not the shared host.
|
|
134
|
+
|
|
135
|
+
After checking out this PR and preparing installer assets/dependencies, run as the
|
|
136
|
+
test user (administrator provisions subordinate ranges and linger beforehand):
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
uname -m # x86_64
|
|
140
|
+
getenforce # Enforcing
|
|
141
|
+
podman version # native client 6.1.2
|
|
142
|
+
export PODMAN_COMPOSE_PROVIDER=/absolute/path/to/docker-compose
|
|
143
|
+
unset OURS_PODMAN_SOCKET DOCKER_HOST DOCKER_CONTEXT CONTAINER_HOST CONTAINER_CONNECTION
|
|
144
|
+
unset CONTAINERS_CONF CONTAINERS_STORAGE_CONF PODMAN_USERNS
|
|
145
|
+
systemctl --user enable --now podman.socket
|
|
146
|
+
systemctl --user enable podman-restart.service
|
|
147
|
+
systemctl --user show podman-restart.service --property=ExecStart
|
|
148
|
+
loginctl show-user "$(id -u)" --property=Linger # yes
|
|
149
|
+
export PODMAN_TEST_ROOT="$HOME/ours-podman-qualification"
|
|
150
|
+
node install.mjs server install --mode docker --container-engine podman \
|
|
151
|
+
--state-dir "$PODMAN_TEST_ROOT" --identity-name RootlessQualification
|
|
152
|
+
node install.mjs server status --state-dir "$PODMAN_TEST_ROOT"
|
|
153
|
+
node install.mjs server backup server before-rebuild --state-dir "$PODMAN_TEST_ROOT"
|
|
154
|
+
node install.mjs server rebuild --state-dir "$PODMAN_TEST_ROOT"
|
|
155
|
+
node install.mjs server restore server before-rebuild --state-dir "$PODMAN_TEST_ROOT"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Record all five healthy services and authenticated gateway requests. From an
|
|
159
|
+
external controller, end **all** test-user sessions, wait, reconnect, and repeat
|
|
160
|
+
status/authenticated checks. Then reboot the VM and repeat the same checks before
|
|
161
|
+
running any explicit start command. Capture relevant user-unit journal and
|
|
162
|
+
SELinux AVC evidence; no denial should be bypassed by changing enforcement.
|
|
163
|
+
|
|
164
|
+
Next explicitly stop the installation, verify empty running status, reboot, and
|
|
165
|
+
verify it remains stopped. Only then start explicitly and verify all services.
|
|
166
|
+
For unexpected-exit recovery, select the exact project from its retained record
|
|
167
|
+
and terminate only its verified container-init host process through a PID handle,
|
|
168
|
+
then verify automatic recovery and retained identity/credentials. Do not use
|
|
169
|
+
`podman kill` for this case: an explicit engine stop suppresses restart policy.
|
|
170
|
+
The following refuses a PID whose cgroup does not identify the selected container:
|
|
171
|
+
|
|
172
|
+
```sh
|
|
173
|
+
node install.mjs server stop --state-dir "$PODMAN_TEST_ROOT"
|
|
174
|
+
node install.mjs server status --state-dir "$PODMAN_TEST_ROOT" # no running services
|
|
175
|
+
# Disposable-VM controller reboots here; reconnect and repeat status before start.
|
|
176
|
+
node install.mjs server start --state-dir "$PODMAN_TEST_ROOT"
|
|
177
|
+
PODMAN_TEST_PROJECT=$(node -e 'console.log(require(process.argv[1]).project)' "$PODMAN_TEST_ROOT/installation.json")
|
|
178
|
+
podman inspect --format '{{.State.StartedAt}} {{.RestartCount}}' "${PODMAN_TEST_PROJECT}-daemon-1"
|
|
179
|
+
python3 - "$PODMAN_TEST_PROJECT" <<'PYTHON'
|
|
180
|
+
import json, subprocess, sys
|
|
181
|
+
project = sys.argv[1]
|
|
182
|
+
container = json.loads(subprocess.check_output(['podman', 'inspect', project+'-daemon-1']))[0]
|
|
183
|
+
assert container['Config']['Labels']['com.docker.compose.project'] == project
|
|
184
|
+
assert container['State']['Running'] and container['State']['Pid'] > 1
|
|
185
|
+
script = """
|
|
186
|
+
import os, signal, sys
|
|
187
|
+
pid, cid = int(sys.argv[1]), sys.argv[2]
|
|
188
|
+
fd = os.pidfd_open(pid)
|
|
189
|
+
try:
|
|
190
|
+
assert cid in open('/proc/'+str(pid)+'/cgroup').read(), 'Container identity mismatch'
|
|
191
|
+
assert os.stat('/proc/'+str(pid)).st_uid == 1000, 'Unexpected runtime owner'
|
|
192
|
+
signal.pidfd_send_signal(fd, signal.SIGKILL)
|
|
193
|
+
finally:
|
|
194
|
+
os.close(fd)
|
|
195
|
+
"""
|
|
196
|
+
subprocess.run(['podman','unshare','python3','-c',script,str(container['State']['Pid']),container['Id']],check=True)
|
|
197
|
+
PYTHON
|
|
198
|
+
# Wait for recovery; assert changed StartedAt, increased RestartCount and health.
|
|
199
|
+
podman inspect --format '{{.State.StartedAt}} {{.RestartCount}} {{.State.Health.Status}}' "${PODMAN_TEST_PROJECT}-daemon-1"
|
|
200
|
+
# Verify retained identities and authenticated gateway as well.
|
|
201
|
+
node install.mjs server status --state-dir "$PODMAN_TEST_ROOT"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Still required: repeat component backup/reset/restore for daemon, Telegram,
|
|
205
|
+
Cowork and messenger; source update and interrupted retry; fresh schema-1 legacy
|
|
206
|
+
conversion fixtures; foreign/malformed volume refusal; and the equivalent full
|
|
207
|
+
Docker maintenance matrix. These require owned fixture data and before/after
|
|
208
|
+
identity, credential, provenance and mount-boundary assertions; a command exit
|
|
209
|
+
code alone is insufficient. The existing unit conversion tests are not a claim
|
|
210
|
+
that this real-engine legacy fixture matrix has run.
|
package/assets/Dockerfile
CHANGED
|
@@ -6,8 +6,8 @@ WORKDIR /opt/ours
|
|
|
6
6
|
# The host selection is private (0600); this non-secret image policy must be
|
|
7
7
|
# readable by arbitrary runtime UIDs while remaining root-owned and non-writable.
|
|
8
8
|
COPY --chmod=644 sources.json /opt/ours/sources.json
|
|
9
|
-
COPY scripts/build/*.mjs /build-scripts/
|
|
10
|
-
COPY scripts/maintenance/build-context.mjs scripts/maintenance/provenance-compare.mjs scripts/maintenance/release-graph.mjs /maintenance/
|
|
9
|
+
COPY --chmod=644 scripts/build/*.mjs /build-scripts/
|
|
10
|
+
COPY --chmod=644 scripts/maintenance/build-context.mjs scripts/maintenance/provenance-compare.mjs scripts/maintenance/release-graph.mjs /maintenance/
|
|
11
11
|
RUN --mount=type=secret,id=github_token --mount=type=cache,id=ours-dist-2-npm,target=/root/.npm,sharing=locked node /build-scripts/build.mjs
|
|
12
12
|
# Testing delivery: npm resolves transitive versions afresh; repeat builds may differ.
|
|
13
13
|
# build.mjs creates package.json once from the sources.json selections.
|
|
@@ -18,20 +18,22 @@ RUN node /build-scripts/record-build.mjs
|
|
|
18
18
|
# must be able to read it. Protected state/host copies retain private ownership.
|
|
19
19
|
RUN chmod 755 /opt/ours /opt/ours/docker /opt/ours/docker/vendor && chmod 644 package.json package-lock.json dependency-tree.json build-context.json docker/vendor/*.tgz
|
|
20
20
|
LABEL network.ours.build-context="1"
|
|
21
|
-
COPY scripts/maintenance/build-context.mjs scripts/maintenance/provenance-compare.mjs scripts/maintenance/release-graph.mjs /opt/ours/maintenance/
|
|
22
|
-
COPY scripts/runtime/runtime-common.mjs /opt/ours/docker/runtime-common.mjs
|
|
23
|
-
COPY scripts/runtime/check-client.mjs /opt/ours/docker/check-client.mjs
|
|
24
|
-
COPY scripts/runtime/check-start.mjs /opt/ours/docker/check-start.mjs
|
|
25
|
-
COPY scripts/runtime/client-setup.mjs /opt/ours/docker/client-setup.mjs
|
|
26
|
-
COPY scripts/runtime/
|
|
27
|
-
COPY scripts/runtime/
|
|
28
|
-
COPY scripts/runtime/
|
|
29
|
-
COPY
|
|
21
|
+
COPY --chmod=644 scripts/maintenance/build-context.mjs scripts/maintenance/provenance-compare.mjs scripts/maintenance/release-graph.mjs /opt/ours/maintenance/
|
|
22
|
+
COPY --chmod=644 scripts/runtime/runtime-common.mjs /opt/ours/docker/runtime-common.mjs
|
|
23
|
+
COPY --chmod=644 scripts/runtime/check-client.mjs /opt/ours/docker/check-client.mjs
|
|
24
|
+
COPY --chmod=644 scripts/runtime/check-start.mjs /opt/ours/docker/check-start.mjs
|
|
25
|
+
COPY --chmod=644 scripts/runtime/client-setup.mjs /opt/ours/docker/client-setup.mjs
|
|
26
|
+
COPY --chmod=644 scripts/runtime/diagnostics.mjs /opt/ours/docker/diagnostics.mjs
|
|
27
|
+
COPY --chmod=644 scripts/runtime/legacy-import.mjs /opt/ours/docker/legacy-import.mjs
|
|
28
|
+
COPY --chmod=644 scripts/runtime/entrypoint.sh /opt/ours/docker/entrypoint.sh
|
|
29
|
+
COPY --chmod=644 scripts/runtime/healthcheck.mjs /opt/ours/docker/healthcheck.mjs
|
|
30
|
+
COPY --chmod=644 scripts/runtime/start-telegram.sh scripts/runtime/health-telegram.sh scripts/runtime/start-cowork.sh scripts/runtime/health-cowork.sh scripts/runtime/start-messenger.sh scripts/runtime/health-messenger.mjs scripts/runtime/notifications-gateway.mjs scripts/runtime/supervise.mjs scripts/runtime/recover.mjs scripts/runtime/dependency-ready.mjs /opt/ours/docker/
|
|
31
|
+
RUN chmod 755 /opt/ours/maintenance /opt/ours/docker
|
|
30
32
|
FROM node:24 AS maintenance
|
|
31
33
|
LABEL network.ours.build-context="1"
|
|
32
34
|
WORKDIR /opt/ours
|
|
33
35
|
COPY --from=build /opt/ours /opt/ours
|
|
34
|
-
COPY scripts/maintenance/*.mjs /opt/ours/docker/
|
|
36
|
+
COPY --chmod=644 scripts/maintenance/*.mjs /opt/ours/docker/
|
|
35
37
|
COPY --chmod=644 scripts/maintenance/package.json /opt/ours/docker/package.json
|
|
36
38
|
RUN --mount=type=cache,id=ours-dist-2-npm,target=/root/.npm,sharing=locked npm install --prefix /opt/ours/docker --omit=dev --ignore-scripts --no-audit --no-fund
|
|
37
39
|
USER 1000:1000
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
FROM nginx:1.28-alpine@sha256:a8b39bd9cf0f83869a2162827a0caf6137ddf759d50a171451b335cecc87d236
|
|
2
|
+
COPY --chmod=644 nginx.conf /etc/nginx/ours.conf.template
|
|
3
|
+
COPY --chmod=644 gateway-entrypoint.sh /gateway-entrypoint.sh
|
|
4
|
+
USER 101:101
|
|
5
|
+
ENTRYPOINT ["/bin/sh", "/gateway-entrypoint.sh"]
|
|
@@ -83,6 +83,7 @@ services:
|
|
|
83
83
|
|
|
84
84
|
daemon:
|
|
85
85
|
<<: *runtime
|
|
86
|
+
restart: unless-stopped
|
|
86
87
|
environment: *owner-environment
|
|
87
88
|
volumes:
|
|
88
89
|
- {type: volume, source: server-storage, target: /var/lib/ours, volume: {nocopy: true, subpath: state/daemon}}
|
|
@@ -107,6 +108,7 @@ services:
|
|
|
107
108
|
|
|
108
109
|
telegram:
|
|
109
110
|
<<: *runtime
|
|
111
|
+
restart: unless-stopped
|
|
110
112
|
entrypoint: [/bin/sh, -e, /opt/ours/docker/start-telegram.sh]
|
|
111
113
|
environment:
|
|
112
114
|
HOME: /tmp
|
|
@@ -129,6 +131,7 @@ services:
|
|
|
129
131
|
|
|
130
132
|
cowork:
|
|
131
133
|
<<: *runtime
|
|
134
|
+
restart: unless-stopped
|
|
132
135
|
entrypoint: [/bin/sh, -e, /opt/ours/docker/start-cowork.sh]
|
|
133
136
|
environment:
|
|
134
137
|
HOME: /tmp
|
|
@@ -153,6 +156,7 @@ services:
|
|
|
153
156
|
|
|
154
157
|
messenger:
|
|
155
158
|
<<: *runtime
|
|
159
|
+
restart: unless-stopped
|
|
156
160
|
entrypoint: [/bin/sh, -e, /opt/ours/docker/start-messenger.sh]
|
|
157
161
|
environment:
|
|
158
162
|
HOME: /tmp
|
|
@@ -164,8 +168,11 @@ services:
|
|
|
164
168
|
OURS_MESSENGER_PORT: "8420"
|
|
165
169
|
OURS_MESSENGER_PUBLIC_ORIGIN: "http://127.0.0.1:${OURS_MESSENGER_PORT:-8420}"
|
|
166
170
|
OURS_MESSENGER_STATE_DIR: /var/lib/ours-messenger
|
|
171
|
+
# Started beside Messenger when the runtime ships @ours.network/notifications.
|
|
172
|
+
OURS_NOTIFICATIONS_CONFIG: /var/lib/ours-notifications/config.json
|
|
167
173
|
volumes:
|
|
168
174
|
- {type: volume, source: server-storage, target: /var/lib/ours-messenger, volume: {nocopy: true, subpath: state/messenger}}
|
|
175
|
+
- {type: volume, source: server-storage, target: /var/lib/ours-notifications, volume: {nocopy: true, subpath: state/notifications}}
|
|
169
176
|
- {type: volume, source: server-storage, target: /credentials/messenger, read_only: true, volume: {nocopy: true, subpath: state/credentials/messenger}}
|
|
170
177
|
ports:
|
|
171
178
|
- {target: 8420, published: "${OURS_MESSENGER_PORT:-8420}", host_ip: 127.0.0.1}
|
|
@@ -215,7 +222,7 @@ services:
|
|
|
215
222
|
OURS_STATE_ROOT: /storage
|
|
216
223
|
OURS_LIVE_ROOT: "${OURS_LIVE_ROOT:-/storage/state}"
|
|
217
224
|
OURS_BUILD_ROOT: /opt/ours
|
|
218
|
-
|
|
225
|
+
OURS_DAEMON_BIN_DIR: /opt/ours/node_modules/.bin
|
|
219
226
|
OURS_DAEMON_CONFIG: /var/lib/ours/config.json
|
|
220
227
|
OURS_COWORK_CLI_PATH: /opt/ours/node_modules/.bin/ours-cowork
|
|
221
228
|
OURS_COWORK_CONFIG: /var/lib/ours-cowork/config.json
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"subscriptions": [
|
|
3
|
+
"codex"
|
|
4
|
+
],
|
|
5
|
+
"assignmentStrategy": "one-model",
|
|
6
|
+
"models": {
|
|
7
|
+
"development": {
|
|
8
|
+
"harness": "codex",
|
|
9
|
+
"session": "acp",
|
|
10
|
+
"model": "gpt-6-astra",
|
|
11
|
+
"efforts": [
|
|
12
|
+
"low",
|
|
13
|
+
"medium",
|
|
14
|
+
"high",
|
|
15
|
+
"xhigh",
|
|
16
|
+
"max",
|
|
17
|
+
"ultra"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"review": {
|
|
21
|
+
"harness": "codex",
|
|
22
|
+
"session": "acp",
|
|
23
|
+
"model": "gpt-6-astra",
|
|
24
|
+
"efforts": [
|
|
25
|
+
"low",
|
|
26
|
+
"medium",
|
|
27
|
+
"high",
|
|
28
|
+
"xhigh",
|
|
29
|
+
"max",
|
|
30
|
+
"ultra"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"coordination": {
|
|
34
|
+
"harness": "codex",
|
|
35
|
+
"session": "acp",
|
|
36
|
+
"model": "gpt-6-astra",
|
|
37
|
+
"efforts": [
|
|
38
|
+
"low",
|
|
39
|
+
"medium",
|
|
40
|
+
"high",
|
|
41
|
+
"xhigh",
|
|
42
|
+
"max",
|
|
43
|
+
"ultra"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"reasoning": "balanced"
|
|
48
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
# Replace only our resolver marker. Never expand nginx's $variables.
|
|
4
|
+
resolvers=$(awk '
|
|
5
|
+
function ipv4(s, a,n,i) {
|
|
6
|
+
n=split(s,a,"."); if(n!=4)return 0;
|
|
7
|
+
for(i=1;i<=n;i++) if(a[i]!~/^[0-9]+$/ || length(a[i])>3 || a[i]+0>255 || (length(a[i])>1 && substr(a[i],1,1)=="0"))return 0;
|
|
8
|
+
return 1
|
|
9
|
+
}
|
|
10
|
+
function ipv6(s, a,n,i,count,copy,compressed) {
|
|
11
|
+
if(s!~/:/ || s~/[^0-9a-fA-F:.]/ || s~/:::/)return 0;
|
|
12
|
+
copy=s; compressed=gsub(/::/,"X",copy); if(compressed>1)return 0;
|
|
13
|
+
if(!compressed && (s~/^:/ || s~/:$/))return 0;
|
|
14
|
+
n=split(s,a,":"); count=0;
|
|
15
|
+
for(i=1;i<=n;i++) {
|
|
16
|
+
if(a[i]=="")continue;
|
|
17
|
+
if(a[i]~/\./) {if(i!=n || !ipv4(a[i]))return 0; count+=2}
|
|
18
|
+
else {if(a[i]!~/^[0-9a-fA-F]+$/ || length(a[i])>4)return 0; count++}
|
|
19
|
+
}
|
|
20
|
+
return compressed ? count<8 : count==8
|
|
21
|
+
}
|
|
22
|
+
$1=="nameserver" {
|
|
23
|
+
if(ipv4($2))address=$2;
|
|
24
|
+
else if(ipv6($2))address="[" $2 "]";
|
|
25
|
+
else next;
|
|
26
|
+
if(!seen[address]++) {printf "%s%s",sep,address; sep=" "}
|
|
27
|
+
}
|
|
28
|
+
' "${OURS_RESOLV_CONF:-/etc/resolv.conf}")
|
|
29
|
+
if [ -z "$resolvers" ]; then echo 'Gateway: no valid runtime DNS nameserver' >&2; exit 1; fi
|
|
30
|
+
umask 077
|
|
31
|
+
config=$(mktemp /tmp/ours-nginx.XXXXXX)
|
|
32
|
+
trap 'rm -f "$config"' EXIT HUP INT TERM
|
|
33
|
+
sed "s/@@OURS_RESOLVERS@@/$resolvers/g" "${OURS_NGINX_TEMPLATE:-/etc/nginx/ours.conf.template}" > "$config"
|
|
34
|
+
nginx -t -c "$config"
|
|
35
|
+
# nginx opens the config before the shell exits; exec leaves this file in tmpfs.
|
|
36
|
+
trap - EXIT HUP INT TERM
|
|
37
|
+
exec nginx -c "$config" -g 'daemon off;'
|