GitHub Container Registry → Coolify Deploy Setup
Switches from Coolify/Nixpacks on-droplet builds to GitHub Actions → ghcr.io → Coolify pull. The droplet no longer builds the image; it only runs the pre-built container.
Overview
Push to master
└─► GitHub Actions (ubuntu-latest)
└─► docker build (multi-stage, Node 22 Alpine)
└─► push ghcr.io/ioncernenchii/itinera:latest + :sha-<short>
└─► curl webhook → Coolify redeploys
Step 1 — Add GitHub Repository Secrets
GitHub → ioncernenchii/itinera → Settings → Secrets and variables → Actions → New repository secret
| Secret name | Value |
|---|---|
NEXT_PUBLIC_GOOGLE_MAPS_API_KEY | Google Maps API key (baked in at build time) |
COOLIFY_WEBHOOK_URL | Coolify deploy webhook URL (see Step 3a) |
COOLIFY_WEBHOOK_TOKEN | Coolify API token with deploy permission (see Step 3a) |
GITHUB_TOKENis automatically provided — no manual secret needed for ghcr.io push.
Step 2 — Verify ghcr.io Package Visibility
After the first successful workflow run, a package named itinera will appear at
https://github.com/ioncernenchii?tab=packages.
- Click the package → Package settings
- Under Danger Zone, set visibility to Private
- Under Manage Actions access, add the
ioncernenchii/itinerarepository with Write access
Step 3 — Configure Coolify Application
3a. Get the Coolify deploy webhook and API token
- Open Coolify UI → select the Itinera application → Webhooks tab
- Copy the Deploy Webhook URL →
COOLIFY_WEBHOOK_URLGitHub secret - Coolify left sidebar → Keys & Tokens → API Tokens → create token:
- Description:
github-actions-deploy - Permission:
deployonly - Copy token →
COOLIFY_WEBHOOK_TOKENGitHub secret
- Description:
3b. Confirm Coolify build pack and Docker Registry
In Coolify → Itinera application → General tab:
- Build Pack:
Dockerfile(leave as-is — Coolify uses the Docker Registry image below) - Docker Registry → Docker Image:
ghcr.io/ioncernenchii/itinera:latest - Docker Image Tag: leave empty (Coolify uses the commit SHA tag automatically)
There is no registry credentials UI in Coolify v4 for private ghcr.io images. Authentication is handled directly on the host (see Step 4).
3c. Environment variables
Verify these are set in Coolify → Environment Variables tab (not baked into the image):
DATABASE_URL=...
NEXTAUTH_SECRET=...
NEXTAUTH_URL=https://app.getitinera.com
SENTRY_DSN=...
TELEGRAM_BOT_TOKEN=...
TELEGRAM_CHAT_ID=...
NEXT_PUBLIC_GOOGLE_MAPS_API_KEYis baked in at build time via the GitHub Actions secret — do not add it here.
Step 4 — Authenticate Docker on the Droplet
Coolify v4 has no UI for private registry credentials — it uses the host Docker daemon's stored credentials.
SSH into the droplet and run:
echo <YOUR_CLASSIC_PAT> | docker login ghcr.io -u ioncernenchii --password-stdin
Create the classic PAT:
- GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) → Generate new token (classic)
Fine-grained tokens do not support GitHub Packages — use classic.
- Note:
coolify-ghcr-pull - Expiration: 1 year (set a calendar reminder to rotate)
- Scope:
read:packagesonly
Credentials are saved to /root/.docker/config.json and persist across reboots.
Rotate annually — when the PAT expires, re-run the docker login command with the new token.
Step 5 — First Deploy
- Push to
master(or re-run the last workflow manually in GitHub → Actions) - Watch GitHub → Actions → Build & Push Docker Image
- After it succeeds, Coolify receives the webhook and redeploys automatically
- Verify at https://app.getitinera.com
Cleanup Notes
Nixpacks config
No nixpacks.toml exists in this repo — no action needed.
/swapfile
The droplet no longer builds Docker images (7GB GitHub Actions runners handle that now).
Keep /swapfile — the running Node.js process and PostgreSQL still benefit from swap headroom.
To check current swap:
swapon --show
free -h
Old build cache on droplet
If Coolify left stale build layers:
docker builder prune --filter until=24h
Rollback
To roll back to a previous image:
- In Coolify → General tab → Docker Image Tag → enter
sha-<previous-short-sha> - Click Redeploy
- After confirming the rollback, clear the tag field to resume tracking
latest
SHA tags are retained in ghcr.io for every push. Find them at:
https://github.com/ioncernenchii/itinera/pkgs/container/itinera