- Drop the Docker and GitHub apt repositories and the Ruby build headers
from the image; keep build-essential, bubblewrap, zip and unzip.
- Document home installs for the Docker CLI with its Compose and Buildx
plugins, gh, Go, Rust, Python, Node and Java, ordered so each installer
writes to ~/.zshrc and SDKMAN stays last.
- Drop the Ruby, GitLab CLI and jq instructions.
- Install the Docker CLI with its Compose and Buildx plugins, and the GitHub
CLI, from Docker's and GitHub's signed apt repositories; drop their home
installs and the GitLab CLI from the README.
- Select the shell with SHELL and the start folder with DEFAULT_WORKSPACE
instead of chsh and working_dir.
- Add an optional CODE_SERVER_APP_NAME.
- Document installing Java with SDKMAN.
Add an entrypoint wrapper that reads the socket's GID, adds coder to a
matching group and re-execs the image's entrypoint under it, so docker
works without sudo on any host. Install build-essential and the headers
rbenv needs to build Ruby, and make zsh the login shell. Document home
installs for rbenv, Docker Compose and Buildx plugins, and jq.
The gateway's allow-lists read only the profile .env under the default
multiplex mode, so Telegram values passed from the environment left every
user blocked. Drop the passthrough and document the dashboard as the one
place to set them, plus the dashboard secret's 16-byte minimum.
Service READMEs now cover only what the service is and how to deploy it.
Known issues, log noise and troubleshooting move to docs/<service>/, named
after the service directory, so editing them never redeploys the service.
Drop alloy's validate workflow, which never ran from a subdirectory.
A skill under gitea-mirror/ redeployed the stack on every edit, since the
Coolify watch path is gitea-mirror/**, and only loaded once a session touched
that directory. Service directories now hold deploy files only; skills live
in the root .claude/skills/.
Add cleanup-renamed-repos.sh, which groups Gitea mirrors and gitea-mirror
rows by GitHub repo id, keeps the copy at the current name (renaming a
case-only mismatch in place), deletes the rest and re-imports.
cleanup-archived-repos.sh now deletes every mirror whose GitHub source 404s
when the source belongs to the gh user or an org it administers, keeps
third-party ones, and aborts on a GitHub rate limit.
Gitea's migrate API stays silent until the clone ends, and Bun's fetch
drops a connection idle for 5 minutes. gitea-mirror then marked large
repositories failed while Gitea kept cloning, and a later retry took the
half-made repository for a finished mirror. GITEA_CLONE_TIMEOUT now also
sets BUN_CONFIG_HTTP_IDLE_TIMEOUT.
Deletes the archived-* Gitea copies gitea-mirror keeps when a source in the
given owners disappears, and removes their tracking rows so they are not
re-mirrored. Dry run by default.
The skill reached Gitea on localhost and the mirror database inside the
container, which only worked on a local host. It now uses tea for Gitea
and the gitea-mirror API key for repository status and retries, in bash.
Private upstreams are no longer probed anonymously, which reported them
as deleted.
sources/ holds gitignored upstream checkouts for debugging a service
against its real code; the debug-service skill walks through it. Coolify
is now the primary deployment target and Dokploy optional.
Drop the localhost-bound ports, read the database password and both
public URLs from the environment, pin gitea to its major tag, add a gitea
health check and disable gitea's SSH server.
A service README now describes only its own service: no links to other
services or to the root, and no restating of the shared conventions that
the root README and CLAUDE.md already carry. Each service is a separate
Coolify app on a <service>/** watch path, so a cross-link made editing one
service redeploy another. The rule is recorded at the root; the alloy
compose comment now points at a heading that exists.