# Deploy and update your code

> Source: https://www.allsweb.com/sixpanel/docs/deploy-update
> Markdown for agents: https://www.allsweb.com/sixpanel/docs/deploy-update.md
> Publisher: AllsWeb (www.allsweb.com)

Part of: SixPanel documentation

**What this page is for.** Bring new 6ammart code onto the live server safely — by hand, by uploading a new zip, or automatically on every `git push`.

**You need**

- 6ammart already installed here (**[Install your 6ammart
  code](https://www.allsweb.com/sixpanel/docs/install-app)**).
- For the git paths: the server able to read that repository by itself — see
  **[Put your code in a git repository](https://www.allsweb.com/sixpanel/docs/put-your-code-in-git)**, section
  5.
- Your new code pushed to the branch the panel deploys, or the new zip on your
  computer.
- A recent backup, if the change is a big one (**[Backups](https://www.allsweb.com/sixpanel/docs/backups)**).

> **Do this first** — this page is about **your 6ammart code**. Updating
> SixPanel itself is a different thing on a different page: **[Update SixPanel
> itself](https://www.allsweb.com/sixpanel/docs/update-sixpanel)**. Mixing the two up is the most common
> misunderstanding in this product.

---

## Four ways to run an update

They all end in the same safe sequence, and they all appear in the same
**Deploy history**.

| Way | When to use it |
|---|---|
| **Get the latest code**, on the **Deploys** page | You installed from git and want to see what will change before it changes. |
| **Update from a zip**, on the same page | You installed from a zip, or a new CodeCanyon download is what you have. |
| **Automatic deploys on git push** | Set it up once and never press anything again. |
| `sudo sixpanel deploy` over SSH | Scripts, or when you are already at a terminal. |

> **The three git paths need the server to reach your repository on its own.**
> The token you typed at install time is not kept. Create the read-only deploy
> key on the **Deploys** page — section 5 of **[Put your code in a git
> repository](https://www.allsweb.com/sixpanel/docs/put-your-code-in-git)** — and all three start working.

---

## 1. The Update button

The **Deploys** page opens with one screen that answers three questions: is my
project live, which version is running, and what do I press. When the project is
installed from git, the button on it is **Get the latest code**.

1. Open **Deploys**.
2. Press **Get the latest code**.
3. Read the preview. It tells you:
   - how many updates you are behind, and on which branch,
   - the list of changes, with who made each one,
   - whether **database changes** are included,
   - whether **dependency changes** are included.
4. Press **Back up first** if the change looks big. It takes you to the
   **Backups** page.
5. Press the button that starts the deploy.

If nothing is waiting, the preview says your site already runs the newest code
and there is nothing to do.

**Expected result:** the live log ends with the update finished, and a new row
appears at the top of **Deploy history**.

The site may pause for a few seconds while the caches rebuild.

> **This cannot be undone** — database changes run during a deploy and a
> rollback does not reverse them. Take a backup before a release that includes
> them.

## 1b. Update from a zip

If you installed from a CodeCanyon zip, the same first screen offers **Update
from a zip** instead.

1. Press it and choose the new zip.
2. Confirm. The upload starts, and the progress is on screen.
3. The panel unpacks it into a staging area first, finds the Laravel root, and
   only then lays it over your code — so a half-finished upload can never leave
   a half-finished site.

Your `.env` and your uploaded files are left alone. After the files land the
panel runs the same tail as any other deploy: Composer if the lock file
changed, database migrations, cache rebuild, then PHP reload and the workers
restarted.

The panel keeps its own history of the zips installed here, so **rollback still
works** on a zip project — it puts the previous zip's code back.

---

## 2. Automatic deploys on every push

### One webhook per repository

You can run two repositories for a project: the **admin app** (the panel, the
API, the apps' backend) and the **customer website**. Each one gets its own
webhook, with its own address and its own secret. You can connect them
separately, and replacing one secret does not touch the other.

Both addresses use **your project's own domain**, not the panel's. Your domain
already reaches this server from the internet, so the panel port never has to
be open for this, and GitHub is never told where your panel lives.

| Repository | The address the panel shows |
|---|---|
| Admin app | `https://YOUR-DOMAIN/.stack/webhook/admin` |
| Customer website | `https://YOUR-DOMAIN/.stack/webhook/react` |

Always copy the address from the panel rather than typing it from this page.

### Turn one on — the panel proves each step

Setting this up is a small wizard. It does **not** switch deploys on when you
press the first button; it switches them on when it has evidence the connection
works.

1. Open **Deploys**, find the repository's automatic-deploys card and press
   **Set up automatic deploys**.
2. **Get the address** — the panel shows the address and the secret, with the
   GitHub fields underneath.

   > **Save the secret now.** This is the one moment it is on screen. You can
   > ask for it again later, but you have to confirm it is you first.

   At this point the card reads **almost ready**. A push right now is checked
   and written down — and deploys nothing. That is deliberate.
3. **Give this server read access.** The card called **Read access for this
   server** creates a read-only deploy key and shows you the public half; paste
   it into your repository's **Deploy keys** with write access left off. A push
   that reaches a server which cannot read the repository would fail at the
   first step, so the wizard asks for this before it goes live.
4. Paste the webhook fields into GitHub (next section), then come back and
   press **Check the connection**. The panel sends itself a signed test
   delivery over the public address, looks at the certificate GitHub would see,
   and reads whether a real delivery from your repository has arrived and
   verified.
5. When the check passes, press the button that switches automatic deploys on.
   The card turns to **working**.

If you skip straight to the last step the panel refuses and tells you to run
the connection check first.

The customer website card stays disabled until the website itself is installed.
Install it first — see **[The customer website](https://www.allsweb.com/sixpanel/docs/customer-website)**.

### Fill in GitHub

Open your repository on GitHub → **Settings** → **Webhooks** → **Add
webhook**, then enter:

| GitHub field | Value |
|---|---|
| **Payload URL** | the address the panel shows for **that** repository |
| **Content type** | `application/json` |
| **Secret** | the secret the panel just showed you for **that** repository |
| **SSL verification** | leave it enabled |
| **Which events?** | keep **Just the push event** |
| Active | ticked |

Press **Add webhook**.

Do this once for each repository, with each repository's own address and
secret. Pasting the admin secret into the website's webhook does not work.

`application/json` is the one to pick. The other option,
`application/x-www-form-urlencoded`, also works — SixPanel checks the signature
against the raw message either way, and reads both shapes. So if your git
service only offers the other one, that is fine.

### Fill in Gitea or Forgejo

Repository → **Settings** → **Webhooks** → **Add webhook** → **Gitea**. Same
address, same secret, method `POST`, content type `application/json`, trigger
on push. SixPanel accepts both GitHub's and Gitea's signatures.

### See the secret again, or replace it

Two buttons sit under each block that is turned on:

- **Show the secret again** — the panel asks for your password (and your
  6-digit code) first, then shows it. Anyone holding that secret can start a
  deploy on your site, so do not paste it into a chat or a support ticket.
- **Replace the secret** — a new secret is issued at once and the old one stops
  working immediately, so the webhook in GitHub fails until you paste the new
  one in. Use it if you think the old one was seen by someone else.

### What happens on a push

The public web server passes the message to the panel. The panel checks the
signature, then runs the exact same job the **Get the latest code** button
runs. You watch it in **Deploy history** like any other deploy.

Some pushes are ignored on purpose, and the panel records why:

- a push to any branch other than the one shown as the deploy branch,
- a delivery that was already processed,
- a delivery whose commit is more than five minutes old (a late retry),
- a push that arrived at the wrong address — the website's repository pushing
  to the admin webhook, or the other way round,
- a push from a repository that is neither your app nor your website.

Deploys never overlap. A push that arrives while a deploy is running is handled
after it.

### If you set this up on an older build

Older servers had **one shared address** for both repositories, and the panel
worked out which one had pushed by reading the message. That still works
exactly as it did, and needs no action from you. The panel shows it folded
away, marked as the old way.

To move to the new way: add the new per-repository address in GitHub first,
check that a push deploys, and only then turn the old shared block off.

### Turn one off

Press the off button on that repository's block. Pushes to it stop deploying
and its secret is deleted, so the webhook in GitHub stops working. Turning it
back on later gives you a new secret to paste in. The other repository is not
affected.

---

## 3. Over SSH

```bash
sudo sixpanel deploy preview   # what would be pulled — changes nothing
sudo sixpanel deploy           # pull, migrate, rebuild caches, restart workers
sudo sixpanel deploy history   # recent deploys and how they ended
```

`sudo sixpanel deploy` means **your 6ammart code**. `sudo sixpanel server
update` means **SixPanel itself**. They are different commands because they are
different things.

`sudo sixpanel deploy history --repo react` shows the customer website's
deploys instead of the admin app's.

---

## History and going back

**Deploy history** on the **Deploys** page lists every install, update and
rollback for that repository, newest first: when it ran, which version, what
changed, whether it worked, and what triggered it (by hand, git push, or
rollback). Each row opens its full log.

To go back, press **Roll back to this** on an older row and confirm. The
rollback is itself a deploy, with the same safe sequence, recorded in the
history.

> **This cannot be undone** — a rollback moves your **code** back. It does
> **not** move the **database** back. If a bad release also changed the
> database, restore a backup from before it instead: **[Backups](https://www.allsweb.com/sixpanel/docs/backups)**.

---

## What actually runs

Every update — button, zip, push, or command — runs this sequence and stops at
the first failure:

1. Refuse to continue if the code folder has been edited by hand on the server
   (git installs only).
2. Bring in the new code: pull fast-forward only, or lay the new zip over the
   checkout.
3. Clear the app's caches.
4. Apply database changes (`migrate`).
5. Install PHP libraries, but only if the lock file changed.
6. Rebuild the caches.
7. Reload PHP and restart the queue worker and the scheduler.

A rollback does the same, except that it moves the code to the chosen version
instead of pulling the newest one, and it does not run database changes.

Everything that touches your code runs as **the project's own Linux user**,
never as root. That is why a file the panel wrote is always readable by the app
and never leaves you with a folder the site cannot write to.

---

## How to check it worked

- **Deploy history** shows a new row with a green result.
- The top row carries the live badge and the version you expected.
- Your site loads and the change is visible.
- **Server → Health** is still green, including **The app answers requests**.

## If it went wrong

**The update refuses to start: local changes**
Somebody edited files on the server through the **Files** tab or over SSH. A
deploy will not silently throw that away.

The deploy log names the files. Open the failed row's log and read the lines
above the failure — up to the first fifteen changed files are printed there.
You can also list them yourself over SSH:

```bash
sudo sixpanel exec php git status --short
```

That runs inside your project's code directory, as the project's own user. A
line marked `M` is an edited file. A line marked `??` is a new file that is not
in git. The app's own `.env` is ignored by this check, so it never appears as a
problem.

The clean way out is to make the same change in git and push it. If the edit
was a mistake and you want it gone:

> **This cannot be undone** — the command below throws the hand edit away for
> good. There is no copy of it anywhere. If you are not sure what was changed,
> run the `status --short` command above first and read the list.

```bash
sudo sixpanel exec php git checkout -- .
```

That restores the edited files. Files marked `??` are new and stay — delete
those through the **Files** tab, or add them to git.

**"could not check the repository for new commits"**
The server cannot read your repository by itself. Create the read-only deploy
key on the **Deploys** page and paste it into the repository — section 5 of
**[Put your code in a git repository](https://www.allsweb.com/sixpanel/docs/put-your-code-in-git)**.

**GitHub shows a red delivery with 401**
There are three causes, and the content type is not one of them. Either that
repository's webhook is turned off in the panel, or GitHub sent no signature at
all (the **Secret** box on the webhook is empty), or the secret does not match
— often because the admin secret was pasted into the website's webhook. Press
**Replace the secret** on the right block, paste the fresh secret into GitHub,
then use GitHub's **Redeliver** on a recent delivery to test.

**GitHub shows green but nothing deployed**
Three things to check, in order. The **address**: a push that lands on the
other repository's webhook is accepted and then ignored, and the panel says so
in the activity log. The **branch**: only the deploy branch deploys. Then
**Deploy history**: a delivery can be accepted and the job still fail, and the
reason is in the job log, not in GitHub.

**The deploy failed part-way**
The log names the failing step and the update stops there. Nothing after that
step ran. Fix the cause and deploy again.

**The site broke after a good-looking deploy**
Press **Roll back to this** on the previous row. If the release also changed
the database, restore a backup instead.

More causes and fixes: **[When something is broken](https://www.allsweb.com/sixpanel/docs/troubleshooting)**.
