The checks, commands, and recovery steps I keep for when something breaks.
4 notes · Current setups, past observations, and future plans stay as recorded.
Procedures / Note 01
Proxmox Recovery
In this note
Recovery and validation procedure for the HP ProDesk 600 G4 Proxmox host after reboot, outage, certificate problems, VM startup failures, or other host-level issues.
Do not expect every service to recover at exactly the same second.
Controlled Reboot Already Tested
A controlled reboot has already been performed successfully:
sudo reboot
During the test:
Proxmox restarted
VM100 became temporarily unavailable
VM102 became temporarily unavailable
Jellyfin went down temporarily
Gluetun Push heartbeat stopped
NPM went down
Portainer went down
Uptime Kuma detected application outages
VMs started automatically
Docker started automatically
Applications returned automatically
Beszel agents reconnected
Uptime Kuma reported recovery
No manual application startup was required.
Important Test Limitation
The completed test was a:
Graceful controlled reboot
It was not an abrupt power-loss test.
Therefore:
Graceful reboot recovery
→ VERIFIED
Unexpected hard power loss
→ Not yet intentionally tested
Do not document abrupt-power recovery as proven until it has actually been tested.
Proxmox Monitor Timing
During the previous reboot test, application monitors went down while the Proxmox host monitor remained Up.
This occurred because the original Proxmox monitor retry window was long enough for the physical host to reboot before Kuma officially declared it Down.
The Proxmox monitor was then tightened to approximately:
Use this procedure when a Proxmox VM needs to be restored after:
VM corruption
Failed update
Broken Docker configuration
Accidental configuration damage
Failed migration
Storage problem
VM deletion
Recovery testing
Returning to a known-good state
The goal is to restore the VM without creating:
Duplicate VM IDs
Duplicate IP addresses
Duplicate hostnames
Duplicate Tailscale identities
Conflicting Docker services
Current VM Inventory
Current Proxmox VM layout:
VM100 - Jellyfin
Network: Private LAN
Role: Always-on media server
VM101 - OpenLabFrame Dev
Network: Private LAN
Role: On-demand development VM
VM102 - Management
Network: Private LAN
Role: Always-on NPM / Portainer / management VM
Always verify which VM is being restored before starting.
Important Principle
A restore is not complete when Proxmox says:
Restore finished
A complete restore means:
VM exists
↓
VM boots
↓
Network identity is correct
↓
Guest OS works
↓
Docker/services work
↓
Monitoring reconnects
↓
Dependent services recover
Before Restoring
Before making any changes, identify:
Which VM?
Which backup?
Which VMID?
Which storage?
Which network identity?
Which services depend on it?
Do not restore first and investigate later.
Step 1 - Identify the VM
Determine the correct VM:
100
101
or
102
From the Proxmox host:
qm list
Expected entries:
100
101
102
Record whether the target VM currently exists.
Step 2 - Check Current VM State
For VM100:
qm status 100
For VM101:
qm status 101
For VM102:
qm status 102
If the VM still exists and is running:
Do not restore over it immediately.
First determine whether:
It should be stopped
It should be backed up
It should be renamed/replaced
A restore test should use another VMID
Step 3 - Identify the Backup
In the Proxmox web interface:
Datacenter
→ Storage
→ Backups
Locate the correct backup for the VM.
Verify:
VM ID
Backup timestamp
Backup size
Storage location
Backup type
Do not rely only on the newest timestamp if the newest backup may contain the problem being recovered from.
Backup Selection Rule
Choose:
Newest known-good backup
not automatically:
Newest backup
If a recent update broke the VM, the immediately preceding backup may be the correct recovery point.
Step 4 - Decide Restore Strategy
There are two common restore strategies.
Replace Original VM
Use this when:
Original VM is broken
Original identity should remain
Original VMID should be preserved
Example:
VM100 backup
→ Restore as VM100
Only do this after ensuring the old VM100 will not conflict.
Restore to Temporary VMID
Use this when:
Testing backup integrity
Comparing configurations
Recovering files
Validating a restore before replacement
Example:
VM100 backup
→ Restore temporarily as VM900
This can be safer for validation.
However, a temporary clone/restore must not be allowed to create network conflicts.
Duplicate Identity Warning
A restored VM may contain the same:
Static IP
Hostname
SSH host keys
Tailscale state
Docker configuration
Application data
as the original.
If both are powered on simultaneously:
Network conflicts may occur.
Never boot both copies blindly.
Static IP Conflict Example
Suppose the original VM100 is still online:
VM100
<private Jellyfin host>
and a restored test copy also boots with:
<private Jellyfin host>
then:
Two machines
→ Same IP
→ Unpredictable connectivity
Therefore test restores should remain isolated until their networking is changed.
Step 5 - Stop Original VM if Replacing It
Example for VM100:
qm shutdown 100
Check:
qm status 100
Expected:
status: stopped
If the guest does not shut down cleanly, investigate before forcing it.
Avoid:
qm stop 100
unless a hard stop is actually necessary.
Step 6 - Preserve Current VM if Needed
If the existing VM still contains useful data or configuration, consider keeping it temporarily before replacement.
Options may include:
Backup current VM
Clone current VM
Rename documentation
Leave powered off temporarily
The exact method depends on the failure situation.
Do not start it yet if there may still be a duplicate network identity.
Step 9 - Inspect VM Configuration
Before startup:
qm config <VMID>
Example:
qm config 100
Review important settings such as:
Memory
CPU cores
Boot order
Disks
Network adapter
Startup behavior
Machine type
BIOS/UEFI
PCI/device passthrough
VM100 Special Check - Intel GPU
VM100 depends on Intel UHD 630 / Quick Sync access.
If restoring VM100, verify the required hardware/device configuration has also returned.
Check:
qm config 100
Look for the known-good graphics/device assignment.
After boot, verify inside the guest:
ls -l /dev/dri
Do not assume hardware acceleration survived the restore until verified.
Step 10 - Confirm Startup Behavior
Expected VM roles:
VM100
→ Always on
VM101
→ On-demand
VM102
→ Always on
A restore should not unintentionally change those roles.
VM101 should not be converted to automatic always-on operation unless deliberately desired.
Step 11 - Start the Restored VM
Example:
qm start 100
Then:
qm status 100
Expected:
status: running
Give the guest OS time to boot.
Step 12 - Verify Network Reachability
VM100
ping <private Jellyfin host>
VM101
ping <private development host>
VM102
ping <private management host>
Expected:
Reply
If ping fails:
Do not immediately rebuild the VM.
Check:
Guest boot
Network adapter
Bridge assignment
Static IP
Interface naming
Router/LAN
Duplicate IP conflict
Step 13 - SSH Test
VM100
ssh <jellyfin-alias>
VM101
ssh <development-alias>
VM102
ssh <management-alias>
If SSH reports a host-key mismatch after a legitimate restore, first confirm that the restored VM is truly the expected system before changing known-host entries.
Do not ignore SSH identity warnings automatically.
Step 14 - Check Guest Identity
Inside the restored VM:
hostname
Verify it matches the expected role.
Examples:
VM100
→ Jellyfin/media host identity
VM101
→ Open Lab Frame development host
VM102
→ <private-management-hostname>
Also verify:
ip addr
or:
hostname -I
Confirm the expected private network identity.
Step 15 - Check System Health
Inside Linux:
uptime
Then:
systemctl --failed
Unexpected failures should be investigated before declaring recovery complete.
Step 16 - Check Docker
For VMs that run Docker:
docker ps
Also:
docker ps -a
The second command reveals containers that exist but failed to start.
Remember that monitor recovery can lag behind actual service startup by one or more heartbeat intervals.
Restore Test Strategy
A backup should ideally be proven through a restore test.
A safe test process is:
Backup
↓
Restore to temporary VMID
↓
Keep networking isolated
↓
Boot
↓
Verify filesystem / services
↓
Power off
↓
Delete test VM
This validates backup integrity without replacing production.
Temporary Restore Warning
Do not boot a restored production copy onto the normal LAN if it still has the production:
IP
Tailscale identity
Hostname
Application identity
unless the original is offline.
Tailscale Duplicate Warning
Tailscale state may be included inside the restored VM's filesystem.
A test restore of VM100 could therefore appear as the same Tailscale node.
For isolated restore testing:
Avoid unrestricted network connectivity
until identity behavior is understood.
Backup Age Considerations
An older VM backup may restore:
Older Docker images
Older application databases
Older configs
Older SSH state
Older packages
Older certificates
Older Tailscale state
After restoration, do not immediately mass-update everything.
First verify the restored state works.
Then update deliberately.
Application Data May Be External
A VM backup may not necessarily contain every piece of application data if some storage is mounted externally.
Always identify whether the application uses:
VM-local disk
Host mount
NAS mount
Network share
Passthrough disk
External volume
before assuming the Proxmox backup contains everything.
VM100 Media Data
Jellyfin's application and automation environment is inside VM100, but large media data may eventually live separately on the future NAS Compute Build.
In that future architecture:
Restoring VM100
≠
Restoring the media library storage
These should be treated as separate recovery layers.
Restore Does Not Mean Rollback Everything
If only one application is broken, a full VM restore may be excessive.
Recovery should move from least destructive to most destructive:
Restart service
↓
Repair container/config
↓
Restore application data
↓
Restore VM
Use full VM restore when the entire guest state needs to be rolled back.
Do Not Restore Because of a Monitoring Failure Alone
Example:
Beszel says VM100 offline
does not automatically mean the VM needs restoration.
First verify:
Ping
SSH
Docker
Application
Agent
The problem may only be the monitoring agent.
Do Not Restore Because NPM Is Down
If:
This example was not included in the public notes.
fails but:
<private service endpoint>
The problem may only be:
NPM
DNS
TLS
A VM restore would be unnecessary.
Restore Decision Tree
Service broken?
↓
Is VM reachable?
├── Yes
│ ↓
│ Check application / Docker
│
└── No
↓
Is VM running in Proxmox?
├── Yes
│ ↓
│ Check guest/network
│
└── No
↓
Try normal startup
↓
Still unusable?
↓
Consider restore
Post-Restore Security Checks
After restore, verify:
SSH still uses expected key authentication
No unexpected passwords were re-enabled
Tailscale identity is correct
Application users/permissions are correct
Reverse proxy configuration is correct
Certificates are valid
No old secrets/configurations unintentionally returned
A backup may reintroduce older security settings.
Post-Restore Update Strategy
After confirming the restored VM is stable:
1. Verify service health
2. Verify data
3. Verify networking
4. Verify monitoring
5. Take a fresh backup if appropriate
6. Then consider updates
Avoid updating everything before confirming that the restore itself succeeded.
Recovery Complete - VM100
VM100 recovery is complete when:
VM100 running
<private Jellyfin host> reachable
SSH works
Docker works
Jellyfin responds
Media libraries present
Quick Sync works
Gluetun healthy
ARR Stack services healthy
Tailscale healthy
<private Jellyfin Tailscale endpoint> correct
Public Jellyfin works
Beszel reports
Uptime Kuma green
Recovery Complete - VM101
VM101 recovery is complete when:
VM boots when requested
<private development host> reachable
SSH works
Git repository present
main branch correct
Node/npm usable
npm ci works
npm run build works
dist/ generated
Development preview works
<private development hostname> works while VM is on
Recovery Complete - VM102
VM102 recovery is complete when:
VM102 running
<private management host> reachable
SSH works
Docker works
NPM responds
Portainer responds
Private proxy hosts work
Wildcard HTTPS works
Beszel agent reports
Uptime Kuma monitors green
Minimal Restore Checklist
1. Identify VM and known-good backup
2. Check whether original VM still exists
3. Prevent duplicate IP/identity conflicts
4. Stop original VM if replacing it
5. Restore backup
6. Check qm config
7. Verify network/device settings
8. Start VM
9. Ping expected IP
10. SSH into guest
11. Check systemctl --failed
12. Check Docker
13. Validate application
14. Validate Tailscale where applicable
15. Validate Quick Sync for VM100
16. Validate NPM/Portainer for VM102
17. Validate build environment for VM101
18. Check Beszel
19. Check Uptime Kuma
20. Confirm dependent services work
Things Not to Do
Avoid:
Restoring over a running production VM blindly
Booting two copies with the same static IP
Booting two copies with the same Tailscale identity
Deleting the original VM before confirming backup validity
Assuming a completed restore means applications are healthy
Safe troubleshooting procedure for Docker-based homelab services without accidentally deleting persistent data or turning a small container problem into a larger outage.
Permission denied
Connection refused
Address already in use
File not found
Database locked
Authentication failure
DNS resolution failure
Network unreachable
Invalid configuration
Read-only filesystem
Out of space
Do not assume every warning is fatal.
Look for the first error around the time the container stopped.
Is the host/container running?
How much resource is it using?
Beszel can help identify:
CPU spikes
RAM pressure
Disk growth
Container restart state
Host temperature
Network traffic
But:
Beszel Health: None
does not prove a service is broken.
Common Problem - Container Is Up but Service Is Down
Possible causes:
Application still starting
Application failed internally
Port not bound
Wrong configuration
Database problem
Dependency unavailable
Reverse proxy misconfigured
Check logs and direct backend response.
Common Problem - Service Works Locally Only
Example:
<loopback>:<SERVICE_PORT>
→ works
<private Pi 5 host>:<SERVICE_PORT>
→ fails
provided persistent data is properly mounted and backed up.
Things Not to Do
Avoid:
docker compose down -v as a generic fix
Deleting volumes without backups
chmod -R 777
docker system prune -a without understanding the impact
Recreating every container because one service failed
Editing multiple Compose projects simultaneously
Updating images during unrelated troubleshooting
Resetting Tailscale for a Docker-only problem
Changing Pi-hole for an application-only problem
Rebooting Proxmox because one container failed
Deleting databases because of startup errors
Exposing services publicly just to make access easier
Minimal Docker Troubleshooting Checklist
1. Confirm host is reachable
2. SSH to correct host
3. Check Docker service
4. Run docker ps
5. Run docker ps -a
6. Read container logs
7. Check exit code / restart count
8. Check Compose project
9. Validate docker compose config
10. Check ports / bindings
11. Test backend directly
12. Test from the actual source host
13. Check Docker networking
14. Check mounts
15. Check disk space
16. Check permissions
17. Restart only affected service if appropriate
18. Recreate only if configuration requires it
19. Check Uptime Kuma
20. Check Beszel
Host healthy
Docker engine healthy
Expected container running
Logs show no critical repeating failure
Persistent data present
Correct ports bound
Direct backend works
Dependencies work
Proxy works if applicable
DNS works if applicable
Remote route works if applicable
Uptime Kuma reports UP
Beszel reports expected status
Use this procedure when the Proxmox web interface has a certificate-related problem such as:
Browser certificate warning
Expired certificate
Wrong certificate being served
Certificate hostname mismatch
Certificate/private-key mismatch
ACME renewal problem
Certificate replacement after recovery
pveproxy serving an unexpected certificate
The trusted Proxmox hostname is:
<private Proxmox hostname>
Normal trusted interface:
<private Proxmox URL>
Direct recovery interface:
<private service endpoint>
Current Proxmox Host
Physical system:
HP ProDesk 600 G4 SFF
Proxmox hostname:
Proxmox host
LAN IP:
<private Proxmox host>
Expected shell:
<admin-user>@<proxmox-host>
Current Certificate State
The trusted certificate for:
<private Proxmox hostname>
has already been restored and validated successfully.
ACME is also configured for the Proxmox hostname.
This procedure exists so that future certificate work can be performed safely without repeating risky trial-and-error changes.
Important Principle
A certificate problem does not automatically mean Proxmox itself is broken.
For example:
<private service endpoint>
may still work while:
<private Proxmox URL>
shows a certificate problem.
That means the problem may only exist at the:
TLS / certificate layer
rather than:
Proxmox host
VMs
Networking
Applications
Recovery Order
Use this order:
Confirm host is reachable
↓
Confirm port <Proxmox management port> is listening
↓
Inspect currently served certificate
↓
Check hostname / expiration
↓
Verify replacement certificate
↓
Verify replacement private key
↓
Verify certificate and key match
↓
Back up current working files
↓
Install only if required
↓
Restart / reload pveproxy
↓
Verify served certificate
↓
Test trusted hostname
Do not begin by overwriting certificate files.
Phase 1 - Confirm Proxmox Is Actually Running
From Windows:
ping <private Proxmox host>
Expected:
Reply from <private Proxmox host>
Then test the direct interface:
<private service endpoint>
If the direct interface loads, the host and web service are likely operational.
Phase 2 - Check Port <Proxmox management port>
From the Proxmox shell:
ss -ltnp | grep <Proxmox management port>
Expected:
A listener on <Proxmox management port>
If nothing is listening on <Proxmox management port>, investigate:
pveproxy
before working on certificate replacement.
Phase 3 - Check pveproxy
systemctl status pveproxy --no-pager
Expected:
active (running)
Also:
systemctl status pvedaemon pvestatd --no-pager
These help confirm that the Proxmox management stack itself is healthy.
Phase 4 - Inspect the Certificate Currently Being Served
Keep restrictive permissions on anything containing a private key.
Private-Key Permissions
A private key should never become broadly readable.
After copying/replacing a key, confirm permissions with:
ls -l <KEY_FILE>
Do not make a private key world-readable just to solve a permissions problem.
Install Only After Validation
Before any replacement, confirm all of the following:
Certificate readable
Private key readable
Hostname correct
Certificate not expired
Certificate/key hashes match
Current files backed up
Recovery path available
Only then should certificate installation proceed.
Restarting pveproxy
After a legitimate certificate update:
systemctl restart pveproxy
Then:
systemctl status pveproxy --no-pager
Expected:
active (running)
If pveproxy Does Not Start
Immediately check:
journalctl -u pveproxy -n 100 --no-pager
Possible causes include:
Invalid certificate
Invalid private key
Certificate/key mismatch
Wrong file permissions
Incorrect path
Malformed PEM content
Do not continue changing additional files until the error is understood.
Verify Port <Proxmox management port> After Restart