The Valheim world and mod manager that keeps everyone in sync.
Modding Valheim is easy. Keeping mods perfectly in sync across your server and every player? Nearly impossible. Mod managers like Thunderstore work great individually, but they don't coordinate across a group — eventually someone's client drifts out of sync and the session breaks.
PhValheim is a two-part system (server + client) that locks server and client mod configurations together. Deploy worlds with any combination of Thunderstore mods, and every player automatically gets the exact same files when they connect. No more "which version do you have?" conversations.
| One-Click Worlds | Deploy unique Valheim worlds with any combination of Thunderstore mods at the click of a button. |
| Automatic Mod Sync | Server and client mods stay in lock-step. Players always have the right files. |
| Setup Wizard | Guided first-run configuration — just start the container and follow the steps. No environment variables required. |
| Steam Authentication | Players log in with their Steam account. Per-world access control lists manage who can see and join each world. |
| Thunderstore Integration | Full Thunderstore mod catalog synced every 12 hours. Search, select, and deploy mods with dependency resolution built in. |
| Backup System | Activity-aware scheduled backups with compression (gzip/zstd), tiered retention, one-click restore, and per-world overrides. Supports separate backup volumes. |
| Live Monitoring | Real-time CPU, memory, and load metrics for every running world, visible in both the admin and public UIs. |
| AI Helper | Built-in AI-powered log analysis (OpenAI, Gemini, Claude, or self-hosted Ollama). Identifies mod errors, missing dependencies, and server health issues. |
| Custom Configs | Push custom configuration files to clients, or keep server-only configs that persist across updates. |
| Single Container | Everything runs in one Docker container — NGINX, PHP, MariaDB, Supervisor, and the PhValheim engine. |
services:
phvalheim:
image: theoriginalbrian/phvalheim-server:latest
container_name: phvalheim
ports:
- "8080:8080/tcp" # Public UI
- "8081:8081/tcp" # Admin UI (do NOT expose publicly)
- "25000-26000:25000-26000/udp" # Game ports
volumes:
- /path/to/data:/opt/stateful:Z
- /path/to/backups:/opt/stateful/backups:Z # ideally a separate disk
restart: unless-stoppedThat's it. Start the container and open http://your-host:8081 — the Setup Wizard will walk you through configuration.
docker create \
--name phvalheim \
-p 8080:8080/tcp \
-p 8081:8081/tcp \
-p 25000-26000:25000-26000/udp \
-v /path/to/data:/opt/stateful:Z \
-v /path/to/backups:/opt/stateful/backups:Z \
theoriginalbrian/phvalheim-server:latest
docker start phvalheim Search for PhValheim in the Community Apps store.
A Helm chart is included in the repo at helm/phvalheim/.
# Minimal install
helm install phvalheim ./helm/phvalheim/
# With Ingress for the public UI
helm install phvalheim ./helm/phvalheim/ \
--set ingress.public.enabled=true \
--set ingress.public.hosts[0].host=phvalheim.example.com \
--set ingress.public.hosts[0].paths[0].path=/ \
--set ingress.public.hosts[0].paths[0].pathType=Prefix
# With an existing PVC
helm install phvalheim ./helm/phvalheim/ \
--set persistence.data.existingClaim=my-phvalheim-pvcHow it works:
-
The pod runs with
hostNetwork: trueby default so Valheim's UDP game ports (25000-26000) bind directly to the node — no NodePort or LoadBalancer gymnastics required. -
Two ClusterIP Services are created: one for the public UI (8080) and one for the admin UI (8081). Each has an optional Ingress resource (disabled by default).
-
A 20Gi PersistentVolumeClaim is created for
/opt/stateful. An optional separate PVC for backups can be enabled withpersistence.backups.enabled=true. -
Without Ingress enabled, access the admin UI via port-forward to run the Setup Wizard:
kubectl port-forward svc/phvalheim-admin 8081:8081 # Then open http://localhost:8081
See helm/phvalheim/values.yaml for the full set of configurable values.
All settings are configured through the Admin UI after first launch. No environment variables are needed for new installations.
Upgrading from an older version? Your existing environment variables will be automatically migrated to the database on first boot. A one-time migration notice will confirm the imported values.
| Setting | Description |
|---|---|
| Steam API Key | Required. Used for player authentication. Get one here. |
| PhValheim Host | Public FQDN for the web UI. |
| Game DNS | DNS name players use to connect to game servers. Can be the same as PhValheim Host. |
| Base Port | First UDP port for worlds (must match the container's port range). |
| Backups to Keep | Number of backup snapshots to retain per world. |
| Client Download URL | URL for the PhValheim Client installer. |
PhValheim includes a full backup system with activity-aware scheduling, compression, tiered retention, and one-click restore.
Mount a separate volume for backups to keep them isolated from game data:
volumes:
- /path/to/data:/opt/stateful:Z
- /path/to/backups:/opt/stateful/backups:Z # separate disk recommendedIf no dedicated backup volume is detected, the admin UI will display a warning and automatic backups are disabled. Manual backups can still be created.
| Setting | Default | Description |
|---|---|---|
| Backup Interval | 30 min |
How often scheduled backups run. The cron runs every 10 minutes but self-gates based on this interval. |
| Require Player Activity | Yes |
Only create backups when players have connected since the last backup. Prevents redundant backups of idle worlds. |
| Setting | Default | Description |
|---|---|---|
| Compression | None |
Algorithm: none (uncompressed tar), gzip, or zstd. Zstd is faster with better compression ratios. |
| Compression Schedule | 3:00 AM |
Hour to run deferred compression. Set to Immediate to compress at backup time. Deferred mode reduces CPU impact during active hours. |
| Compression Level | 0 (default) |
Higher levels = smaller files but more CPU. 0 uses each algorithm's default level. |
Disk space note: Compression requires temporary space for both the uncompressed tar and the compressed output (~2x world size). If insufficient space is available, the backup is saved uncompressed with a warning.
Backups are pruned automatically using a tiered retention policy. Manual backups are never auto-pruned.
| Tier | Default | Description |
|---|---|---|
| Keep All | 24 hours |
Every backup within this window is kept. |
| Daily | 7 days |
After the keep-all window, one backup per day is retained. |
| Weekly | 30 days |
After the daily tier, one backup per week is retained. |
| Monthly | 6 months |
After the weekly tier, one backup per month is retained. |
These settings control how aggressively backup operations use system resources. Lower priority = less impact on active players.
| Setting | Default | Description |
|---|---|---|
| CPU Priority | Low (10) |
nice value for tar and compression. Normal (0) = full speed, Low (10) = reduced, Lowest (19) = minimal. |
| I/O Priority | Low |
ionice class. Idle = backups only use disk when the game server isn't reading/writing. Normal = no throttling. |
Each world can override the global backup settings. In the world settings modal, switch to the Backups tab and uncheck Use Global Defaults to configure per-world intervals, retention, compression, and performance settings.
Restoring a backup replaces the current world directory with the backup contents:
- A pre-restore safety backup is created automatically (unless disk space is insufficient).
- The current world directory is cleared.
- The backup is extracted. Legacy backups (pre-2.38) are detected and extracted to the correct path.
- File ownership is fixed and the world is set to rebuild on next engine cycle.
- The world process is restarted.
Restores are blocked while a world is in a transitional state (starting, stopping, updating, etc.).
On startup, PhValheim reconciles backup records with files on disk:
- Orphaned records: DB entries pointing to missing files are flagged as orphaned.
- Untracked files: Backup files on disk with no DB record are discovered and imported.
- Recovery: If an orphaned file reappears (e.g., backup volume remounted), the orphan flag is cleared.
Orphaned records are shown in the dashboard Storage card and in the per-world backup table. Use the Clean up button to purge orphaned records.
| Setting | Default | Description |
|---|---|---|
| Thunderstore Chunk Size | 1000 |
Number of mods processed per batch during Thunderstore sync. |
The Thunderstore sync runs every 12 hours and processes the full Valheim mod catalog using parallel worker threads — one thread per chunk. The chunk size directly controls the parallelism:
- Lower value → more chunks → more parallel threads → higher CPU and MariaDB load, but faster sync on multi-core hosts.
- Higher value → fewer chunks → fewer threads → lower CPU pressure, more memory per thread.
Thread count math (based on ~9,400 mods in the Thunderstore Valheim catalog as of early 2026):
| Goal | Chunk Size | Threads spawned |
|---|---|---|
| 1 thread | 9400 |
9400 / 9400 = 1 |
| 2 threads | 4700 |
9400 / 4700 = 2 |
| 5 threads | 1880 |
9400 / 1880 = 5 |
| 10 threads | 940 |
9400 / 940 = 10 |
| Default | 1000 |
9400 / 1000 ≈ 10 |
The default of 1000 spawns roughly 10 parallel threads. On low-resource hosts (shared VMs, small cloud instances), raising the chunk size to 4700–9400 reduces the sync to 1–2 threads and keeps the host responsive during the sync window.
Note: Running at a single thread (chunk size
9400) serializes all mod processing through one worker. Depending on the single-core clock speed of your CPU, a full sync at this setting could take several hours to complete. A chunk size in the2000–5000range is generally a better balance for resource-constrained hosts — enough parallelism to finish in a reasonable time without saturating the CPU.
If you see this warning in tsSync.log, your chunk size is too aggressive for the host — increase the value:
WARNING: a previous thunderstore sync process is still running. This could mean
your thunderstore chunk size is too aggressive for your system. Consider
increasing the 'thunderstore_chunk_size' database value.
Adjust Thunderstore Chunk Size in the Admin UI under Server Settings.
Configure one or more AI providers in Server Settings to enable the built-in log analysis assistant.
| Provider | What you need |
|---|---|
| OpenAI | API key — enables GPT-4o models |
| Google Gemini | API key — enables Gemini 2.0 Flash and Gemini 1.5 Pro |
| Anthropic Claude | API key — enables Claude Haiku 4.5 and Claude Sonnet 4.5 |
| Ollama | URL of your self-hosted instance — models detected automatically |
| Container Path | Purpose |
|---|---|
/opt/stateful |
All persistent data — worlds, mods, database, configuration. |
/opt/stateful/backups |
World backups. Point this to a separate disk for safety. |
| Port | Purpose |
|---|---|
8080/tcp |
Public web UI — expose this to your players. |
8081/tcp |
Admin web UI — keep this private. |
25000-26000/udp |
Game server port range for Valheim worlds. |
The server is only half the equation. PhValheim Client is a cross-platform companion app (Windows, Linux, macOS) that registers a custom phvalheim:// URL protocol. When a player clicks a launch link:
- The client compares the remote world's checksum against the local copy.
- If outdated, it downloads the new payload (mods, configs, dependencies).
- It launches Valheim, connecting to the correct server and world automatically.
| Platform | Installer | Config location |
|---|---|---|
| Windows | .msi |
%appdata%\PhValheim |
| Linux | .deb, .rpm, or .tar.gz |
~/.config/PhValheim |
| macOS | .pkg (universal — Intel + Apple Silicon) |
~/Library/Application Support/PhValheim |
Client repo: brianmiller/phvalheim-client
Access to each world is controlled by the PhValheim database. Steam IDs are associated with each world, gating both the web UI (world visibility) and the game server allow-list.
Example NGINX config for TLS termination:
server {
listen 80;
server_name phvalheim.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name phvalheim.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 1200s;
client_max_body_size 0;
}
}| Folder | Behavior |
|---|---|
custom_configs/ |
Pushed to clients on world update. Use for shared game configs. |
custom_configs_secure/ |
Server-only. Persists across updates but never sent to clients. |
PhValheim makes mod management effortless, but not all mods play well together. If you're experiencing crashes or unexpected behavior, deploy a vanilla world (no mods) first to rule out mod conflicts. Most mod issues occur after major Valheim updates.



