Auto-deploy on push
Make Synq rebuild and ship your app every time you push, from GitHub or from GitLab, Bitbucket, Gitea and Forgejo. Covers webhook setup per provider, signatures, branch matching, the delivery log and troubleshooting.
Once your app is deployed, you don't want to press Deploy every time you change something. Auto-deploy does it for you: you push to the project's branch as usual, the Git host tells Synq about the push through a webhook (a small HTTP message sent the moment you push), and Synq builds and ships that commit.
Which setup applies
| Where the project's code comes from | How pushes reach Synq | Set it up in |
|---|---|---|
| A repository from the GitHub tab | A GitHub webhook Synq creates for you, or your own GitHub App | GitHub |
| A repository from the Git URL tab (GitLab, Bitbucket, Gitea, Forgejo, Codeberg, other) | A webhook you add in the provider, with a URL and secret Synq gives you | GitLab, Bitbucket, Gitea and Forgejo |
| A folder, archive, pasted Dockerfile or Compose file, or a Docker image | No repository to push to | Use a deploy hook |
In every case the push has to reach Synq over the internet: the panel needs a public address:
SYNQ_PUBLIC_URL (for example https://panel.example.com, set by the installer's --domain or by
synq panel-domain), or a verified, SSL-ready
primary domain on the Synq app itself. The GitHub setup has a way around that (a
verified project domain); the others do not.
GitHub
What you need first
- A project linked to a GitHub repository (see Deploy from GitHub).
- A way for GitHub to reach Synq: Synq on a public web address, or a verified domain on the project for direct delivery. Synq tells you which one applies.
Open the project's Source tab
Open your project, then Source & Triggers → Source. The Source Repository card holds the deploy triggers for this repository.
Turn on Auto Deploy
Switch on the Auto Deploy card. When it is on, the card reads Enabled and "Pushes trigger deployments automatically". When it is off, it reads Disabled and "Deployments must be started manually".
From now on, every git push to the deploy branch builds and ships automatically.
If Synq asks for a webhook endpoint
When Synq cannot be reached from the internet on its own (a laptop, a private network, no public URL), you see an Enable auto-deploy notice: "Auto-deploy needs a direct webhook endpoint. Expose this Synq API on a public URL or configure a verified webhook domain for direct delivery."
The fix is the Webhook Endpoint card. Pick one of the project's verified domains from the Select domain... menu, and GitHub delivers push events straight to that domain. To stop using it, open the same menu and choose Clear selection.
Don't see the Webhook Endpoint card?
The card appears once the project has at least one verified domain. Attach and verify a domain first (see Custom domains), then come back. The menu only lists this project's verified domains.
Check the status
The Webhook card shows whether GitHub is reaching Synq: Active ("Repository events are reaching Synq"), Direct (events arrive through your chosen domain), or Inactive ("Webhook has not been configured or is not responding"). After your next push, glance at this card and at the delivery log.
How the GitHub webhook is wired
Synq picks the simplest route that works:
- Public Synq: turning on Auto Deploy registers a webhook on the repository that points at
<public URL>/api/proxy/api/webhooks/github, for examplehttps://app.example.com/api/proxy/api/webhooks/github. Each project gets its own webhook secret, and every delivery'sX-Hub-Signature-256signature is checked against it. - Verified domain: with a Webhook Endpoint set, GitHub delivers to
https://<your-domain>/_synq/hooks/github, which the edge passes to Synq. This is the option for private installs. - Your own GitHub App: with a self-hosted GitHub App, push events arrive through the App; there is no separate per-repository webhook to manage.
Creating the repository webhook needs admin access to the repository through your GitHub connection.
Which GitHub pushes deploy
- Only pushes to the project's deploy branch deploy. Pushes to other branches are ignored (preview environments, if you use them, track their own branches; see Preview environments).
- For a Compose or monorepo project, Synq reads which files changed and rebuilds only the services they affect. A push that touches none of them is skipped.
- A commit that is already building or live is not deployed twice, and a redelivered webhook is recognized.
From the CLI
You need the project's ID (synq project list).
# Turn auto-deploy on, or off again
synq project git auto-deploy <project-id> --enable
synq project git auto-deploy <project-id> --disable
# Deliver webhooks to a verified project domain (for private instances), or stop
synq project git webhook-domain <project-id> deploy.yourapp.com
synq project git webhook-domain <project-id> --clear
# Change the deploy branch
synq project git branch <project-id> mainGitLab, Bitbucket, Gitea and Forgejo
A project imported from the Git URL tab (see Deploy from any Git URL) has its own webhook URL and secret. You turn auto-deploy on in Synq, then add that webhook in your Git provider once.
Open the project's Source tab
Open the project, then Source & Triggers → Source. Below the Git repository card is the Deploy on push card.
Turn on Auto-deploy on push
Switch it on. The card then says "Pushes to main deploy this project automatically." (with your branch). While it is off, deliveries are received and logged but nothing deploys.
If you see "This instance has no public URL yet, so a hosted Git provider cannot reach this webhook", give Synq
a public URL first: set SYNQ_PUBLIC_URL (see Installation) or add a
verified domain to the Synq app itself.
A Git server on your own network can still reach a private address.
Copy the webhook URL and secret
The card shows:
- Webhook URL, for example
https://app.example.com/api/proxy/api/webhooks/git/<project-id>. One URL per project. - Secret (masked; use the eye button to show it, and the copy button to copy it).
Add the webhook in your provider
Set up the webhook has a tab per provider with the exact steps. They are repeated below. Use a branch filter in the provider when it offers one; Synq checks the branch either way.
Send a test
Use the provider's test button, or push a commit, and watch Recent deliveries. A ping (Bitbucket's
connection test, for example) is logged as ignored and answered "Webhook reachable and verified". A test
push (GitLab, Gitea and Forgejo send a sample push of the latest commit) is handled like a real push: it
deploys when it is for the deploy branch, and is skipped when that commit is already live. A real push
arrives as dispatched.
GitLab
- In GitLab, open the project, then Settings → Webhooks → Add new webhook.
- Paste the Webhook URL into URL.
- Paste the Secret into Secret token.
- Under Trigger, select Push events (you can filter to your deploy branch), then Add webhook.
GitLab sends the secret as the X-Gitlab-Token header. Works for gitlab.com and self-managed GitLab.
Gitea
- In Gitea, open the repository, then Settings → Webhooks → Add webhook → Gitea.
- Paste the Webhook URL into Target URL and keep POST with
application/json. - Paste the Secret into Secret.
- Choose Push events, set Branch filter to your deploy branch, then Add webhook.
Forgejo and Codeberg
- In Forgejo, open the repository, then Settings → Webhooks → Add webhook → Forgejo.
- Paste the Webhook URL into Target URL and keep POST with
application/json. - Paste the Secret into Secret.
- Choose Push events, set Branch filter to your deploy branch, then Add webhook.
Bitbucket
- In Bitbucket, open the repository, then Repository settings → Webhooks → Add webhook.
- Enter a title and paste the Webhook URL into URL.
- Paste the Secret into Secret.
- Under Triggers, keep Repository push, then Save. Pushes to other branches are ignored.
Bitbucket Cloud (repo:push) and Bitbucket Data Center (repo:refs_changed) are both understood.
GitHub repositories imported by Git URL
If you imported a GitHub repository through the Git URL tab, add a repository webhook on GitHub
yourself: Settings → Webhooks → Add webhook, Payload URL set to the Webhook URL, Content type
application/json, Secret set to the Secret, and Just the push event.
Git servers without webhooks
A plain Git server (for example one reached only over SSH) has no webhook settings. Create a
deploy hook and call it from the repository's post-receive hook, for example
curl -fsS -X POST -H "Authorization: Bearer <token>" <delivery URL>.
How deliveries are verified
The secret proves a delivery is for this project. Each provider sends it differently:
| Provider | Header | Value |
|---|---|---|
| GitLab | X-Gitlab-Token | The secret itself. |
| Forgejo | X-Forgejo-Signature | HMAC-SHA256 of the body, hex. |
| Gitea | X-Gitea-Signature | HMAC-SHA256 of the body, hex. |
| GitHub and compatible | X-Hub-Signature-256 | sha256= plus the HMAC-SHA256 of the body, hex. |
| Bitbucket | X-Hub-Signature | sha256= plus the HMAC-SHA256 of the body, hex. |
A delivery with none of these, or with an old SHA-1 signature, is refused with 401. The body must be
JSON (content type application/json).
Which pushes deploy
- Only a push to the project's Branch deploys. When the branch field is empty, the repository's default branch counts. A deleted branch never deploys.
- A provider's ping or test event is answered and logged as
ignored. Other events (tags, merge requests, issues) areignoredtoo. - With Auto-deploy on push off, a push is logged as
skipped("Auto-deploy on push is off for this project."). - A commit that is already deployed or deploying is
skipped, so redeliveries are harmless. - For a Compose or monorepo project, GitLab, Gitea and Forgejo include the changed files, so only the affected services rebuild. Bitbucket does not send file lists, and neither does any provider for a force push or a push of 20 commits or more: then every service rebuilds.
- The deploy runs as the organization's owner, since no person pressed the button.
Rotate the secret
Press Rotate secret on the Deploy on push card. Deliveries fail with 401 until you paste the new
secret into the provider's webhook settings, so do both at once.
Delivery log
Every push delivery and deploy hook call is logged per project:
- For Git URL projects, Recent deliveries sits under the Deploy on push card ("No deliveries yet. Use your provider's test button to send one." until the first arrives).
- For every project, Source & Triggers → Webhooks shows the same feed under Recent deliveries ("GitHub pushes and custom hook calls received for this project.").
Each row shows the outcome (dispatched, skipped, ignored, failed), the branch and short commit for a
push, when it arrived, and the error for a failed delivery. Load more loads older rows.
Troubleshooting
The GitHub Auto Deploy toggle won't turn on
You see the Enable auto-deploy notice, and the error reads "Set a webhook domain or expose this Synq API on a public URL to enable auto-deploy." GitHub has no way to reach Synq yet. Put Synq on a public address, or set a Webhook Endpoint domain on the Source tab.
“Domain must be verified before it can receive webhooks”
The domain you picked is not verified yet. Verify it first (Custom domains), then select it again.
“Could not create webhook”
Synq could not add the webhook to your GitHub repository, usually because your GitHub connection lacks admin access to it. Reconnect GitHub, make sure the repository is included with full access, then toggle Auto Deploy again.
GitLab, Gitea, Forgejo or Bitbucket shows 401
The secret in the provider does not match the project's secret, or it was not set. The delivery log says which: "No signature or token header. Set the secret in the provider's webhook settings." or "The signature or token does not match this project's webhook secret." Copy the Secret again (after a rotate, the old one no longer works).
The provider shows 400
The body was not JSON. In Gitea or Forgejo, set the content type to application/json.
The provider shows 404
The URL does not belong to a Git URL project with a webhook secret: check that you copied the whole Webhook URL from this project, and that the project still exists.
I pushed, but nothing deployed
Open the delivery log. No row at all means the delivery never reached Synq: check the
public URL, your firewall, and the provider's own delivery history. A skipped row says why (another
branch, auto-deploy off, commit already live, no service affected). For GitHub, also check the Webhook
card; Inactive means delivery is not reaching Synq.
If another deployment is running, a GitHub push is reported as a failed delivery, with the reason in the
delivery log. Wait for the running deployment to finish or cancel it, then Redeliver the failed event
from GitHub's webhook delivery history (GitHub does not retry on its own). Synq accepts a retry of the same
failed delivery and only retries the projects not yet handled; a successful delivery is never deployed
twice. A Git URL provider that gets a 500 ("The deployment could not be started.") offers the same
redelivery.
Related
Preview environments
Make a separate, safe copy of your project from a git branch — so you can try changes before they reach your real site.
Deploy hooks
Give a project its own URL that redeploys it (or runs a job) when called, from CI, a registry, a cron service or a script. Covers token, HMAC and open authentication, service selection, responses and the delivery log.