A Helm chart for Blocky DNS Server - Fast and lightweight DNS proxy with ad-blocking.
helm repo add leventyalcin https://leventyalcin.github.io/blocky-helm-chart
helm repo update
helm install blocky leventyalcin/blockyAll chart versions are preserved and can be installed at any time.
# List all available versions
helm search repo leventyalcin/blocky --versions
# Install a specific version
helm install blocky leventyalcin/blocky --version 1.0.0
# Upgrade to a specific version
helm upgrade blocky leventyalcin/blocky --version 1.0.5See the Releases page for changelog.
# Add the Helm repository
helm repo add leventyalcin https://leventyalcin.github.io/blocky-helm-chart
helm repo update
# Install with default values
helm install blocky leventyalcin/blocky
# Install in a specific namespace
helm install blocky leventyalcin/blocky -n dns --create-namespace
# Install with custom values file
helm install blocky leventyalcin/blocky -f my-values.yamlgit clone https://github.com/leventyalcin/blocky-helm-chart.git
cd blocky-helm-chart
helm install blocky .See values.yaml for the full list of configurable parameters.
Everything under config: is passed straight through to Blocky's config.yml with toYaml.
The chart does not maintain a list of supported keys, so any Blocky setting can be used
here — including ones added after this chart was released. Check the
Blocky configuration reference for
what is available.
Blocky v0.31+ validates its config against a JSON schema with
additionalProperties: false. An unknown or misspelled key is fatal at start-up, not ignored. If the pod crashes right after an upgrade, the first few log lines name the offending key.
Three keys under config: are chart-specific and are translated rather than passed through,
because Blocky itself does not accept them:
| You set | Blocky receives |
|---|---|
config.queryLog.mysql / config.queryLog.postgresql |
queryLog.target (DSN, password injected at runtime) |
config.redis.enabled / .external / .image / .resources |
redis.address (+ password references) |
empty config.conditional / config.customDNS / config.hostsFile.sources |
omitted entirely |
| Parameter | Description | Default |
|---|---|---|
replicaCount |
Number of replicas | 1 |
image.repository |
Blocky container image | ghcr.io/0xerr0r/blocky |
image.tag |
Image tag | latest |
dnsService.type |
DNS service type | LoadBalancer |
dnsService.port |
DNS port | 53 |
dnsService.clusterIP |
Pin the in-cluster IP (must be free, inside the service CIDR) | "" (auto-allocated) |
webService.type |
Blocky API service type | ClusterIP |
webService.port |
Blocky API port | 4000 |
blockyUI.enabled |
Enable Blocky UI sidecar | false |
blockyUI.ingress.enabled |
Enable ingress for Blocky UI | false |
config.queryLog.type |
Query logging: none, mysql, postgresql, console |
none |
config.blocking.loading.refreshPeriod |
How often to refresh blocklists (Go duration, e.g. 168h for 7 days) |
168h |
config.blocking.loading.strategy |
List loading strategy: fast, failOnError, blocking |
fast |
config.statistics.enable |
In-memory 24h stats at /api/stats (required by Blocky UI v2) |
false |
config.redis.enabled |
Enable Redis for cache synchronization | false |
config.redis.external.address |
External Redis address (disables sidecar if set) | "" |
serviceMonitor.enabled |
Enable ServiceMonitor | true |
# values.yaml
config:
upstreams:
groups:
default:
- https://dns.cloudflare.com/dns-query
- https://dns.google/dns-queryBlocky UI provides a web interface for managing Blocky. It runs as a sidecar container in the same pod.
# values.yaml
blockyUI:
enabled: true
image:
repository: ghcr.io/gabeduartem/blocky-ui
tag: "1.5.0"
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hostname: blocky.example.com
tls:
secretName: blocky-tls# values.yaml
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/dns
operator: Exists
tolerations:
- key: "dedicated"
operator: "Equal"
value: "dns"
effect: "NoSchedule"# values.yaml
config:
customDNS:
customTTL: 1h
mapping:
printer.home: 192.168.1.100
nas.home: 192.168.1.50This chart includes optional support for Blocky UI, a web interface for Blocky.
Blocky UI v2.0.0 requires
config.statistics.enable: true. v2 dropped Prometheus as its dashboard source and reads Blocky's rolling-24h/api/statsendpoint instead. That endpoint only exists when statistics are enabled, so leaving itfalsegives you an empty overview. Needs Blocky v0.34.0 or newer.
When config.queryLog.type is mysql or postgresql, the chart also wires the UI's query-log
browser automatically — it sets QUERY_LOG_TYPE and QUERY_LOG_TARGET for you. The database
password is injected via secretKeyRef and referenced as $(BLOCKY_DATABASE_PASSWORD), which
kubelet expands at start-up, so the password never appears in the rendered manifest. No
extra configuration is needed.
Anything else can be passed via blockyUI.env, for example INSTANCE_NAME.
| Parameter | Description | Default |
|---|---|---|
blockyUI.enabled |
Enable Blocky UI sidecar | false |
blockyUI.image.repository |
Blocky UI image | ghcr.io/gabeduartem/blocky-ui |
blockyUI.image.tag |
Blocky UI image tag | 2.0.0 |
blockyUI.port |
Blocky UI port | 3000 |
blockyUI.ingress.enabled |
Enable ingress | false |
blockyUI.ingress.className |
Ingress class | "" |
blockyUI.ingress.hostname |
Ingress hostname | blocky-ui.local |
blockyUI.ingress.tls.secretName |
TLS secret name | "" |
The chart creates a ServiceMonitor with release: prometheus label by default, compatible with kube-prometheus-stack.
Import the Grafana dashboard: Dashboard ID 13768
Note that Blocky UI no longer consumes these metrics — since v2.0.0 it reads /api/stats
instead (see Blocky UI). Prometheus and the ServiceMonitor remain useful for
Grafana, alerting and long-range history, and are independent of the UI.
The chart supports query logging to MySQL, PostgreSQL, or console. Only one type can be enabled at a time.
| Parameter | Description | Default |
|---|---|---|
config.queryLog.type |
Logging type: none, mysql, postgresql, console |
none |
config.queryLog.fields |
Fields to log | [clientIP, clientName, responseReason, responseAnswer, question, duration] |
config.queryLog.flushInterval |
Flush interval | 30s |
config:
queryLog:
type: mysql
mysql:
database: blocky
user: blocky
# Use existing secret (must have 'mysql-root-password' and 'mysql-password' keys)
existingSecret: "" # If empty, a secret is auto-generated
resources:
limits:
cpu: 500m
memory: 512Mi
persistence:
enabled: true
storageClass: "" # Uses default if empty
size: 5GiUse an external MySQL database instead of deploying one:
config:
queryLog:
type: mysql
mysql:
database: blocky
user: blocky
external:
hostname: mysql.example.com
port: 3306
secretName: my-mysql-secret
secretKey: passwordconfig:
queryLog:
type: postgresql
postgresql:
database: blocky
user: blocky
# Use existing secret (must have 'postgresql-password' key)
existingSecret: "" # If empty, a secret is auto-generated
resources:
limits:
cpu: 500m
memory: 512Mi
persistence:
enabled: true
storageClass: ""
size: 5GiUse an external PostgreSQL database instead of deploying one:
config:
queryLog:
type: postgresql
postgresql:
database: blocky
user: blocky
external:
hostname: postgresql.example.com
port: 5432
secretName: my-postgresql-secret
secretKey: passwordconfig:
queryLog:
type: console- StevenBlack
- blocklistproject
- Abuse: https://blocklistproject.github.io/Lists/abuse.txt
- Ads: https://blocklistproject.github.io/Lists/ads.txt
- Crypto: https://blocklistproject.github.io/Lists/crypto.txt
- Drugs: https://blocklistproject.github.io/Lists/drugs.txt
- Fraud: https://blocklistproject.github.io/Lists/fraud.txt
- Gambling: https://blocklistproject.github.io/Lists/gambling.txt
- Malware: https://blocklistproject.github.io/Lists/malware.txt
- Phishing: https://blocklistproject.github.io/Lists/phishing.txt
- Piracy: https://blocklistproject.github.io/Lists/piracy.txt
- Ransomware: https://blocklistproject.github.io/Lists/ransomware.txt
- Redirect: https://blocklistproject.github.io/Lists/redirect.txt
- Scam: https://blocklistproject.github.io/Lists/scam.txt
- Tracking: https://blocklistproject.github.io/Lists/tracking.txt
- Smart TV: https://blocklistproject.github.io/Lists/smart-tv.txt
- Firebog
- Suspicious Lists
- Advertising Lists
- https://adaway.org/hosts.txt
- https://v.firebog.net/hosts/AdguardDNS.txt
- https://v.firebog.net/hosts/Admiral.txt
- https://raw.githubusercontent.com/anudeepND/blacklist/master/adservers.txt
- https://v.firebog.net/hosts/Easylist.txt
- https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext
- https://raw.githubusercontent.com/FadeMind/hosts.extras/master/UncheckyAds/hosts
- https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts
- Tracking & Telemetry Lists
- https://v.firebog.net/hosts/Easyprivacy.txt
- https://v.firebog.net/hosts/Prigent-Ads.txt
- https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.2o7Net/hosts
- https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt
- https://hostfiles.frogeye.fr/firstparty-trackers-hosts.txt
- Malicious Lists
- https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareHosts.txt
- https://v.firebog.net/hosts/Prigent-Crypto.txt
- https://raw.githubusercontent.com/FadeMind/hosts.extras/master/add.Risk/hosts
- https://phishing.army/download/phishing_army_blocklist_extended.txt
- https://gitlab.com/quidsup/notrack-blocklists/raw/master/notrack-malware.txt
- https://raw.githubusercontent.com/Spam404/lists/master/main-blacklist.txt
- https://raw.githubusercontent.com/AssoEchap/stalkerware-indicators/master/generated/hosts
- https://urlhaus.abuse.ch/downloads/hostfile/
- https://lists.cyberhost.uk/malware.txt
- hagezi
- Multi PRO - Extended protection (Recommended): https://gitlab.com/hagezi/mirror/-/raw/main/dns-blocklists/wildcard/pro.txt
- kboghdady
- osid.nl
Apache 2.0