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
|
||||
```
|
||||
|
||||
## 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