chrome-extension-deploy
Skill2 starsChanged 51 days agoMITView on GitHub
Use to deploy a Chrome extension backend (API + Postgres + admin dashboard) to a VPS, or publish/release a new extension version. Triggers: "deploy extension backend", "VPS docker nginx", "let's encrypt cloudflare 521", "publish extension update", "chrome web store api", "release extension". Covers shared-VPS topology (named Compose project, Postgres never published, API/admin on 127.0.0.1, host nginx proxy, Let's Encrypt via certbot webroot + renewal hook, Cloudflare "Full (strict)", real client IP); prod secret checks, warn-only webhook secrets; first-time setup, upload (Windows gotchas), idempotent redeploys, health checks, rollback, backups; post-deploy webhook/OAuth wiring, CORS smoke tests; `wxt zip --mode store`, dashboard upload, staged rollout, Chrome Web Store Publish API v2 for CI. Real incidents: port 80 clashes, Cloudflare 521, nginx http2 syntax, spoofed X-Forwarded-For. Skips listing copy, OAuth/payment setup, and extension code — see sibling skills.
- Reads credentials
In this repository4 other files it gives its agents.
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 2 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 21
If the task touches those, do the deploy/release part here and hand off the rest.
- Very specific: line 37
Treat
.env.exampleas the contract: Every var the app reads must have a line there. - Very specific: line 101
Never read, print, or commit a real .env file, server.txt, *.pem, or *.key — only .env.example is safe to view or template.
- Distinctive: line 103
Every production secret that gates money movement or auth (session secret, admin secret, webhook signing keys) must fail closed: missing or …
- Very specific: line 109
Run a secret scan before every push (references/env-and-secrets.md has the command).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Chrome Extension Deploy
Scope
This skill handles shipping the backend and releasing the extension: VPS topology, Docker Compose, host nginx, TLS, secrets, the deploy/rollback runbook, and Chrome Web Store publishing.
It does not handle:
- Store listing copy, screenshots, privacy-policy wording →
chrome-web-store-listing - Setting up the OAuth provider or payment processor accounts themselves →
chrome-extension-auth,chrome-extension-payments(this skill only wires their redirect URIs / webhook URLs once HTTPS exists) - Extension code, manifest, content scripts →
chrome-extension-dev
If the task touches those, do the deploy/release part here and hand off the rest.
Workflow
- Confirm the topology before writing any config. One VPS, possibly shared with other sites,
one Docker Compose project with its own
name:, Postgres never published to the host, API and admin containers bound to127.0.0.1:<port>only, host nginx as the single thing listening on 80/443, Cloudflare in front. Readreferences/server-topology.md. - Write the Compose file and nginx vhosts from the templates, not from scratch —
assets/docker-compose.prod.template.ymlandassets/nginx-site.template.conf. Readreferences/docker-compose-and-nginx.mdfor what each service/directive does and why. - Get TLS right before touching Cloudflare's proxy toggle. Issue the cert with certbot
webroot on port 80 first, confirm nginx serves 443 directly, then enable the Cloudflare
orange cloud with SSL mode "Full (strict)". Read
references/tls-cloudflare.md— it documents the exact 521 failure mode when this order is reversed, plus the nginx 1.24listen 443 ssl http2syntax trap and X-Forwarded-For spoofing. - Treat
.env.exampleas the contract. Every var the app reads must have a line there. Production boot must refuse to start on placeholder secrets; webhook secrets are the one deliberate exception (warn-only, because they can't exist before HTTPS does). Readreferences/env-and-secrets.mdbefore editing config/secret-loading code or.env.example. - Run the first-time server setup once, then use the same idempotent redeploy procedure for
every update after that (
git pullor tarball upload →docker compose up -d --build→ migration-on-boot → health check). Readreferences/deploy-runbook.md, including the Windows Git Bash upload gotchas if deploying from Windows. - Wire what only works after HTTPS exists: PayPal/Alchemy-style webhooks, OAuth redirect
URIs, the public privacy-policy URL. Smoke-test with
curl /healthand a CORS preflight usingOrigin: chrome-extension://<id>. Covered at the end ofreferences/deploy-runbook.md. - Schedule backups before declaring the deploy done.
assets/backup.template.shon a daily cron, pushed off the VPS. Restore procedure lives in the same file's header comment. - For an extension release: bump the version,
pnpm zip(store mode — no manifestkey), verify the zip's contents, upload via the Chrome Web Store dashboard, use staged rollout for a material change. First-ever upload issues a new item ID — feed it back intoALLOWED_ORIGINSand the OAuth client's redirect URIs. Readreferences/extension-release.md. - Automate publishing only after a manual upload has succeeded once. The Chrome Web Store
Publish API (v2) can drive CI, but verify current auth/endpoint details against
developer.chrome.com/docs/webstore/using-apibefore relying onassets/github-actions-publish.template.yml— this API is mid-migration and some details in the reference file are marked unverified. - Before calling it done, check
references/troubleshooting.md— real symptom → cause → fix entries from a shipped deployment (port 80 clash, Cloudflare 521, nginx syntax errors, spoofed client IP, stuck migrations, rejected webhooks, CORS failures).
Go-live checklist
| # | Item | Required for |
| 1 | Compose project has its own name:, Postgres has no host port mapping | prod |
| 2 | API and admin containers publish only 127.0.0.1:<port> | prod |
| 3 | Host nginx vhosts installed, nginx -t clean, reloaded | prod |
| 4 | Let's Encrypt cert issued via webroot, renewal hook reloads nginx | prod |
| 5 | Cloudflare proxied with SSL mode Full (strict), not Full or Flexible | prod (if using Cloudflare) |
| 6 | .env has real values for every required var; assertProductionSecrets-style boot check passes | prod |
| 7 | ALLOWED_ORIGINS lists every extension ID actually in use (dev key + store ID once assigned) | prod |
| 8 | curl https://<domain>/health returns healthy; CORS preflight from the extension origin succeeds | prod |
| 9 | Daily backup cron installed and one restore has been test-run | prod |
| 10 | Webhooks (payment/on-chain) registered against the live HTTPS URL, signing secrets set | store launch |
| 11 | OAuth redirect URIs include both the dev and store extension IDs | store launch |
| 12 | Privacy policy URL is live and matches what the store listing links to | store submission |
| 13 | pnpm zip --mode store output verified to exclude the dev signing key | every release |
| 14 | .gitignore/.gitattributes cover secrets and shell-script line endings; pre-push secret scan run | always |
Reference files
references/server-topology.md— shared VPS layout, Compose project isolation, port binding, why Postgres is never publishedreferences/docker-compose-and-nginx.md— Compose service walkthrough, Dockerfile choices, nginx vhost anatomy, enabling a sitereferences/tls-cloudflare.md— certbot webroot issuance/renewal, Cloudflare SSL modes, the 521 incident, nginx http2 syntax, real client IP restorationreferences/env-and-secrets.md—.env.exampleas contract, production secret assertions, warn-only webhook secrets,ALLOWED_ORIGINS, git hygiene for secretsreferences/deploy-runbook.md— first-time setup, upload methods (incl. Windows Git Bash gotchas), redeploy, migrations, health checks, logs, rollback, backups, post-deploy wiringreferences/extension-release.md— version bump,wxt zip --mode store, dashboard upload, staged rollout, item-ID follow-up, Chrome Web Store Publish API for CIreferences/troubleshooting.md— symptom → cause → fix, from a shipped deployment
Assets
assets/docker-compose.prod.template.yml— Postgres + API + admin, no host-published database, loopback-only app portsassets/nginx-site.template.conf— HTTP→HTTPS redirect + ACME challenge + TLS proxy vhost, one per subdomainassets/backup.template.sh— encryptedpg_dumpto off-site remote storage, with restore instructions in the headerassets/github-actions-publish.template.yml— CI publish to the Chrome Web Store, credentials read from repo secrets (verify endpoint/auth details before use — seereferences/extension-release.md)assets/env.example.template— annotated env-var contract with placeholder values only; copy to.env.exampleand fill in real names
Security
- Never read, print, or commit a real
.envfile,server.txt,*.pem, or*.key— only.env.exampleis safe to view or template. Never SSH anywhere as part of this skill's tasks. - Every production secret that gates money movement or auth (session secret, admin secret,
webhook signing keys) must fail closed: missing or default value either refuses boot or rejects
every request to the endpoint it guards. See
references/env-and-secrets.md. - Nginx must overwrite (not append)
X-Forwarded-Forfrom a trusted source (Cloudflare'sCF-Connecting-IPviareal_ip, or$remote_addrwith no CDN) — a downstream service that rate-limits or gates signups on this header must never let a client set it itself. - Run a secret scan before every push (
references/env-and-secrets.mdhas the command); do not rely on.gitignorealone once a secret has already been committed once.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

