generated from coulomb/repo-seed
Remove public Gitea NodePort side door
All checks were successful
Forge Runner Smoke / compatibility-smoke (push) Successful in 0s
All checks were successful
Forge Runner Smoke / compatibility-smoke (push) Successful in 0s
This commit is contained in:
5
Makefile
5
Makefile
@@ -7,6 +7,8 @@ GITEA_CHART ?= gitea-charts/gitea
|
|||||||
GITEA_VALUES ?= helm/gitea-values.sops.yaml
|
GITEA_VALUES ?= helm/gitea-values.sops.yaml
|
||||||
GITEA_REGISTRY_VALUES ?= helm/gitea-registry-values.yaml
|
GITEA_REGISTRY_VALUES ?= helm/gitea-registry-values.yaml
|
||||||
GITEA_INGRESS ?= manifests/gitea-ingress.yaml
|
GITEA_INGRESS ?= manifests/gitea-ingress.yaml
|
||||||
|
GITEA_HTTP_SERVICE ?= gitea-http
|
||||||
|
GITEA_SSH_SERVICE ?= gitea-ssh-nodeport
|
||||||
GITEA_DB_CLUSTER ?= gitea-db
|
GITEA_DB_CLUSTER ?= gitea-db
|
||||||
GITEA_DB_NAMESPACE ?= databases
|
GITEA_DB_NAMESPACE ?= databases
|
||||||
REGISTRY_DOCS ?= docs/gitea-container-registry.md docs/gitea-package-registry.md
|
REGISTRY_DOCS ?= docs/gitea-container-registry.md docs/gitea-package-registry.md
|
||||||
@@ -89,7 +91,8 @@ gitea-ingress-deploy: ## Apply the public Gitea HTTPS ingress
|
|||||||
|
|
||||||
gitea-status: ## Read-only status for current Gitea runtime and database
|
gitea-status: ## Read-only status for current Gitea runtime and database
|
||||||
kubectl get pods -n $(GITEA_NAMESPACE) -l app.kubernetes.io/instance=$(GITEA_RELEASE)
|
kubectl get pods -n $(GITEA_NAMESPACE) -l app.kubernetes.io/instance=$(GITEA_RELEASE)
|
||||||
kubectl get svc -n $(GITEA_NAMESPACE) $(GITEA_RELEASE) --ignore-not-found
|
kubectl get svc -n $(GITEA_NAMESPACE) $(GITEA_HTTP_SERVICE) --ignore-not-found
|
||||||
|
kubectl get svc -n $(GITEA_NAMESPACE) $(GITEA_SSH_SERVICE) --ignore-not-found
|
||||||
kubectl get ingress -n $(GITEA_NAMESPACE) $(GITEA_RELEASE) --ignore-not-found
|
kubectl get ingress -n $(GITEA_NAMESPACE) $(GITEA_RELEASE) --ignore-not-found
|
||||||
@if kubectl cnpg status $(GITEA_DB_CLUSTER) -n $(GITEA_DB_NAMESPACE) >/dev/null 2>&1; then \
|
@if kubectl cnpg status $(GITEA_DB_CLUSTER) -n $(GITEA_DB_NAMESPACE) >/dev/null 2>&1; then \
|
||||||
kubectl cnpg status $(GITEA_DB_CLUSTER) -n $(GITEA_DB_NAMESPACE); \
|
kubectl cnpg status $(GITEA_DB_CLUSTER) -n $(GITEA_DB_NAMESPACE); \
|
||||||
|
|||||||
3
SCOPE.md
3
SCOPE.md
@@ -117,7 +117,8 @@ The Fabric graph declarations for forge capabilities and edges live in
|
|||||||
- Implementation: repository contract, registry docs, initial operating
|
- Implementation: repository contract, registry docs, initial operating
|
||||||
contracts, deploy-capable Gitea files, and operator targets are present.
|
contracts, deploy-capable Gitea files, and operator targets are present.
|
||||||
- Stability: emerging but now live-facing; forge owns the reviewed public
|
- Stability: emerging but now live-facing; forge owns the reviewed public
|
||||||
Gitea HTTPS ingress for the web UI, package registry, and OCI registry.
|
Gitea HTTPS ingress for the web UI, package registry, and OCI registry. Raw
|
||||||
|
node IP HTTP access is not part of the supported forge surface.
|
||||||
- Usage: canonical reference point for forge and registry responsibilities
|
- Usage: canonical reference point for forge and registry responsibilities
|
||||||
currently transitioning out of `railiance-apps`.
|
currently transitioning out of `railiance-apps`.
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ Observed on 2026-06-07:
|
|||||||
| live runner process | PID `5911` after activation |
|
| live runner process | PID `5911` after activation |
|
||||||
| registration file | `/root/.runner`, mode `0644`, owner `root:root` |
|
| registration file | `/root/.runner`, mode `0644`, owner `root:root` |
|
||||||
| registration name | `haskelseed` |
|
| registration name | `haskelseed` |
|
||||||
| registration address | `http://92.205.130.254:32166` |
|
| historical registration address | `http://92.205.130.254:32166` before the public NodePort was retired under `FORGE-WP-0005` |
|
||||||
| registration labels before activation | `haskelseed:host`, `linux:host`, `x86_64:host` |
|
| registration labels before activation | `haskelseed:host`, `linux:host`, `x86_64:host` |
|
||||||
| registration labels after activation | `self-hosted:host`, `haskelseed:host`, `linux:host`, `linux_amd64:host`, `x86_64:host`, `container-build:host`, `registry-publish:host` |
|
| registration labels after activation | `self-hosted:host`, `haskelseed:host`, `linux:host`, `linux_amd64:host`, `x86_64:host`, `container-build:host`, `registry-publish:host` |
|
||||||
| ephemeral | `false` |
|
| ephemeral | `false` |
|
||||||
@@ -146,8 +146,8 @@ Run from an operator host with registry access:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
for tag in 91037a4 ae9e497 fa96fb8 7cc3173 latest; do
|
for tag in 91037a4 ae9e497 fa96fb8 7cc3173 latest; do
|
||||||
skopeo inspect --tls-verify=false \
|
skopeo inspect \
|
||||||
"docker://92.205.130.254:32166/coulomb/inter-hub:${tag}" \
|
"docker://gitea.coulomb.social/coulomb/inter-hub:${tag}" \
|
||||||
--format "${tag} {{.Name}} {{.Digest}}"
|
--format "${tag} {{.Name}} {{.Digest}}"
|
||||||
done
|
done
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ Use `gitea.coulomb.social` as the approved forge and registry host. The public
|
|||||||
ingress serves the Gitea web route at `https://gitea.coulomb.social/`, the OCI
|
ingress serves the Gitea web route at `https://gitea.coulomb.social/`, the OCI
|
||||||
registry route at `/v2`, and the Python package route at `/api/packages`. The
|
registry route at `/v2`, and the Python package route at `/api/packages`. The
|
||||||
`/v2` route returns the OCI registry authentication challenge over HTTPS.
|
`/v2` route returns the OCI registry authentication challenge over HTTPS.
|
||||||
|
Do not use raw node IP HTTP ports for web or registry traffic; the Gitea HTTP
|
||||||
|
Service is internal-only and the public standard is the HTTPS host.
|
||||||
|
|
||||||
Registry-specific Gitea settings are carried in
|
Registry-specific Gitea settings are carried in
|
||||||
`helm/gitea-registry-values.yaml`, a non-secret overlay applied after the SOPS
|
`helm/gitea-registry-values.yaml`, a non-secret overlay applied after the SOPS
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ reconcile the Gitea Helm release with `helm/gitea-registry-values.yaml` so
|
|||||||
|
|
||||||
Status on 2026-06-13: the root web route returns `200`, live `ROOT_URL` is
|
Status on 2026-06-13: the root web route returns `200`, live `ROOT_URL` is
|
||||||
`https://gitea.coulomb.social/`, and package artifact links render HTTPS URLs.
|
`https://gitea.coulomb.social/`, and package artifact links render HTTPS URLs.
|
||||||
|
Raw node IP HTTP access is not a supported package or web entry point.
|
||||||
|
|
||||||
## Python Packages
|
## Python Packages
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ curl -i https://gitea.coulomb.social/v2/
|
|||||||
curl -i https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/
|
curl -i https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The raw node IP HTTP NodePort is intentionally not part of the public health
|
||||||
|
surface. Treat any reachable `http://<node-ip>:<gitea-nodeport>/` web route as
|
||||||
|
a regression to close, not as an alternate supported endpoint.
|
||||||
|
|
||||||
Git SSH:
|
Git SSH:
|
||||||
|
|
||||||
- If a Git SSH endpoint is published, verify it with a read-only `git ls-remote`
|
- If a Git SSH endpoint is published, verify it with a read-only `git ls-remote`
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
# Non-secret Gitea registry settings layered after the SOPS values file.
|
# Non-secret Gitea public endpoint and registry settings layered after the SOPS
|
||||||
|
# values file.
|
||||||
|
service:
|
||||||
|
http:
|
||||||
|
# Public web/API access is provided by manifests/gitea-ingress.yaml.
|
||||||
|
# Keep the Service internal so the raw node IP:port path is not a
|
||||||
|
# supported or reachable Gitea entry point.
|
||||||
|
type: ClusterIP
|
||||||
gitea:
|
gitea:
|
||||||
config:
|
config:
|
||||||
packages:
|
packages:
|
||||||
|
|||||||
@@ -20,21 +20,21 @@ spec:
|
|||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: gitea
|
name: gitea-http
|
||||||
port:
|
port:
|
||||||
number: 3000
|
number: 3000
|
||||||
- path: /v2
|
- path: /v2
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: gitea
|
name: gitea-http
|
||||||
port:
|
port:
|
||||||
number: 3000
|
number: 3000
|
||||||
- path: /
|
- path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: gitea
|
name: gitea-http
|
||||||
port:
|
port:
|
||||||
number: 3000
|
number: 3000
|
||||||
tls:
|
tls:
|
||||||
|
|||||||
97
workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md
Normal file
97
workplans/FORGE-WP-0005-remove-gitea-nodeport-side-door.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
---
|
||||||
|
id: FORGE-WP-0005
|
||||||
|
type: workplan
|
||||||
|
title: "Remove public Gitea NodePort side door"
|
||||||
|
domain: railiance
|
||||||
|
repo: railiance-forge
|
||||||
|
status: finished
|
||||||
|
owner: codex
|
||||||
|
topic_slug: railiance
|
||||||
|
planning_priority: high
|
||||||
|
created: "2026-06-14"
|
||||||
|
updated: "2026-06-14"
|
||||||
|
state_hub_workstream_id: "d6af707c-d9b1-463b-b24e-b384c5fb390d"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Remove public Gitea NodePort side door
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
After `FORGE-WP-0004`, `https://gitea.coulomb.social/` is the canonical public
|
||||||
|
Gitea endpoint. The legacy `default/gitea` Service still exposed HTTP through
|
||||||
|
NodePort `32166`, which made `http://92.205.130.254:32166/` look like a second
|
||||||
|
Gitea entry point. It reached the same pod and database, but it bypassed the
|
||||||
|
canonical HTTPS host and created operator confusion.
|
||||||
|
|
||||||
|
## T01 - Make the HTTP Service internal-only
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FORGE-WP-0005-T01
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "1ab4f7d0-0eef-4618-84d9-a84d72db9629"
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the non-secret Gitea Helm overlay to `service.http.type: ClusterIP` so the
|
||||||
|
chart-supported `gitea-http` Service stays internal-only and the web/API surface
|
||||||
|
is only public through the forge-owned HTTPS ingress. Keep Git SSH exposure
|
||||||
|
separate and unchanged.
|
||||||
|
|
||||||
|
## T02 - Reconcile live Gitea and verify the side door is gone
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FORGE-WP-0005-T02
|
||||||
|
status: done
|
||||||
|
priority: high
|
||||||
|
state_hub_task_id: "34a9759e-10f1-4202-b8e9-443265495022"
|
||||||
|
```
|
||||||
|
|
||||||
|
Apply a pinned chart `--reuse-values` Helm reconciliation that keeps the
|
||||||
|
chart-supported HTTP service internal-only while preserving the existing Gitea
|
||||||
|
app version and HTTPS `ROOT_URL`. Move the ingress backend to `gitea-http`, then
|
||||||
|
delete the legacy `default/gitea` NodePort Service because it is no longer part
|
||||||
|
of the current chart's supported public endpoint model.
|
||||||
|
|
||||||
|
Verify:
|
||||||
|
|
||||||
|
- `default/gitea` is absent and `default/gitea-http` is internal-only;
|
||||||
|
- `http://92.205.130.254:32166/` is no longer reachable;
|
||||||
|
- `https://gitea.coulomb.social/` still returns `200`;
|
||||||
|
- `/api/v1/version` still returns the live Gitea version;
|
||||||
|
- `/v2/` still returns the OCI authentication challenge;
|
||||||
|
- the package-specific PyPI simple index for `issue-core` still returns `200`.
|
||||||
|
|
||||||
|
Completed on 2026-06-14. A pinned Helm `--reuse-values` reconciliation kept
|
||||||
|
chart `gitea-12.5.0`, app `1.25.4`, and
|
||||||
|
`gitea.config.server.ROOT_URL=https://gitea.coulomb.social/` while setting
|
||||||
|
`service.http.type=ClusterIP`. The forge ingress backend was moved from the
|
||||||
|
legacy `gitea` Service to the chart-supported internal `gitea-http` Service,
|
||||||
|
then the legacy `default/gitea` NodePort Service was deleted.
|
||||||
|
|
||||||
|
Verification evidence:
|
||||||
|
|
||||||
|
- `kubectl get svc -n default -l app.kubernetes.io/instance=gitea` lists
|
||||||
|
`gitea-http` as `ClusterIP`, `gitea-ssh` as `ClusterIP`, and
|
||||||
|
`gitea-ssh-nodeport` for Git SSH only; the legacy `gitea` Service is absent;
|
||||||
|
- `http://92.205.130.254:32166/` timed out;
|
||||||
|
- `https://gitea.coulomb.social/` returned `200`;
|
||||||
|
- `https://gitea.coulomb.social/api/v1/version` returned `200`;
|
||||||
|
- `https://gitea.coulomb.social/v2/` returned `401`, preserving the OCI auth
|
||||||
|
challenge;
|
||||||
|
- `https://gitea.coulomb.social/api/packages/coulomb/pypi/simple/issue-core/`
|
||||||
|
returned `200`.
|
||||||
|
|
||||||
|
## T03 - Sync State Hub and record closure evidence
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: FORGE-WP-0005-T03
|
||||||
|
status: done
|
||||||
|
priority: medium
|
||||||
|
state_hub_task_id: "0f9f6b29-aeef-4558-a5f8-d1039a136224"
|
||||||
|
```
|
||||||
|
|
||||||
|
Run State Hub consistency sync for `railiance-forge`, record a progress note,
|
||||||
|
and keep the repo docs clear that raw HTTP NodePort access is not a supported
|
||||||
|
Gitea entry point.
|
||||||
|
|
||||||
|
Completed on 2026-06-14 after live verification.
|
||||||
Reference in New Issue
Block a user