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 server

This 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: ubuntu

Two 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 node field 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.yml before 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 node field — 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: core

The 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 proxmox role (declared in network.yml → management.hosts)

Clean Separation#

Management hosts and targets serve completely different purposes:

Management HostsTargets
What are they?Physical infrastructure you set upDeployment destinations PSW manages
Created by?You (manually)PSW (automatically)
PurposeProvide infrastructure (hypervisor, routing)Run your apps
ExamplesProxmox server, OPNsense routerManaged containers, bare servers (VPS)
Defined innetwork.yml → management.hostsnetwork.yml → targets

There is no overlap — a machine is either a management host or a target, never both.

Quick Reference#

TermWhat It IsWhere It’s DefinedExample
Management HostInfrastructure machine (not managed by PSW)network.yml → management.hostsProxmox server, OPNsense router
NodeA Proxmox server (management host with proxmox role)network.yml → management.hosts + nodes/<name>/small
TargetWhere apps get deployed (managed by PSW)network.yml → targetscore, media, my-vps
Managed TargetA container created by PSW on a Proxmox node (type: lxc)network.yml → targets (type: lxc)core, media
Bare TargetAn external servernetwork.yml → targets (type: bare)my-vps
Bootstrap TargetThe target hosting core apps + convergenceproject.yml → bootstrap.targetcore

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.