tambah trust proxy
This commit is contained in:
9
.claude/settings.json
Normal file
9
.claude/settings.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(rm -f deploy/myansuran-webhook.service deploy/hooks.json deploy/README.md deploy/deploy.sh)",
|
||||||
|
"Bash(rmdir deploy *)",
|
||||||
|
"Bash(mkdir -p docker/webhook)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Pastikan skrip shell sentiasa guna line ending LF walaupun di-commit dari Windows.
|
# Pastikan skrip shell sentiasa guna line ending LF walaupun di-commit dari Windows.
|
||||||
*.sh text eol=lf
|
*.sh text eol=lf
|
||||||
deploy/deploy.sh text eol=lf
|
deploy.sh text eol=lf
|
||||||
docker/php-apache/entrypoint.sh text eol=lf
|
docker/php-apache/entrypoint.sh text eol=lf
|
||||||
|
|||||||
29
deploy.sh
Normal file
29
deploy.sh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# myAnsuran KIK-JPPH — Production Deploy Script
|
||||||
|
# Dipanggil oleh webhook selepas git push ke Gitea (branch master)
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PROJECT_DIR="/srv/myansuran"
|
||||||
|
LOG="$PROJECT_DIR/deploy.log"
|
||||||
|
|
||||||
|
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG"; }
|
||||||
|
|
||||||
|
log "=== Deploy dimulakan ==="
|
||||||
|
|
||||||
|
cd "$PROJECT_DIR"
|
||||||
|
|
||||||
|
log "git pull..."
|
||||||
|
git pull origin master
|
||||||
|
|
||||||
|
# Kod di-bind-mount (./src:/var/www/html) jadi perubahan terus aktif —
|
||||||
|
# tak perlu rebuild image untuk perubahan kod biasa.
|
||||||
|
log "composer install..."
|
||||||
|
docker exec myansuran-app composer install --no-dev --optimize-autoloader --no-interaction
|
||||||
|
|
||||||
|
log "migrate database..."
|
||||||
|
docker exec myansuran-app php artisan migrate --force
|
||||||
|
|
||||||
|
log "optimize cache..."
|
||||||
|
docker exec myansuran-app php artisan optimize
|
||||||
|
|
||||||
|
log "=== Deploy selesai ==="
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
# Auto-deploy via Git Webhook
|
|
||||||
|
|
||||||
Bila ada `git push` ke Gitea, Gitea hantar webhook ke server. Server tarik kod
|
|
||||||
terbaru dan jalankan `docker compose up --build -d` secara automatik.
|
|
||||||
|
|
||||||
Aliran: **push → Gitea webhook → `webhook` listener (port 9001) → `deploy.sh`**
|
|
||||||
|
|
||||||
> Nota: port **9001** digunakan (bukan 9000 default) kerana server ini sudah
|
|
||||||
> ada satu lagi app guna webhook di port 9001. Pastikan tiada port bertindih.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. Setup di server production (sekali sahaja)
|
|
||||||
|
|
||||||
Andaikan repo berada di `/opt/myansuran` (laraskan path dalam `hooks.json`
|
|
||||||
dan `myansuran-webhook.service` jika berbeza).
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# a) Pasang webhook listener
|
|
||||||
sudo apt-get update && sudo apt-get install -y webhook
|
|
||||||
|
|
||||||
# b) Pastikan user 'deploy' wujud & ahli group docker (boleh tukar nama user)
|
|
||||||
sudo useradd -m -G docker deploy 2>/dev/null || sudo usermod -aG docker deploy
|
|
||||||
|
|
||||||
# c) Pastikan skrip executable
|
|
||||||
chmod +x /opt/myansuran/deploy/deploy.sh
|
|
||||||
|
|
||||||
# d) Set secret rahsia dalam hooks.json (ganti GANTI_DENGAN_SECRET_RAHSIA)
|
|
||||||
# Jana satu secret kuat:
|
|
||||||
openssl rand -hex 32
|
|
||||||
# Lepas tu edit /opt/myansuran/deploy/hooks.json -> letak nilai itu pada "secret"
|
|
||||||
|
|
||||||
# e) Pasang service systemd
|
|
||||||
sudo cp /opt/myansuran/deploy/myansuran-webhook.service /etc/systemd/system/
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable --now myansuran-webhook
|
|
||||||
sudo systemctl status myansuran-webhook
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. Setup webhook di Gitea
|
|
||||||
|
|
||||||
Repo → **Settings → Webhooks → Add Webhook → Gitea**:
|
|
||||||
|
|
||||||
- **Target URL:** `http://SERVER_IP:9001/hooks/myansuran-deploy`
|
|
||||||
- **HTTP Method:** `POST`
|
|
||||||
- **Content Type:** `application/json`
|
|
||||||
- **Secret:** secret SAMA seperti dalam `hooks.json`
|
|
||||||
- **Trigger:** Push events sahaja
|
|
||||||
- **Branch filter:** `main`
|
|
||||||
|
|
||||||
Klik **Test Delivery** untuk uji.
|
|
||||||
|
|
||||||
## 3. Uji manual
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Jalankan deploy terus tanpa webhook (untuk debug)
|
|
||||||
/opt/myansuran/deploy/deploy.sh
|
|
||||||
|
|
||||||
# Lihat log webhook
|
|
||||||
sudo journalctl -u myansuran-webhook -f
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Nota keselamatan
|
|
||||||
|
|
||||||
- Port `9001` hanya perlu dicapai oleh Gitea. Hadkan dengan firewall:
|
|
||||||
`sudo ufw allow from <IP_GITEA> to any port 9001 proto tcp`
|
|
||||||
- Atau letak di belakang Nginx/Apache reverse proxy dengan HTTPS.
|
|
||||||
- Signature HMAC-SHA256 menghalang sesiapa tanpa secret daripada trigger deploy.
|
|
||||||
|
|
||||||
## Tukar branch
|
|
||||||
|
|
||||||
Default deploy branch ialah `main`. Untuk branch lain, set dalam service:
|
|
||||||
`ExecStart=... ` tambah `Environment=BRANCH=staging`, dan tukar `refs/heads/main`
|
|
||||||
dalam `hooks.json` kepada branch berkenaan.
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# Skrip deploy yang dipanggil oleh webhook bila ada push ke Gitea.
|
|
||||||
# Ia mengesan sendiri lokasi repo (folder induk kepada deploy/),
|
|
||||||
# tarik kod terbaru, dan bina semula container.
|
|
||||||
#
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
# Cabang yang akan di-deploy (boleh override: BRANCH=staging ./deploy.sh)
|
|
||||||
BRANCH="${BRANCH:-master}"
|
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
||||||
REPO_DIR="$(dirname "$SCRIPT_DIR")"
|
|
||||||
cd "$REPO_DIR"
|
|
||||||
|
|
||||||
LOG() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
|
|
||||||
|
|
||||||
LOG "Mula deploy untuk $REPO_DIR (branch: $BRANCH)"
|
|
||||||
|
|
||||||
# Tarik kod terbaru — reset --hard supaya server sentiasa padan dengan remote.
|
|
||||||
git fetch --prune origin
|
|
||||||
git reset --hard "origin/${BRANCH}"
|
|
||||||
|
|
||||||
# Bina & start semula container
|
|
||||||
docker compose up --build -d
|
|
||||||
|
|
||||||
# Bersihkan image lama supaya disk tak penuh
|
|
||||||
docker image prune -f >/dev/null 2>&1 || true
|
|
||||||
|
|
||||||
# Optional: jalankan migration (buang komen kalau perlu)
|
|
||||||
# docker compose exec -T app php artisan migrate --force
|
|
||||||
|
|
||||||
LOG "Deploy selesai."
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"id": "myansuran-deploy",
|
|
||||||
"execute-command": "/opt/myansuran/deploy/deploy.sh",
|
|
||||||
"command-working-directory": "/opt/myansuran",
|
|
||||||
"response-message": "Deploy myansuran dicetuskan.",
|
|
||||||
"include-command-output-in-response": false,
|
|
||||||
"trigger-rule": {
|
|
||||||
"and": [
|
|
||||||
{
|
|
||||||
"match": {
|
|
||||||
"type": "payload-hmac-sha256",
|
|
||||||
"secret": "GANTI_DENGAN_SECRET_RAHSIA",
|
|
||||||
"parameter": { "source": "header", "name": "X-Gitea-Signature" }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"match": {
|
|
||||||
"type": "value",
|
|
||||||
"value": "refs/heads/master",
|
|
||||||
"parameter": { "source": "payload", "name": "ref" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=myAnsuran git deploy webhook listener
|
|
||||||
After=network.target docker.service
|
|
||||||
Requires=docker.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
# User mesti ahli group 'docker' supaya boleh jalankan docker compose tanpa sudo.
|
|
||||||
User=deploy
|
|
||||||
WorkingDirectory=/opt/myansuran
|
|
||||||
ExecStart=/usr/bin/webhook -hooks /opt/myansuran/deploy/hooks.json -port 9001 -verbose -hotreload
|
|
||||||
Restart=always
|
|
||||||
RestartSec=5
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -21,6 +21,24 @@ services:
|
|||||||
networks:
|
networks:
|
||||||
- backend_net
|
- backend_net
|
||||||
|
|
||||||
|
# ── Webhook Deploy (Gitea → auto pull + migrate) ───────────────────────────
|
||||||
|
webhook:
|
||||||
|
build:
|
||||||
|
context: ./docker/webhook
|
||||||
|
container_name: myansuran-webhook
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
WEBHOOK_SECRET: ${WEBHOOK_SECRET}
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /root/.ssh:/root/.ssh:ro
|
||||||
|
- ./docker/webhook/hooks.json:/etc/webhook/hooks.json:ro
|
||||||
|
- ./deploy.sh:/deploy.sh:ro
|
||||||
|
- .:/srv/myansuran
|
||||||
|
command: -hooks=/etc/webhook/hooks.json -template -verbose
|
||||||
|
networks:
|
||||||
|
- backend_net
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
backend_net:
|
backend_net:
|
||||||
name: backend_net
|
name: backend_net
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y \
|
|||||||
&& docker-php-ext-install pdo_mysql gd intl zip \
|
&& docker-php-ext-install pdo_mysql gd intl zip \
|
||||||
&& pecl install redis \
|
&& pecl install redis \
|
||||||
&& docker-php-ext-enable redis \
|
&& docker-php-ext-enable redis \
|
||||||
&& a2enmod rewrite headers \
|
&& a2enmod rewrite headers proxy proxy_http \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
|||||||
@@ -2,6 +2,12 @@
|
|||||||
ServerAdmin webmaster@localhost
|
ServerAdmin webmaster@localhost
|
||||||
DocumentRoot /var/www/html/public
|
DocumentRoot /var/www/html/public
|
||||||
|
|
||||||
|
# ── Webhook deploy (Gitea) — proxy ke container webhook ───────────────────
|
||||||
|
# https://myansuran.mbip.my/hooks/myansuran-deploy → myansuran-webhook:9000
|
||||||
|
ProxyPreserveHost On
|
||||||
|
ProxyPass /hooks/ http://myansuran-webhook:9000/hooks/
|
||||||
|
ProxyPassReverse /hooks/ http://myansuran-webhook:9000/hooks/
|
||||||
|
|
||||||
<Directory /var/www/html/public>
|
<Directory /var/www/html/public>
|
||||||
AllowOverride All
|
AllowOverride All
|
||||||
Require all granted
|
Require all granted
|
||||||
|
|||||||
8
docker/webhook/Dockerfile
Normal file
8
docker/webhook/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
FROM golang:1.23-alpine AS builder
|
||||||
|
RUN go install github.com/adnanh/webhook@2.8.1
|
||||||
|
|
||||||
|
FROM alpine:3.21
|
||||||
|
RUN apk add --no-cache git openssh-client docker-cli
|
||||||
|
COPY --from=builder /go/bin/webhook /usr/local/bin/webhook
|
||||||
|
EXPOSE 9000
|
||||||
|
ENTRYPOINT ["/usr/local/bin/webhook"]
|
||||||
32
docker/webhook/hooks.json
Normal file
32
docker/webhook/hooks.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "myansuran-deploy",
|
||||||
|
"execute-command": "/deploy.sh",
|
||||||
|
"command-working-directory": "/srv/myansuran",
|
||||||
|
"response-message": "Deploy myAnsuran dimulakan.",
|
||||||
|
"trigger-rule": {
|
||||||
|
"and": [
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"type": "payload-hmac-sha256",
|
||||||
|
"secret": "{{ getenv "WEBHOOK_SECRET" }}",
|
||||||
|
"parameter": {
|
||||||
|
"source": "header",
|
||||||
|
"name": "X-Gitea-Signature"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"type": "value",
|
||||||
|
"value": "refs/heads/master",
|
||||||
|
"parameter": {
|
||||||
|
"source": "payload",
|
||||||
|
"name": "ref"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -11,6 +11,10 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||||||
health: '/up',
|
health: '/up',
|
||||||
)
|
)
|
||||||
->withMiddleware(function (Middleware $middleware): void {
|
->withMiddleware(function (Middleware $middleware): void {
|
||||||
|
// App berada di belakang reverse proxy (proxy host → Apache → Laravel),
|
||||||
|
// jadi percaya header X-Forwarded-* supaya HTTPS, host & IP klien betul.
|
||||||
|
$middleware->trustProxies(at: '*');
|
||||||
|
|
||||||
$middleware->alias([
|
$middleware->alias([
|
||||||
'role' => \App\Http\Middleware\EnsureRole::class,
|
'role' => \App\Http\Middleware\EnsureRole::class,
|
||||||
'profile.completed' => \App\Http\Middleware\EnsureProfileCompleted::class,
|
'profile.completed' => \App\Http\Middleware\EnsureProfileCompleted::class,
|
||||||
|
|||||||
Reference in New Issue
Block a user