docs: comprehensive README with setup, usage, and pitfalls
This commit is contained in:
@@ -8,8 +8,131 @@ Lightweight webhook container for NAS auto-deploy. Alpine-based with `docker-cli
|
|||||||
registry.gitlab.com/bgrolleman/nas-webhook:latest
|
registry.gitlab.com/bgrolleman/nas-webhook:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
Built automatically by GitLab CI on every push to `main`. Image is **public** — no registry login needed on the NAS to pull it.
|
||||||
|
|
||||||
See the [webhook documentation](https://github.com/adnanh/webhook) for hook configuration.
|
## How it works
|
||||||
|
|
||||||
Requires `/var/run/docker.sock` mounted to execute Docker commands from within the container.
|
1. A GitLab CI pipeline builds and pushes a new image (e.g. `hugo_basg.nl:latest`)
|
||||||
|
2. The CI pipeline sends a POST to `http://webhook.nas.basg.nl/hooks/<hook-id>` with a secret token in the `X-Webhook-Token` header
|
||||||
|
3. The webhook container receives the request, validates the token, and runs `deploy.sh <compose-dir>`
|
||||||
|
4. `deploy.sh` does `docker compose pull && docker compose up -d` in the project directory
|
||||||
|
|
||||||
|
## Deployment on NAS
|
||||||
|
|
||||||
|
Place the following files in a directory on the NAS (e.g. `/volume1/docker/webhook/`):
|
||||||
|
|
||||||
|
```
|
||||||
|
webhook/
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── hooks.json
|
||||||
|
└── scripts/
|
||||||
|
└── deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Then bring it up via the UGREEN web interface or `docker compose up -d`.
|
||||||
|
|
||||||
|
The Docker socket (`/var/run/docker.sock`) must be mounted so the container can run Docker commands. The NAS docker directory (`/volume1/docker`) must also be mounted so `deploy.sh` can reach the project compose files.
|
||||||
|
|
||||||
|
### docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
networks:
|
||||||
|
external:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
webhook:
|
||||||
|
image: registry.gitlab.com/bgrolleman/nas-webhook:latest
|
||||||
|
restart: always
|
||||||
|
command: ["-hooks", "/config/hooks.json", "-verbose", "-hotreload"]
|
||||||
|
volumes:
|
||||||
|
- ./hooks.json:/config/hooks.json:ro
|
||||||
|
- ./scripts:/scripts:ro
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /volume1/docker:/volume1/docker
|
||||||
|
expose:
|
||||||
|
- 9000
|
||||||
|
environment:
|
||||||
|
- VIRTUAL_HOST=webhook.nas.basg.nl
|
||||||
|
- VIRTUAL_PORT=9000
|
||||||
|
networks:
|
||||||
|
- external
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: No `LETSENCRYPT_HOST` — running HTTP only. The ACME challenge (Let's Encrypt) doesn't work for this container because it only exposes port 9000, not 80. Since it's only called by GitLab CI (not a browser), HTTP is fine.
|
||||||
|
|
||||||
|
## Adding a new project
|
||||||
|
|
||||||
|
### 1. Add a hook to `hooks.json`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "my-project",
|
||||||
|
"execute-command": "/scripts/deploy.sh",
|
||||||
|
"command-working-directory": "/scripts",
|
||||||
|
"pass-arguments-to-command": [
|
||||||
|
{
|
||||||
|
"source": "string",
|
||||||
|
"name": "/volume1/docker/my-project"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"trigger-rule": {
|
||||||
|
"match": {
|
||||||
|
"type": "value",
|
||||||
|
"value": "YOUR_SECRET_TOKEN_HERE",
|
||||||
|
"parameter": {
|
||||||
|
"source": "header",
|
||||||
|
"name": "X-Webhook-Token"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate a token with: `openssl rand -hex 32`
|
||||||
|
|
||||||
|
The webhook container uses `-hotreload` so it picks up `hooks.json` changes without a restart.
|
||||||
|
|
||||||
|
### 2. Add deploy stage to the project's `.gitlab-ci.yml`
|
||||||
|
|
||||||
|
Store the token as a masked CI variable (e.g. `DEPLOY_WEBHOOK_TOKEN`) in the GitLab project settings.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
deploy:
|
||||||
|
stage: deploy
|
||||||
|
image: alpine:latest
|
||||||
|
before_script:
|
||||||
|
- apk add --no-cache curl
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
curl -f -X POST \
|
||||||
|
-H "X-Webhook-Token: $DEPLOY_WEBHOOK_TOKEN" \
|
||||||
|
http://webhook.nas.basg.nl/hooks/my-project
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||||
|
needs: [build]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Make sure the project image is public
|
||||||
|
|
||||||
|
The NAS pulls images without authentication. Either make the GitLab registry public (project → Settings → General → Visibility → Public) or set up a deploy token and run `sudo docker login registry.gitlab.com` on the NAS.
|
||||||
|
|
||||||
|
## Testing a hook manually
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X POST \
|
||||||
|
-H "X-Webhook-Token: YOUR_TOKEN" \
|
||||||
|
http://webhook.nas.basg.nl/hooks/your-hook-id
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current hooks
|
||||||
|
|
||||||
|
| Hook ID | Project | Compose dir |
|
||||||
|
|---------|---------|-------------|
|
||||||
|
| `hugo-basg` | bgrolleman/hugo_basg.nl | `/volume1/docker/basg-hugo` |
|
||||||
|
|
||||||
|
## Known issues / pitfalls
|
||||||
|
|
||||||
|
- **No HTTPS**: Let's Encrypt won't issue a cert because the container doesn't serve HTTP on port 80. Since only GitLab CI calls this endpoint, HTTP is acceptable. If HTTPS is needed in the future, put a separate nginx container in front that handles port 80/443 and proxies to port 9000.
|
||||||
|
- **Docker socket permissions**: The webhook runs as root inside the container (required to use the socket). This is standard for Docker-in-Docker patterns on a home NAS.
|
||||||
|
- **Image must be public or NAS must be logged in**: The deploy script runs `docker compose pull` which needs registry access. Easiest solution is a public GitLab project.
|
||||||
|
|||||||
Reference in New Issue
Block a user