Chrome Extension Deploy
CSecurityUse 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 cl...
- 2 stars
- 0 votes
- 0 copies
- 1 view
- Added September 24, 2026
Works with
Security analysis
67/100- Uses curl or wget to download content
- Exfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
Pro scans all 13 files and shows the line behind each finding
npx -y skills add thomaslimited/chrome-extension-skills --skill chrome-extension-deploy --agent claude-codeAre you the author of Chrome Extension Deploy?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/thomaslimited-chrome-extension-deploy)---
name: chrome-extension-deploy
description: 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.
license: MIT
---
# 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
1. **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 to `127.0.0.1:<port>` only, host nginx as the single thing listening on
80/443, Cloudflare in front. Read `references/server-topology.md`.
2. **Write the Compose file and nginx vhosts from the templates**, not from scratch —
`assets/docker-compose.prod.template.yml` and `assets/nginx-site.template.conf`. Read
`references/docker-compose-and-nginx.md` for what each service/directive does and why.
3. **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.24
`listen 443 ssl http2` syntax trap and X-Forwarded-For spoofing.
4. **Treat `.env.example` as 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). Read
`references/env-and-secrets.md` before editing config/secret-loading code or `.env.example`.
5. **Run the first-time server setup once**, then use the same idempotent redeploy procedure for
every update after that (`git pull` or tarball upload → `docker compose up -d --build` →
migration-on-boot → health check). Read `references/deploy-runbook.md`, including the Windows
Git Bash upload gotchas if deploying from Windows.
6. **Wire what only works after HTTPS exists**: PayPal/Alchemy-style webhooks, OAuth redirect
URIs, the public privacy-policy URL. Smoke-test with `curl /health` and a CORS preflight using
`Origin: chrome-extension://<id>`. Covered at the end of `references/deploy-runbook.md`.
7. **Schedule backups before declaring the deploy done.** `assets/backup.template.sh` on a daily
cron, pushed off the VPS. Restore procedure lives in the same file's header comment.
8. **For an extension release**: bump the version, `pnpm zip` (store mode — no manifest `key`),
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 into `ALLOWED_ORIGINS`
and the OAuth client's redirect URIs. Read `references/extension-release.md`.
9. **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-api` before relying on `assets/github-actions-publish.template.yml`
— this API is mid-migration and some details in the reference file are marked unverified.
10. **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 published
- `references/docker-compose-and-nginx.md` — Compose service walkthrough, Dockerfile choices, nginx vhost anatomy, enabling a site
- `references/tls-cloudflare.md` — certbot webroot issuance/renewal, Cloudflare SSL modes, the 521 incident, nginx http2 syntax, real client IP restoration
- `references/env-and-secrets.md` — `.env.example` as contract, production secret assertions, warn-only webhook secrets, `ALLOWED_ORIGINS`, git hygiene for secrets
- `references/deploy-runbook.md` — first-time setup, upload methods (incl. Windows Git Bash gotchas), redeploy, migrations, health checks, logs, rollback, backups, post-deploy wiring
- `references/extension-release.md` — version bump, `wxt zip --mode store`, dashboard upload, staged rollout, item-ID follow-up, Chrome Web Store Publish API for CI
- `references/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 ports
- `assets/nginx-site.template.conf` — HTTP→HTTPS redirect + ACME challenge + TLS proxy vhost, one per subdomain
- `assets/backup.template.sh` — encrypted `pg_dump` to off-site remote storage, with restore instructions in the header
- `assets/github-actions-publish.template.yml` — CI publish to the Chrome Web Store, credentials read from repo secrets (verify endpoint/auth details before use — see `references/extension-release.md`)
- `assets/env.example.template` — annotated env-var contract with placeholder values only; copy to `.env.example` and fill in real names
## Security
- Never read, print, or commit a real `.env` file, `server.txt`, `*.pem`, or `*.key` — only
`.env.example` is 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-For` from a trusted source (Cloudflare's
`CF-Connecting-IP` via `real_ip`, or `$remote_addr` with 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.md` has the command); do not
rely on `.gitignore` alone once a secret has already been committed once.
Files in this skill
- SKILL.md
- assets/backup.template.sh
- assets/docker-compose.prod.template.yml
- assets/env.example.template
- assets/github-actions-publish.template.yml
- assets/nginx-site.template.conf
- references/deploy-runbook.md
- references/docker-compose-and-nginx.md
- references/env-and-secrets.md
- references/extension-release.md
- references/server-topology.md
- references/tls-cloudflare.md
- references/troubleshooting.md
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.