8.8 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this repo is
This is not an application codebase. It is an operations toolkit: PowerShell
wrapper scripts plus context/runbook documentation that let an agent diagnose and
manage a single local Proxmox host (192.168.0.200, node thinkcentre) and the
self-hosted Coolify stack running inside its LXC 102. There is no build, lint,
or test step — the "commands" are the operational scripts in scripts/ and
coolify_skill/scripts/.
User-facing docs are in Spanish; scripts and skill files are in English.
Core architecture
Everything reaches the host through one SSH path. There is no direct Docker or local network access. The layering is:
PowerShell script → Invoke-ProxmoxSshCommand (scripts/ProxmoxAgent.ps1)
→ ssh [email protected]
→ pct exec 102 -- docker ... (for any Docker/Coolify container work)
- scripts/ProxmoxAgent.ps1 is the shared library. Dot-source it (
. .\scripts\ProxmoxAgent.ps1) to getGet-ProxmoxConfig,Invoke-ProxmoxSshCommand, andInvoke-ProxmoxApi. Every other script dot-sources it rather than reimplementing connection logic. - Config resolution:
Get-ProxmoxConfigreads env vars (PROXMOX_HOST,PROXMOX_NODE,PROXMOX_SSH_KEY,PROXMOX_COOLIFY_LXC, etc.) and falls back to hardcoded local defaults. SSH works with defaults alone; API calls requirePROXMOX_API_TOKEN_ID+PROXMOX_API_TOKEN_SECRET(otherwiseInvoke-ProxmoxApithrows). The Coolify LXC ID (102) comes from config — don't hardcode it in new scripts; use$config.CoolifyLxc. - Two independent APIs: the Proxmox REST API (via
curl.exe -k, PVE token header) and the Coolify API (viaInvoke-RestMethod, Bearer token, basehttps://coolify.urieljareth.org/api/v1). They use different scripts and different env vars. - Docker is not managed on the Proxmox host directly — it lives inside LXC
102. Any container command must be wrapped aspct exec 102 -- docker .... - The deploy pipeline (deploy_skill/) is the end-to-end path from "local project" to "live on
*.urieljareth.org": scaffold compliant Dockerfile/compose → pre-deploy checklist → create GitHub repo → push → register + deploy via Coolify API → verify. It also covers rollback. RequiresGITHUB_TOKEN+COOLIFY_TOKENin.env.local.ps1;git pushuses Windows Credential Manager (wincred), verified for theurieljarethbusiness-cpuGitHub account. See deploy_skill/SKILL.md and docs/AGENTS-coolify-apps.md.
Common commands
Run from the project root in PowerShell.
# Load private secrets (gitignored) — needed for any API call
. .\.env.local.ps1
# Smoke test: config + SSH read + Docker sample + API auth (exits 1 on any FAIL)
.\scripts\Test-ProxmoxConnection.ps1
# Full inventory snapshot (host, LXC, QEMU, Docker in LXC 102)
.\scripts\Get-ProxmoxInventory.ps1
# Arbitrary read-only SSH command
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct list"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps -a"
# Proxmox REST API (after env token loaded)
. .\scripts\ProxmoxAgent.ps1
Invoke-ProxmoxApi -Path "/version"
# Coolify container status through LXC 102
.\coolify_skill\scripts\Get-CoolifyDockerStatus.ps1 -All
# Coolify API (requires COOLIFY_TOKEN)
.\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Path "/projects"
.\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Method POST -Path "/projects" -BodyJson $body
# Cloudflare API (requires CLOUDFLARE_API_TOKEN) — full tunnel/DNS control
.\scripts\Invoke-CloudflareApi.ps1 -Path "/user/tokens/verify"
# Gitea API (requires GITEA_URL + GITEA_TOKEN) — self-hosted git hosting
.\gitea_skill\scripts\Test-GiteaConnection.ps1
.\gitea_skill\scripts\Get-GiteaRepo.ps1 -List
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/user"
.\gitea_skill\scripts\Sync-GiteaRemote.ps1 -AppPath .\my-app -CreateIfMissing -Force
For the Coolify API reference: don't read the whole tree. Search
coolify_skill/references/ with rg, then open the single matching
references/ops/*.md operation file.
Deploying a new project to Coolify
End-to-end pipeline (scaffold → checklist → GitHub repo → push → Coolify app +
deploy → verify). Requires GITHUB_TOKEN and COOLIFY_TOKEN in
.env.local.ps1. git push uses Windows Credential Manager, not the PAT.
. .\.env.local.ps1
# Full pipeline on a local project
.\deploy_skill\scripts\Publish-ProjectToCoolify.ps1 `
-AppPath .\my-app -AppName my-app `
-Fqdn https://my-app.urieljareth.org `
-Stack node -AppPort 8080 -Init
# Or step-by-step
.\deploy_skill\scripts\Initialize-CoolifyProject.ps1 -Path .\my-app -Stack node
.\deploy_skill\scripts\Test-PreDeployChecklist.ps1 -Path .\my-app -Strict
.\deploy_skill\scripts\New-GitHubRepo.ps1 -Name my-app
.\deploy_skill\scripts\New-CoolifyApplication.ps1 -RepoUrl https://github.com/urieljarethbusiness-cpu/my-app.git `
-Fqdn https://my-app.urieljareth.org -PortsExposes 8080
.\deploy_skill\scripts\Test-PostDeploy.ps1 -Fqdn https://my-app.urieljareth.org -ContainerName my-app-main
# Rollback to a previous commit
.\deploy_skill\scripts\Invoke-CoolifyRollback.ps1 -AppPath .\my-app -ApplicationUuid <uuid> -CommitSha <sha>
Operating rules (enforced by the skills — follow them)
- Read-only first. Default to diagnostics: list, status, logs, inspect, health checks.
- Confirm before any state change. Explicitly ask the user before:
pct/qmstart/stop/reboot/destroy;dockerrestart/stop/rm/compose up/down; Coolify deploys or anyPOST/PUT/PATCH/DELETE; env-var writes; and any firewall/network/storage/volume/key/token change. For risky actions, capture current state and state the rollback path first. - Never write secrets into the repo. No tokens, passwords, private keys, cookies, or PVE token secrets in Markdown, scripts, or logs. Secrets live only in
.env.local.ps1(gitignored) or the OS secret store..gitignorealso blocksACCESS.md,*.key,*.pem,*.crt, etc. When debugging databases, verify connectivity without echoing credentials. - Prefer repo scripts over long manual command strings, and don't run broad destructive commands built from generated strings.
Docker networking gotcha
When a Coolify app and its database are sibling containers on the same Docker
network, the app must reach the DB by its Docker service name, not localhost
(e.g. Nextcloud uses host nextcloud-db). Service-to-service DNS is the usual
root cause of "database connection" failures here — check with
pct exec 102 -- docker exec <app> getent hosts <service-name>.
Where context lives
- docs/proxmox-inventory.md — verified topology, LXC list, observed containers, access model. Treat as the source of truth for current state.
- docs/runbooks/ — concrete procedures:
conexion.md,diagnostico.md,coolify-docker.md,seguridad.md,cloudflare-tunnel.md,autostart-coolify.md(power-outage auto-start of LXC 102 + tunnel), plus app-specificnextcloud.mdandbaserow.md. - Cloudflare tunnel: the tunnel is dashboard-managed (ingress comes from the edge, see
INF Updated to new configuration version=Nincloudflaredlogs) — fix routes in the dashboard or via scripts/Invoke-CloudflareApi.ps1, not by editing files on the host. Ports 6001/6002 must usehttp://. See docs/runbooks/cloudflare-tunnel.md. - agent/SKILL.md + agent/TOOLS.md — Proxmox agent operating skill.
- coolify_skill/SKILL.md + coolify_skill/TOOLS.md — Coolify agent operating skill and API reference index.
- docs/AGENTS-coolify-apps.md — compatibility guide for agents developing an app to deploy on this Coolify instance (networking, ports, domains/TLS, env, volumes, healthchecks) + pre-deploy checklist. Source this when building a new app, not when operating an existing one.
- deploy_skill/SKILL.md + deploy_skill/TOOLS.md — deploy pipeline skill (scaffold → push → Coolify API → verify → rollback).
- gitea_skill/SKILL.md + gitea_skill/TOOLS.md — self-hosted Gitea skill: list/create/mirror repos, wire a
gitearemote, push headlessly via one-shothttp.extraHeader(token never persisted). Distinct from deploy_skill (which targets Coolify); this manages the git hosting layer. PROXMOX/,proxmox-agent/,proxmox-skill/are legacy pointer folders — they only redirect to the live docs above. Don't add content there.