# Service Startup Order

## Purpose

This page documents the preferred startup and validation order after:

<div id="bkmrk-a-power-interruption" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- A power interruption.
- A planned Proxmox shutdown.
- A Proxmox reboot.
- Network maintenance.
- Storage maintenance.
- A full-stack restart.

</div>Starting services in dependency order reduces DNS, OIDC, proxy, and monitoring failures.

<div id="bkmrk-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Preferred Startup Order

<div id="bkmrk-order-service-1-prox" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;"><div aria-expanded="false" class="___5wvz9a0 ftgm304 f1oy3dpc fm6nont f48hbct" data-stable-ignore="true" data-tabster="{"restorer":{"type":1}}" role="presentation" tabindex="0"><div class="___1dmoc29 f10pi13n ftgm304 f1enuhaj fdclmfp f1nbblvp fat0sn4 f1ov4xf1 fekwl8i f1lmfglv f1oz7aqm f1abmfm4 f1w619qj f16h0jq8"><table class="___1vyiefv f1ddd56o f16vktn6 f1ahpp82 f11qra4b f1uinfot fibjyge fvueend f9yszdx f1fu4s3n f3l3pb3 f10ghnd0 f8fmt76 fjvbh62 f1qrqxae f1vw5qpk fc02sbz fxawf59 fymf513 f1aoyrul f1el8yx3 f1pymoxg f1ofu761 fe6itr f7coize f1794535 f1o0pw0q fbjjl9v fk1v6el f16pyhcb f1ixlhx9 f12zef0i flu5r5u f19haqzy f1owmcxx f1oddm8q f1004tna fcoaxci fh0ee9u f15v23i2 f1dmj53 f1r1gcv9 f14z1veh ffufd3x f1ypplot f1660cg"><tbody><tr><th>Order</th><th>Service</th></tr><tr><td>1</td><td>Proxmox VE</td></tr><tr><td>2</td><td>Pi-hole</td></tr><tr><td>3</td><td>WireGuard Gateway</td></tr><tr><td>4</td><td>Authentik database and Redis</td></tr><tr><td>5</td><td>Authentik server and worker</td></tr><tr><td>6</td><td>Traefik</td></tr><tr><td>7</td><td>Uptime Kuma</td></tr><tr><td>8</td><td>Nextcloud AIO</td></tr><tr><td>9</td><td>Vikunja</td></tr><tr><td>10</td><td>BookStack</td></tr><tr><td>11</td><td>Plex, when deployed</td></tr><tr><td>12</td><td>Game server, when deployed</td></tr><tr><td>13</td><td>Navidrome, when deployed</td></tr></tbody></table>

</div></div>---

</div>## 1. Proxmox VE

Confirm that the hypervisor completed booting.

Validate:

<div id="bkmrk-management-ip-is-192" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Management IP is `192.168.2.254`.
- Network bridge is active.
- Storage pools are active.
- `pveproxy` is active.
- TCP port 8006 is listening.
- Backup HDD is mounted.

</div>Useful checks:

<div id="bkmrk-systemctl-is-active-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `systemctl is-active pveproxy`
- `ss -lntp | grep ':8006'`
- `pvesm status`
- `findmnt /mnt/pve/pve-backup`

</div>Do not start troubleshooting application guests until required Proxmox storage is active.

<div id="bkmrk--1" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 2. Pi-hole

Pi-hole should start before services that require split DNS.

Validate:

<div id="bkmrk-pi-hole-owns-192.168" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Pi-hole owns `192.168.2.65`.
- TCP port 53 responds.
- UDP port 53 responds.
- Internal records resolve.
- Public records resolve.

</div>Test:

`nslookup portal.bytek.ca 192.168.2.65`

Expected result:

<div id="bkmrk-192.168.2.182" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `192.168.2.182`

</div>Test:

`nslookup google.com 192.168.2.65`

Expected result:

<div id="bkmrk-a-public-address." style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- A public address.

</div>Containers that started before Pi-hole may need to be restarted after Pi-hole becomes healthy.

<div id="bkmrk--2" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 3. WireGuard Gateway

Validate:

<div id="bkmrk-gateway-owns-192.168" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Gateway owns `192.168.2.64`.
- WireGuard interface exists.
- VPS peer appears.
- Recent handshake exists.
- Transfer counters increase.
- IPv4 forwarding is enabled.
- Firewall and NAT rules loaded.

</div>Useful checks:

<div id="bkmrk-sudo-wg-show-sysctl-" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `sudo wg show`
- `sysctl net.ipv4.ip_forward`
- `ip route`
- `sudo ufw status numbered`

</div>The WireGuard tunnel must be working before external application access can recover.

<div id="bkmrk--3" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 4. Authentik Database and Redis

Authentik depends on PostgreSQL and Redis.

Validate the Authentik Compose stack using:

`sudo docker compose ps`

Confirm:

<div id="bkmrk-postgresql-is-runnin" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- PostgreSQL is running.
- Redis is running.
- Persistent data is available.
- No storage or permission errors appear.

</div>Do not treat Authentik as ready merely because the server container has started.

<div id="bkmrk--4" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 5. Authentik Server and Worker

After PostgreSQL and Redis are healthy, validate:

<div id="bkmrk-authentik-server.-au" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Authentik server.
- Authentik worker.
- Direct readiness endpoint.
- OIDC discovery endpoint.
- Embedded outpost.

</div>Direct readiness should return HTTP 200.

The outpost ping should return HTTP 204.

OIDC-dependent applications should not be treated as healthy until Authentik is ready.

<div id="bkmrk--5" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 6. Traefik

Traefik depends on:

<div id="bkmrk-pi-hole-for-its-conf" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Pi-hole for its configured Docker DNS.
- Authentik for ForwardAuth and Proxy Providers.
- WireGuard for public ingress.

</div>Validate:

<div id="bkmrk-traefik-vm-owns-192." style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Traefik VM owns `192.168.2.182`.
- Docker is active.
- Traefik container is running.
- TCP port 443 is listening.
- Pi-hole DNS works inside the container.
- Dynamic routers loaded.
- Certificates are available.
- Authentik route works.

</div>Useful checks:

<div id="bkmrk-sudo-docker-compose--1" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- `sudo docker compose ps`
- `sudo docker inspect --format='DNS={{json .HostConfig.Dns}}' traefik`
- `sudo tail -n 100 /opt/traefik/logs/traefik.log`

</div>If Traefik started before Pi-hole and DNS remains broken, recreate the Traefik container after Pi-hole is healthy.

<div id="bkmrk--6" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 7. Uptime Kuma

Start monitoring after DNS, identity, and routing are operational.

Validate:

<div id="bkmrk-vm-owns-192.168.2.11" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- VM owns `192.168.2.115`.
- Docker is active.
- Container is running.
- Container health is healthy.
- Embedded database is available.
- Container DNS resolves internal hostnames.
- Dashboard route works.
- Monitors begin recovering.

</div>Do not immediately modify every failed monitor after a reboot. Allow dependencies to recover first.

<div id="bkmrk--7" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 8. Nextcloud AIO

Before starting the Nextcloud application stack, validate:

<div id="bkmrk-vm-owns-192.168.2.10" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- VM owns `192.168.2.100`.
- 500 GB data disk is attached.
- `/mnt/nextcloud-data` is mounted.
- `/mnt/nextcloud-data/ncdata` exists.
- Docker is active.
- AIO management is reachable.

</div>Then confirm:

<div id="bkmrk-postgresql.-redis.-n" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- PostgreSQL.
- Redis.
- Nextcloud.
- Apache.
- Notify Push.
- Collabora.

</div>Test:

<div id="bkmrk-tcp-port-11000.-clou" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- TCP port 11000.
- `cloud.bytek.ca`.
- Authentik login.
- File access.

</div>Do not run Nextcloud normally if the data disk is not mounted.

<div id="bkmrk--8" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 9. Vikunja

Validate:

<div id="bkmrk-vm-owns-192.168.2.12" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- VM owns `192.168.2.121`.
- Docker is active.
- PostgreSQL is healthy.
- Vikunja container is running.
- `/health` returns HTTP 200.
- Authentik login works.

</div>If the container cannot reach Authentik, confirm DNS before changing OIDC credentials.

<div id="bkmrk--9" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## 10. BookStack

Validate:

<div id="bkmrk-vm-owns-its-reserved" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- VM owns its reserved private address.
- Docker is active.
- MariaDB is running.
- BookStack is running.
- Application key is available.
- Direct backend responds.
- `docs.bytek.ca` works.
- Authentik login works.
- Existing pages open.

</div>If OIDC fails, temporarily restore standard authentication rather than rebuilding BookStack.

<div id="bkmrk--10" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Future Plex Startup

When Plex is deployed, validate:

<div id="bkmrk-plex-vm-boots.-rtx-2" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Plex VM boots.
- RTX 2060 is present.
- NVIDIA driver loads.
- `nvidia-smi` works.
- Docker has GPU access.
- Plex configuration storage is mounted.
- Media storage is mounted.
- Plex web interface responds.
- Hardware transcoding is available.

</div>Do not start Plex if expected media storage is missing.

<div id="bkmrk--11" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Future Game-Server Startup

When a game server is deployed, validate:

<div id="bkmrk-vm-owns-its-reserved-1" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- VM owns its reserved address.
- Game-data disk is mounted.
- SteamCMD or LinuxGSM files exist.
- Game server starts.
- Required game ports listen.
- World or save data loads.
- Public game-port forwarding works.
- Monitoring works.

</div>Do not expose RCON or management ports publicly without additional protection.

<div id="bkmrk--12" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Docker DNS Recovery

A recurring risk after a full power loss is that containers start before Pi-hole is ready.

Symptoms include:

<div id="bkmrk-oidc-discovery-endpo" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- OIDC discovery endpoint unreachable.
- Let’s Encrypt DNS lookup failures.
- Internal hostnames failing inside containers.
- Uptime Kuma monitors remaining down.
- Host DNS works while container DNS fails.

</div>Recovery process:

<div id="bkmrk-confirm-pi-hole.-con" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">1. Confirm Pi-hole.
2. Confirm DNS from the VM host.
3. Confirm DNS from the affected container.
4. Check the container’s explicit DNS configuration.
5. Restart the affected container.
6. Recreate the container if Docker-level DNS configuration changed.
7. Retry the failed operation.

</div>Do not regenerate application secrets because of a DNS-only failure.

<div id="bkmrk--13" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">---

</div>## Full Validation Checklist

<div id="bkmrk-proxmox-web-interfac" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- Proxmox web interface works.
- Required Proxmox storage is active.
- Backup HDD is mounted.
- Pi-hole resolves internal records.
- Pi-hole resolves public records.
- WireGuard handshake exists.
- Public VPS ingress works.
- Authentik direct readiness returns HTTP 200.
- Authentik routed readiness returns HTTP 200.
- Authentik outpost returns HTTP 204.
- Traefik routers loaded.
- Traefik certificates are available.
- Uptime Kuma is healthy.
- Nextcloud status is healthy.
- Nextcloud data disk is mounted.
- Collabora works.
- Vikunja health returns HTTP 200.
- BookStack opens existing documentation.
- OIDC login works on all configured applications.
- External access works from cellular or another remote network.

---

</div>## Document Control

<div id="bkmrk-owner%3A-bryan-gagne-p" style="font-family: 'Segoe UI'; font-size: 14px; font-style: normal; font-weight: 400; line-height: 20px;">- **Owner:** Bryan Gagne-Plante
- **Startup authority:** Proxmox VE
- **DNS dependency:** Pi-hole
- **Public-ingress dependency:** VPS and WireGuard
- **Authentication dependency:** Authentik
- **HTTPS dependency:** Traefik
- **Last verified:** YYYY-MM-DD
- **Last power-failure recovery:** YYYY-MM-DD
- **Last full-stack restart:** YYYY-MM-DD
- **Known issue:** Containers may require restart or recreation if started before Pi-hole

</div>