mirror of
https://github.com/RWejlgaard/pez-infra.git
synced 2026-09-01 16:05:34 +00:00
decomm copenhagen-b and copenhagen-c (#144)
This commit is contained in:
parent
0e55029bea
commit
4e2ea9e35b
34 changed files with 67 additions and 2624 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
host_role: idle
|
||||
host_description: "Idle/available"
|
||||
host_location: "Copenhagen"
|
||||
prometheus_location: copenhagen
|
||||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
- name: Restart mariadb
|
||||
ansible.builtin.systemd:
|
||||
name: mariadb
|
||||
state: restarted
|
||||
|
|
@ -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
|
||||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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`
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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) |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue