feat: rename VMs to zamolxis(900)/decebal(901), raise RAM to 24GB/30GB, decebal to 6vCPU, innodb_buffer_pool 26G
This commit is contained in:
106
README.md
106
README.md
@@ -123,12 +123,12 @@ FreeBSD 15.0 over 14.x specifically because PHP 8.5 is a **binary package** on 1
|
||||
## Target Architecture
|
||||
|
||||
```
|
||||
[internet] → [NPM node, Tailscale] → [dracula-new FreeBSD 15.0, Tailscale] → [transilvan-new FreeBSD 15.0, Tailscale]
|
||||
[internet] → [NPM node, Tailscale] → [zamolxis FreeBSD 15.0, Tailscale] → [decebal FreeBSD 15.0, Tailscale]
|
||||
|
||||
dracula-new (FreeBSD 15.0) transilvan-new (FreeBSD 15.0)
|
||||
zamolxis (FreeBSD 15.0) decebal (FreeBSD 15.0)
|
||||
────────────────────────── ─────────────────────────────
|
||||
nginx (pkg) ZFS pool → /var/db/mysql
|
||||
PHP 8.5 (ports build) recordsize=16K (InnoDB optimal)
|
||||
PHP 8.5.6 (pkg) recordsize=16K (InnoDB optimal)
|
||||
gd, imagick, intl, mbstring, compression=lz4
|
||||
opcache, pdo_mysql, redis, primarycache=metadata
|
||||
soap, sockets, sodium, MySQL 8.4 LTS (ports)
|
||||
@@ -171,10 +171,10 @@ Proxmox native monitoring
|
||||
|
||||
| Host | CPU | Logical CPUs | RAM | Storage | Available to VMs | VM |
|
||||
|---|---|---|---|---|---|---|
|
||||
| dracula host | Xeon E5-1620 v2 @ 3.70GHz | 8 (4 cores + HT) | 64GB | Datacenter HDD | ~full | dracula-new (web) |
|
||||
| transilvan host | Xeon E5-1620 v2 @ 3.70GHz | 8 (4 cores + HT) | 32GB | SSD (160GB total, ~130GB free after Proxmox) | 130GB | transilvan-new (db) |
|
||||
| dracula host | Xeon E5-1620 v2 @ 3.70GHz | 8 (4 cores + HT) | 64GB | Datacenter HDD | ~full | zamolxis / ID 900 (web) |
|
||||
| transilvan host | Xeon E5-1620 v2 @ 3.70GHz | 8 (4 cores + HT) | 32GB | SSD 160GB (~130GB free) | 130GB | decebal / ID 901 (db) — sole VM |
|
||||
|
||||
Both hosts run Proxmox VE (confirmed via qemu-guest-agent on current VMs). New VMs are the sole tenants on their respective hosts.
|
||||
Both hosts run Proxmox VE (confirmed via qemu-guest-agent on current VMs). Decebal's host is dedicated — no other VMs share it.
|
||||
|
||||
---
|
||||
|
||||
@@ -193,34 +193,34 @@ With nginx fastcgi_cache, the vast majority of requests never invoke PHP. On a n
|
||||
| PHP-FPM peak RAM | ~1.4GB | 40 workers × 35MB |
|
||||
| nginx HIT response time | <5ms | Served from UBC, no PHP involved |
|
||||
| nginx MISS response time | 100–400ms | WP query + render |
|
||||
| InnoDB buffer pool hit rate | >99% | 20GB pool, 9.6GB dataset fits entirely in RAM |
|
||||
| InnoDB buffer pool hit rate | >99% | 26GB pool, 9.6GB dataset fits entirely in RAM with 16GB to spare |
|
||||
| Active DB connections | ≤ 40 | One per active PHP-FPM worker |
|
||||
|
||||
### dracula-new (web VM on HDD host)
|
||||
### zamolxis (web VM on HDD host)
|
||||
|
||||
| Parameter | Value |
|
||||
|---|---|
|
||||
| vCPU | 6 |
|
||||
| RAM | 14GB |
|
||||
| RAM | 24GB |
|
||||
| Disk | 80GB single virtual disk (HDD-backed) |
|
||||
| Balloon | Enabled (web VM, acceptable) |
|
||||
|
||||
RAM breakdown: PHP-FPM peak 1.4GB + Redis 512MB + nginx + UBC page cache for hot articles (~4–6GB effective) + OS 1GB + headroom.
|
||||
RAM breakdown: PHP-FPM peak 1.4GB + Redis ~150MB + nginx + OS ~1GB + **~20GB available for UBC page cache**. With 20GB of UBC headroom, the entire nginx fastcgi_cache working set lives in RAM regardless of what is on disk — HDD latency becomes irrelevant for cached pages. Cold cache startup and log writes (sequential) are the only HDD operations that matter.
|
||||
|
||||
HDD is acceptable for the web node. The fastcgi_cache working set for a news site fits in UBC (RAM). HDD latency only affects cold cache startup and log writes (sequential). The CPU and PHP-FPM worker slots are the actual bottleneck, not disk.
|
||||
|
||||
### transilvan-new (DB VM on SSD host)
|
||||
### decebal (DB VM on SSD host — sole VM)
|
||||
|
||||
| Parameter | Value |
|
||||
|---|---|
|
||||
| vCPU | 4 |
|
||||
| RAM | 26GB |
|
||||
| vCPU | 6 |
|
||||
| RAM | 30GB |
|
||||
| Disk 1 — OS | 20GB virtual (SSD-backed) |
|
||||
| Disk 2 — ZFS data pool | 100GB virtual (SSD-backed) |
|
||||
| Total disk | 120GB — fits within 130GB available, 10GB buffer for Proxmox overhead |
|
||||
| Balloon | **Disabled** — memory ballooning must not reclaim InnoDB buffer pool RAM |
|
||||
|
||||
RAM breakdown: innodb_buffer_pool_size 20GB + MySQL overhead 2GB + OS 4GB.
|
||||
RAM breakdown: innodb_buffer_pool_size 26GB + MySQL overhead ~2GB + OS ~2GB. Decebal is the sole VM on its host — 30GB allocation leaves 2GB for the Proxmox host OS, which is the practical minimum.
|
||||
|
||||
6 vCPU (from 8 logical CPUs on host) gives MySQL adequate threads for InnoDB background I/O, parallel queries, and connection handling while leaving 2 threads for Proxmox.
|
||||
|
||||
**Disk sizing rationale:** FreeBSD base installs to ~2GB; 20GB for the OS disk is generous for binaries, ports tree fragments, and logs. The 100GB ZFS data pool provides: 9.6GB current dataset (likely 6–7GB after lz4 compression), 7 days of compressed mysqldumps (~4GB each = ~28GB), binlog rotation buffer (expire_logs_days = 3), and substantial growth headroom at the current data trajectory.
|
||||
|
||||
@@ -230,21 +230,21 @@ Both virtual disks originate from the same physical SSD pool in Proxmox. Separat
|
||||
|
||||
## VM Provisioning (Proxmox)
|
||||
|
||||
### 1. Download FreeBSD 14.2 ISO on each Proxmox host
|
||||
### 1. Download FreeBSD 15.0 ISO on each Proxmox host
|
||||
|
||||
```sh
|
||||
wget -P /var/lib/vz/template/iso/ \
|
||||
https://download.freebsd.org/releases/amd64/amd64/ISO-IMAGES/15.0/FreeBSD-15.0-RELEASE-amd64-disc1.iso
|
||||
```
|
||||
|
||||
### 2. Create dracula-new (run on the HDD host)
|
||||
### 2. Create zamolxis / ID 900 (run on the HDD host)
|
||||
|
||||
Via CLI:
|
||||
```sh
|
||||
qm create 200 \
|
||||
--name dracula-new \
|
||||
--memory 14336 \
|
||||
--balloon 14336 \
|
||||
qm create 900 \
|
||||
--name zamolxis \
|
||||
--memory 24576 \
|
||||
--balloon 24576 \
|
||||
--cores 6 \
|
||||
--cpu host \
|
||||
--machine q35 \
|
||||
@@ -261,24 +261,24 @@ qm create 200 \
|
||||
|
||||
Via UI:
|
||||
```
|
||||
General → Name: dracula-new
|
||||
General → Name: zamolxis
|
||||
OS → FreeBSD (other), ISO: FreeBSD-15.0-RELEASE-amd64-disc1.iso
|
||||
System → Machine: q35, BIOS: OVMF (UEFI), Qemu Agent: ✓
|
||||
Disks → VirtIO SCSI, 80GB, Cache: None
|
||||
CPU → 6 cores, Type: host
|
||||
Memory → 14336 MB
|
||||
Memory → 24576 MB
|
||||
Network → VirtIO, vmbr0
|
||||
```
|
||||
|
||||
### 3. Create transilvan-new (run on the SSD host)
|
||||
### 3. Create decebal / ID 901 (run on the SSD host — sole VM)
|
||||
|
||||
```sh
|
||||
# VM with OS disk
|
||||
qm create 201 \
|
||||
--name transilvan-new \
|
||||
--memory 26624 \
|
||||
qm create 901 \
|
||||
--name decebal \
|
||||
--memory 30720 \
|
||||
--balloon 0 \
|
||||
--cores 4 \
|
||||
--cores 6 \
|
||||
--cpu host \
|
||||
--machine q35 \
|
||||
--bios ovmf \
|
||||
@@ -292,7 +292,7 @@ qm create 201 \
|
||||
--agent enabled=1
|
||||
|
||||
# Add second disk for ZFS data pool
|
||||
qm set 201 --scsi1 local:100,format=raw,discard=on,ssd=1
|
||||
qm set 901 --scsi1 local:100,format=raw,discard=on,ssd=1
|
||||
```
|
||||
|
||||
`--balloon 0` disables memory ballooning on the DB VM. This is required — ballooning can silently reclaim pages from the InnoDB buffer pool under host memory pressure.
|
||||
@@ -302,7 +302,7 @@ qm set 201 --scsi1 local:100,format=raw,discard=on,ssd=1
|
||||
```
|
||||
Welcome screen → Install
|
||||
Keymap → your preference
|
||||
Hostname → dracula-new (or transilvan-new)
|
||||
Hostname → zamolxis (or decebal)
|
||||
Distribution → base, kernel (nothing else)
|
||||
Partitioning → Auto (ZFS)
|
||||
Pool type → stripe (single disk)
|
||||
@@ -339,13 +339,13 @@ service qemu-guest-agent start
|
||||
# Join Tailscale network
|
||||
sysrc tailscaled_enable=YES
|
||||
service tailscaled start
|
||||
tailscale up --hostname=dracula-new # or transilvan-new
|
||||
tailscale up --hostname=zamolxis # or decebal
|
||||
|
||||
# Note the assigned Tailscale IP — plug into pf.conf and wp-config placeholders
|
||||
tailscale ip -4
|
||||
```
|
||||
|
||||
After both VMs have Tailscale IPs, replace all `<dracula-new Tailscale IP>` and `<transilvan-new Tailscale IP>` placeholders throughout this document and in all config files.
|
||||
After both VMs have Tailscale IPs, replace all `<zamolxis Tailscale IP>` and `<decebal Tailscale IP>` placeholders throughout this document and in all config files.
|
||||
|
||||
---
|
||||
|
||||
@@ -416,7 +416,7 @@ ssh -i /root/.ssh/id_ed25519 -p 79 root@transilvan \
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — DB Node (transilvan-new)
|
||||
## Phase 1 — DB Node (decebal)
|
||||
|
||||
### 1.1 FreeBSD base + ZFS
|
||||
|
||||
@@ -444,10 +444,10 @@ sysrc mysql_dbdir=/var/db/mysql
|
||||
`/usr/local/etc/mysql/my.cnf`:
|
||||
```ini
|
||||
[mysqld]
|
||||
bind-address = <transilvan-new Tailscale IP>
|
||||
bind-address = <decebal Tailscale IP>
|
||||
datadir = /var/db/mysql
|
||||
socket = /tmp/mysql.sock
|
||||
innodb_buffer_pool_size = 24G
|
||||
innodb_buffer_pool_size = 26G
|
||||
innodb_log_file_size = 1G
|
||||
innodb_flush_log_at_trx_commit = 1
|
||||
innodb_flush_method = O_DIRECT
|
||||
@@ -463,7 +463,7 @@ skip-name-resolve
|
||||
```
|
||||
ext_if = "vtnet0"
|
||||
ts_if = "tailscale0"
|
||||
web_ts = "<dracula-new Tailscale IP>"
|
||||
web_ts = "<zamolxis Tailscale IP>"
|
||||
|
||||
set skip on lo0
|
||||
block all
|
||||
@@ -483,7 +483,7 @@ service pf start
|
||||
pkg install tailscale
|
||||
sysrc tailscaled_enable=YES
|
||||
service tailscaled start
|
||||
tailscale up --hostname=transilvan-new
|
||||
tailscale up --hostname=decebal
|
||||
```
|
||||
|
||||
### 1.5 DB restore
|
||||
@@ -494,14 +494,14 @@ tailscale up --hostname=transilvan-new
|
||||
ssh root@transilvan \
|
||||
"mysqldump -S /tmp/mysqld.sock --single-transaction \
|
||||
--routines --triggers --events sql_sibiuindepen" \
|
||||
| ssh root@transilvan-new "mysql -u root sql_sibiuindepen"
|
||||
| ssh root@decebal "mysql -u root sql_sibiuindepen"
|
||||
|
||||
# Create app user (use same password as current DB_PASSWORD in wp-config)
|
||||
mysql -u root -e "
|
||||
CREATE USER 'sql_sibiuindepen'@'<dracula-new Tailscale IP>'
|
||||
CREATE USER 'sql_sibiuindepen'@'<zamolxis Tailscale IP>'
|
||||
IDENTIFIED BY '<password>';
|
||||
GRANT ALL ON sql_sibiuindepen.* TO
|
||||
'sql_sibiuindepen'@'<dracula-new Tailscale IP>';
|
||||
'sql_sibiuindepen'@'<zamolxis Tailscale IP>';
|
||||
FLUSH PRIVILEGES;"
|
||||
```
|
||||
|
||||
@@ -528,7 +528,7 @@ Crontab:
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Web Node (dracula-new)
|
||||
## Phase 2 — Web Node (zamolxis)
|
||||
|
||||
### 2.1 Base packages
|
||||
|
||||
@@ -703,7 +703,7 @@ service pf start
|
||||
pkg install tailscale
|
||||
sysrc tailscaled_enable=YES
|
||||
service tailscaled start
|
||||
tailscale up --hostname=dracula-new
|
||||
tailscale up --hostname=zamolxis
|
||||
```
|
||||
|
||||
### 2.7 rsync web files
|
||||
@@ -726,7 +726,7 @@ Two changes on the new node only:
|
||||
|
||||
```php
|
||||
// 1. Update DB_HOST to new transilvan Tailscale IP
|
||||
define( 'DB_HOST', '<transilvan-new Tailscale IP>' );
|
||||
define( 'DB_HOST', '<decebal Tailscale IP>' );
|
||||
|
||||
// 2. WP_CACHE stays true for Redis Object Cache drop-in
|
||||
// Remove the W3TC comment, keep the constant:
|
||||
@@ -851,17 +851,17 @@ curl -s https://connect.facebook.net/ro_RO/sdk.js > ${WEBROOT}/fb-sdk-ro.js
|
||||
|
||||
## Phase 3 — Zero-downtime Cutover
|
||||
|
||||
### Pre-cutover checklist (run on dracula-new before touching NPM)
|
||||
### Pre-cutover checklist (run on zamolxis before touching NPM)
|
||||
|
||||
```sh
|
||||
# 1. Site responds via new stack directly
|
||||
curl -sk -o /dev/null -w "%{http_code}" \
|
||||
http://<dracula-new Tailscale IP>/ \
|
||||
http://<zamolxis Tailscale IP>/ \
|
||||
-H "Host: sibiuindependent.ro"
|
||||
# Expected: 200
|
||||
|
||||
# 2. DB connection live
|
||||
mysql -h <transilvan-new Tailscale IP> \
|
||||
mysql -h <decebal Tailscale IP> \
|
||||
-u sql_sibiuindepen -p sql_sibiuindepen \
|
||||
-e "SELECT COUNT(*) FROM wp_posts WHERE post_status='publish';"
|
||||
|
||||
@@ -872,7 +872,7 @@ wp --path=/var/www/sibiuindependent.ro --allow-root redis-cache status
|
||||
php85 -m | grep -E "imagick|redis|pdo_mysql|opcache|intl|soap|sodium"
|
||||
|
||||
# 5. nginx fastcgi_cache working — second request should be HIT
|
||||
curl -sI http://<dracula-new Tailscale IP>/ -H "Host: sibiuindependent.ro" \
|
||||
curl -sI http://<zamolxis Tailscale IP>/ -H "Host: sibiuindependent.ro" \
|
||||
| grep X-Cache-Status
|
||||
# First request: MISS, second request: HIT
|
||||
```
|
||||
@@ -893,11 +893,11 @@ T-2 Final DB dump and import:
|
||||
ssh root@transilvan \
|
||||
"mysqldump -S /tmp/mysqld.sock --single-transaction \
|
||||
--routines --triggers --events sql_sibiuindepen" \
|
||||
| ssh root@transilvan-new "mysql -u root sql_sibiuindepen"
|
||||
| ssh root@decebal "mysql -u root sql_sibiuindepen"
|
||||
|
||||
T-3 Switch NPM upstream:
|
||||
old: 100.99.157.56 (dracula Tailscale IP)
|
||||
new: <dracula-new Tailscale IP>
|
||||
new: <zamolxis Tailscale IP>
|
||||
(single upstream change in NPM — no DNS TTL involved, instant)
|
||||
|
||||
T-4 Smoke test:
|
||||
@@ -932,11 +932,11 @@ zfs snapshot data/mysql@post-migration-$(date +%Y%m%d)
|
||||
## Open Items at Time of Planning
|
||||
|
||||
- [ ] Confirm new Tailscale hostnames for both nodes (determines pf rules and wp-config DB_HOST)
|
||||
- [ ] Confirm NPM node Tailscale IP (determines pf rule on dracula-new)
|
||||
- [ ] Confirm NPM node Tailscale IP (determines pf rule on zamolxis)
|
||||
- [x] PHP 8.5 — binary package on FreeBSD 15.0, `pkg install php85`. No compilation. All extensions confirmed available.
|
||||
- [ ] Redis Object Cache plugin — already in plugins dir or fresh install needed
|
||||
- [ ] W3TC features in use beyond caching: minify? If yes, switch to standalone nginx-based minification or keep W3TC minify only with nginx page cache
|
||||
- [ ] ZFS pool disk — confirm second disk available on transilvan-new VM
|
||||
- [ ] ZFS pool disk — confirm second disk available on decebal VM
|
||||
- [ ] MySQL 8.4 vs MariaDB 11.4 LTS — plan targets MySQL 8.4; revisit if preferred
|
||||
- [x] Beszel and Telegraf — dropped. Proxmox native VM monitoring is sufficient.
|
||||
- [x] Redis placement — local to dracula-new (unix socket). No 3rd host. WordPress object cache uses 50–150MB RAM; a dedicated VM would cost more resources than Redis itself consumes. A separate Redis host is only justified when scaling to multiple web nodes sharing a single cache.
|
||||
- [x] Redis placement — local to zamolxis (unix socket). No 3rd host. WordPress object cache uses 50–150MB RAM; a dedicated VM would cost more resources than Redis itself consumes. A separate Redis host is only justified when scaling to multiple web nodes sharing a single cache.
|
||||
|
||||
Reference in New Issue
Block a user