---
title: Installing Podman Locally and on a VPS
description: A practical install guide for Podman on macOS and Debian/Ubuntu servers, including first-run checks.
pubDate: '2026-03-04T21:51:00+01:00'
category: en/on-premises-private-cloud
tags:
  - podman
seriesParent: astro-ssr-with-podman
seriesOrder: 1
---

I wanted the same container runtime on my MacBook and on the VPS — same commands, same compose file, same mental model. I picked Podman over Docker mostly because it runs rootless by default and doesn't need a daemon on Linux, which matters on a small VPS where every background process costs something.

This post is the install baseline the rest of the series rests on.

## The setup

- **Local**: macOS with Homebrew, Podman running inside its managed VM.
- **Server**: Debian/Ubuntu VPS, Podman installed from the distro packages.
- **Compose**: `podman-compose` on both sides — no Docker binaries involved.

## Local installation (macOS)

```bash
brew update
brew install podman podman-compose
```

Podman on macOS runs inside a lightweight Linux VM — initialise and start it:

```bash
podman machine init
podman machine start
```

A quick sanity pass to make sure the client can reach the VM:

```bash
podman --version
podman info
podman system connection list
```

**Gotcha:** Homebrew installs both `podman compose` (the subcommand) and `podman-compose` (a separate Python project). The subcommand will happily call out to `docker-compose` if it's on the `PATH`, which defeats the point. Pin the provider explicitly:

```bash
export PODMAN_COMPOSE_PROVIDER=/opt/homebrew/bin/podman-compose
echo 'export PODMAN_COMPOSE_PROVIDER=/opt/homebrew/bin/podman-compose' >> ~/.zshrc
source ~/.zshrc
```

## Server installation (Debian/Ubuntu VPS)

```bash
sudo apt-get update
sudo apt-get -y install podman podman-compose git
```

Same verification pass as on macOS:

```bash
podman --version
podman info
podman system connection list
```

**Problem:** On multi-container compose setups I wanted service-name DNS (one service reaching another by its compose service name) to work out of the box. The default installation doesn't always include the network plugins that provide this.

**Implementation:** Install the netavark + aardvark stack — Podman's modern network + DNS layer:

```bash
sudo apt-get -y install netavark aardvark-dns
```

**Solution:** Compose services resolve each other by name inside the Podman network, without me having to hand-wire IPs.

## First-run check (both environments)

Pulling a real image and running a throwaway container is the cheapest way to confirm the runtime and the registry path both work:

```bash
podman pull docker.io/library/node:20-bookworm-slim
podman run --rm docker.io/library/node:20-bookworm-slim node --version
```

A Node version back on stdout means the whole chain — runtime, image resolver, registry auth, container exec — is healthy.

## Common first-install issues

- **`connection refused` on the Podman socket (macOS).** The VM is either not running or in a bad state. `podman machine stop && podman machine start` resolves it almost every time.
- **`invalid username/password` pulling public images.** Stale auth state in `~/.config/containers/auth.json`. A plain `podman pull` often clears it without any extra login.
- **`podman compose` picks the wrong provider.** Set `PODMAN_COMPOSE_PROVIDER` explicitly — don't rely on the auto-detection.

## Day-to-day commands

The three commands I run ninety percent of the time:

```bash
podman compose -f compose.yml up --build -d
podman compose -f compose.yml logs -f
podman compose -f compose.yml down
```

Same three commands on laptop and server — that's the whole point.

## What to take away

- Keeping the local and server installations symmetric pays off on every deploy — no mental translation needed.
- Rootless Podman is the default, and it's the right default for a small single-service VPS.
- Pin `PODMAN_COMPOSE_PROVIDER` explicitly; the auto-detected fallback to `docker-compose` is a silent behaviour change waiting to happen.
- Install `netavark` and `aardvark-dns` on the server if you use compose service-name DNS.
- A successful `podman run --rm node:20 node --version` is a complete smoke test.
