Nixpacks auto-detect could not find a 'start' script in package.json and bailed out. Astro builds to static files in dist/ — there is no Node server to start. Switching to a Dockerfile + nginx fixes the 'No start command could be found' error from EasyPanel. The workflow also pointed at the source-code branch, but the panel's git source ref for the dealplustech-astro service is 'main', so the trigger was firing for the wrong ref. Both workflows now run on push to main. - Dockerfile: multi-stage node:20-alpine build + nginx:1.27-alpine serve - nginx.conf: gzip, security headers, 1-year cache for hashed assets, try_files fallback for UTF-8 slugs (Astro file-based routing) - .dockerignore: keep build context small (skip CI, docs, .gitea, IDE) - build-and-deploy.yml + lint.yml: branch source-code -> main - docs/ci-setup.md: corrected project + service names (customerwebsite / dealplustech-astro), documented the Dockerfile rationale, added a note for the 'Failed to sync changes' server-side error
3.4 KiB
CI/CD Setup — EasyPanel Deploy
Push to main triggers build-and-deploy.yml:
- Builds the Astro static site into
dist/ - Uploads
dist/as a 7-day artifact - Calls EasyPanel tRPC endpoint to trigger a redeploy
Required Gitea repo secrets
Go to Settings → Actions → Secrets and add three secrets:
| Name | Value (for this site) | Where to get it |
|---|---|---|
EASYPANEL_TOKEN |
cmq61xwrv000407qn9e2hhfuw |
EasyPanel → profile/settings → API tokens |
EASYPANEL_PROJECT_NAME |
customerwebsite |
EasyPanel → project name in the dashboard |
EASYPANEL_SERVICE_NAME |
dealplustech-astro |
EasyPanel → service name inside the project |
⚠️ Project name ≠ repo name. The site lives in the
customerwebsiteproject on the panel; the repo isdealplustech-astroreal.
If any of these are empty, the workflow logs a warning and skips the deploy trigger. The build still runs and the artifact is still uploaded.
EasyPanel service requirements
The service on the panel side must be:
- Type:
app - Source: Git, pointing at this repo (
kunthawat/dealplustech-astroreal) on branchmain(notsource-code). - Build type:
dockerfile, file:Dockerfileat the repo root.The workflow used to trigger nixpacks builds, but nixpacks expects a
startscript inpackage.jsonand an Astro static site doesn't have one. Switching to a Dockerfile + nginx fixes that. - Port:
80
If you need a different service type later, swap the endpoint in
.gitea/workflows/build-and-deploy.yml to the matching procedure:
services.app.deployService(Dockerfile / app)services.box.rebuildDockerImage(low-level)services.compose.deployService(docker-compose)
Why Dockerfile and not nixpacks
Astro builds to static files in dist/ — there is no Node server to run.
Nixpacks tries to find a start command and fails. The Dockerfile in
this repo:
- Stage 1 (
node:20-alpine): runsnpm cithennpm run buildto producedist/. - Stage 2 (
nginx:1.27-alpine): copiesdist/to nginx's web root and serves it.
nginx.conf ships gzip, security headers, 1-year cache for hashed
assets, and a try_files fallback for client-side routes (Astro's
file-based routing produces UTF-8 slugs).
Verifying the trigger payload
If the deploy runs but the panel rejects it, the response in the workflow
log will show the exact zodErrors field telling you which field name
or shape is wrong. Update the PAYLOAD JSON in the workflow accordingly.
To test the payload shape from your local machine:
curl -sS -X POST \
"https://panelwebsite.moreminimore.com/api/trpc/services.app.deployService" \
-H "Authorization: Bearer *** -H "Content-Type: application/json" \
-d '{"json":{"projectName":"customerwebsite","serviceName":"dealplustech-astro"}}'
A 2xx response = the panel accepted the trigger. The service will start rebuilding/redploying in the EasyPanel dashboard.
Common failure: "Failed to sync changes" (HTTP 500)
This is a server-side error, not a payload problem. It usually means:
- The EasyPanel service is currently in a state that can't be redeployed (e.g. the previous container is stuck, or a build is in progress).
- The Docker daemon on the panel host is busy.
Try again in a few seconds. If it persists, open the EasyPanel dashboard and check the service's container state.