Skip to content
Documentation Prelude Collector 1.0.0

Podman deployment

Run Prelude Collector under Podman, including rootless considerations, SELinux labels, and Quadlet/systemd integration.

This page is the reference for running Prelude Collector under Podman. Podman is a daemonless, rootless OCI runtime that is mostly drop-in compatible with Docker - the same image and the same Compose file work, with a handful of differences called out below.

For the matching Docker reference, see Docker deployment. For every config field the collector accepts, see the Configuration reference.

Prerequisites

Requirement Version Notes
Podman 4.0 or later Includes the podman compose subcommand.
podman-compose 1.0 or later Optional, only if you prefer the standalone tool.
RAM 2 GB minimum Same as Docker.

The collector image is published to the public registry registry.arolo-solutions.com/prelude/prelude-collector. The examples below use the :1.0 tag, the current stable release.

Pull the image

The registry is publicly pullable — no authentication required:

podman pull registry.arolo-solutions.com/prelude/prelude-collector:1.0.0

Quick start with Compose

The same docker-compose.yml shown in the Docker deployment works under Podman with no changes for most workflows:

podman compose up -d
# or, if you use the standalone tool:
podman-compose up -d

The schema migrates automatically on startup and a default admin (admin / @rolo!Pass246) is seeded on first boot — sign in on the web UI and change the password. Then issue an API token (with COLLECTOR_AUTO_MIGRATE=false, run migrate up first):

podman compose exec collector ./prelude-collector user token \
  -u admin -d api-token

Standalone (without Compose)

podman run -d \
  --name prelude-collector \
  --restart unless-stopped \
  -p 4030:4030 \
  -e COLLECTOR_DB_HOST=your-postgres-host \
  -e COLLECTOR_DB_PORT=5432 \
  -e COLLECTOR_DB_USER=prelude \
  -e COLLECTOR_DB_PASSWORD=change-me-sE43kapqD8df5fds \
  -e COLLECTOR_DB_NAME=collector \
  -v collector-data:/app/storage:Z \
  registry.arolo-solutions.com/prelude/prelude-collector:1.0.0

Rootless differences

Podman runs rootless by default. There are three differences from Docker worth knowing about.

Port binding below 1024

Rootless containers cannot bind to privileged ports. The default collector port 4030 is fine. If you need to bind 80 or 443, either lower the unprivileged port floor on the host or front the collector with a reverse proxy:

sudo sysctl net.ipv4.ip_unprivileged_port_start=80

SELinux volume labels

On SELinux-enforcing distributions (RHEL, Fedora, Rocky, CentOS Stream), bind-mounted host paths need a :z or :Z suffix so Podman relabels them. The quick-start stack uses a named volume for storage, but if you bind-mount a host directory instead, relabel it:

services:
  collector:
    volumes:
      - ./storage:/app/storage:Z

Use :z if the volume is shared between containers, :Z if it is private to one container.

Inter-container DNS

Podman uses its own DNS resolver for inter-container name lookup. If service names do not resolve out of the box, define a named network explicitly and attach the services to it:

podman network create prelude
networks:
  default:
    name: prelude
    external: true

Quadlet and systemd

For production Podman deployments, manage containers as systemd units through Quadlet rather than running Compose under a shell. Quadlet reads .container files and generates systemd units at boot, which gives you proper start ordering, restart policy, and journal logging.

Place unit files under ~/.config/containers/systemd/ for rootless or /etc/containers/systemd/ for rootful.

Network

[Network]
NetworkName=prelude

PostgreSQL

[Container]
ContainerName=prelude-postgres
Image=docker.io/library/postgres:16-alpine
Environment=POSTGRES_USER=prelude
Environment=POSTGRES_PASSWORD=change-me-sE43kapqD8df5fds
Environment=POSTGRES_DB=collector
PublishPort=5432:5432
Volume=prelude-pgdata.volume:/var/lib/postgresql/data
Network=prelude.network

[Service]
Restart=always

[Install]
WantedBy=default.target

NATS

[Container]
ContainerName=prelude-nats
Image=docker.io/library/nats:2
PublishPort=4222:4222
Network=prelude.network

[Service]
Restart=always

[Install]
WantedBy=default.target

Collector

[Container]
ContainerName=prelude-collector
Image=registry.arolo-solutions.com/prelude/prelude-collector:1.0.0
PublishPort=4030:4030
Environment=COLLECTOR_DB_HOST=prelude-postgres
Environment=COLLECTOR_DB_PORT=5432
Environment=COLLECTOR_DB_USER=prelude
Environment=COLLECTOR_DB_PASSWORD=change-me-sE43kapqD8df5fds
Environment=COLLECTOR_DB_NAME=collector
Volume=prelude-storage.volume:/app/storage:Z
Network=prelude.network

[Service]
Restart=always
After=prelude-postgres.service prelude-nats.service

[Install]
WantedBy=default.target

Manage with systemd

# Pick up new unit files
systemctl --user daemon-reload

# Start the stack
systemctl --user start prelude-postgres prelude-nats prelude-collector

# Enable at boot (rootless needs lingering)
loginctl enable-linger $USER
systemctl --user enable prelude-postgres prelude-nats prelude-collector

# Status and logs
systemctl --user status prelude-collector
journalctl --user -u prelude-collector -f

For rootful Quadlet, drop --user and place the units under /etc/containers/systemd/.

Networking and ports

Same as Docker - see the port table on the Docker page. Inside a Podman network, services resolve each other by container name (postgres, nats).

Volumes

Same as Docker - see Volumes on the Docker page. Remember the SELinux label note above when bind-mounting on RHEL or Fedora hosts.

Podman vs Docker quick reference

Operation Docker Podman
Start stack docker compose up -d podman compose up -d
View logs docker compose logs -f podman compose logs -f
Exec into container docker compose exec collector sh podman compose exec collector sh
Pull images docker compose pull podman compose pull
Auto-start at boot Docker daemon enabled Quadlet + systemctl enable
Rootless by default No Yes
SELinux volume labels Not needed :z or :Z on bind mounts

Troubleshooting

Symptom Likely cause Fix
Cannot resolve service name Default network lacks DNS Create an explicit Podman network and attach services to it
Permission denied on a bind mount SELinux blocking access Add :z or :Z to the volume
Port already in use Rootless port conflict podman port -a to inspect, change the host port
Containers don't start at boot Lingering not enabled loginctl enable-linger $USER, then re-enable the units

Air-gapped environments

For an air-gapped Podman host, transfer the image with podman save and podman load. See the Air-gapped install tutorial for the step-by-step, and Air-gap deployment for the operational reference.

See also

Filtering by: