Files
deploy_home/ansible/roles/podman/defaults/main.yml
T
Bastian de BylandClaude Opus 5 32748d1786 fix: stop the query filter banning every player who tries to connect
The anti-scanner rules dropped 53-byte Steam query packets above 1/hour with a
burst of 2, per source IP, on the theory that only scanners send queries and
that real players would already have been marked verified by the priority-2
rule when they sent something larger.

That premise is inverted. A client's first contact with the server IS a 53-byte
query, so nobody can be verified before querying, and nobody can query more
than twice an hour without being dropped. The counters said so plainly: five
packets had ever matched the verified-accept rule, against 30,563 drops.
fail2ban then banned each dropped player for a week -- 32 live bans, 550 total,
firing every ten minutes, every one of them a residential address.

Keeps the shape of the protection and moves the threshold somewhere no real
client reaches: opening the server browser or retrying a connection is a
handful of queries, a flood is thousands. Removes the old rules first so hosts
carrying them converge instead of stacking a second copy.

The bans themselves were also hooked into INPUT for tcp only, so they never
blocked the UDP game traffic they were meant to -- the drop rule was doing all
the damage on its own. Cleared the outstanding 32.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 13:26:45 -04:00

277 lines
11 KiB
YAML

---
# Where Nextcloud backup failure alerts are mailed (see containers/cloud-backup.yml).
backup_alert_email: bastian@debyl.io
bookstack_path: "{{ podman_volumes }}/bookstack"
cam2ip_path: "{{ podman_volumes }}/cam2ip"
cloud_path: "{{ podman_volumes }}/cloud"
cloud_skudak_path: "{{ podman_volumes }}/skudakcloud"
debyltech_path: "{{ podman_volumes }}/debyltech"
# drone_path: removed - Drone CI decommissioned
factorio_path: "{{ podman_volumes }}/factorio"
fulfillr_path: "{{ podman_volumes }}/fulfillr"
fulfillr_cases_table: "debyltech-cases-prod"
fulfillr_tickets_table: "debyltech-tickets-prod"
# Turso ecommerce store (self-hosted checkout).
# PROD store URL (non-secret); the RW token `fulfillr_prod_store_auth_token` is in the vault.
fulfillr_prod_store_database_url: "libsql://debyltech-store-prod-debyltech.aws-us-east-1.turso.io"
# Staging back-office (fulfillr-dev.debyltech.com, port 9055) -> staging Turso store.
# Its RW token is `fulfillr_dev_store_auth_token` and EasyPost test key is
# `fulfillr_dev_easypost_api_key`, both in the encrypted vault.
fulfillr_dev_path: "{{ podman_volumes }}/fulfillr-dev"
fulfillr_dev_server_name: fulfillr-dev.debyltech.com
fulfillr_dev_store_database_url: "libsql://debyltech-store-staging-debyltech.aws-us-east-1.turso.io"
gregtime_path: "{{ podman_volumes }}/gregtime"
hass_path: "{{ podman_volumes }}/hass"
# nginx_path: removed - nginx no longer used
# nosql_path: removed - nosql/redis no longer used
partsy_path: "{{ podman_volumes }}/partsy"
partsy_skudak_path: "{{ podman_volumes }}/partsy-skudak"
photos_path: "{{ podman_volumes }}/photos"
uptime_kuma_path: "{{ podman_volumes }}/uptime-kuma"
uptime_kuma_personal_path: "{{ podman_volumes }}/uptime-kuma-personal"
zomboid_path: "{{ podman_volumes }}/zomboid"
# Whether to deploy and run the Zomboid server at all.
#
# Was off for months because it was the heaviest tenant on this host: ~9 GB
# resident and ~10 MB/s of continuous log writes, which on a 4-core box also
# running Gitea, Immich, Graylog and two Nextclouds saturated the QLC SSD and
# starved CI -- a firmware build stretched to 17 minutes and one release job
# was killed outright by Gitea's zombie-task timeout.
#
# Back on now that log growth is bounded: the container logs to a rotating
# k8s-file instead of the shared journal, and logrotate caps the server's own
# server-console.txt and Logs/ (see containers/home/zomboid.yml). Memory is
# unchanged -- idle draw is nowhere near MAX_RAM.
#
# Pass -e zomboid_enabled=false to keep it down through a CI-heavy stretch.
# World data under {{ zomboid_path }} is left in place either way.
zomboid_enabled: true
# Server name, and also the on-disk identity: PZ derives Server/<name>.ini,
# Saves/Multiplayer/<name>/ and db/<name>.db from it. Renaming it therefore
# starts a brand-new world and leaves the previous one intact for rollback.
zomboid_server_name: debbzoid
zomboid_public_name: Debbzoid
# Sophie 42 ships map_distanciado as its map mod. Muldraugh must stay last --
# the base map is the fallback layer.
zomboid_map: "map_distanciado;Muldraugh, KY"
# Zomboid RCON port for remote administration
zomboid_rcon_port: "27015"
# Discord channel the server's own chat bridge posts into. Build 42 replaced
# B41's DiscordChannel/DiscordChannelID pair with DiscordChatChannel, which
# takes a channel *name*, not a snowflake ID.
zomboid_discord_chat_channel: zomboidbot
# JVM heap, written into ProjectZomboid64.json by the container entrypoint.
zomboid_min_ram: 8g
zomboid_max_ram: 24g
# The modlist itself lives in vars/zomboid_sophie_mods.yml -- 283 mod IDs and
# 256 workshop items vendored from the upstream Sophie 42 preset.
zomboid_preset_version: "sophie-42 @ 2026-07-31"
# Mods subtracted from the vendored Sophie lists before they reach the INI.
# Explicit and reasoned so that re-vendoring a newer preset cannot silently
# reintroduce something we deliberately dropped.
zomboid_mods_excluded:
# Already absent from the 2026-07-31 preset; listed so it stays that way.
- workshop_id: "3718412967"
mod_id: IconsInventory
reason: Sophie recommends removing Icon Inventory
# Per-source-IP ceiling on 53-byte Steam/PZ query packets before they are
# logged and dropped. Set well above anything a real client produces -- opening
# the server browser or retrying a connection is a handful of queries, while a
# scanner flood is thousands. The previous 1/hour burst 2 was below normal play
# and made the server unreachable. See containers/home/zomboid.yml.
zomboid_query_rate_limit: 60/minute
zomboid_query_burst: 120
# How long to keep PZ's own log archive under data/Logs.
#
# PZ rolls logs into dated directories and never prunes them; logrotate cannot
# bound that, because the growth is in the number of files rather than the size
# of any one of them. See containers/home/zomboid.yml.
zomboid_log_retention_days: 14
# Mod IDs the Sophie preset's `Mods=` line gets wrong for a 42.20.3 server.
#
# Every workshop item below is in the preset's own WorkshopItems= list and
# downloads fine -- only the ID it is referenced by is stale, so the server
# logs `required mod ... not found` and quietly runs without it. Verified
# against the id= field of each mod.info on disk, not guessed from folder
# names (folder name and mod ID are unrelated). Applied by server.ini.j2 so a
# re-vendor of a newer preset keeps the corrections.
zomboid_mods_renamed:
- old: "FWOBenchPress&Treadmill"
new: FWOBenchPressTreadmill
reason: preset carries a stray ampersand; mod.info in 2940354599 has none
- old: Ladders42131
new: Ladders4220
reason: 3629835761 ships per-build variants; 42131 is the 42.16 one, 4220 is ours
- old: ServingPlatesB42
new: ServingPlates42
reason: mod.info in 3399320470 declares ServingPlates42
- old: NewMusic_OrchestraMix
new: NewMusic_CMM
reason: author renamed it to "Classical Music Mix" in 3760471726
# Server config is seeded once and then left alone, so it can be hand-edited
# between world regenerations. Set true to overwrite it from the templates.
zomboid_config_force: false
sshpass_cron_path: "{{ podman_volumes }}/sshpass_cron"
caddy_path: "{{ podman_volumes }}/caddy"
# Drone CI variables removed - infrastructure decommissioned
# drone_server_proto, drone_runner_proto, drone_runner_capacity
# Server names (used by Caddy)
base_server_name: bdebyl.net
assistant_server_name: assistant.bdebyl.net
bookstack_server_name: wiki.skudakrennsport.com
# ci_server_name: removed - Drone CI decommissioned
cloud_server_name: cloud.bdebyl.net
cloud_skudak_server_name: cloud.skudakrennsport.com
fulfillr_server_name: fulfillr.debyltech.com
home_server_name: home.debyl.io
uptime_kuma_server_name: uptime.debyltech.com
uptime_kuma_personal_server_name: uptime.debyl.io
parts_server_name: parts.bdebyl.net
photos_server_name: photos.bdebyl.net
# debyl.io domains (migration from bdebyl.net)
base_server_name_io: debyl.io
assistant_server_name_io: assistant.debyl.io
cloud_server_name_io: cloud.debyl.io
home_server_name_io: home.debyl.io
parts_server_name_io: parts.debyl.io
photos_server_name_io: photos.debyl.io
gitea_debyl_server_name: git.debyl.io
# skudak.com domains (migration from skudakrennsport.com)
parts_skudak_server_name: parts.skudak.com
bookstack_server_name_new: wiki.skudak.com
# partsy_skudak_admin_password: defined in vault
cloud_skudak_server_name_new: cloud.skudak.com
gitea_skudak_server_name: git.skudak.com
# LibreSign root certificate authority identity for skudak-cloud. This is the
# issuer name that appears on every signed document, so it must match the
# entity's legal name -- it was previously generated as "Skudak Rennsport LLP",
# the pre-rename name. Changing these values does NOT re-issue the CA on its
# own; see the guarded generate task in containers/skudak/cloud.yml.
# Skudak brand palette, mirroring ~/src/skudak/skudak-site/src/styles/variables.css.
# --color-gray-900 for the mail header band and UI chrome; the white signature
# logo is legible on it. --color-accent is spent only on the CTA button, and
# lives in the skudakmail app rather than here since theming has no second
# colour slot.
theming_skudak_primary: "#0A0A0A"
libresign_skudak_cert_cn: Skudak LLP
libresign_skudak_cert_o: Skudak LLP
libresign_skudak_cert_c: US
libresign_skudak_cert_st: New Hampshire
libresign_skudak_cert_l: Newbury
# Legacy nginx/ModSecurity configuration removed - Caddy provides built-in security
# Web server configuration (Caddy is the default)
# Legacy nginx variables kept for cleanup tasks
# Caddy configuration
caddy_email: "{{ ssl_email }}"
# Use staging for testing, production for real certificates
caddy_acme_ca: https://acme-v02.api.letsencrypt.org/directory
# For testing/staging:
# caddy_acme_ca: https://acme-staging-v02.api.letsencrypt.org/directory
# Caddy ports
caddy_admin_port: 2019
# Caddy network configuration
caddy_local_networks:
- 192.168.0.0/16
- 127.0.0.1
# Caddy logging configuration
caddy_log_level: INFO
caddy_log_format: json
# Log rotation. Caddy rotates on implicit defaults (100MiB / keep 10 / 90d)
# without these, and those were demonstrably not holding: 20 rotated files per
# stream for the busiest logs and a 190-day-old .gz, for 1.3 GB across 16
# streams. Kept short deliberately -- fluent-bit tails every one of these into
# Graylog (see roles/common/templates/fluent-bit/fluent-bit.conf.j2), so
# Graylog is the system of record and the local files are only a buffer.
caddy_log_roll_size: 10MiB
caddy_log_roll_keep: 3
caddy_log_roll_keep_for: 168h
# Caddy performance tuning
caddy_max_request_body_mb: 500
# Caddy security headers (global defaults)
caddy_security_headers:
Strict-Transport-Security: "max-age=31536000; includeSubDomains"
X-Content-Type-Options: "nosniff"
Referrer-Policy: "same-origin"
X-Frame-Options: "SAMEORIGIN"
# Graylog logging stack
graylog_path: "{{ podman_volumes }}/graylog"
logs_server_name: logs.debyl.io
# gelf_auth_token: defined in vault - X-Gelf-Token header for Lambda GELF HTTP auth
# Fluent Bit is deployed as a systemd service (not container)
# for direct journal access - see containers/base/fluent-bit.yml
# Fluent-bit Caddy log forwarding
caddy_log_path: "{{ caddy_path }}/logs"
caddy_log_names:
- caddy
- photos
- wiki
- assistant
- parts
- uptime-kuma
- uptime-kuma-personal
- graylog
- cloud
- cloud-skudak
- gitea-debyl
- gitea-skudak
- fulfillr
# GeoIP configuration for Graylog
# Requires free MaxMind account: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
geoip_path: "{{ graylog_path }}/geoip"
geoip_database_edition: GeoLite2-City
# geoip_maxmind_account_id: defined in vault
# geoip_maxmind_license_key: defined in vault
# Weekly podman prune (see templates/podman-prune.sh.j2). Both rootless users
# have their own image store; the git user runs the Gitea pods.
podman_prune_users:
- "{{ podman_user }}"
- "{{ git_user }}"
# Keep 30 days of unused images so a rollback needs no rebuild or re-pull.
podman_prune_until: 720h
podman_prune_oncalendar: "Sun *-*-* 02:00:00"
# Hardened CIFS options for the TrueNAS shares (see containers/home/photos.yml).
# x-systemd.automount is what makes a failed mount recoverable without a human.
cifs_mount_opts: >-
credentials=/etc/cifs/photos.creds,uid={{ podman_subuid.stdout }},gid={{ podman_subuid.stdout }},_netdev,nofail,soft,x-systemd.automount,x-systemd.mount-timeout=30,x-systemd.idle-timeout=600,vers=3.1.1,resilienthandles,echo_interval=10
# How often the watchdog checks mount health and heals immich.
cifs_watchdog_oncalendar: "*:0/5"
cifs_watchdog_mounts:
- "{{ photos_path }}/storage"
- "{{ photos_path }}/immich"