12 Commits
Author SHA1 Message Date
shadowdaoandClaude Opus 5.5 14957dbbe1 fix(build): NodeSource repo via pkg-cache-repos.sh (pinned key, cache-aware)
install-node.sh no longer runs `curl https://rpm.nodesource.com/setup_N.x | bash`
(an unverified remote script). `pkg-cache-repos.sh nodesource N` writes the same
nodesource-nodejs repo (origin URL in the shipped image, gpgcheck=1) with the
signing key committed in keys/pkg-cache/RPM-GPG-KEY-nodesource. With PKG_CACHE
the repo goes through the internal cache (https://192.168.1.40/nodesource/,
origin as 2nd baseurl) and the RUN restores the origin files at the end.
The unused N|Solid repo (18/20/22) is no longer added.

pkg-cache-repos.sh + keys/pkg-cache synced byte-identical from
cloud-apache-container branch ci/pkg-cache-more-upstreams (canonical).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 07:14:39 -07:00
shadowdaoandClaude Opus 5.5 6b015141dc ci: pin base images by digest resolved directly from Docker Hub
With the pkg-cache BuildKit mirror on, `FROM almalinux/10-base` was resolved
by tag through the cache, so a compromised cache could substitute the image.

Each job using the mirror now looks up the base tag's digest DIRECTLY at
registry-1.docker.io (.gitea/scripts/resolve-base-image.sh, HTTPS, HEAD on
the manifest, regex-validated) and builds FROM image@sha256:... via the
BASE_IMAGE build-arg, so the mirror can only serve content-addressed blobs.
If the lookup fails, the mirror is NOT used for that job and the tag is pulled
straight from Docker Hub. The digest is resolved every run (no manual bumps);
local builds default to the tag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 06:58:18 -07:00
shadowdaoandClaude Opus 5.5 0edd0d3c53 fix(ci): build through the internal package cache; keep bundled npm on Node 18/20
- The first Node 24/26 run timed out on every job: public AlmaLinux mirrors
  served the runners at 1-150 kB/s. Use the CT130 package cache the same way
  cloud-apache-container does (same pkg-cache-repos.sh and pinned CA), with
  the upstream repos as fallback when the probe fails. epel-release is now
  GPG-verified before install instead of fetched unverified by URL.
- npm 12 requires Node >=22.22.2; on 18/20 keep the npm Node ships with.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 06:52:07 -07:00
shadowdaoandClaude Opus 5.5 ae6acdd009 feat: Node.js 24 and 26 images; refuse builds below the Oct 2026 security floor
- One install-node.sh <major> replaces install-node{18,20,22}.sh. It fails the
  build if NodeSource hands back a version below the newest security release
  for the line (22.23.4 / 24.22.1 / 26.12.1: CVE-2026-111497 Brotli OOB write
  and 9 others), so a lagging mirror can't ship a vulnerable image silently.
  18 and 20 are EOL: they still build, with a warning.
- CI matrix adds 24 and 26; fail-fast off so one line can't cancel the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 05:50:49 -07:00
shadowdaoandClaude Opus 5 e417a908f2 Upgrade to AlmaLinux 10 and fix WebSocket proxying
Base image moves from AlmaLinux 9 to 10, which forces two related changes:
EPEL repo URL bumps to the el10 release RPM, and tini is replaced with
dumb-init as PID 1 since tini is not packaged in EPEL 10. Both provide the
signal forwarding and zombie reaping the wedged-container fix relies on.
Nginx 1.26 in AlmaLinux 10 deprecates the `listen ... http2` parameter, so
the server block now uses the separate `http2 on;` directive.

Also fixes three issues that affected WebSocket apps (socket.io, ws):

- `Connection: upgrade` was hardcoded on every proxied request, including
  ordinary HTTP. Now driven by a `map $http_upgrade $connection_upgrade`
  so only genuine upgrade requests carry it.
- No explicit proxy read/send timeout meant idle WebSockets were cut at
  nginx's 60s default. Set to 600s, which clears any sane heartbeat without
  pinning connection slots (worker_connections is 512, two per client).
- `large_client_header_buffers 2 1k` returned 400 for any single header
  line over 1KB, which session cookies and bearer tokens routinely exceed.
  Raised to the nginx default of 4 8k; buffers are allocated on demand, so
  this only costs memory for requests that need it.

Verified by rendering the generated config and running it under nginx with
a Node backend: WebSocket handshakes return 101 and reach the upstream
'upgrade' event, polling requests arrive with `Connection: close`, and a
3KB cookie returns 200 where the old buffer setting returned 400.

README gains a WebSocket Support section covering the PM2 cluster-mode
trap, the concurrency ceiling, and reconnects on memory restarts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 07:54:32 -07:00
shadowdaoandClaude Opus 4.7 b431a66a7b Fix wedged-container outage: TCP healthcheck + tini-managed PID 1
A 10s postgresql restart took down transcribe.shadowdao.com-01 for ~17h
because pm2 gave up after 5 fast retries, the entrypoint's trailing
tail -f kept PID 1 alive, and the healthcheck (wget --spider on nginx
port 80) succeeded on the 301-to-https redirect regardless of whether
Node was alive.

Three coordinated fixes to the cnoc image:

- HEALTHCHECK: replace the redirect-passing wget probe with TCP-level
  checks on 127.0.0.1:3000 (Node) and :80 (nginx). Tenant-agnostic, no
  /ping dependency — catches the exact incident scenario (port 3000
  closed when pm2 exits).
- entrypoint.sh: exec pm2 via tini so it becomes PID 1. When pm2
  exhausts max_restarts and exits, the container exits and the
  unless-stopped restart policy brings it back. Logs are tailed in the
  background with -F (logrotate-safe).
- Dockerfile: install tini from EPEL for proper signal forwarding and
  zombie reaping of nginx/crond children that reparent to PID 1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 06:59:52 -07:00
shadowdaoandClaude Opus 4.6 821db4873e Fix healthcheck to validate full stack through Nginx
Cloud Node Container / Build-and-Push (18) (push) Successful in 2m15s
Cloud Node Container / Build-and-Push (20) (push) Successful in 4m12s
Cloud Node Container / Build-and-Push (22) (push) Successful in 1m58s
Changed healthcheck from hitting Node.js directly on port 3000/ping to
going through Nginx on port 80, ensuring the entire stack is validated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 07:57:10 -07:00
shadowdaoandClaude 88d0d4e64b Fix Dockerfile build error - use dnf instead of yum for groupinstall
Cloud Node Container / Build-and-Push (18) (push) Successful in 1m51s
Cloud Node Container / Build-and-Push (20) (push) Successful in 1m52s
Cloud Node Container / Build-and-Push (22) (push) Successful in 1m50s
Changed 'yum groupinstall' to 'dnf group install -y' to match AlmaLinux 9
package manager and ensure non-interactive installation.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-24 09:03:33 -07:00
shadowdaoandClaude 9f0aa4b8b1 Implement auto-generation of ecosystem.config.js and improve container setup
Cloud Node Container / Build-and-Push (18) (push) Failing after 38s
Cloud Node Container / Build-and-Push (20) (push) Failing after 33s
Cloud Node Container / Build-and-Push (22) (push) Failing after 33s
- Add automatic ecosystem.config.js generation from package.json
- Create app directory automatically if missing
- Copy simple-website example when app directory is empty
- Remove redundant default app files from configs/
- Add HAProxy support with proper real IP forwarding
- Configure nginx to trust proxy headers from private networks
- Simplify entrypoint logic - always use /home/$user/app

This makes the container more user-friendly by eliminating the need for
manual PM2 configuration and ensuring the server always has a working app.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-24 09:01:08 -07:00
shadowdaoandClaude e9d4d11177 Fix package conflict by removing curl dependency
Cloud Node Container / Build-and-Push (18) (push) Successful in 49s
Cloud Node Container / Build-and-Push (20) (push) Successful in 54s
Cloud Node Container / Build-and-Push (22) (push) Successful in 1m12s
- Remove curl from package installation to avoid curl/curl-minimal conflict
- Replace curl with wget in health check and Node.js installation scripts
- wget is already installed and provides same functionality

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 16:05:37 -07:00
shadowdaoandClaude 0b99f5f011 Fix Dockerfile build error - remove non-existent default.conf
Cloud Node Container / Build-and-Push (18) (push) Failing after 26s
Cloud Node Container / Build-and-Push (20) (push) Failing after 23s
Cloud Node Container / Build-and-Push (22) (push) Failing after 25s
The nginx default.conf is generated dynamically by create-nginx-config.sh
script at runtime, not copied during build.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 16:03:18 -07:00
shadowdaoandClaude 2989cd590a Complete Node.js container implementation with multi-version support
Cloud Node Container / Build-and-Push (18) (push) Failing after 10s
Cloud Node Container / Build-and-Push (20) (push) Failing after 8s
Cloud Node Container / Build-and-Push (22) (push) Failing after 8s
- Add Dockerfile with AlmaLinux 9 base, Nginx reverse proxy, and PM2
- Support Node.js versions 18, 20, 22 with automated installation
- Implement memory-optimized configuration (256MB minimum, 512MB recommended)
- Add Memcached session storage for development environments
- Create comprehensive documentation (README, USER-GUIDE, MEMORY-GUIDE, CLAUDE.md)
- Include example applications (simple website and REST API)
- Add Gitea CI/CD pipeline for automated multi-version builds
- Provide local development script with helper utilities
- Implement health monitoring, log rotation, and backup systems

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 16:00:46 -07:00