decomm copenhagen-b and copenhagen-c (#144)
Some checks failed
Deploy (on merge) / Discover hosts (push) Waiting to run
Deploy (on merge) / deploy (push) Blocked by required conditions
Terraform / Plan (push) Has been cancelled
Terraform / Apply (push) Has been cancelled

This commit is contained in:
Rasmus Wejlgaard 2026-07-28 11:54:23 +02:00 committed by GitHub
parent 0e55029bea
commit 4e2ea9e35b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 67 additions and 2624 deletions

View file

@ -18,9 +18,8 @@ graph TD
TS --> LB[london-b<br/>Storage, media<br/>Docker + systemd]
TS --> LA[london-a<br/>Proxmox VE hypervisor]
TS --> LC[london-c<br/>Raspberry Pi<br/>Octopus Energy exporter]
TS --> CA[copenhagen-a<br/>Gaming<br/>Minecraft, WoW MaNGOS]
TS --> CA[copenhagen-a<br/>Proxmox VE hypervisor]
TS --> NUR[nuremberg-a<br/>Mail, poste.io]
TS --> CC[copenhagen-c<br/>Raspberry Pi<br/>cloudflared, idle]
TS -.-> GC[Grafana Cloud<br/>metrics, logs, traces]
```
@ -35,8 +34,7 @@ DNS (Hetzner DNS for `pez.sh`, managed via Terraform) points directly at a Caddy
| london-a | London | Debian 13 / Proxmox VE | Hypervisor (currently runs a Mac VM; platform for future VMs) |
| london-c | London | Debian 13 (Raspberry Pi) | Octopus Energy exporter, edge utility box |
| nuremberg-a | Hetzner Cloud (Nuremberg) | Debian 13 | Mail server (poste.io) |
| copenhagen-a | Copenhagen | Ubuntu 22.04 | Gaming servers (Minecraft, WoW/MaNGOS) |
| copenhagen-c | Copenhagen | Debian 12 (Raspberry Pi) | cloudflared tunnel, idle/available |
| copenhagen-a | Copenhagen | Debian 12 (Bookworm) / Proxmox VE | Hypervisor (platform for future VMs) |
## Directory Structure

View file

@ -24,7 +24,7 @@ update-linux:
docker-status:
ansible-playbook playbooks/docker-status.yml
# Reboot a specific host: make reboot HOST=copenhagen-c
# Reboot a specific host: make reboot HOST=london-c
reboot:
ansible-playbook playbooks/reboot.yml --limit $(HOST)

View file

@ -42,8 +42,7 @@ The deploy playbook runs in stages, each independently taggable (see `deploy.yml
- `docker_hosts`: Docker Compose stacks from `services/`
- `nuremberg-a`: poste.io mail (Docker)
- `london-b`: `media_stack` + `backup` (rclone to B2)
- `copenhagen-a`: MaNGOS systemd units + MariaDB
- `london-a`: `proxmox_ve` (apt repo, nag patch, CIFS storage)
- `proxmox_hosts` (`london-a`, `copenhagen-a`): `proxmox_ve` (apt repo, nag patch, CIFS storage)
- `zfs_hosts`: ZFS scrub scheduling
Observability (node_exporter, systemd_exporter, Grafana Alloy) is part of the `common` baseline — every host gets it.
@ -63,7 +62,6 @@ Run a single stage: `ansible-playbook deploy.yml --tags docker`
| `systemd_services` | Custom systemd units from `services/` |
| `media_stack` | *Arr stack, Plex/Jellyfin, Samba, Syncthing on london-b |
| `backup` | rclone-to-B2 cron job on london-b |
| `mariadb` | Native MariaDB (used by MaNGOS on copenhagen-a) |
| `proxmox_ve` | PVE no-subscription repo, UI lockdown, CIFS storage |
| `zfs` | Weekly scrub cron on ZFS hosts |
@ -75,6 +73,5 @@ Per-host variables in `inventory/host_vars/<hostname>.yml`.
## Safety Notes
- **london-b**: Reboot playbook requires interactive confirmation (critical storage)
- **copenhagen-a**: Reboot includes netplan pre-flight check (static IP verification)
- All playbooks use `ignore_unreachable: true` for fleet operations
- `--check --diff` is your friend — always dry-run first on production

View file

@ -55,15 +55,8 @@
- role: media_stack
- role: backup
- name: Gaming servers (copenhagen-a)
hosts: copenhagen-a
tags: [services, gaming]
roles:
- role: systemd_services
- role: mariadb
- name: Proxmox VE (london-a)
hosts: london-a
- name: Proxmox VE (london-a, copenhagen-a)
hosts: proxmox_hosts
tags: [services, proxmox]
roles:
- role: proxmox_ve

View file

@ -62,8 +62,7 @@ Most servers run Fish as root shell. Current state captured from live fleet (202
| london-b | fish | Yes (pez@pez.sh) | Partial (fish default, tmux custom) |
| nuremberg-a | fish | No | No |
| london-a | sh (FreeBSD) | No | No |
| copenhagen-a | fish | No (SpigotMC default) | No |
| copenhagen-c | fish | No | No |
| copenhagen-a | bash (fresh PVE install) | No | No |
## Relationship to upstream

View file

@ -1,24 +1,5 @@
---
host_role: gaming
host_description: "Gaming servers (Minecraft, WoW/MaNGOS)"
host_role: proxmox-ve
host_description: "Proxmox VE hypervisor"
host_location: "Copenhagen"
prometheus_location: copenhagen
# MaNGOS runs as systemd services, not Docker
# MariaDB is the MaNGOS database backend (character, world, auth DBs)
systemd_services:
- mangos-realmd
- mangos-world
# Docker Compose services deployed by docker_services role
docker_services:
- minecraft
- smartctl-exporter
# MaNGOS database backend — installed by apt; config managed by mariadb role
system_packages_services:
- mariadb
common_ufw_allowed_ports:
- {port: 3724, proto: tcp, comment: "MaNGOS Realmd"}
- {port: 8085, proto: tcp, comment: "MaNGOS World Server"}
ansible_python_interpreter: /usr/bin/python3

View file

@ -1,5 +0,0 @@
---
host_role: idle
host_description: "Idle/available"
host_location: "Copenhagen"
prometheus_location: copenhagen

View file

@ -6,8 +6,7 @@ helsinki-a ansible_host=100.67.6.27
london-a ansible_host=100.122.180.98
london-b ansible_host=100.84.65.101
london-c ansible_host=100.123.72.87
copenhagen-a ansible_host=100.89.206.60
copenhagen-c ansible_host=100.115.45.53
copenhagen-a ansible_host=100.91.240.29
nuremberg-a ansible_host=100.70.180.24
[zfs_hosts]
@ -18,6 +17,9 @@ helsinki-a
london-b
london-c
nuremberg-a
[proxmox_hosts]
london-a
copenhagen-a
[all:vars]

View file

@ -2,8 +2,7 @@
# Reboot a specific host and wait for it to come back.
# Usage: ansible-playbook playbooks/reboot.yml --limit <hostname>
#
# Safety: copenhagen-a has netplan pre-flight check.
# london-b should NOT be rebooted without manual approval.
# Safety: london-b should NOT be rebooted without manual approval.
- name: Reboot host safely
hosts: all
@ -29,23 +28,6 @@
msg: "Reboot of london-b was not confirmed."
when: inventory_hostname == 'london-b' and london_b_confirm.user_input != 'yes'
- name: Check netplan config (copenhagen-a)
ansible.builtin.command: netplan get all
register: netplan_config
failed_when: false
changed_when: false
when: inventory_hostname == 'copenhagen-a'
- name: Verify copenhagen-a static IP
ansible.builtin.assert:
that:
- "'192.168.0.251' in netplan_config.stdout"
fail_msg: >
ABORT: copenhagen-a netplan doesn't show expected static IP
192.168.0.251. Check netplan config before rebooting.
success_msg: "copenhagen-a netplan OK — static IP present."
when: inventory_hostname == 'copenhagen-a'
- name: Reboot
ansible.builtin.reboot:
reboot_timeout: 300

View file

@ -131,17 +131,15 @@
# Cloudflare Tunnels were retired in favour of Caddy + Authelia (PESO-134, #56),
# which removed cloudflared from ansible config. copenhagen-a was unreachable at
# the time, so its cloudflared.service was never actually stopped and is still
# running. Remove it wherever the unit lingers. copenhagen-c legitimately runs a
# hand-configured cloudflared tunnel — never touch it.
# running (it has since been repaved as Proxmox VE, so this is now historical).
# Remove it wherever the unit lingers.
- name: Detect lingering cloudflared unit
ansible.builtin.stat:
path: /etc/systemd/system/cloudflared.service
register: common_cloudflared_unit
when: inventory_hostname != 'copenhagen-c'
- name: Remove orphaned cloudflared
when:
- inventory_hostname != 'copenhagen-c'
- common_cloudflared_unit.stat.exists | default(false)
block:
- name: Stop and disable cloudflared

View file

@ -1,5 +0,0 @@
[mysqld]
# Restrict MariaDB to loopback only.
# UFW blocks port 3306 externally, but binding to 127.0.0.1 provides
# defense in depth — the socket never reaches the network stack at all.
bind-address = 127.0.0.1

View file

@ -1,5 +0,0 @@
---
- name: Restart mariadb
ansible.builtin.systemd:
name: mariadb
state: restarted

View file

@ -1,9 +0,0 @@
---
- name: Deploy MariaDB bind-address config
ansible.builtin.copy:
src: bind-local.cnf
dest: /etc/mysql/mariadb.conf.d/99-bind-local.cnf
owner: root
group: root
mode: '0644'
notify: Restart mariadb

View file

@ -30,15 +30,13 @@ There is **no** per-host subdirectory — services are named by what they are, a
| navidrome | Docker | london-b | Music streaming |
| bookshelf | Docker | london-b | Ebook/audiobook manager (Readarr revival) |
| slskd | Docker | london-b | Soulseek client |
| smartctl-exporter | Docker | london-b, copenhagen-a | SMART metrics |
| smartctl-exporter | Docker | london-b | SMART metrics |
| plex-exporter | Docker | london-b | Plex metrics |
| octopus-exporter | Docker | london-c | Octopus Energy metrics |
| minecraft | Docker | copenhagen-a | PaperMC server |
| radarr / sonarr / lidarr / prowlarr / whisparr | systemd | london-b | *Arr stack (systemd unit files here) |
| transmission | systemd | london-b | Config files (the daemon itself is apt) |
| samba / vsftpd | systemd | london-b | File-sharing config |
| ollama | systemd | london-b | Custom unit + binary install |
| mangos-realmd / mangos-world / mangos-zero | systemd | copenhagen-a | MaNGOS WoW server |
| promtail | systemd | (currently unused; historical) | Log shipper, replaced by Alloy |
| status-page | Cron script | helsinki-a | `update-status.sh` writes `/srv/status` |
| rc.d | FreeBSD rc.conf | (historical) | Snapshot of london-a's old FreeBSD setup |

View file

@ -1,16 +0,0 @@
[Unit]
Description=MaNGOS Zero Realm Server
After=network.target mariadb.service
Requires=mariadb.service
[Service]
Type=simple
User=mangos
Group=mangos
WorkingDirectory=/home/mangos/mangos/zero/bin
ExecStart=/home/mangos/mangos/zero/bin/realmd
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target

View file

@ -1,17 +0,0 @@
[Unit]
Description=MaNGOS Zero World Server
After=network.target mariadb.service mangos-realmd.service
Requires=mariadb.service
Wants=mangos-realmd.service
[Service]
Type=simple
User=mangos
Group=mangos
WorkingDirectory=/home/mangos/mangos/zero/bin
ExecStart=/home/mangos/mangos/zero/bin/mangosd
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target

View file

@ -1,33 +0,0 @@
# MaNGOS Zero (Vanilla WoW)
Classic WoW private server running on **copenhagen-a**.
## Components
- **mangosd** — World server (`mangos-world.service`)
- **realmd** — Authentication/realm server (`mangos-realmd.service`)
- **MariaDB** — Database backend (system service)
## Config Files
| File | Description |
|------|-------------|
| `etc/mangosd.conf` | World server configuration |
| `etc/realmd.conf` | Realm server configuration |
| `etc/ahbot.conf` | Auction house bot configuration |
| `etc/aiplayerbot.conf` | AI playerbot configuration |
Config files use `{{ mangos_db_password }}` as a placeholder for the database password.
The actual password is stored in `ansible/group_vars/all/secrets.enc.yaml`.
## Paths on copenhagen-a
- Binary: `/home/mangos/mangos/zero/bin/`
- Config: `/home/mangos/mangos/zero/etc/`
- User: `mangos:mangos`
## Systemd Services
Service files are in:
- `../mangos-realmd/mangos-realmd.service`
- `../mangos-world/mangos-world.service`

View file

@ -1,265 +0,0 @@
################################################################################
# Auction house bot configuration #
################################################################################
[AhbotConf]
ConfVersion=2021010100
################################################################################
# AUCTION HOUSE BOT SETTINGS
#
# AuctionHouseBot.CharacterName
# The name of the character that the bot will use to auction
# items in the Alliance, Horde and neutral auction houses.
# Default "" (No owner)
#
# AuctionHouseBot.Seller.Enabled
# Enable or disable sales functionality
# Default 0 (Disabled)
#
# AuctionHouseBot.DEBUG.Seller
# Enable or disable sales debug mode
# Default 0 (Disabled)
#
# AuctionHouseBot.Alliance.Items.Amount.Ratio
# Enable or disable sales on Alliance auction houses
# Default 100 (Enabled with 100% of items)
#
# AuctionHouseBot.Horde.Items.Amount.Ratio
# Enable or disable sales on Horde auction houses
# Default 100 (Enabled with 100% of items)
#
# AuctionHouseBot.Neutral.Items.Amount.Ratio
# Enable or disable sales on neutral auction houses
# Default 100 (Enabled with 100% of items)
#
# AuctionHouseBot.MinTime
# Minimum time for new auctions
# Default 1 (Hour)
#
# AuctionHouseBot.MaxTime
# Maximum time for new auctions
# Default 72 (Hours)
#
# AuctionHouseBot.Items.Vendor
# Offer items sold by vendors as auctions
# Default 0
#
# AuctionHouseBot.Items.Loot
# Offer lootable/fishable items as auctions
# Default 1
#
# AuctionHouseBot.Items.Misc
# Offer miscellaneous items as auctions (not recommended)
# Default 0
#
# AuctionHouseBot.Bind.*
# Indicates which bonding types can be put up for auction
# No - Items that don't bind Default 1 (Allowed)
# Pickup - Items that bind on pickup Default 0 (Not Allowed)
# Equip - Items that bind on equip Default 1 (Allowed)
# Use - Items that bind on use Default 1 (Allowed)
# Quest - Quest Items Default 0 (Not Allowed)
#
# AuctionHouseBot.LockBox.Enabled
# Enable or disable sales of lock boxes
# Default 0 (Disabled)
#
# AuctionHouseBot.ItemsPerCycle.Boost
# Uses to define how many auctions to add per cycle in an uninitialized
# auction table.
# Default 75
#
# AuctionHouseBot.ItemsPerCycle.Normal
# Uses to define how many auctions to add per cycle in an initialized
# auction table.
# Default 20
#
# AuctionHouseBot.BuyPrice.Seller
# Enable or disable the use of BuyPrice or SellPrice to determine bid
# pricing
# Default 1 (use SellPrice)
#
# AuctionHouseBot.Alliance.Price.Ratio
# Defines the price ratio for auctions on the Alliance auction houses
# Default 200
#
# AuctionHouseBot.Horde.Price.Ratio
# Defines the price ratio for auctions on the Horde auction houses
# Default 200
#
# AuctionHouseBot.Neutral.Price.Ratio
# Defines the price ratio for auctions on the neutral auction houses
# Default 200
#
# AuctionHouseBot.Items.ItemLevel.*
# Enable or disable listing items below/above this item level
# Default 0 (Disabled)
#
# AuctionHouseBot.Items.ReqLevel.*
# Enable or disable listing items below/above this required level
# Default 0 (Disabled)
#
# AuctionHouseBot.Items.ReqSkill.*
# Enable or disable listing items below/above this skill level
# Default 0 (Disabled)
#
# AuctionHouseBot.Items.Amount.*
# Defines the amount of auctions to be created for each item quality
# Values will be adjusted using faction specific settings (if specified)
# Default 0, 2000, 2500, 1500, 1000, 0, 0
# (grey, white, green, blue, purple, orange, yellow)
#
# AuctionHouseBot.Class.*
# Defines which item classes can be put up for auction. See pre-defined
# classes in ItemClass.dbc.
# These value are preference values, maximum is 10, minimum is 0.
# Default 6,4,8,8,1,2,0,6,1,1,1,5
#
#
# ITEM FINE TUNING
# The following are useful for limiting what character levels can benefit
# from the auction house.
#
# AuctionHouseBot.Class.Misc.Mount.ReqLevel.*
# Enable or disable listing mounts below/above this required level
# Default 0
#
# AuctionHouseBot.Class.Misc.Mount.ReqSkill.*
# Enable or disable listing mounts below/above this skill level
# Default 0
#
# AuctionHouseBot.Class.TradeGood.ItemLevel.*
# Enable or disable listing trade good items below/above this item level
# Default 0
#
# AuctionHouseBot.Class.Container.ItemLevel.*
# Enable or disable listing containers below/above this item level
# Default 0
#
# AuctionHouseBot.forceIncludeItems
# Allows to include items which would normally be ignored by filter
# settings.
# List of ids with delimiter ','
# Default ""
#
# AuctionHouseBot.forceExcludeItems
# Allows to exclude items which would normally be included by filter
# settings.
# List of ids with delimiter ','
# Default ""
#
################################################################################
AuctionHouseBot.CharacterName = ""
AuctionHouseBot.Seller.Enabled = 1
AuctionHouseBot.DEBUG.Seller = 0
AuctionHouseBot.Alliance.Items.Amount.Ratio = 100
AuctionHouseBot.Horde.Items.Amount.Ratio = 100
AuctionHouseBot.Neutral.Items.Amount.Ratio = 100
AuctionHouseBot.MinTime = 1
AuctionHouseBot.MaxTime = 72
AuctionHouseBot.Items.Vendor = 0
AuctionHouseBot.Items.Loot = 1
AuctionHouseBot.Items.Misc = 0
AuctionHouseBot.Bind.No = 1
AuctionHouseBot.Bind.Pickup = 0
AuctionHouseBot.Bind.Equip = 1
AuctionHouseBot.Bind.Use = 1
AuctionHouseBot.Bind.Quest = 0
AuctionHouseBot.LockBox.Enabled = 0
AuctionHouseBot.ItemsPerCycle.Boost = 75
AuctionHouseBot.ItemsPerCycle.Normal = 20
AuctionHouseBot.BuyPrice.Seller = 1
AuctionHouseBot.Alliance.Price.Ratio = 200
AuctionHouseBot.Horde.Price.Ratio = 200
AuctionHouseBot.Neutral.Price.Ratio = 200
AuctionHouseBot.Items.ItemLevel.Min = 0
AuctionHouseBot.Items.ItemLevel.Max = 0
AuctionHouseBot.Items.ReqLevel.Min = 0
AuctionHouseBot.Items.ReqLevel.Max = 0
AuctionHouseBot.Items.ReqSkill.Min = 0
AuctionHouseBot.Items.ReqSkill.Max = 0
AuctionHouseBot.Items.Amount.Grey = 0
AuctionHouseBot.Items.Amount.White = 2000
AuctionHouseBot.Items.Amount.Green = 2500
AuctionHouseBot.Items.Amount.Blue = 1500
AuctionHouseBot.Items.Amount.Purple = 1000
AuctionHouseBot.Items.Amount.Orange = 0
AuctionHouseBot.Items.Amount.Yellow = 0
AuctionHouseBot.Class.Consumable = 6
AuctionHouseBot.Class.Container = 4
AuctionHouseBot.Class.Weapon = 8
AuctionHouseBot.Class.Armor = 8
AuctionHouseBot.Class.Reagent = 1
AuctionHouseBot.Class.Projectile = 2
AuctionHouseBot.Class.TradeGood = 10
AuctionHouseBot.Class.Recipe = 6
AuctionHouseBot.Class.Quiver = 1
AuctionHouseBot.Class.Quest = 1
AuctionHouseBot.Class.Key = 1
AuctionHouseBot.Class.Misc = 5
AuctionHouseBot.Class.Misc.Mount.ReqLevel.Min = 0
AuctionHouseBot.Class.Misc.Mount.ReqLevel.Max = 0
AuctionHouseBot.Class.Misc.Mount.ReqSkill.Min = 0
AuctionHouseBot.Class.Misc.Mount.ReqSkill.Max = 0
AuctionHouseBot.Class.TradeGood.ItemLevel.Min = 0
AuctionHouseBot.Class.TradeGood.ItemLevel.Max = 0
AuctionHouseBot.Class.Container.ItemLevel.Min = 0
AuctionHouseBot.Class.Container.ItemLevel.Max = 0
AuctionHouseBot.forceIncludeItems = ""
AuctionHouseBot.forceExcludeItems = ""
################################################################################
# Buyer configuration
#
# AuctionHouseBot.Buyer.Enabled
# Enable or disable buyer mode
# Default 0 (Disabled)
#
# AuctionHouseBot.DEBUG.Buyer
# Enable or disable buyer debug mode
# Default 0 (Disabled)
#
# AuctionHouseBot.Buyer.FACTION.Enabled
# Enable or disable buyer mode for a specific faction
#
# AuctionHouseBot.Buyer.BuyPrice
# Enable or disable the use of BuyPrice or SellPrice to determine bid
# pricing
# Default 0 (use SellPrice)
#
# AuctionHouseBot.Buyer.Recheck.Interval
# This specifies the time interval (in minute) between evaluations of
# identical items.
# The lower the value is, the higher the chance for an item to be bought
# Default 20 (20min.)
#
# AuctionHouseBot.Buyer.FACTION.Chance.Ratio
# Determines the chance for buying an item.
# Default 3 (literally 1 chance by 3)
#
################################################################################
AuctionHouseBot.Buyer.Enabled = 0
AuctionHouseBot.DEBUG.Buyer = 0
AuctionHouseBot.Buyer.Alliance.Enabled = 1
AuctionHouseBot.Buyer.Horde.Enabled = 1
AuctionHouseBot.Buyer.Neutral.Enabled = 1
AuctionHouseBot.Buyer.BuyPrice = 0
AuctionHouseBot.Buyer.Recheck.Interval = 20
AuctionHouseBot.Buyer.Alliance.Chance.Ratio = 3
AuctionHouseBot.Buyer.Horde.Chance.Ratio = 3
AuctionHouseBot.Buyer.Neutral.Chance.Ratio = 3

View file

@ -1,164 +0,0 @@
##########################################
# MANGOS Ai Playerbot Configuration file #
##########################################
[AiPlayerbotConf]
ConfVersion=2010102201
# Enable or disable AI Playerbot
AiPlayerbot.Enabled = 0
# Warrior
AiPlayerbot.RandomClassSpecProbability.1.0 = 20
AiPlayerbot.RandomClassSpecProbability.1.1 = 30
AiPlayerbot.RandomClassSpecProbability.1.2 = 50
# Paladin
AiPlayerbot.RandomClassSpecProbability.2.0 = 20
AiPlayerbot.RandomClassSpecProbability.2.1 = 50
AiPlayerbot.RandomClassSpecProbability.2.2 = 30
# Hunter
AiPlayerbot.RandomClassSpecProbability.3.0 = 25
AiPlayerbot.RandomClassSpecProbability.3.1 = 50
AiPlayerbot.RandomClassSpecProbability.3.2 = 25
# Rogue
AiPlayerbot.RandomClassSpecProbability.4.0 = 40
AiPlayerbot.RandomClassSpecProbability.4.1 = 50
AiPlayerbot.RandomClassSpecProbability.4.2 = 10
# Priest
AiPlayerbot.RandomClassSpecProbability.5.0 = 40
AiPlayerbot.RandomClassSpecProbability.5.1 = 40
AiPlayerbot.RandomClassSpecProbability.5.2 = 20
# Shaman
AiPlayerbot.RandomClassSpecProbability.7.0 = 10
AiPlayerbot.RandomClassSpecProbability.7.1 = 45
AiPlayerbot.RandomClassSpecProbability.7.2 = 45
# Mage
AiPlayerbot.RandomClassSpecProbability.8.0 = 20
AiPlayerbot.RandomClassSpecProbability.8.1 = 10
AiPlayerbot.RandomClassSpecProbability.8.2 = 70
# Warlock
AiPlayerbot.RandomClassSpecProbability.9.0 = 33
AiPlayerbot.RandomClassSpecProbability.9.1 = 33
AiPlayerbot.RandomClassSpecProbability.9.2 = 33
# Druid
AiPlayerbot.RandomClassSpecProbability.11.0 = 10
AiPlayerbot.RandomClassSpecProbability.11.1 = 45
AiPlayerbot.RandomClassSpecProbability.11.2 = 45
#
# All other parameters are optional but can be changed by uncommenting them here
#
# Prefix for bot chat commands (e.g. follow, stay)
AiPlayerbot.CommandPrefix = ~
# Max AI iterations per tick
#AiPlayerbot.IterationsPerTick = 10
# Allow/deny bots from your guild
#AiPlayerbot.AllowGuildBots = 1
# Delay between two short-time spells cast
#AiPlayerbot.GlobalCooldown = 500
# Max wait time when moving
#AiPlayerbot.MaxWaitForMove = 5000
# Delay between two bot actions
#AiPlayerbot.ReactDelay = 100
# Distances
#AiPlayerbot.SightDistance = 50.0
#AiPlayerbot.SpellDistance = 30.0
#AiPlayerbot.ReactDistance = 150.0
#AiPlayerbot.GrindDistance = 100.0
#AiPlayerbot.LootDistance = 20.0
#AiPlayerbot.FleeDistance = 20.0
#AiPlayerbot.TooCloseDistance = 7.0
#AiPlayerbot.MeleeDistance = 1.0
#AiPlayerbot.FollowDistance = 1.5
#AiPlayerbot.WhisperDistance = 6000.0
#AiPlayerbot.ContactDistance = 0.5
# Bot can flee for enemy
#AiPlayerbot.FleeingEnabled = 1
# Health/Mana levels
#AiPlayerbot.CriticalHealth = 25
#AiPlayerbot.LowHealth = 45
#AiPlayerbot.MediumHealth = 65
#AiPlayerbot.AlmostFullHealth = 85
#AiPlayerbot.LowMana = 15
#AiPlayerbot.MediumMana = 40
# Enable random bot system
#AiPlayerbot.RandomBotAutologin = 1
# Random bot default strategies (applied after defaults)
#AiPlayerbot.RandomBotCombatStrategies = +dps,+attack weak
#AiPlayerbot.RandomBotNonCombatStrategies = +grind,+move random,+loot
# Create random bot characters automatically
#AiPlayerbot.RandomBotAutoCreate = 1
# Random bot count
#AiPlayerbot.MinRandomBots = 50
#AiPlayerbot.MaxRandomBots = 200
#AiPlayerbot.RandomBotMinLevel = 1
#AiPlayerbot.RandomBotMaxLevel = 255 (ignored if more than MaxPlayerLevel mangosd.conf value)
# Accounts to create for random bots
#AiPlayerbot.RandomBotAccountPrefix = rndbot
#AiPlayerbot.RandomBotAccountCount = 50
# Delete all random bot accounts
#AiPlayerbot.DeleteRandomBotAccounts = 0
# Maps to teleport random bots
#AiPlayerbot.RandomBotMaps = 0,1,530,571
# Change random bot has lower gear
#AiPlayerbot.RandomGearLoweringChance = 0.15
# Chance random bot has max level on first randomize
#AiPlayerbot.RandomBotMaxLevelChance = 0.4
# Quest items to leave (do not destroy)
#AiPlayerbot.RandomBotQuestItems = 6948,5175,5176,5177,5178
# Spells every random bot will learn on randomize (54197 - cold weather flying)
#AiPlayerbot.RandomBotSpellIds = 54197
# Enable LFG for random bots
#AiPlayerbot.RandomBotJoinLfg = 1
# Level diff between random bots and nearby creatures for random teleports
AiPlayerbot.RandomBotTeleLevel = 3
# Intervals
#AiPlayerbot.RandomBotUpdateInterval = 60
#AiPlayerbot.RandomBotCountChangeMinInterval = 86400
#AiPlayerbot.RandomBotCountChangeMaxInterval = 259200
#AiPlayerbot.MinRandomBotInWorldTime = 7200
#AiPlayerbot.MaxRandomBotInWorldTime = 1209600
#AiPlayerbot.MinRandomBotRandomizeTime = 7200
#AiPlayerbot.MaxRandomRandomizeTime = 1209600
#AiPlayerbot.MinRandomBotsPerInterval = 50
#AiPlayerbot.MaxRandomBotsPerInterval = 100
#AiPlayerbot.MinRandomBotsPriceChangeInterval = 7200
#AiPlayerbot.MaxRandomBotsPriceChangeInterval = 172800
# Log on all random bots on start
#AiPlayerbot.RandomBotLoginAtStartup = 1
# How far random bots are teleported after death
#AiPlayerbot.RandomBotTeleportDistance = 1000
# Debug switches
#AiPlayerbot.SpellDump = 0
#AiPlayerbot.LogInGroupOnly = 1
#AiPlayerbot.LogValuesPerTick = 0
#AiPlayerbot.RandomChangeMultiplier = 1
# Command server port, 0 - disabled
#AiPlayerbot.CommandServerPort = 8888

File diff suppressed because it is too large Load diff

View file

@ -1,132 +0,0 @@
################################################################################
# Realm list demon configuration #
################################################################################
[RealmdConf]
ConfVersion=2021010100
################################################################################
# REALMD SETTINGS
#
# LoginDatabaseInfo
# Connection settings for the realm/authentication database
# Default: hostname;port;username;password;database
# Use named pipes at Windows
# .;somenumber;username;password;database
#
# Use Unix sockets on Unix/Linux
# .;/path/to/unix_socket;username;password;database
#
# LogsDir
# Directory where log files should be written
# The given path has to exist, and be writable for the realm list demon
# Default: "" No log directory prefix, thus log files will be stored in
# the same path where the realm list demon is running
#
# PidFile
# Realm list demon PID file
# Default: "" Do not create a PID file.
#
# MaxPingTime
# Settings for maximum database-ping interval (minutes between pings)
# Default: 30
#
# RealmServerPort
# Port on which the server will listen
# Default: 3724
#
# BindIP
# Bind realm list demon to IP/hostname
# DO NOT CHANGE THIS UNLESS YOU _REALLY_ KNOW WHAT YOU'RE DOING
# Default: "0.0.0.0" Listen on all available addresses
#
# LogLevel
# Server console level of logging
# 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug
# Default: 0
#
# LogTime
# Include time in server console output [hh:mm:ss]
# Default: 0 (no time)
# 1 (print time)
#
# LogFile
# Logfile name
# Default: "Realmd.log"
# "" - empty name disable creating log file
#
# LogTimestamp
# Logfile with timestamp of server start in name
# Default: 0 - no timestamp appended
# 1 - append timestamp in form of _YYYY-MM-DD_HH-MM-SS
#
# LogFileLevel
# Server file level of logging
# 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug
# Default: 0
#
# LogColors
# Color for messages (format "normal_color details_color debug_color error_color)
# Colors: 0 - BLACK, 1 - RED, 2 - GREEN, 3 - BROWN, 4 - BLUE, 5 - MAGENTA, 6 - CYAN, 7 - GREY,
# 8 - YELLOW, 9 - LRED, 10 - LGREEN, 11 - LBLUE, 12 - LMAGENTA, 13 - LCYAN, 14 - WHITE
# Default: "" - none colors
# "13 7 11 9" - for example :)
#
# UseProcessors
# Used processors mask for multi-processors system (Used only at Windows)
# Default: 0 (selected by OS)
# number (bitmask value of selected processors)
#
# ProcessPriority
# Process proirity setting (Used only at Windows)
# Default: 1 (HIGH)
# 0 (Normal)
#
# WaitAtStartupError
# After startup error report wait <Enter> or some time before continue (and possible close console window)
# -1 (wait until <Enter> press)
# Default: 0 (not wait)
# N (>0, wait N secs)
#
# RealmsStateUpdateDelay
# Realm list Update up delay (updated at realm list request if delay expired).
# Default: 20
# 0 (Disabled)
#
# WrongPass.MaxCount
# Number of login attemps with wrong password before the account or IP is banned
# Default: 3 (Never ban)
#
# WrongPass.BanTime
# Duration of the ban in seconds (0 means permanent ban)
# Default: 300
#
# WrongPass.BanType
# Ban the IP or account on which login is attempted
# Default: 0 (Ban IP)
# 1 (Ban Account)
#
################################################################################
LoginDatabaseInfo = "127.0.0.1;3306;mangos;{{ mangos_db_password }};realmd"
LogsDir = ""
PidFile = ""
MaxPingTime = 30
RealmServerPort = 3724
BindIP = "0.0.0.0"
LogLevel = 0
LogTime = 0
LogFile = "realm-list.log"
LogTimestamp = 0
LogFileLevel = 0
LogColors = "13 7 11 9"
UseProcessors = 0
ProcessPriority = 1
WaitAtStartupError = 0
RealmsStateUpdateDelay = 20
WrongPass.MaxCount = 100
WrongPass.BanTime = 300
WrongPass.BanType = 0

View file

@ -1,10 +0,0 @@
# Minecraft
PaperMC server.
- **Host:** copenhagen-a
- **Port:** 25565
- **Memory:** 3GB
- **Data:** Docker volume (`minecraft_minecraftserver`)
- **Java:** OpenJDK 21 (bundled in image)
- **Note:** copenhagen-a also runs a WoW server (MaNGOS Zero) as system services, not Docker

View file

@ -1,25 +0,0 @@
---
# Minecraft - PaperMC server
# Host: copenhagen-a (100.89.206.60)
# Data: Docker volume (minecraft_minecraftserver)
services:
minecraft:
image: itzg/minecraft-server:latest
container_name: mcserver
restart: always
ports:
- "25565:25565"
environment:
EULA: true
DIFFICULTY: hard
MEMORYSIZE: 3G
VERSION: 1.21.11
MOTD: Pez Solutions
volumes:
- minecraft_data:/data
volumes:
minecraft_data:
name: minecraft_minecraftserver

View file

@ -1,6 +1,6 @@
---
# smartctl-exporter - SMART disk metrics for Prometheus
# Hosts: london-b (100.84.65.101), copenhagen-a (100.89.206.60)
# Hosts: london-b (100.84.65.101)
# Access: http://<host>:9633/metrics
services:

View file

@ -21,5 +21,4 @@ Everything you need to understand how this infrastructure works.
| london-b | 100.84.65.101 | London | Storage, media, Docker services |
| london-c | 100.123.72.87 | London | Raspberry Pi, Octopus Energy exporter |
| nuremberg-a | 100.70.180.24 | Hetzner Cloud (Nuremberg) | Mail (poste.io) |
| copenhagen-a | 100.89.206.60 | Copenhagen | Minecraft, WoW/MaNGOS |
| copenhagen-c | 100.115.45.53 | Copenhagen | Raspberry Pi, cloudflared, idle |
| copenhagen-a | 100.91.240.29 | Copenhagen | Proxmox VE hypervisor |

View file

@ -21,12 +21,9 @@ graph TD
TS --> LA["<b>london-a</b><br/>Proxmox VE hypervisor<br/>(Debian 13)"]
TS --> LC["<b>london-c</b><br/>Raspberry Pi<br/>Octopus Energy exporter"]
TS --> NA["<b>nuremberg-a</b><br/>Mail<br/>poste.io"]
TS --> CA["<b>copenhagen-a</b><br/>Gaming<br/>Minecraft / WoW (MaNGOS)"]
TS --> CC["<b>copenhagen-c</b><br/>Raspberry Pi<br/>cloudflared, idle"]
TS --> CA["<b>copenhagen-a</b><br/>Proxmox VE hypervisor<br/>(Debian 12)"]
TS -.->|Alloy| GC["<b>Grafana Cloud</b><br/>metrics, logs, traces<br/>synthetic checks"]
style CC stroke-dasharray: 5 5
```
## Traffic Flow

View file

@ -45,8 +45,7 @@ ssh root@helsinki-a # or ssh root@100.67.6.27
ssh root@london-a # Proxmox VE host
ssh root@london-b # storage / media
ssh root@london-c # Raspberry Pi
ssh root@copenhagen-a
ssh root@copenhagen-c # Raspberry Pi
ssh root@copenhagen-a # Proxmox VE host
ssh root@nuremberg-a
```
@ -139,8 +138,8 @@ ZFS is set up with 3× RAIDZ1 vdevs of 4 drives each (12 drives total) on the `h
## OS Choice
- **Debian (12 or 13)** is the default for new hosts — including the Raspberry Pis. Stable, well-supported by Ansible, predictable.
- **Ubuntu LTS** is on london-b and copenhagen-a (historical — both came up before the Debian standard).
- **Proxmox VE** (Debian Bookworm under the hood) on london-a.
- **Ubuntu LTS** is on london-b (historical — came up before the Debian standard).
- **Proxmox VE** (Debian Bookworm under the hood) on london-a and copenhagen-a.
- **No more FreeBSD.** london-a used to run FreeBSD for Prometheus/Grafana; that's all on Grafana Cloud now and london-a is Linux/Proxmox.
Alpine has been tried and rejected — the missing GNU binaries / systemd caused enough Ansible headaches to not be worth the size savings.

View file

@ -1,15 +1,15 @@
# copenhagen-a
Game servers. Located at my dad's place in Copenhagen as an off-site location.
Proxmox VE hypervisor. Located at my dad's place in Copenhagen as an off-site location — the Copenhagen counterpart to london-a.
## Overview
| | |
|---|---|
| **Location** | Copenhagen |
| **OS** | Ubuntu 22.04 LTS |
| **Tailscale IP** | 100.89.206.60 |
| **Role** | Gaming servers (Minecraft, WoW) |
| **OS** | Debian 12 (Bookworm) with Proxmox VE |
| **Tailscale IP** | 100.91.240.29 |
| **Role** | Hypervisor (Proxmox VE) |
| **Form factor** | Lenovo "tiny" desktop (lunchbox-sized) |
## Hardware
@ -20,50 +20,42 @@ Game servers. Located at my dad's place in Copenhagen as an off-site location.
| Memory | 16 GB |
| Boot disk | 500 GB |
Compact Lenovo desktop — powered by a standard ThinkPad charging brick. Small, quiet, and draws minimal power.
Compact Lenovo desktop — powered by a standard ThinkPad charging brick. Small, quiet, and draws minimal power. Previously ran the gaming servers directly on bare metal; now repaved as a Proxmox VE host.
## Services
### Minecraft
| Service | Port | Status | Notes |
|---------|------|--------|-------|
| Proxmox VE | 8006 | Active | Web UI — reachable via `copenhagen-a.pez.sh` (Caddy) or Tailscale IP |
| Tailscale | — | Active | Mesh networking |
| node_exporter, systemd_exporter, Alloy | — | Active | Observability baseline (Ansible-managed) |
| | |
|---|---|
| Image | `itzg/minecraft-server` |
| Port | 25565 |
| Deployment | Docker |
### Storage
Not proxied through Caddy — accessed directly via Tailscale or the host's public IP.
Proxmox is connected to the same CIFS share on **london-b** (`100.84.65.101 /pve`) used by london-a, for ISO/template/backup storage. The mount is configured by the `proxmox_ve` Ansible role.
### World of Warcraft (MaNGOS Zero)
| Storage ID | Type | Backing |
|---|---|---|
| `local-lvm` | LVM-Thin | Local boot disk |
| `hdd` | CIFS | london-b `/pve` share |
WoW 1.12 (Vanilla) private server using the MaNGOS Zero emulator. Runs natively — not in Docker.
### VMs
| Service | Port | Managed by |
|---------|------|-----------|
| mangos-realmd | 3724 | systemd |
| mangos-world | 8085 | systemd |
| MariaDB | 3306 | systemd (apt-managed) |
No VMs provisioned yet — this is the landing zone for future workloads at the Copenhagen site.
- Runs as the `mangos` user
- Install path: `/home/mangos/mangos/zero/`
- MariaDB hosts the character, world, and auth databases locally
- Both `mangos-realmd` and `mangos-world` start automatically on boot via systemd
- The `mariadb` Ansible role manages package + secrets; the `systemd_services` role drops the unit files (`ansible/services/mangos-realmd/`, `ansible/services/mangos-world/`)
## Ansible
### Other
Part of the `proxmox_hosts` group alongside london-a, sharing the `proxmox_ve` role:
| Service | Port | Deployment | Notes |
|---------|------|-----------|-------|
| smartctl_exporter | 9633 | Docker | Disk SMART metrics scraped by Alloy |
| node_exporter | 9100 | Native | Host metrics |
| systemd_exporter | — | Native | systemd unit metrics |
| Alloy | — | Native | Ships everything to Grafana Cloud |
| Tailscale | — | Native | Mesh networking |
- Swaps the enterprise apt repo for `pve-no-subscription` so updates work without a paid subscription
- Patches `proxmoxlib.js` to suppress the subscription nag dialog
- Restricts the web UI to the `tailscale0` interface via UFW
- Mounts the london-b CIFS storage
## Networking
Connected directly to the ISP router's built-in switch. Symmetrical 500 Mbit connection — more than enough for game servers.
Connected directly to the ISP router's built-in switch. Symmetrical 500 Mbit connection.
## Notes
## History
copenhagen-a has a static public IP, which is needed for game servers that require direct client connections (WoW realm list, Minecraft server list). The reboot playbook (`ansible/playbooks/reboot.yml`) does a netplan pre-flight check before rebooting to make sure the static IP config will come back up cleanly.
copenhagen-a used to run gaming servers directly on bare metal: a Minecraft server (`itzg/minecraft-server`, Docker) and a WoW 1.12 (Vanilla) MaNGOS Zero private server (native systemd + local MariaDB). Both were decommissioned and the host was repaved as Proxmox VE — the Tailscale identity (and IP) changed as part of the reinstall. The old static public IP used for direct game-client connections (Minecraft server list, WoW realm list) is no longer needed since nothing here accepts direct client connections anymore.

View file

@ -1,29 +0,0 @@
# copenhagen-c
Raspberry Pi at the Copenhagen site. General-purpose / off-site utility box.
## Overview
| | |
|---|---|
| **Location** | Copenhagen |
| **OS** | Debian 12 (Bookworm), aarch64 |
| **Tailscale IP** | 100.115.45.53 |
| **Role** | Idle / cloudflared tunnel |
| **Form factor** | Raspberry Pi (ARM64) |
## Services
| Service | Deployment | Notes |
|---------|-----------|-------|
| cloudflared | Native (systemd) | Cloudflare-managed tunnel for ad-hoc exposure of services from this site |
| Tailscale | Native | Mesh networking |
| Alloy | Native | Ships metrics/logs to Grafana Cloud |
| node_exporter | Native | Host metrics |
| Docker / containerd | Native | Available, but no compose services currently scheduled here |
The cloudflared token is stored directly in the systemd unit (`/etc/systemd/system/cloudflared.service`); the tunnel itself is configured in the Cloudflare dashboard.
## Notes
Part of the Copenhagen off-site setup at my dad's place. Otherwise idle — available if I need to spin up something that benefits from a Copenhagen location or just need another always-on box.

View file

@ -38,7 +38,7 @@ The `common` role drops a `10-resilience.conf` systemd override onto every host
|---|---|---|
| node_exporter | All hosts | CPU, memory, disk, network, system uptime |
| systemd_exporter | All hosts | Per-unit systemd state |
| smartctl_exporter (Docker) | london-b, copenhagen-a | Disk SMART data |
| smartctl_exporter (Docker) | london-b | Disk SMART data |
| prom-plex-exporter (Docker) | london-b | Plex streaming activity |
| octopus_exporter (Docker) | london-c | Octopus Energy electricity usage |
| Caddy `/metrics` | helsinki-a | HTTP request metrics, upstream health (per host) |

View file

@ -13,8 +13,7 @@ All inter-server communication uses Tailscale IPs:
| london-b | 100.84.65.101 |
| london-c | 100.123.72.87 |
| nuremberg-a | 100.70.180.24 |
| copenhagen-a | 100.89.206.60 |
| copenhagen-c | 100.115.45.53 |
| copenhagen-a | 100.91.240.29 |
### What Tailscale is used for
@ -43,7 +42,7 @@ A stack of servers at my dad's place — acts as an off-site location.
- **Router:** ISP-provided (not my house, can't exactly install a Ubiquiti rack)
- **ISP:** Symmetrical 500 Mbit — plenty for what's running there
- **Servers:** copenhagen-a (Lenovo tiny desktop) and copenhagen-c (Raspberry Pi) connected directly to the ISP router's built-in switch
- **Servers:** copenhagen-a (Lenovo tiny desktop, now running Proxmox VE) connected directly to the ISP router's built-in switch
### Helsinki / Nuremberg (Hetzner Cloud)
@ -95,6 +94,7 @@ All subdomains resolve directly to helsinki-a, where Caddy terminates TLS. Hosts
| signup.pez.solutions | helsinki-a:/srv/pez-signup (static) | — |
| naveen.pez.sh | helsinki-a:/srv/naveen (static) | — |
| london-a.pez.sh | london-a:8006 (Proxmox UI) | Proxmox login |
| copenhagen-a.pez.sh | copenhagen-a:8006 (Proxmox UI) | Proxmox login |
| jellyfin.pez.sh / .solutions | london-b:8096 | Own auth |
| plex.pez.sh / .solutions | london-b:32400 | Own auth |
| music.pez.sh | london-b:4533 (Navidrome) | Own auth |
@ -108,7 +108,7 @@ All subdomains resolve directly to helsinki-a, where Caddy terminates TLS. Hosts
| soulseek.pez.sh / .solutions | london-b:5030 (slskd) | Authelia |
| download.pez.sh / .solutions | london-b:9091 (Transmission) | Authelia |
A few `pez.sh` records bypass Caddy entirely: `mail` points at nuremberg-a, `minecraft` and `wow` point at copenhagen-a's public IP (game clients connect directly), and `public` is a CNAME to a Cloudflare R2 public bucket (`public.r2.dev`).
A few `pez.sh` records bypass Caddy entirely: `mail` points at nuremberg-a, and `public` is a CNAME to a Cloudflare R2 public bucket (`public.r2.dev`).
### Mail DNS

View file

@ -95,27 +95,15 @@ poste.io bundles everything — postfix, dovecot, rspamd, webmail — into a sin
n8n (workflow automation) binds 5678 to the Tailscale IP only; public access is proxied by Caddy on helsinki-a. It manages its own user auth.
## copenhagen-a — Gaming
## copenhagen-a — Proxmox VE Hypervisor
Game servers. Not publicly exposed via Caddy — accessed directly over the public IP/Tailscale.
Repurposed gaming PC (previously ran Minecraft and a WoW/MaNGOS private server) at the Copenhagen off-site location, now reinstalled as a Proxmox VE hypervisor — the Copenhagen counterpart to london-a.
| Service | Port | Deployment | Auth | URL |
|---------|------|-----------|------|-----|
| Minecraft (`itzg/minecraft-server`) | 25565 | Docker | — | (direct connection) |
| MaNGOS realmd | 3724 | Native (systemd) | — | (direct connection) |
| MaNGOS world | 8085 | Native (systemd) | — | (direct connection) |
| MariaDB | 3306 | Native (apt) | — | (local, used by MaNGOS) |
| smartctl_exporter | 9633 | Docker | — | (scraped by Alloy → Grafana Cloud) |
| Proxmox VE | 8006 | Native (Debian Bookworm-based PVE) | Proxmox login | copenhagen-a.pez.sh |
MaNGOS Zero is a WoW 1.12 (Vanilla) private server. Runs natively under systemd as the `mangos` user from `/home/mangos/mangos/zero/`. Not containerised — it predates the Docker setup on this host.
## copenhagen-c — Idle (Raspberry Pi)
Raspberry Pi running Debian 12 at the Copenhagen site. Mostly idle, but runs a cloudflared tunnel for one-off use.
| Service | Port | Deployment | Auth | URL |
|---------|------|-----------|------|-----|
| cloudflared | — | Native (systemd) | — | (Cloudflare-managed tunnel) |
The web UI is exposed via Caddy at `copenhagen-a.pez.sh` but is also reachable directly over Tailscale. Proxmox storage is augmented with the same london-b CIFS share used by london-a (configured by the `proxmox_ve` Ansible role).
## Observability Agents

View file

@ -19,6 +19,13 @@ resource "grafana_fleet_management_collector" "london_c" {
}
}
resource "grafana_fleet_management_collector" "copenhagen_a" {
id = "copenhagen-a"
remote_attributes = {
location = "copenhagen"
}
}
resource "grafana_fleet_management_collector" "helsinki_a" {
id = "helsinki-a"
remote_attributes = {

View file

@ -7,7 +7,6 @@ locals {
helsinki_a = hcloud_server.helsinki-a.ipv4_address
nuremberg_a = hcloud_server.nuremberg-a.ipv4_address
nuremberg_aaaa = hcloud_server.nuremberg-a.ipv6_address
copenhagen = "83.94.248.182"
dns_ttl = 300
}
@ -37,15 +36,6 @@ resource "hcloud_zone_rrset" "nuremberg_mail" {
records = [{ value = each.value }]
}
resource "hcloud_zone_rrset" "A_copenhagen" {
for_each = toset(["minecraft", "wow"])
zone = hcloud_zone.pezsh.name
name = each.value
type = "A"
ttl = local.dns_ttl
records = [{ value = local.copenhagen }]
}
resource "hcloud_zone_rrset" "CNAME_forms" {
zone = hcloud_zone.pezsh.name
name = "forms"