Deploying with Git
A website that comes out of a Git repository does not need FTP any more. You bring the repository in once, and from then on publishing is one button: the server writes out a copy of exactly one commit into a directory of its own and points
Written for: Reseller, Administrator
A website that comes out of a Git repository does not need FTP any more. You bring the repository in once, and from then on publishing is one button: the server writes out a copy of exactly one commit into a directory of its own and points the website at it. If it turns out badly, one button puts the website back on the previous version. No file is moved in either direction — only a symbolic link.
You will find it under Accounts → your account → Git. If the tab is not there you are looking with an account that may not: it is a tab for hosting companies and administrators, not for the end customer.
Why there are two directories
In a classic setup your code sits in the directory the web server shows. Here two things sit beside each other:
- the working copy — the repository itself,
repos/<name>by default. This is where the.gitdirectory is and where new commits arrive. - the releases directory —
deploys/<name>by default. Under it sits areleases/directory with one directory per publish, and acurrentlink pointing at whichever release is live.
You point the website's document root at that link. This is what makes publishing cheap: the new release is written out in full, and only when that has worked does the link move. If the extraction fails halfway, no visitor ever saw it.
A release never contains a .git directory. That is deliberate: a .git under a document root means anybody with a browser can download your whole history, including whatever once landed in a commit by accident.
Bringing in a private repository
A public repository needs nothing but an https:// URL. For a private one, make a deploy key first:
- Git → ⋯ → Create a deploy key, and give it a name — the provider it belongs to, for instance.
- Copy the public key you get and paste it at GitHub, GitLab or Gitea under Deploy keys of that repository. Read-only is enough.
- Clone a repository, fill in the
ssh://orgit@host:pathURL and pick the key you just made.
The private half of that key stays on the server, mode 0600, and is never in a response or in a log. It does not give access to the server either: it is not kept with the account's login keys.
Reading the list of keys
Under Git → Keys each key is one card, carrying everything you need to recognise it: the name you gave it, its fingerprint (SHA256:…, with the type and length beside it), whether the private half is still on the server, and which repositories use it. If it says none do, that is not a fault — it is the normal state of a key you have just generated and not yet chosen anywhere.
The fingerprint is shown in full and not abbreviated. That is deliberate: it is there to be compared with what your provider shows under Deploy keys, and half a fingerprint compares to nothing. On a phone it now breaks across lines inside its card — since round 5, because before that it pushed the screen sideways.
What you never see, and nor does anyone else, is the private half. "Replace key" generates a new pair; the old public key at your provider stops working after that, so replace it there with the new one.
On the command line it is the same thing in two commands:
corectl git key add github --account demo
corectl git clone site --account demo \
--remote git@github.com:yourteam/site.git --key githubWhat CoreCP refuses to clone is a short list, and every line has a reason: ext::… (that runs a command instead of fetching anything), file:// and a path on the server itself (that is what the file manager is for), git:// (no encryption and no check on what comes back) and a URL with a password in it (that would end up readable on the server — use a deploy key).
Publishing and going back
Choose Set the releases directory, fill in the directory (deploys/site is fine), pick the branch or tag that gets published, and say how many releases to keep — at least two, because the previous release is the way back. Then point the website's document root at deploys/site/current, which you do on the website screen under Document root.
From then on, publishing is one button. Publish fetches the newest commits, writes the chosen branch out into a new release and moves the link. The top of the screen says the whole time which release is live, which commit it came from and when it went up.
Go back one release does exactly the opposite: the link returns to the release before it. The release you came from stays where it is, so going forward again is just as easy. In the release list you can also pick a specific older one. A release that has already been cleared up — because you published more than you keep — is still listed, marked cleared up and without a button: that one really is off the disk.
What happens when something goes wrong
- The remote does not answer. Nothing is published and your website keeps showing what it was showing. The message carries git's own words.
- The branch does not exist. The same: the refusal comes before anything is written out.
- The extraction fails. The half-written release is removed and the link never moved.
- You changed something on the server by hand. Bring up to date refuses and shows you which files. Throwing those changes away is a separate, explicit action.
Publishing is always safe to repeat: nothing is ever written into an existing release, every publish makes a new directory beside it.
A private repository over https
Not every provider offers deploy keys, and not every network lets SSH out. For those, store an access token instead:
- Make the token at your provider. On GitHub that is a fine-grained personal access token with read access to the repository; on GitLab a project or deploy token; on Gitea a token on your own account.
- Git → ⋯ → Store a token. Give it a name, fill in the server it is for (
github.com,gitlab.com, your own address), the user name it travels with, and paste the token. - Clone a repository, fill in the
https://URL and pick the token.
About the user name: providers disagree, so CoreCP asks instead of guessing. GitHub accepts any word beside a token, GitLab wants oauth2, Gitea wants your login. Your provider's own documentation says which.
The token is stored on the server with mode 0600 and is never shown again — not on a screen, not in an answer, not in a log. If you lose it, make a new one at your provider and store that; there is nothing to recover here. It is also tied to the server you named: a token for github.com is never sent anywhere else, even if the repository's address is changed later.
A repository uses a deploy key or a token, not both. The address decides which: ssh:// and git@host:path ask for the key, https:// for the token.
corectl git token add github --account demo --host github.com --username deploy
corectl git clone site --account demo \
--remote https://github.com/yourteam/site.git --token githubPublishing automatically after a push
Instead of pressing Publish yourself, you can let your provider tell CoreCP that something has been pushed.
- Git → ⋯ → Create an address. Pick the repository and the branch that should be published.
- You get an address and a secret, both once. Copy them.
- At your provider, add a webhook: paste the address in the URL field and the secret in the Secret field (GitHub) or Secret token field (GitLab). Content type JSON, and the push event is the only one that matters.
From then on, a push to that branch publishes a new release, exactly as the button does. Everything else your provider sends — a push to another branch, a tag, a pull request, the test delivery it makes when you save the webhook — is received, written down and does nothing.
The secret is what proves the message came from your provider and not from somebody who guessed the address. Without a matching secret the message is refused, and the refusal is written down too: that line is how you find out somebody is knocking. If you lose the secret, delete the address and make a new one — there is nothing to look up.
The same push delivered twice publishes once. That holds whether your provider retried it after a timeout, you pressed redeliver yourself, or somebody replayed a message they had seen before: what CoreCP recognises is the message, not the label your provider put on it.
When a message says failed, your server could not be asked to publish at that moment — because the repository is no longer under management, for instance. Nobody tries that again by itself: not CoreCP, and not your provider either. Fix what the line says and press redeliver at your provider.
Log on the address shows the last hundred messages, newest first, with what each of them did: published, did nothing, already handled, refused or failed. That list is the answer to "why did the site change at three in the morning", and just as often to "why did it not".
Switch off keeps the address and stops it publishing — useful while you are working on something. Your provider keeps delivering; the messages arrive, are written down and are refused.
Protecting a branch
On a repository's screen you can name the branches this panel refuses to throw work away on. On a protected branch, Take the server's version and discard my changes and switch are refused, and the repository's working copy cannot be deleted until you take the protection off.
It is a handbrake against a wrong click, not a lock. Everything here runs as your hosting account in its own home, so anyone with SSH access to that account can still do all of it by hand. The panel says so on the screen rather than letting you believe otherwise.
When your copy and the server have moved apart
Bring up to date is a fast-forward or a refusal — it never leaves a half-finished merge in your home. If there are commits on the server that are not on your provider's side and the other way round, the panel says the two have moved apart and offers three things.
Show what moved apart lists how many commits each way, and — more usefully — the files that were worked on from both sides. That short list is what a reconciliation would actually be about.
Keep this work under a name adds a branch pointing at the commits that exist only on this server. Nothing goes away, and the work stays reachable in the history and the differences afterwards.
Take the server's version throws away every commit that exists only here, along with changes that were never committed. Files you added and never told Git about are left alone.
The order is the advice: keep first, then take. That is what turns a loss into a choice.
What this does not do
Committing, merging and pushing from the panel are deliberately not here, and neither is an editor in the browser. Composing a commit needs somewhere to write it, and resolving a merge needs somewhere to read both sides — a hosting panel is a poor place for both. What this panel does is get a repository onto the server, publish exactly one commit from it, put the previous one back, and explain clearly what is in the way when it cannot.