Compare commits

...

80 Commits

Author SHA1 Message Date
6d4e30e8a9 v11.5.1
Some checks failed
Docker (tags) / security (push) Failing after 3s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-19 16:54:39 +00:00
0e308b692b fix(project): no changes to commit 2026-03-19 16:54:39 +00:00
9f74b6e063 v11.5.0
Some checks failed
Docker (tags) / security (push) Failing after 3s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-19 16:41:16 +00:00
1d0f47f256 feat(opsserver): add configurable OpsServer port and update related tests and documentation 2026-03-19 16:41:16 +00:00
4e9301ae2a v11.4.0
Some checks failed
Docker (tags) / security (push) Failing after 2m0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-19 14:58:08 +00:00
7e2142ce53 feat(docs): document OCI container deployment and enable verbose docker build scripts 2026-03-19 14:58:08 +00:00
67190605a6 v11.3.0
Some checks failed
Docker (tags) / security (push) Failing after 13s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-18 16:22:02 +00:00
9479a07ddf feat(docker): add OCI container startup configuration and migrate Docker release pipeline to tsdocker 2026-03-18 16:22:02 +00:00
fbed56092f v11.2.56
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-18 00:13:58 +00:00
547b82b35b fix(deps): bump @serve.zone/remoteingress to ^4.9.0 2026-03-18 00:13:58 +00:00
3dc63fa02e v11.2.55
Some checks failed
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 23:29:58 +00:00
e0154f5b70 fix(deps): bump @serve.zone/catalog to ^2.7.0 and @serve.zone/remoteingress to ^4.8.18 2026-03-17 23:29:58 +00:00
b268409897 v11.2.54
Some checks failed
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 19:14:26 +00:00
f3a9fd12c5 fix(deps): bump @serve.zone/remoteingress to ^4.8.16 2026-03-17 19:14:26 +00:00
ef741d84fb v11.2.53
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 16:49:17 +00:00
b0ea97b922 fix(deps): bump @push.rocks/smartproxy and @serve.zone/remoteingress patch versions 2026-03-17 16:49:17 +00:00
d1560811f5 v11.2.52
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 15:51:31 +00:00
5e872c4e6a fix(deps): bump @serve.zone/remoteingress to ^4.8.13 2026-03-17 15:51:31 +00:00
3620e4549a v11.2.51
Some checks failed
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 13:28:33 +00:00
b32865e790 fix(deps): bump @serve.zone/remoteingress to ^4.8.12 2026-03-17 13:28:33 +00:00
ebe71a2a94 v11.2.50
Some checks failed
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 13:06:39 +00:00
877a2ad0ee fix(deps): bump @serve.zone/remoteingress to ^4.8.11 2026-03-17 13:06:39 +00:00
7be1aaedb3 v11.2.49
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 12:50:44 +00:00
05eb8e9723 fix(deps): bump @serve.zone/remoteingress to ^4.8.10 2026-03-17 12:50:44 +00:00
d95d89ea6f v11.2.48
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 12:36:14 +00:00
5d1b988579 fix(deps): bump @serve.zone/remoteingress to ^4.8.9 2026-03-17 12:36:14 +00:00
bae85eea9e v11.2.47
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 12:24:37 +00:00
2be7974991 fix(deps): bump @push.rocks/smartproxy to ^25.11.23 2026-03-17 12:24:37 +00:00
ac03b1f081 v11.2.46
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 12:13:49 +00:00
5ca209dd5a fix(deps): bump @push.rocks/smartproxy to ^25.11.22 2026-03-17 12:13:49 +00:00
867e93b246 v11.2.45
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 12:05:41 +00:00
aa9c4c1c28 fix(deps): bump @push.rocks/smartproxy and @serve.zone/remoteingress dependencies 2026-03-17 12:05:41 +00:00
207f21cb77 v11.2.44
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 11:18:11 +00:00
96a47ef588 fix(deps): bump @serve.zone/remoteingress to ^4.8.3 2026-03-17 11:18:11 +00:00
3bac80eb41 v11.2.43
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 10:35:25 +00:00
19d67a644c fix(deps): bump @serve.zone/remoteingress to ^4.8.2 2026-03-17 10:35:25 +00:00
341e4113bd v11.2.42
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 01:51:04 +00:00
81eb19a9ab fix(deps): bump @serve.zone/remoteingress to ^4.8.1 2026-03-17 01:51:04 +00:00
e0221c0d05 v11.2.41
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 01:33:47 +00:00
e6a1f23c84 fix(deps): bump @push.rocks/smartproxy to ^25.11.20 2026-03-17 01:33:47 +00:00
f77772e1c0 v11.2.40
Some checks failed
Docker (tags) / security (push) Failing after 4s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 01:00:41 +00:00
0a706c03c4 fix(deps): bump @serve.zone/remoteingress to ^4.8.0 2026-03-17 01:00:41 +00:00
df5547fda0 v11.2.39
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 00:43:03 +00:00
a677ee081c fix(repository): no changes to commit 2026-03-17 00:43:03 +00:00
7339a91513 v11.2.38
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-17 00:41:16 +00:00
cd27645489 fix(deps): bump @serve.zone/remoteingress to ^4.7.2 2026-03-17 00:41:16 +00:00
71f2d53e45 v11.2.37
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 23:36:55 +00:00
f74fcc68de fix(deps): bump @serve.zone/remoteingress to ^4.7.0 2026-03-16 23:36:55 +00:00
abcaf9c858 v11.2.36
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 20:58:17 +00:00
c9f185dd82 fix(deps): bump @push.rocks/smartproxy to ^25.11.19 2026-03-16 20:58:17 +00:00
5e3186d311 v11.2.35
Some checks failed
Docker (tags) / security (push) Failing after 3s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 20:01:59 +00:00
db35c01a09 fix(deps): bump @push.rocks/smartproxy, @serve.zone/catalog, and @serve.zone/remoteingress dependencies 2026-03-16 20:01:59 +00:00
3cf6c84a60 v11.2.34
Some checks failed
Docker (tags) / security (push) Failing after 2s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 14:32:19 +00:00
d570d5c916 fix(deps): bump @push.rocks/smartproxy and @serve.zone/catalog patch versions 2026-03-16 14:32:19 +00:00
4f6afb62f3 v11.2.33
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 14:12:00 +00:00
e5edfdc052 fix(deps): bump smartproxy and remoteingress dependencies 2026-03-16 14:12:00 +00:00
55cbb92a00 v11.2.32
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 13:49:26 +00:00
928be6a5c6 fix(deps): bump smartproxy and remoteingress dependencies 2026-03-16 13:49:26 +00:00
dff3e3c80d v11.2.31
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 13:03:33 +00:00
8db2118a78 fix(deps): bump @push.rocks/smartproxy to ^25.11.11 2026-03-16 13:03:33 +00:00
dc6da4ce34 v11.2.30
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 12:35:27 +00:00
63eb99ae5d fix(deps): bump @push.rocks/smartproxy and @serve.zone/catalog dependencies 2026-03-16 12:35:27 +00:00
6b533fba9f v11.2.29
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 11:31:30 +00:00
d3e102b6d2 fix(deps): bump @serve.zone/remoteingress to ^4.5.9 2026-03-16 11:31:30 +00:00
2bc9761d21 v11.2.28
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 10:53:17 +00:00
d60b9fb8e2 fix(deps): bump @serve.zone/remoteingress to ^4.5.8 2026-03-16 10:53:17 +00:00
b2705f3e88 v11.2.27
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 09:45:33 +00:00
4dea263cb0 fix(deps): bump smartproxy and remoteingress dependencies 2026-03-16 09:45:33 +00:00
54593d0a9b v11.2.26
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 09:03:08 +00:00
225a75a81b fix(deps): bump @serve.zone/remoteingress to ^4.5.5 2026-03-16 09:03:08 +00:00
72ae4e8a9b v11.2.25
Some checks failed
Docker (tags) / security (push) Failing after 2s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 08:59:55 +00:00
b171590179 fix(deps): bump @push.rocks/smartproxy to ^25.11.8 2026-03-16 08:59:55 +00:00
c46f79914f v11.2.24
Some checks failed
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 03:02:18 +00:00
914223972a fix(deps): bump @push.rocks/smartproxy to ^25.11.7 2026-03-16 03:02:18 +00:00
559435d13c v11.2.23
Some checks failed
Docker (tags) / security (push) Failing after 0s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 02:07:39 +00:00
47300e4ced fix(deps): bump @push.rocks/smartproxy to ^25.11.6 2026-03-16 02:07:39 +00:00
a35a35f302 v11.2.22
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-16 00:04:18 +00:00
3b09587ca9 fix(deps): bump @push.rocks/smartproxy to ^25.11.5 2026-03-16 00:04:18 +00:00
1cb2de2c3e v11.2.21
Some checks failed
Docker (tags) / security (push) Failing after 1s
Docker (tags) / test (push) Has been skipped
Docker (tags) / release (push) Has been skipped
Docker (tags) / metadata (push) Has been skipped
2026-03-15 23:47:30 +00:00
f972c38784 fix(deps): bump @push.rocks/smartproxy to ^25.11.4 2026-03-15 23:47:30 +00:00
25 changed files with 1377 additions and 979 deletions

View File

@@ -6,7 +6,7 @@ on:
- '**' - '**'
env: env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci IMAGE: code.foss.global/host.today/ht-docker-node:szci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}} NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}} NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}

View File

@@ -6,7 +6,7 @@ on:
- '*' - '*'
env: env:
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci IMAGE: code.foss.global/host.today/ht-docker-node:szci
NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git NPMCI_COMPUTED_REPOURL: https://${{gitea.repository_owner}}:${{secrets.GITEA_TOKEN}}@gitea.lossless.digital/${{gitea.repository}}.git
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}} NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}} NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
@@ -74,7 +74,7 @@ jobs:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: registry.gitlab.com/hosttoday/ht-docker-dbase:npmci image: code.foss.global/host.today/ht-docker-node:dbase_dind
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@@ -82,15 +82,13 @@ jobs:
- name: Prepare - name: Prepare
run: | run: |
pnpm install -g pnpm pnpm install -g pnpm
pnpm install -g @shipzone/npmci pnpm install -g @git.zone/tsdocker
- name: Release - name: Release
run: | run: |
npmci docker login tsdocker login
npmci docker build tsdocker build
npmci docker test tsdocker push
# npmci docker push gitea.lossless.digital
npmci docker push dockerregistry.lossless.digital
metadata: metadata:
needs: test needs: test

View File

@@ -1,44 +1,24 @@
# gitzone dockerfile_service # gitzone dockerfile_service
## STAGE 1 // BUILD ## STAGE 1 // BUILD
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node1 FROM code.foss.global/host.today/ht-docker-node:lts AS build
COPY ./ /app COPY ./ /app
WORKDIR /app WORKDIR /app
ARG NPMCI_TOKEN_NPM2
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
RUN npmci npm prepare
RUN pnpm config set store-dir .pnpm-store RUN pnpm config set store-dir .pnpm-store
RUN rm -rf node_modules && pnpm install RUN rm -rf node_modules && pnpm install
RUN pnpm run build RUN pnpm run build
RUN rm -rf .pnpm-store node_modules && pnpm install --prod
## STAGE 2 // PRODUCTION
FROM code.foss.global/host.today/ht-docker-node:alpine-node AS production
# gcompat + libstdc++ for glibc-linked Rust binaries (smartproxy, smartmta, remoteingress)
RUN apk add --no-cache gcompat libstdc++
# gitzone dockerfile_service
## STAGE 2 // install production
FROM registry.gitlab.com/hosttoday/ht-docker-node:npmci as node2
WORKDIR /app WORKDIR /app
COPY --from=node1 /app /app COPY --from=build /app /app
RUN rm -rf .pnpm-store
ARG NPMCI_TOKEN_NPM2
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
RUN npmci npm prepare
RUN pnpm config set store-dir .pnpm-store
RUN rm -rf node_modules/ && pnpm install --prod
ENV DCROUTER_MODE=OCI_CONTAINER
## STAGE 3 // rebuild dependencies for alpine
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpinenpmci as node3
WORKDIR /app
COPY --from=node2 /app /app
ARG NPMCI_TOKEN_NPM2
ENV NPMCI_TOKEN_NPM2 $NPMCI_TOKEN_NPM2
RUN npmci npm prepare
RUN pnpm config set store-dir .pnpm-store
RUN pnpm rebuild -r
## STAGE 4 // the final production image with all dependencies in place
FROM registry.gitlab.com/hosttoday/ht-docker-node:alpine as node4
WORKDIR /app
COPY --from=node3 /app /app
### Healthchecks
RUN pnpm install -g @servezone/healthy RUN pnpm install -g @servezone/healthy
HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=3 CMD [ "healthy" ] HEALTHCHECK --interval=30s --timeout=30s --start-period=30s --retries=3 CMD [ "healthy" ]

View File

@@ -1,5 +1,220 @@
# Changelog # Changelog
## 2026-03-19 - 11.5.1 - fix(project)
no changes to commit
## 2026-03-19 - 11.5.0 - feat(opsserver)
add configurable OpsServer port and update related tests and documentation
- introduces an optional `opsServerPort` configuration that overrides the default OpsServer port 3000
- updates OpsServer startup logic to use the configured port
- adjusts integration tests to run against dedicated OpsServer ports to avoid conflicts
- documents the new OpsServer port option in the README and TypeScript docs
- includes dependency updates and a remote ingress port range type refinement
## 2026-03-19 - 11.4.0 - feat(docs)
document OCI container deployment and enable verbose docker build scripts
- adds a new README section covering Docker/OCI container deployment, environment variables, and image build/push commands
- updates docker build and release npm scripts to pass the --verbose flag for more detailed output
## 2026-03-18 - 11.3.0 - feat(docker)
add OCI container startup configuration and migrate Docker release pipeline to tsdocker
- adds OCI container mode startup that reads DcRouter options from environment variables and an optional JSON config file
- simplifies the Docker image to a two-stage build with production dependencies only and Alpine runtime compatibility packages
- updates Gitea workflows and npm scripts to use tsdocker for image build and release
## 2026-03-18 - 11.2.56 - fix(deps)
bump @serve.zone/remoteingress to ^4.9.0
- Updates @serve.zone/remoteingress from ^4.8.18 to ^4.9.0 in package.json
## 2026-03-17 - 11.2.55 - fix(deps)
bump @serve.zone/catalog to ^2.7.0 and @serve.zone/remoteingress to ^4.8.18
- updates @serve.zone/catalog from ^2.6.2 to ^2.7.0
- updates @serve.zone/remoteingress from ^4.8.16 to ^4.8.18
## 2026-03-17 - 11.2.54 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.16
- Updates @serve.zone/remoteingress from ^4.8.14 to ^4.8.16 in package.json.
## 2026-03-17 - 11.2.53 - fix(deps)
bump @push.rocks/smartproxy and @serve.zone/remoteingress patch versions
- update @push.rocks/smartproxy from ^25.11.23 to ^25.11.24
- update @serve.zone/remoteingress from ^4.8.13 to ^4.8.14
## 2026-03-17 - 11.2.52 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.13
- Updates the @serve.zone/remoteingress dependency from ^4.8.12 to ^4.8.13.
## 2026-03-17 - 11.2.51 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.12
- Updates @serve.zone/remoteingress from ^4.8.11 to ^4.8.12 in package.json
## 2026-03-17 - 11.2.50 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.11
- updates @serve.zone/remoteingress from ^4.8.10 to ^4.8.11
## 2026-03-17 - 11.2.49 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.10
- Updates @serve.zone/remoteingress from ^4.8.9 to ^4.8.10 in package.json
## 2026-03-17 - 11.2.48 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.9
- Updates @serve.zone/remoteingress from ^4.8.7 to ^4.8.9 in package.json
## 2026-03-17 - 11.2.47 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.23
- Updates the @push.rocks/smartproxy dependency from ^25.11.22 to ^25.11.23 in package.json
## 2026-03-17 - 11.2.46 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.22
- Updates the @push.rocks/smartproxy dependency from ^25.11.21 to ^25.11.22 in package.json.
## 2026-03-17 - 11.2.45 - fix(deps)
bump @push.rocks/smartproxy and @serve.zone/remoteingress dependencies
- update @push.rocks/smartproxy from ^25.11.20 to ^25.11.21
- update @serve.zone/remoteingress from ^4.8.3 to ^4.8.7
## 2026-03-17 - 11.2.44 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.3
- Updates @serve.zone/remoteingress from ^4.8.2 to ^4.8.3 in package.json
## 2026-03-17 - 11.2.43 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.2
- Updates the @serve.zone/remoteingress dependency from ^4.8.1 to ^4.8.2.
## 2026-03-17 - 11.2.42 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.1
- Updates @serve.zone/remoteingress from ^4.8.0 to ^4.8.1 in package.json
## 2026-03-17 - 11.2.41 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.20
- Updates the @push.rocks/smartproxy dependency from ^25.11.19 to ^25.11.20 in package.json.
## 2026-03-17 - 11.2.40 - fix(deps)
bump @serve.zone/remoteingress to ^4.8.0
- Updates the @serve.zone/remoteingress dependency from ^4.7.2 to ^4.8.0 in package.json.
## 2026-03-17 - 11.2.39 - fix(repository)
no changes to commit
## 2026-03-17 - 11.2.38 - fix(deps)
bump @serve.zone/remoteingress to ^4.7.2
- Updates @serve.zone/remoteingress from ^4.7.0 to ^4.7.2 in package.json
## 2026-03-16 - 11.2.37 - fix(deps)
bump @serve.zone/remoteingress to ^4.7.0
- updates the @serve.zone/remoteingress dependency from ^4.6.0 to ^4.7.0
## 2026-03-16 - 11.2.36 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.19
- Updates the @push.rocks/smartproxy dependency from ^25.11.18 to ^25.11.19 in package.json
## 2026-03-16 - 11.2.35 - fix(deps)
bump @push.rocks/smartproxy, @serve.zone/catalog, and @serve.zone/remoteingress dependencies
- updates @push.rocks/smartproxy from ^25.11.17 to ^25.11.18
- updates @serve.zone/catalog from ^2.6.1 to ^2.6.2
- updates @serve.zone/remoteingress from ^4.5.11 to ^4.6.0
## 2026-03-16 - 11.2.34 - fix(deps)
bump @push.rocks/smartproxy and @serve.zone/catalog patch versions
- updates @push.rocks/smartproxy from ^25.11.16 to ^25.11.17
- updates @serve.zone/catalog from ^2.6.0 to ^2.6.1
## 2026-03-16 - 11.2.33 - fix(deps)
bump smartproxy and remoteingress dependencies
- update @push.rocks/smartproxy from ^25.11.14 to ^25.11.16
- update @serve.zone/remoteingress from ^4.5.10 to ^4.5.11
## 2026-03-16 - 11.2.32 - fix(deps)
bump smartproxy and remoteingress dependencies
- update @push.rocks/smartproxy from ^25.11.11 to ^25.11.14
- update @serve.zone/remoteingress from ^4.5.9 to ^4.5.10
## 2026-03-16 - 11.2.31 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.11
- Updates the @push.rocks/smartproxy dependency from ^25.11.10 to ^25.11.11 in package.json.
## 2026-03-16 - 11.2.30 - fix(deps)
bump @push.rocks/smartproxy and @serve.zone/catalog dependencies
- update @push.rocks/smartproxy from ^25.11.9 to ^25.11.10
- update @serve.zone/catalog from ^2.5.0 to ^2.6.0
## 2026-03-16 - 11.2.29 - fix(deps)
bump @serve.zone/remoteingress to ^4.5.9
- Updates @serve.zone/remoteingress from ^4.5.8 to ^4.5.9 in package.json
## 2026-03-16 - 11.2.28 - fix(deps)
bump @serve.zone/remoteingress to ^4.5.8
- Updates the @serve.zone/remoteingress dependency from ^4.5.7 to ^4.5.8.
## 2026-03-16 - 11.2.27 - fix(deps)
bump smartproxy and remoteingress dependencies
- update @push.rocks/smartproxy from ^25.11.8 to ^25.11.9
- update @serve.zone/remoteingress from ^4.5.5 to ^4.5.7
## 2026-03-16 - 11.2.26 - fix(deps)
bump @serve.zone/remoteingress to ^4.5.5
- Updates the @serve.zone/remoteingress dependency from ^4.5.4 to ^4.5.5.
## 2026-03-16 - 11.2.25 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.8
- updates the smartproxy dependency from ^25.11.7 to ^25.11.8
## 2026-03-16 - 11.2.24 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.7
- Updates the @push.rocks/smartproxy dependency from ^25.11.6 to ^25.11.7.
## 2026-03-16 - 11.2.23 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.6
- Updates the @push.rocks/smartproxy dependency from ^25.11.5 to ^25.11.6.
## 2026-03-16 - 11.2.22 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.5
- updates the @push.rocks/smartproxy dependency from ^25.11.4 to ^25.11.5
## 2026-03-15 - 11.2.21 - fix(deps)
bump @push.rocks/smartproxy to ^25.11.4
- updates the @push.rocks/smartproxy dependency from ^25.11.3 to ^25.11.4
## 2026-03-15 - 11.2.20 - fix(deps) ## 2026-03-15 - 11.2.20 - fix(deps)
bump @serve.zone/remoteingress to ^4.5.4 bump @serve.zone/remoteingress to ^4.5.4

View File

@@ -72,9 +72,14 @@
"dockerRegistryRepoMap": { "dockerRegistryRepoMap": {
"registry.gitlab.com": "code.foss.global/serve.zone/dcrouter" "registry.gitlab.com": "code.foss.global/serve.zone/dcrouter"
}, },
"dockerBuildargEnvMap": {
"NPMCI_TOKEN_NPM2": "NPMCI_TOKEN_NPM2"
},
"npmRegistryUrl": "verdaccio.lossless.digital" "npmRegistryUrl": "verdaccio.lossless.digital"
},
"@git.zone/tsdocker": {
"registries": ["code.foss.global"],
"registryRepoMap": {
"code.foss.global": "serve.zone/dcrouter",
"dockerregistry.lossless.digital": "serve.zone/dcrouter"
},
"platforms": ["linux/amd64", "linux/arm64"]
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "@serve.zone/dcrouter", "name": "@serve.zone/dcrouter",
"private": false, "private": false,
"version": "11.2.20", "version": "11.5.1",
"description": "A multifaceted routing service handling mail and SMS delivery functions.", "description": "A multifaceted routing service handling mail and SMS delivery functions.",
"type": "module", "type": "module",
"exports": { "exports": {
@@ -16,6 +16,8 @@
"start": "(node --max_old_space_size=250 ./cli.js)", "start": "(node --max_old_space_size=250 ./cli.js)",
"startTs": "(node cli.ts.js)", "startTs": "(node cli.ts.js)",
"build": "(tsbuild tsfolders --allowimplicitany && npm run bundle)", "build": "(tsbuild tsfolders --allowimplicitany && npm run bundle)",
"build:docker": "tsdocker build --verbose",
"release:docker": "tsdocker push --verbose",
"bundle": "(tsbundle)", "bundle": "(tsbundle)",
"watch": "tswatch" "watch": "tswatch"
}, },
@@ -23,7 +25,7 @@
"@git.zone/tsbuild": "^4.3.0", "@git.zone/tsbuild": "^4.3.0",
"@git.zone/tsbundle": "^2.9.1", "@git.zone/tsbundle": "^2.9.1",
"@git.zone/tsrun": "^2.0.1", "@git.zone/tsrun": "^2.0.1",
"@git.zone/tstest": "^3.3.2", "@git.zone/tstest": "^3.5.0",
"@git.zone/tswatch": "^3.3.0", "@git.zone/tswatch": "^3.3.0",
"@types/node": "^25.5.0" "@types/node": "^25.5.0"
}, },
@@ -38,7 +40,7 @@
"@push.rocks/lik": "^6.3.1", "@push.rocks/lik": "^6.3.1",
"@push.rocks/projectinfo": "^5.0.2", "@push.rocks/projectinfo": "^5.0.2",
"@push.rocks/qenv": "^6.1.3", "@push.rocks/qenv": "^6.1.3",
"@push.rocks/smartacme": "^9.1.3", "@push.rocks/smartacme": "^9.3.0",
"@push.rocks/smartdata": "^7.1.0", "@push.rocks/smartdata": "^7.1.0",
"@push.rocks/smartdns": "^7.9.0", "@push.rocks/smartdns": "^7.9.0",
"@push.rocks/smartfile": "^13.1.2", "@push.rocks/smartfile": "^13.1.2",
@@ -51,15 +53,15 @@
"@push.rocks/smartnetwork": "^4.4.0", "@push.rocks/smartnetwork": "^4.4.0",
"@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpath": "^6.0.0",
"@push.rocks/smartpromise": "^4.2.3", "@push.rocks/smartpromise": "^4.2.3",
"@push.rocks/smartproxy": "^25.11.3", "@push.rocks/smartproxy": "^25.14.1",
"@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartradius": "^1.1.1",
"@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrequest": "^5.0.1",
"@push.rocks/smartrx": "^3.0.10", "@push.rocks/smartrx": "^3.0.10",
"@push.rocks/smartstate": "^2.2.0", "@push.rocks/smartstate": "^2.2.0",
"@push.rocks/smartunique": "^3.0.9", "@push.rocks/smartunique": "^3.0.9",
"@serve.zone/catalog": "^2.5.0", "@serve.zone/catalog": "^2.9.0",
"@serve.zone/interfaces": "^5.3.0", "@serve.zone/interfaces": "^5.3.0",
"@serve.zone/remoteingress": "^4.5.4", "@serve.zone/remoteingress": "^4.13.0",
"@tsclass/tsclass": "^9.4.0", "@tsclass/tsclass": "^9.4.0",
"lru-cache": "^11.2.7", "lru-cache": "^11.2.7",
"uuid": "^13.0.0" "uuid": "^13.0.0"

1811
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -30,6 +30,7 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
- [API Reference](#api-reference) - [API Reference](#api-reference)
- [Sub-Modules](#sub-modules) - [Sub-Modules](#sub-modules)
- [Testing](#testing) - [Testing](#testing)
- [Docker / OCI Container Deployment](#docker--oci-container-deployment)
- [License and Legal Information](#license-and-legal-information) - [License and Legal Information](#license-and-legal-information)
## Features ## Features
@@ -343,7 +344,7 @@ graph TB
DcRouter acts purely as an **orchestrator** — it doesn't implement protocols itself. Instead, it wires together best-in-class packages for each protocol: DcRouter acts purely as an **orchestrator** — it doesn't implement protocols itself. Instead, it wires together best-in-class packages for each protocol:
1. **On `start()`**: DcRouter initializes OpsServer (port 3000), then spins up SmartProxy, smartmta, SmartDNS, SmartRadius, and RemoteIngress based on which configs are provided. 1. **On `start()`**: DcRouter initializes OpsServer (default port 3000, configurable via `opsServerPort`), then spins up SmartProxy, smartmta, SmartDNS, SmartRadius, and RemoteIngress based on which configs are provided.
2. **During operation**: Each service handles its own protocol independently. SmartProxy uses a Rust-powered engine for maximum throughput. smartmta uses a hybrid TypeScript + Rust architecture for reliable email delivery. RemoteIngress runs a Rust data plane for edge tunnel networking. SmartAcme v9 handles all certificate operations with built-in concurrency control and rate limiting. 2. **During operation**: Each service handles its own protocol independently. SmartProxy uses a Rust-powered engine for maximum throughput. smartmta uses a hybrid TypeScript + Rust architecture for reliable email delivery. RemoteIngress runs a Rust data plane for edge tunnel networking. SmartAcme v9 handles all certificate operations with built-in concurrency control and rate limiting.
3. **On `stop()`**: All services are gracefully shut down in parallel, including cleanup of HTTP agents and DNS clients. 3. **On `stop()`**: All services are gracefully shut down in parallel, including cleanup of HTTP agents and DNS clients.
@@ -424,6 +425,10 @@ interface IDcRouterOptions {
}; };
}; };
// ── OpsServer ────────────────────────────────────────────────
/** Port for the OpsServer web dashboard (default: 3000) */
opsServerPort?: number;
// ── TLS & Certificates ──────────────────────────────────────── // ── TLS & Certificates ────────────────────────────────────────
tls?: { tls?: {
contactEmail: string; contactEmail: string;
@@ -1015,7 +1020,7 @@ action: {
## OpsServer Dashboard ## OpsServer Dashboard
The OpsServer provides a web-based management interface served on port 3000. It's built with modern web components using [@design.estate/dees-catalog](https://code.foss.global/design.estate/dees-catalog). The OpsServer provides a web-based management interface served on port 3000 by default (configurable via `opsServerPort`). It's built with modern web components using [@design.estate/dees-catalog](https://code.foss.global/design.estate/dees-catalog).
### Dashboard Views ### Dashboard Views
@@ -1278,6 +1283,49 @@ tstest test/test.opsserver-api.ts --verbose --timeout 60
| `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 | | `test.protected-endpoint.ts` | Admin auth, identity verification, public endpoints | 8 |
| `test.storagemanager.ts` | Memory, filesystem, custom backends, concurrency | 8 | | `test.storagemanager.ts` | Memory, filesystem, custom backends, concurrency | 8 |
## Docker / OCI Container Deployment
DcRouter ships with a `Dockerfile` and supports environment-variable-driven configuration for OCI container deployments. When `DCROUTER_MODE=OCI_CONTAINER` is set, DcRouter automatically reads configuration from environment variables (and optionally from a JSON config file).
### Running with Docker
```bash
docker run -d \
-e DCROUTER_MODE=OCI_CONTAINER \
-e DCROUTER_TLS_EMAIL=admin@example.com \
-e DCROUTER_PUBLIC_IP=203.0.113.1 \
-e DCROUTER_DNS_NS_DOMAINS=ns1.example.com,ns2.example.com \
-e DCROUTER_DNS_SCOPES=example.com \
-p 80:80 -p 443:443 -p 25:25 -p 53:53/udp -p 3000:3000 \
code.foss.global/serve.zone/dcrouter:latest
```
### Environment Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `DCROUTER_MODE` | Set to `OCI_CONTAINER` to enable container mode | `OCI_CONTAINER` |
| `DCROUTER_CONFIG_PATH` | Path to a JSON config file (loaded as base, env vars override) | `/config/dcrouter.json` |
| `DCROUTER_BASE_DIR` | Override base data directory | `/data/dcrouter` |
| `DCROUTER_TLS_EMAIL` | ACME contact email | `admin@example.com` |
| `DCROUTER_TLS_DOMAIN` | Primary TLS domain | `example.com` |
| `DCROUTER_PUBLIC_IP` | Public IP for DNS records | `203.0.113.1` |
| `DCROUTER_PROXY_IPS` | Comma-separated ingress proxy IPs | `198.51.100.1,198.51.100.2` |
| `DCROUTER_DNS_NS_DOMAINS` | Comma-separated nameserver domains | `ns1.example.com,ns2.example.com` |
| `DCROUTER_DNS_SCOPES` | Comma-separated authoritative domains | `example.com,other.com` |
| `DCROUTER_EMAIL_HOSTNAME` | SMTP server hostname | `mail.example.com` |
| `DCROUTER_EMAIL_PORTS` | Comma-separated email ports | `25,587,465` |
| `DCROUTER_CACHE_ENABLED` | Enable/disable cache database | `true` |
### Building the Image
```bash
pnpm run build:docker # Build the container image
pnpm run release:docker # Push to registry
```
The Docker build supports multi-platform (`linux/amd64`, `linux/arm64`) via [tsdocker](https://code.foss.global/git.zone/tsdocker).
## License and Legal Information ## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file. This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.

View File

@@ -129,6 +129,7 @@ tap.test('DcRouter class - Email config with domains and routes', async () => {
tls: { tls: {
contactEmail: 'test@example.com' contactEmail: 'test@example.com'
}, },
opsServerPort: 3104,
cacheConfig: { cacheConfig: {
enabled: false, enabled: false,
} }

View File

@@ -9,6 +9,7 @@ tap.test('should NOT instantiate DNS server when dnsNsDomains is not set', async
smartProxyConfig: { smartProxyConfig: {
routes: [] routes: []
}, },
opsServerPort: 3100,
cacheConfig: { enabled: false } cacheConfig: { enabled: false }
}); });

View File

@@ -9,6 +9,7 @@ let identity: interfaces.data.IIdentity;
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
// Minimal config for testing // Minimal config for testing
opsServerPort: 3102,
cacheConfig: { enabled: false }, cacheConfig: { enabled: false },
}); });
@@ -18,7 +19,7 @@ tap.test('should start DCRouter with OpsServer', async () => {
tap.test('should login with admin credentials and receive JWT', async () => { tap.test('should login with admin credentials and receive JWT', async () => {
const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>( const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
'http://localhost:3000/typedrequest', 'http://localhost:3102/typedrequest',
'adminLoginWithUsernameAndPassword' 'adminLoginWithUsernameAndPassword'
); );
@@ -41,7 +42,7 @@ tap.test('should login with admin credentials and receive JWT', async () => {
tap.test('should verify valid JWT identity', async () => { tap.test('should verify valid JWT identity', async () => {
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>( const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
'http://localhost:3000/typedrequest', 'http://localhost:3102/typedrequest',
'verifyIdentity' 'verifyIdentity'
); );
@@ -57,7 +58,7 @@ tap.test('should verify valid JWT identity', async () => {
tap.test('should reject invalid JWT', async () => { tap.test('should reject invalid JWT', async () => {
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>( const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
'http://localhost:3000/typedrequest', 'http://localhost:3102/typedrequest',
'verifyIdentity' 'verifyIdentity'
); );
@@ -74,7 +75,7 @@ tap.test('should reject invalid JWT', async () => {
tap.test('should verify JWT matches identity data', async () => { tap.test('should verify JWT matches identity data', async () => {
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>( const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
'http://localhost:3000/typedrequest', 'http://localhost:3102/typedrequest',
'verifyIdentity' 'verifyIdentity'
); );
@@ -91,7 +92,7 @@ tap.test('should verify JWT matches identity data', async () => {
tap.test('should handle logout', async () => { tap.test('should handle logout', async () => {
const logoutRequest = new TypedRequest<interfaces.requests.IReq_AdminLogout>( const logoutRequest = new TypedRequest<interfaces.requests.IReq_AdminLogout>(
'http://localhost:3000/typedrequest', 'http://localhost:3102/typedrequest',
'adminLogout' 'adminLogout'
); );
@@ -105,7 +106,7 @@ tap.test('should handle logout', async () => {
tap.test('should reject wrong credentials', async () => { tap.test('should reject wrong credentials', async () => {
const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>( const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
'http://localhost:3000/typedrequest', 'http://localhost:3102/typedrequest',
'adminLoginWithUsernameAndPassword' 'adminLoginWithUsernameAndPassword'
); );

View File

@@ -9,6 +9,7 @@ let adminIdentity: interfaces.data.IIdentity;
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
// Minimal config for testing // Minimal config for testing
opsServerPort: 3101,
cacheConfig: { enabled: false }, cacheConfig: { enabled: false },
}); });
@@ -18,7 +19,7 @@ tap.test('should start DCRouter with OpsServer', async () => {
tap.test('should login as admin', async () => { tap.test('should login as admin', async () => {
const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>( const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
'http://localhost:3000/typedrequest', 'http://localhost:3101/typedrequest',
'adminLoginWithUsernameAndPassword' 'adminLoginWithUsernameAndPassword'
); );
@@ -33,7 +34,7 @@ tap.test('should login as admin', async () => {
tap.test('should respond to health status request', async () => { tap.test('should respond to health status request', async () => {
const healthRequest = new TypedRequest<interfaces.requests.IReq_GetHealthStatus>( const healthRequest = new TypedRequest<interfaces.requests.IReq_GetHealthStatus>(
'http://localhost:3000/typedrequest', 'http://localhost:3101/typedrequest',
'getHealthStatus' 'getHealthStatus'
); );
@@ -49,7 +50,7 @@ tap.test('should respond to health status request', async () => {
tap.test('should respond to server statistics request', async () => { tap.test('should respond to server statistics request', async () => {
const statsRequest = new TypedRequest<interfaces.requests.IReq_GetServerStatistics>( const statsRequest = new TypedRequest<interfaces.requests.IReq_GetServerStatistics>(
'http://localhost:3000/typedrequest', 'http://localhost:3101/typedrequest',
'getServerStatistics' 'getServerStatistics'
); );
@@ -66,7 +67,7 @@ tap.test('should respond to server statistics request', async () => {
tap.test('should respond to configuration request', async () => { tap.test('should respond to configuration request', async () => {
const configRequest = new TypedRequest<interfaces.requests.IReq_GetConfiguration>( const configRequest = new TypedRequest<interfaces.requests.IReq_GetConfiguration>(
'http://localhost:3000/typedrequest', 'http://localhost:3101/typedrequest',
'getConfiguration' 'getConfiguration'
); );
@@ -87,7 +88,7 @@ tap.test('should respond to configuration request', async () => {
tap.test('should handle log retrieval request', async () => { tap.test('should handle log retrieval request', async () => {
const logsRequest = new TypedRequest<interfaces.requests.IReq_GetRecentLogs>( const logsRequest = new TypedRequest<interfaces.requests.IReq_GetRecentLogs>(
'http://localhost:3000/typedrequest', 'http://localhost:3101/typedrequest',
'getRecentLogs' 'getRecentLogs'
); );
@@ -104,7 +105,7 @@ tap.test('should handle log retrieval request', async () => {
tap.test('should reject unauthenticated requests', async () => { tap.test('should reject unauthenticated requests', async () => {
const healthRequest = new TypedRequest<interfaces.requests.IReq_GetHealthStatus>( const healthRequest = new TypedRequest<interfaces.requests.IReq_GetHealthStatus>(
'http://localhost:3000/typedrequest', 'http://localhost:3101/typedrequest',
'getHealthStatus' 'getHealthStatus'
); );

View File

@@ -9,6 +9,7 @@ let adminIdentity: interfaces.data.IIdentity;
tap.test('should start DCRouter with OpsServer', async () => { tap.test('should start DCRouter with OpsServer', async () => {
testDcRouter = new DcRouter({ testDcRouter = new DcRouter({
// Minimal config for testing // Minimal config for testing
opsServerPort: 3103,
cacheConfig: { enabled: false }, cacheConfig: { enabled: false },
}); });
@@ -18,7 +19,7 @@ tap.test('should start DCRouter with OpsServer', async () => {
tap.test('should login as admin', async () => { tap.test('should login as admin', async () => {
const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>( const loginRequest = new TypedRequest<interfaces.requests.IReq_AdminLoginWithUsernameAndPassword>(
'http://localhost:3000/typedrequest', 'http://localhost:3103/typedrequest',
'adminLoginWithUsernameAndPassword' 'adminLoginWithUsernameAndPassword'
); );
@@ -34,7 +35,7 @@ tap.test('should login as admin', async () => {
tap.test('should allow admin to verify identity', async () => { tap.test('should allow admin to verify identity', async () => {
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>( const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
'http://localhost:3000/typedrequest', 'http://localhost:3103/typedrequest',
'verifyIdentity' 'verifyIdentity'
); );
@@ -49,7 +50,7 @@ tap.test('should allow admin to verify identity', async () => {
tap.test('should reject verify identity without identity', async () => { tap.test('should reject verify identity without identity', async () => {
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>( const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
'http://localhost:3000/typedrequest', 'http://localhost:3103/typedrequest',
'verifyIdentity' 'verifyIdentity'
); );
@@ -64,7 +65,7 @@ tap.test('should reject verify identity without identity', async () => {
tap.test('should reject verify identity with invalid JWT', async () => { tap.test('should reject verify identity with invalid JWT', async () => {
const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>( const verifyRequest = new TypedRequest<interfaces.requests.IReq_VerifyIdentity>(
'http://localhost:3000/typedrequest', 'http://localhost:3103/typedrequest',
'verifyIdentity' 'verifyIdentity'
); );
@@ -84,7 +85,7 @@ tap.test('should reject verify identity with invalid JWT', async () => {
tap.test('should reject protected endpoints without auth', async () => { tap.test('should reject protected endpoints without auth', async () => {
const healthRequest = new TypedRequest<interfaces.requests.IReq_GetHealthStatus>( const healthRequest = new TypedRequest<interfaces.requests.IReq_GetHealthStatus>(
'http://localhost:3000/typedrequest', 'http://localhost:3103/typedrequest',
'getHealthStatus' 'getHealthStatus'
); );
@@ -100,7 +101,7 @@ tap.test('should reject protected endpoints without auth', async () => {
tap.test('should allow authenticated access to protected endpoints', async () => { tap.test('should allow authenticated access to protected endpoints', async () => {
const configRequest = new TypedRequest<interfaces.requests.IReq_GetConfiguration>( const configRequest = new TypedRequest<interfaces.requests.IReq_GetConfiguration>(
'http://localhost:3000/typedrequest', 'http://localhost:3103/typedrequest',
'getConfiguration' 'getConfiguration'
); );

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '11.2.20', version: '11.5.1',
description: 'A multifaceted routing service handling mail and SMS delivery functions.' description: 'A multifaceted routing service handling mail and SMS delivery functions.'
} }

View File

@@ -163,6 +163,9 @@ export interface IDcRouterOptions {
* Remote Ingress configuration for edge tunnel nodes * Remote Ingress configuration for edge tunnel nodes
* Enables edge nodes to accept incoming connections and tunnel them to this DcRouter * Enables edge nodes to accept incoming connections and tunnel them to this DcRouter
*/ */
/** Port for the OpsServer web UI (default: 3000) */
opsServerPort?: number;
remoteIngressConfig?: { remoteIngressConfig?: {
/** Enable remote ingress hub (default: false) */ /** Enable remote ingress hub (default: false) */
enabled?: boolean; enabled?: boolean;

View File

@@ -5,6 +5,7 @@ export { UnifiedEmailServer } from '@push.rocks/smartmta';
export type { IUnifiedEmailServerOptions, IEmailRoute, IEmailDomainConfig } from '@push.rocks/smartmta'; export type { IUnifiedEmailServerOptions, IEmailRoute, IEmailDomainConfig } from '@push.rocks/smartmta';
// DcRouter // DcRouter
import { DcRouter } from './classes.dcrouter.js';
export * from './classes.dcrouter.js'; export * from './classes.dcrouter.js';
// RADIUS module // RADIUS module
@@ -13,4 +14,24 @@ export * from './radius/index.js';
// Remote Ingress module // Remote Ingress module
export * from './remoteingress/index.js'; export * from './remoteingress/index.js';
export const runCli = async () => {}; export const runCli = async () => {
let options: import('./classes.dcrouter.js').IDcRouterOptions = {};
if (process.env.DCROUTER_MODE === 'OCI_CONTAINER') {
const { getOciContainerConfig } = await import('../ts_oci_container/index.js');
options = getOciContainerConfig();
console.log('[DCRouter] Starting in OCI Container mode...');
}
const dcRouter = new DcRouter(options);
await dcRouter.start();
console.log('[DCRouter] Running. Send SIGTERM or SIGINT to stop.');
const shutdown = async () => {
console.log('[DCRouter] Shutting down...');
await dcRouter.stop();
process.exit(0);
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
};

View File

@@ -50,7 +50,7 @@ export class OpsServer {
// Set up handlers // Set up handlers
await this.setupHandlers(); await this.setupHandlers();
await this.server.start(3000); await this.server.start(this.dcRouterRef.options.opsServerPort ?? 3000);
} }
/** /**

View File

@@ -37,7 +37,7 @@ const router = new DcRouter({
}); });
await router.start(); await router.start();
// OpsServer dashboard at http://localhost:3000 // OpsServer dashboard at http://localhost:3000 (configurable via opsServerPort)
// Graceful shutdown // Graceful shutdown
await router.stop(); await router.stop();
@@ -71,7 +71,10 @@ ts/
│ ├── email.handler.ts # Email operations │ ├── email.handler.ts # Email operations
│ ├── certificate.handler.ts # Certificate management │ ├── certificate.handler.ts # Certificate management
│ ├── radius.handler.ts # RADIUS management │ ├── radius.handler.ts # RADIUS management
── remoteingress.handler.ts # Remote ingress edge + token management ── remoteingress.handler.ts # Remote ingress edge + token management
│ ├── route-management.handler.ts # Programmatic route CRUD
│ ├── api-token.handler.ts # API token management
│ └── security.handler.ts # Security metrics + connections
├── radius/ # RADIUS server integration ├── radius/ # RADIUS server integration
├── remoteingress/ # Remote ingress hub integration ├── remoteingress/ # Remote ingress hub integration
│ ├── classes.remoteingress-manager.ts # Edge CRUD + port derivation │ ├── classes.remoteingress-manager.ts # Edge CRUD + port derivation

View File

@@ -7,7 +7,7 @@ const STORAGE_PREFIX = '/remote-ingress/';
/** /**
* Flatten a port range (number | number[] | Array<{from, to}>) to a sorted unique number array. * Flatten a port range (number | number[] | Array<{from, to}>) to a sorted unique number array.
*/ */
function extractPorts(portRange: number | number[] | Array<{ from: number; to: number }>): number[] { function extractPorts(portRange: number | Array<number | { from: number; to: number }>): number[] {
const ports = new Set<number>(); const ports = new Set<number>();
if (typeof portRange === 'number') { if (typeof portRange === 'number') {
ports.add(portRange); ports.add(portRange);

100
ts_oci_container/index.ts Normal file
View File

@@ -0,0 +1,100 @@
import * as plugins from './plugins.js';
import type { IDcRouterOptions } from '../ts/classes.dcrouter.js';
/**
* Parses a comma-separated env var into a string array.
* Returns undefined if the env var is not set or empty.
*/
function parseCommaSeparated(envVar: string | undefined): string[] | undefined {
if (!envVar || envVar.trim() === '') return undefined;
return envVar.split(',').map((s) => s.trim()).filter(Boolean);
}
/**
* Parses a comma-separated env var into a number array.
* Returns undefined if the env var is not set or empty.
*/
function parseCommaSeparatedNumbers(envVar: string | undefined): number[] | undefined {
const parts = parseCommaSeparated(envVar);
if (!parts) return undefined;
return parts.map((s) => parseInt(s, 10)).filter((n) => !isNaN(n));
}
/**
* Builds IDcRouterOptions from environment variables for OCI container mode.
*
* If DCROUTER_CONFIG_PATH is set and the file exists, it is loaded as a JSON base config.
* Individual env vars are then applied as overrides on top.
*/
export function getOciContainerConfig(): IDcRouterOptions {
let options: IDcRouterOptions = {};
// Load JSON config file if specified
const configPath = process.env.DCROUTER_CONFIG_PATH;
if (configPath && plugins.fs.existsSync(configPath)) {
const raw = plugins.fs.readFileSync(configPath, 'utf8');
options = JSON.parse(raw);
console.log(`[OCI Container] Loaded config from ${configPath}`);
}
// Apply env var overrides
if (process.env.DCROUTER_BASE_DIR) {
options.baseDir = process.env.DCROUTER_BASE_DIR;
}
// TLS config
const tlsEmail = process.env.DCROUTER_TLS_EMAIL;
const tlsDomain = process.env.DCROUTER_TLS_DOMAIN;
if (tlsEmail || tlsDomain) {
options.tls = {
...options.tls,
contactEmail: tlsEmail || options.tls?.contactEmail || '',
...(tlsDomain ? { domain: tlsDomain } : {}),
};
}
// Network config
if (process.env.DCROUTER_PUBLIC_IP) {
options.publicIp = process.env.DCROUTER_PUBLIC_IP;
}
const proxyIps = parseCommaSeparated(process.env.DCROUTER_PROXY_IPS);
if (proxyIps) {
options.proxyIps = proxyIps;
}
// DNS config
const nsDomains = parseCommaSeparated(process.env.DCROUTER_DNS_NS_DOMAINS);
if (nsDomains) {
options.dnsNsDomains = nsDomains;
}
const dnsScopes = parseCommaSeparated(process.env.DCROUTER_DNS_SCOPES);
if (dnsScopes) {
options.dnsScopes = dnsScopes;
}
// Email config
const emailHostname = process.env.DCROUTER_EMAIL_HOSTNAME;
const emailPorts = parseCommaSeparatedNumbers(process.env.DCROUTER_EMAIL_PORTS);
if (emailHostname || emailPorts) {
options.emailConfig = {
...options.emailConfig,
...(emailHostname ? { hostname: emailHostname } : {}),
...(emailPorts ? { ports: emailPorts } : {}),
domains: options.emailConfig?.domains || [],
routes: options.emailConfig?.routes || [],
} as IDcRouterOptions['emailConfig'];
}
// Cache config
const cacheEnabled = process.env.DCROUTER_CACHE_ENABLED;
if (cacheEnabled !== undefined) {
options.cacheConfig = {
...options.cacheConfig,
enabled: cacheEnabled === 'true',
};
}
return options;
}

View File

@@ -0,0 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
export {
fs,
path,
};

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '11.2.20', version: '11.5.1',
description: 'A multifaceted routing service handling mail and SMS delivery functions.' description: 'A multifaceted routing service handling mail and SMS delivery functions.'
} }