Uploading Game Files with pingctl
Download the pingctl CLI, authenticate with a push token, and push a game server build to the PingCore CDN.
pingctl is the PingCore command line tool for uploading game server builds to the CDN. One command pushes a local build directory to a CDN source:
pingctl push ./ServerBuildIt is a single static binary with no runtime dependencies. You do not install Go, Node, rclone, or an SFTP client.
Before you can push, you need a manual CDN source and a push token issued on that source's page. See CDN Sources and Push Tokens.
Download
Download the zip for your platform. Each zip contains a single pingctl binary (pingctl.exe on Windows).
Windows (x64): pingctl-windows-amd64.zip
Linux (x64): pingctl-linux-amd64.zip
Linux (ARM64): pingctl-linux-arm64.zip
macOS (Intel): pingctl-macos-amd64.zip
macOS (Apple Silicon): pingctl-macos-arm64.zip
Install
Extract the zip.
Move the binary somewhere on your
PATH(for example/usr/local/binon Linux and macOS, or a folder listed in the WindowsPathenvironment variable).On Linux and macOS, make it executable if your unzip tool did not preserve the flag:
chmod +x pingctl.Verify the install:
pingctl versionOn macOS, Gatekeeper may block the first run because the binary is not notarized. Remove the quarantine attribute and run it again:
xattr -d com.apple.quarantine ./pingctlIn CI, download and extract in one step instead of committing the binary to your repository:
curl -LO https://pingcore.io/downloads/pingctl-linux-amd64.zip
unzip pingctl-linux-amd64.zip
./pingctl versionAuthenticate
pingctl authenticates with a per-source push token (cdnpush_...). The token identifies exactly one CDN source, so there is no source flag and nothing else to configure.
On a developer machine, validate and store the token once:
pingctl token setThe command prompts for the token without echoing it, validates it against the platform, and saves it owner-only in ~/.pingctl/config.json.
In CI, set the token as an environment variable instead:
export PINGCORE_PUSH_TOKEN=cdnpush_...Token resolution order: the --token flag, then PINGCORE_PUSH_TOKEN, then the token stored by pingctl token set.
Push a build
pingctl push <dir> [flags]Flags:
--token
<cdnpush_...>: push token, overrides the environment variable and the stored token.--dry-run: show what would upload and delete without changing anything.
--no-delete: keep remote files that are absent locally.
--concurrency
<n>: parallel uploads, default 4.--exclude
<pattern>: skip matching paths. Repeatable, for example--exclude "*.pdb" --exclude "logs/".
A push does four things:
Fetches push info from the platform: the source the token denotes, SFTP upload credentials, and the current version.
Delta-uploads over SFTP. Only files whose content changed are transferred. Uploads are parallel and atomic, so an interrupted push never leaves half-written files under real names.
Triggers a publish. The CDN snapshots the staged files into an immutable version and distributes it to all CDN nodes.
Polls until the CDN reports the outcome and prints the published version.
Files staged over SFTP go live only when a publish runs. The CDN never snapshots a manual source on its own schedule, so a slow upload cannot go live half-finished.
Project config
A pingctl.json next to your build (or in any parent directory) holds non-secret defaults:
{
"excludes": ["*.pdb", "logs/"]
}It never contains the token and is safe to commit.
Security notes
Only a SHA-256 hash of the push token exists server-side. The token itself is shown once, when it is issued.
SFTP host keys are pinned on first use in
~/.pingctl/known_hosts.json. A changed host key aborts the push with instructions.The push token is sent only to the PingCore API over HTTPS. The SFTP credential is scoped to the single source being pushed.
CI example
# GitHub Actions, GitLab CI, or any pipeline with a secret store:
export PINGCORE_PUSH_TOKEN="$CDN_PUSH_TOKEN"
curl -LO https://pingcore.io/downloads/pingctl-linux-amd64.zip
unzip -o pingctl-linux-amd64.zip
./pingctl push ./ServerBuild --exclude "*.pdb"A leaked push token can push builds to its one source and do nothing else. Regenerating the token on the source page invalidates the old one immediately.