Infrastructure: Nodes, Targets, and Management Hosts#
The Big Picture#
Your self-hosted solution ’s infrastructure has three layers, from bottom to top:
┌───────────────────────────────────────────────────┐
│ Apps (Jellyfin, Sonarr, Grafana, ...) │ ← What you care about
├───────────────────────────────────────────────────┤
│ Targets │ ← Where apps run
├───────────────────────────────────────────────────┤
│ Nodes & Management Hosts (Proxmox, OPNsense) │ ← The physical foundation
└───────────────────────────────────────────────────┘Let’s go through each layer.
Management Hosts#
A management host is a machine that exists on your network before PSW does anything. These are the physical infrastructure that make everything else possible.
Defined in network.yml under management.hosts:
management:
gateway: 10.10.0.1
hosts:
small: # A Proxmox server
ip: 10.10.0.198
roles: [proxmox]Each management host has:
- A name (the YAML key, e.g.
small) - An IP address to reach it
- One or more roles describing what it does
- Optional SSH credentials
Management hosts are things you set up yourself — PSW reads them, but doesn’t create or destroy them. The router (OPNsense) is also a management host — see networking for how it fits in.
Proxmox Nodes#
A Proxmox
node is a management host with the proxmox role. It’s the physical server running the Proxmox hypervisor (software that creates and runs virtual machines and containers), which creates and manages targets.
The term “node” is used throughout PSW specifically to mean “a Proxmox server.” When you see node in a config file, it always refers to a Proxmox management host.
Each node gets its own directory under nodes/ in your project:
nodes/
└── small/ # Matches the management host name "small"
├── hardware.yml # CPU, RAM, disks, NICs, GPUs, USB devices on this server
└── storage.yml # Storage pools configured on this serverThis is important because PSW needs to know what hardware each node has. If an app
requires a GPU (like Tdarr
for video transcoding), PSW checks nodes/<node>/hardware.yml
to make sure the node actually has one (see app metadata
for hardware requirements).
Targets#
A target is where apps actually run. It’s the deployment destination — the machine that PSW deploys your apps to. Unlike management hosts, targets are managed by PSW (targets are created and destroyed automatically during convergence ).
Defined in network.yml under targets:
targets:
core: # Bootstrap target (core apps + convergence engine)
type: lxc
node: small # ← Lives on the "small" Proxmox node
ssh_user: sysops
ip: 10.10.0.100
cores: 8
memory: 40960
disk: 200
media: # Media apps target
type: lxc
node: small
cores: 4
memory: 4096
disk: 100
my-vps: # External VPS
type: bare
ip: 203.0.113.45
ssh_user: ubuntuTwo Types of Targets#
Managed Targets (type: lxc)#
A managed target (type: lxc) is a lightweight Linux container (LXC) created by Proxmox on your behalf. Think of it as a mini virtual machine that shares the host’s kernel — fast to create, low overhead. It’s the most common type.
- PSW creates the target automatically during convergence
- The
nodefield says which Proxmox server hosts it - Resources (CPU, RAM, disk) are defined in the target config
- IP is the static address the LXC boots with — set in
network.ymlbefore bootstrap/convergence creates the container
Bare Targets#
A bare target is an external server that PSW deploys to directly via SSH (Secure Shell — a protocol for securely connecting to remote machines). No target creation — the server already exists (e.g., a VPS from Hostinger, a Raspberry Pi, etc.).
- No
nodefield — it’s not on a Proxmox server - PSW just SSHes in and runs the deployment
- You manage the server yourself (OS, updates, etc.)
The Bootstrap Target#
One target is special — the bootstrap target. This is the target where PSW deploys the core apps (PostgreSQL , Traefik , Authelia , etc.) and the convergence engine during bootstrap .
Which target is the bootstrap target is recorded in project.yml:
bootstrap:
target: coreThe bootstrap target is just a regular target in the targets section — there’s nothing structurally different about it. PSW just needs to know which one it is so it can find where the convergence engine and core apps live.
How They All Connect#
Here’s how these pieces fit together in practice:
Proxmox Node "small" (physical server, 10.10.0.198)
│
├── Target "core" (bootstrap target, 10.10.0.100)
│ ├── [PostgreSQL](https://www.postgresql.org/)
│ ├── [Traefik](https://github.com/traefik/traefik)
│ ├── [Authelia](https://github.com/authelia/authelia)
│ ├── [LLDAP](https://github.com/lldap/lldap)
│ ├── [Forgejo](https://codeberg.org/forgejo/forgejo)
│ └── PSW Dashboard
│
├── Target "media" (10.10.0.101)
│ ├── [Jellyfin](https://github.com/jellyfin/jellyfin)
│ ├── [Sonarr](https://github.com/Sonarr/Sonarr)
│ └── [Radarr](https://github.com/Radarr/Radarr)
│
└── Target "monitoring" (10.10.0.102)
├── [Prometheus](https://github.com/prometheus/prometheus)
└── [Grafana](https://github.com/grafana/grafana)
Bare Target "my-vps" (external server, 203.0.113.45)
└── [Pangolin](https://github.com/fosrl/pangolin) (remote access tunnel)The Relationship Chain#
App → Target → Node- An app
is deployed to a target (declared in
services/<app>/service.yml) - A managed target lives on a node (declared in
network.yml → targets) - A node is a management host with the
proxmoxrole (declared innetwork.yml → management.hosts)
Clean Separation#
Management hosts and targets serve completely different purposes:
| Management Hosts | Targets | |
|---|---|---|
| What are they? | Physical infrastructure you set up | Deployment destinations PSW manages |
| Created by? | You (manually) | PSW (automatically) |
| Purpose | Provide infrastructure (hypervisor, routing) | Run your apps |
| Examples | Proxmox server, OPNsense router | Managed containers, bare servers (VPS) |
| Defined in | network.yml → management.hosts | network.yml → targets |
There is no overlap — a machine is either a management host or a target, never both.
Quick Reference#
| Term | What It Is | Where It’s Defined | Example |
|---|---|---|---|
| Management Host | Infrastructure machine (not managed by PSW) | network.yml → management.hosts | Proxmox server, OPNsense router |
| Node | A Proxmox server (management host with proxmox role) | network.yml → management.hosts + nodes/<name>/ | small |
| Target | Where apps get deployed (managed by PSW) | network.yml → targets | core, media, my-vps |
| Managed Target | A container created by PSW on a Proxmox node (type: lxc) | network.yml → targets (type: lxc) | core, media |
| Bare Target | An external server | network.yml → targets (type: bare) | my-vps |
| Bootstrap Target | The target hosting core apps + convergence | project.yml → bootstrap.target | core |
Common Questions#
Can one Proxmox node host multiple targets? Yes. A single Proxmox server can host many targets.
Can I have multiple Proxmox nodes?
Yes. Each gets its own entry in management.hosts and its own nodes/<name>/ directory. Targets reference which node they live on via the node field.
What if I only have one Proxmox node?
Then the node field on targets is optional — PSW auto-selects the only available node.
Can a target move between nodes?
In theory, yes — change the node field. In practice, this would require recreating the target on the new node.
What makes the bootstrap target special?
Nothing structural. It’s just the target where core apps
and the convergence
engine run. PSW records which target it is in project.yml so it can find it later. See bootstrap
for the full setup process.