what you need before the first run, in both places the scripts can run from.
| variable | required | where it comes from |
|---|---|---|
CPANEL_HOST |
yes | the cpanel hostname, e.g. server.example.com β no https://, no port |
CPANEL_USER |
yes | your cpanel account username |
CPANEL_API_TOKEN |
yes | cpanel β security β manage api tokens β create |
ROOT_DOMAIN |
yes | the domain the subdomains hang off, e.g. example.com |
SERVER_IP |
yes | the ip subdomains point at (only actually used by the dns step) |
NAMECHEAP_API_USER |
no | only for --with-dns-api |
NAMECHEAP_API_KEY |
no | namecheap β profile β tools β api access |
NAMECHEAP_USERNAME |
no | defaults to NAMECHEAP_API_USER |
NAMECHEAP_CLIENT_IP |
no | must be whitelisted in namecheap β api access |
POSTHOG_PERSONAL_API_KEY |
no | PostHog β settings β personal api keys, scope project:write. without it, the authorized urls step is skipped |
POSTHOG_HOST |
no | defaults to https://eu.posthog.com |
POSTHOG_PROJECT_ID |
no | defaults to 139609 |
GITHUB_PAT |
for auto-deploy and gitflow | a personal access token that can write to the target repo β see below |
a missing variable fails immediately, naming exactly which ones are absent β nothing half-runs.
the cpanel user token acts as one account, and that's all these scripts
need β autossl too, through uapi's SSL::start_autossl_check. no whm
(root/reseller) token is involved; see cpanel api notes.
the phc_ key inside assets/posthog-snippet.html
is ingestion-only and public by design. POSTHOG_PERSONAL_API_KEY is a
phx_ personal api key that can change project settings β keep it scoped to
project:write on the one project, and out of the repo like every other secret.
setup_autodeploy.py writes to a different repository than the one it runs
from β it creates secrets on your project's repo and commits a workflow there.
the automatic GITHUB_TOKEN that exists inside every actions run is scoped to
the repo running the job, so it can't do either. hence the deliberately
different name: the script reads GITHUB_PAT, and picking up the wrong token
by accident isn't possible.
what the pat needs:
| token type | permissions |
|---|---|
| classic | repo and workflow |
| fine-grained, on the target repo | Secrets: write, Contents: write, Workflows: write |
the workflow half is the one people miss. github specifically refuses to let
a token create or update anything under .github/workflows/ without it, and
says so in a 403 β which the script translates into a message naming the scope.
if you'd rather not hand out that scope, --skip-workflow-file prints the
workflow instead of committing it and the token only needs secrets access.
setup_gitflow.py uses the same token and needs less: Contents: write (or a
classic repo) for the initial commit and the branches, plus Administration: write only if you pass --default-develop. auto-deploy on an empty repo does
the same initialization, which Contents: write already covers.
this is a broad token. treat it like one: give it the shortest expiry you can live with, prefer fine-grained scoped to the repos you actually deploy, and regenerate it if it ever lands in a log.
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
chmod 600 .envchmod 600 matters: the file holds a live api token, and the default 644
leaves it readable by every account on the machine.
on macos the venv isn't optional β homebrew python refuses pip install
system-wide with externally-managed-environment (pep 668).
load it before running:
set -a; source .env; set +a.env is gitignored and has never been committed.
settings β secrets and variables β actions β new repository secret, one at a time:
CPANEL_HOST
CPANEL_USER
CPANEL_API_TOKEN
ROOT_DOMAIN
SERVER_IP
that's enough for creating and deleting subdomains, autossl included. add the
NAMECHEAP_* secrets only if you'll use
--with-dns-api, and POSTHOG_PERSONAL_API_KEY if new subdomains should be
added to PostHog's authorized urls by themselves (both the create and delete
workflows read it).
for the auto-deploy and gitflow workflows, add one more:
DEPLOY_GITHUB_PAT
it can't be called GITHUB_PAT here β github reserves the whole GITHUB_
prefix for secret names and rejects it. the workflows map
secrets.DEPLOY_GITHUB_PAT onto the GITHUB_PAT env var the script reads.
github masks secrets in logs automatically β you'll see *** where a value
would be.
triggering a workflow requires write access to the repository. on a public repo, visitors can read the code and the run history but the run workflow button doesn't appear for them, and forks never receive the secrets.
worth being deliberate about, though: write access here is effectively access
to the hosting account, since anyone who can run the workflow can create and
delete subdomains β and anyone with write access can read repository secrets by
editing a workflow to echo them. if you ever add a collaborator, consider
read/triage instead, or move the secrets into an environment with required
reviewers so each run waits for approval.
pip install -r requirements-dev.txt
pytest -qthe tests cover the pure functions only β name validation, the document-root
safety guard, response parsing, dns parameter construction β so they need
neither network nor credentials. anything that talks to an api is checked with
--dry-run instead.