- Add CoreDNS service resolving *.homelab.fhirworx.io → HOST_IP - Add Traefik UDP entrypoint (:53/udp) routing DNS to CoreDNS - Add Traefik to CI network so buildkit containers resolve via Traefik - Distribute Homelab CA cert for Docker and buildkit TLS trust - Migrate all buildx steps from localhost:3000 to gitea.homelab.fhirworx.io - Remove daemon_off, insecure, Docker socket mounts from buildx steps - Use buildkit_driveropt network=ci for DNS resolution in buildkit - Replace extra_hosts on woodpecker-server with dns: CoreDNS
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
# Only runs on pushes to main (i.e. after PR merge).
|
||||
#
|
||||
# Image naming:
|
||||
# gitea:3000/homelab/<service>:sha-<8chars> (registry)
|
||||
# gitea:3000/homelab/<service>:latest (registry)
|
||||
# gitea.homelab.fhirworx.io/homelab/<service>:sha-<8chars>
|
||||
# gitea.homelab.fhirworx.io/homelab/<service>:latest
|
||||
#
|
||||
# The deploy step writes COMMIT_SHA=sha-<short> into .env so
|
||||
# compose.yml resolves the exact image just built.
|
||||
@@ -39,29 +39,25 @@ steps:
|
||||
|
||||
# ── Notebooks image ─────────────────────────────────────────
|
||||
- name: build-push-notebooks
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/notebooks
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/notebooks
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: notebooks/Dockerfile
|
||||
context: notebooks/
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: scan-notebooks
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/notebooks:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/notebooks:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
output: notebooks-scan.json
|
||||
@@ -73,29 +69,25 @@ steps:
|
||||
|
||||
# ── Zotero image ────────────────────────────────────────────
|
||||
- name: build-push-zotero
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/zotero
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/zotero
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: zotero/Dockerfile
|
||||
context: zotero/
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: scan-zotero
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/zotero:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/zotero:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
output: zotero-scan.json
|
||||
@@ -116,31 +108,27 @@ steps:
|
||||
- cp /host-data/bib.sqlite data/ 2>/dev/null || true
|
||||
|
||||
- name: build-push-docs
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/docs
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/docs
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: docs/Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- prep-docs-context
|
||||
|
||||
- name: scan-docs
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/docs:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/docs:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
output: docs-scan.json
|
||||
@@ -152,29 +140,25 @@ steps:
|
||||
|
||||
# ── API image ───────────────────────────────────────────────
|
||||
- name: build-push-api
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/api
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/api
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: api/Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: scan-api
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/api:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/api:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
output: api-scan.json
|
||||
@@ -186,24 +170,20 @@ steps:
|
||||
|
||||
# ── MC (MinIO Client) sidecar ────────────────────────────────
|
||||
- name: build-push-mc
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/mc
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/mc
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: rustfs/Dockerfile.mc
|
||||
context: rustfs/
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
# ── Upload scan results ─────────────────────────────────────
|
||||
- name: upload-notebooks-scan
|
||||
@@ -281,8 +261,10 @@ steps:
|
||||
- cp .env.bak .env 2>/dev/null || true
|
||||
# Retag registry images for compose
|
||||
- TAG=sha-${CI_COMMIT_SHA:0:8}
|
||||
- FQDN=gitea.homelab.fhirworx.io
|
||||
- for SVC in notebooks zotero docs api mc; do
|
||||
docker tag localhost:3000/homelab/$SVC:$TAG fhirworx/$SVC:$TAG;
|
||||
docker pull $FQDN/homelab/$SVC:$TAG &&
|
||||
docker tag $FQDN/homelab/$SVC:$TAG fhirworx/$SVC:$TAG;
|
||||
done
|
||||
- sed -i "s/^COMMIT_SHA=.*/COMMIT_SHA=$TAG/" .env 2>/dev/null || echo "COMMIT_SHA=$TAG" >> .env
|
||||
- docker compose up -d --remove-orphans
|
||||
|
||||
@@ -3,44 +3,36 @@ when:
|
||||
|
||||
steps:
|
||||
- name: build-push-notebooks
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/notebooks
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/notebooks
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: notebooks/Dockerfile
|
||||
context: notebooks/
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: build-push-zotero
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/zotero
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/zotero
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: zotero/Dockerfile
|
||||
context: zotero/
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: prep-docs-context
|
||||
image: alpine:3
|
||||
@@ -51,71 +43,59 @@ steps:
|
||||
- cp /host-data/bib.sqlite data/ 2>/dev/null || true
|
||||
|
||||
- name: build-push-docs
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/docs
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/docs
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: docs/Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
depends_on:
|
||||
- prep-docs-context
|
||||
|
||||
- name: build-push-api
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/api
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/api
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: api/Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: build-push-mc
|
||||
image: woodpeckerci/plugin-docker-buildx:5
|
||||
image: woodpeckerci/plugin-docker-buildx
|
||||
settings:
|
||||
buildkit_driveropt: network=host
|
||||
repo: localhost:3000/homelab/mc
|
||||
registry: localhost:3000
|
||||
repo: gitea.homelab.fhirworx.io/homelab/mc
|
||||
registry: gitea.homelab.fhirworx.io
|
||||
buildkit_driveropt: network=ci
|
||||
dockerfile: rustfs/Dockerfile.mc
|
||||
context: rustfs/
|
||||
tags:
|
||||
- "sha-${CI_COMMIT_SHA:0:8}"
|
||||
- latest
|
||||
daemon_off: true
|
||||
insecure: true
|
||||
username:
|
||||
from_secret: registry_user
|
||||
password:
|
||||
from_secret: registry_pass
|
||||
volumes:
|
||||
- /run/user/1000/docker.sock:/var/run/docker.sock
|
||||
|
||||
- name: scan-notebooks
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/notebooks:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/notebooks:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
volumes:
|
||||
@@ -126,7 +106,7 @@ steps:
|
||||
- name: scan-zotero
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/zotero:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/zotero:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
volumes:
|
||||
@@ -137,7 +117,7 @@ steps:
|
||||
- name: scan-api
|
||||
image: woodpeckerci/plugin-trivy
|
||||
settings:
|
||||
image_ref: "localhost:3000/homelab/api:sha-${CI_COMMIT_SHA:0:8}"
|
||||
image_ref: "gitea.homelab.fhirworx.io/homelab/api:sha-${CI_COMMIT_SHA:0:8}"
|
||||
severity: HIGH,CRITICAL
|
||||
exit_code: 0
|
||||
volumes:
|
||||
@@ -153,8 +133,10 @@ steps:
|
||||
commands:
|
||||
- cd /home/kert/stack
|
||||
- TAG=sha-${CI_COMMIT_SHA:0:8}
|
||||
- FQDN=gitea.homelab.fhirworx.io
|
||||
- for SVC in notebooks zotero docs api mc; do
|
||||
docker tag localhost:3000/homelab/$SVC:$TAG fhirworx/$SVC:$TAG;
|
||||
docker pull $FQDN/homelab/$SVC:$TAG &&
|
||||
docker tag $FQDN/homelab/$SVC:$TAG fhirworx/$SVC:$TAG;
|
||||
done
|
||||
- sed -i "s/^COMMIT_SHA=.*/COMMIT_SHA=$TAG/" .env 2>/dev/null || echo "COMMIT_SHA=$TAG" >> .env
|
||||
- docker compose up -d --remove-orphans
|
||||
|
||||
18
compose.yml
18
compose.yml
@@ -21,6 +21,18 @@ networks:
|
||||
internal: false
|
||||
|
||||
services:
|
||||
coredns:
|
||||
image: coredns/coredns:1.12.0
|
||||
container_name: coredns
|
||||
command: ["-conf", "/etc/coredns/Corefile"]
|
||||
networks:
|
||||
gateway:
|
||||
ipv4_address: 172.25.0.53
|
||||
volumes:
|
||||
- ./coredns/Corefile:/etc/coredns/Corefile:ro
|
||||
- ./coredns/hosts:/etc/coredns/hosts:ro
|
||||
restart: unless-stopped
|
||||
|
||||
traefik:
|
||||
image: traefik:v3.3
|
||||
container_name: traefik
|
||||
@@ -28,6 +40,7 @@ services:
|
||||
- gateway
|
||||
- observability
|
||||
- storage
|
||||
- ci
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
@@ -156,8 +169,8 @@ services:
|
||||
- gateway
|
||||
- storage
|
||||
- ci
|
||||
extra_hosts:
|
||||
- "gitea.${DOMAIN:-homelab.fhirworx.io}:${HOST_IP:-192.168.1.192}"
|
||||
dns:
|
||||
- 172.25.0.53
|
||||
environment:
|
||||
- WOODPECKER_HOST=http://ci.${DOMAIN:-homelab.fhirworx.io}
|
||||
- WOODPECKER_GRPC_ADDR=:9000
|
||||
@@ -193,6 +206,7 @@ services:
|
||||
- WOODPECKER_MAX_WORKFLOWS=4
|
||||
- WOODPECKER_BACKEND=docker
|
||||
- WOODPECKER_BACKEND_DOCKER_NETWORK=ci
|
||||
- WOODPECKER_BACKEND_DOCKER_VOLUMES=/home/kert/stack/traefik/certs/docker-certs.d:/etc/docker/certs.d:ro
|
||||
- DOCKER_API_VERSION=1.44
|
||||
volumes:
|
||||
- ${DOCKER_SOCK:-/run/user/1000/docker.sock}:/var/run/docker.sock
|
||||
|
||||
11
coredns/Corefile
Normal file
11
coredns/Corefile
Normal file
@@ -0,0 +1,11 @@
|
||||
homelab.fhirworx.io {
|
||||
hosts /etc/coredns/hosts {
|
||||
fallthrough
|
||||
}
|
||||
log
|
||||
}
|
||||
|
||||
. {
|
||||
forward . 1.1.1.1 8.8.8.8
|
||||
cache 300
|
||||
}
|
||||
10
coredns/hosts
Normal file
10
coredns/hosts
Normal file
@@ -0,0 +1,10 @@
|
||||
192.168.1.192 homelab.fhirworx.io
|
||||
192.168.1.192 gitea.homelab.fhirworx.io
|
||||
192.168.1.192 ci.homelab.fhirworx.io
|
||||
192.168.1.192 docs.homelab.fhirworx.io
|
||||
192.168.1.192 notebooks.homelab.fhirworx.io
|
||||
192.168.1.192 api.homelab.fhirworx.io
|
||||
192.168.1.192 s3.homelab.fhirworx.io
|
||||
192.168.1.192 grafana.homelab.fhirworx.io
|
||||
192.168.1.192 traefik.homelab.fhirworx.io
|
||||
192.168.1.192 zotero.homelab.fhirworx.io
|
||||
@@ -0,0 +1,20 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDMTCCAhmgAwIBAgIURQevAWH0MWQtBXf/hV8VNsANXk4wDQYJKoZIhvcNAQEL
|
||||
BQAwKDETMBEGA1UEAwwKSG9tZWxhYiBDQTERMA8GA1UECgwIZmhpcndvcngwHhcN
|
||||
MjYwMzIxMjAzMDI5WhcNMzYwMzE4MjAzMDI5WjAoMRMwEQYDVQQDDApIb21lbGFi
|
||||
IENBMREwDwYDVQQKDAhmaGlyd29yeDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
||||
AQoCggEBAMJ8lfw2IQe7sIU8SykD0EwSN9uMOxd9DLkZPfaP/N9CSRvK01smwsdo
|
||||
Nr2riPi+Ng+ufjxOVbe7QlhwSTFK9gR8+/IT7iTJT7vD8EfR6Ud2qSJLcvJDfhUQ
|
||||
Dc5N9oBueC4XJ3Ohad6cHL/tOdH9/D0zwjbdkUd9+iPvDv9VaPf7PH3jiBpcgEKI
|
||||
gLy+noySFFAY8HWu5c33EhiepgXBiXRDAQDighpodcRxHBkDFdRMTQnAjQK2/BQ/
|
||||
si74JTC+GpHvEiDCBTQ+L6BUdPI5aP3mUZ/LCqIiyGFSzbshQ9MWdOa0QWEdyKOy
|
||||
42+aZaH/FLJ4a6ToGx5I1ZmGNyPiHQUCAwEAAaNTMFEwHQYDVR0OBBYEFGDEf48T
|
||||
ZywSgSib037Mty2VaXOuMB8GA1UdIwQYMBaAFGDEf48TZywSgSib037Mty2VaXOu
|
||||
MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAA/vF6bk0MgB5hvW
|
||||
YS90Utf0Njh1ZqSw/qdu2Pdqfc05qInfcL7c8I/77yl8tX6+gd/vDQ3DekHxI0vO
|
||||
SDZMyhW3uglIQMnd+LaXEZATFFuV8PWwXIJ5KgWhUJ6qJbJwO9LT+YnP3XohaHRW
|
||||
oayHGR/h0oJPKJu41ZH5BSMfvIFNCN7x7x7a9cjL0Todu35+vgwsoKjI/fm6dbh4
|
||||
T83eZDhYYxaWJrTYdagMKOpxThVHcooITGifnajelTe+NpH8LOSaszOI2WZqFocN
|
||||
qRG1WQt9TIRqIG4stnSsQ/0bG/Woh4SNd2CkLY2hsKOCJMi+Xbss/PCPew+RwRGW
|
||||
XQQaUuk=
|
||||
-----END CERTIFICATE-----
|
||||
11
traefik/dynamic/dns.yml
Normal file
11
traefik/dynamic/dns.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
udp:
|
||||
routers:
|
||||
dns:
|
||||
entryPoints:
|
||||
- dns
|
||||
service: coredns
|
||||
services:
|
||||
coredns:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- address: "coredns:53"
|
||||
@@ -15,6 +15,8 @@ entryPoints:
|
||||
address: ":80"
|
||||
websecure:
|
||||
address: ":443"
|
||||
dns:
|
||||
address: ":53/udp"
|
||||
|
||||
providers:
|
||||
file:
|
||||
|
||||
Reference in New Issue
Block a user