Skip to content

Auto-start on Boot

Configure pgcli to automatically start PostgreSQL instances and services after a host reboot

pgcli can automatically start PostgreSQL instances, backup containers, PgBouncer services, and etcd members after a host reboot. This feature uses system service managers:

  • Linux: systemd user units
  • macOS: launchd LaunchAgents

How It Works

When you enable auto-start, pgcli creates a system service that runs pg start --autostart at boot time (or user login). The --autostart flag starts only the instances and services marked with autostart: true in your configuration.

Auto-start is config-driven: if you run pg stop (or pg stop --all) on an instance, it will still be started automatically at the next boot. To prevent auto-start, use pg autostart disable.

Default behavior: The backup container has autostart: true by default in new configurations. Instances, PgBouncer, and etcd members default to autostart: false and must be explicitly enabled.

Enable Auto-start

For a Single Instance

pg autostart enable -i <instance-name>

Example:

pg autostart enable -i default

This adds autostart: true to the instance configuration and creates/updates the boot service.

For the Backup Container

pg autostart enable --backup

Enables auto-start for the shared pgBackRest backup container.

For PgBouncer

Enable auto-start for a PgBouncer associated with a specific instance:

pg autostart enable --pgbouncer -i <instance-name>

Or for a remote PgBouncer:

pg autostart enable --pgbouncer --pg-name <remote-name>

For an etcd Member

Enable auto-start for an etcd member installed via pg addon install etcd:

pg autostart enable --etcd --name <member-name>

The member name defaults to etcd when --name is omitted:

pg autostart enable --etcd

Repeat for each member of a cluster (m1, m2, m3, …) — autostart is per-member. On a cross-host cluster, run the command on each host for that host’s member(s).

Boot is start-only. At boot pgcli just brings the member’s existing container up (podman start, recreating the container from config only if it is missing or stuck in an improper state). It never re-registers membership — a data-dir-initialized etcd member reloads its cluster from disk and rejoins on a plain start, so it must have been installed while the cluster was reachable first. Starting members before quorum forms briefly reports etcdserver: no leader; that is normal and resolves once enough members are up.

Disable Auto-start

pg autostart disable -i <instance-name>
pg autostart disable --backup
pg autostart disable --pgbouncer -i <instance-name>
pg autostart disable --pgbouncer --pg-name <remote-name>
pg autostart disable --etcd --name <member-name>

When all auto-start targets are disabled, the boot service is automatically removed.

Check Status

pg autostart status

Shows:

  • Which instances and services have auto-start enabled
  • The boot service unit name and state
  • Linger status (Linux) — required for rootless podman to start services at boot time

Platform-Specific Behavior

Linux (systemd)

The boot service is created as a systemd user unit: pgcli-autostart-<hash>.service

Important: Rootless podman requires loginctl enable-linger to start containers at boot time (before the user logs in). pgcli attempts this automatically but will print a hint if it fails.

Without linger, the service starts at user login instead of at system boot.

Systemd Unit Configuration

The systemd unit generated by pgcli includes the following key settings:

[Service]
Type=oneshot
Delegate=yes
RemainAfterExit=yes
  • Delegate=yes - Delegates cgroup control to the service process, allowing rootless podman to properly manage container cgroup hierarchies
  • RemainAfterExit=yes - Keeps the service in active state after execution completes, rather than immediately transitioning to inactive
  • Type=oneshot - Executes pg start --autostart once and exits

Cgroup Isolation and Automatic Fallback

Problem: When containers are started by a systemd user unit, accessing them from SSH sessions or other contexts may encounter cgroup permission errors:

Error: crun: writing file `/sys/fs/cgroup/.../cgroup.procs`: Permission denied: OCI permission denied

Cause: Containers started by systemd user units reside in the user@1000.service/app.slice cgroup subtree, while SSH sessions are in session-N.scope - different cgroup scopes.

Solution: pgcli automatically detects cgroup permission errors and re-executes the command via systemd-run --user --scope. This creates a transient scope that can join the container’s cgroup subtree.

Affected commands (automatic fallback):

  • pg exec - Execute SQL or container commands
  • pg psql - Interactive psql sessions
  • pg status - Check container status
  • pg backup - Backup operations
  • pg extension - Extension management
  • All other podman exec operations

Unaffected commands:

  • pg start - Start containers (uses systemd-run itself)
  • pg stop - Stop containers
  • pg restart - Restart containers

Viewing Service Status

pg autostart status now displays detailed systemctl information:

pg autostart status

Output includes:

  • Enable status of all auto-start targets
  • systemd unit name, load state, active state
  • Service logs and recent execution records
  • Linger status

Example output:

=== Auto-start targets ===
  instance default         enabled
  backup                 enabled
  etcd m1                  enabled

=== Boot service ===
  Unit:      pgcli-autostart-554d14ed
  Installed: yes
  Enabled:   enabled
  Running:   active
  Linger:    yes

=== Service status ===
     Loaded: loaded (/home/user/.config/systemd/user/pgcli-autostart-554d14ed.service; enabled)
     Active: active (exited) since Mon 2026-09-07 14:30:00 CST; 2h ago
    Process: 1234 pg -c /home/user/.config/pgcli/pg.yaml start --autostart (code=exited, status=0/SUCCESS)
   Main PID: 1234 (code=exited, status=0/SUCCESS)

macOS (launchd)

The boot service is created as a LaunchAgent: com.pgcli.autostart-<hash>.plist

Note: macOS LaunchAgents run at user login, not at system boot. This is a macOS limitation — rootless podman cannot start services before the user logs in.

Configuration File

The autostart: true flag appears in your pgcli configuration file:

instances:
  default:
    # ... other settings ...
    autostart: true

backup:
  # ... other settings ...
  autostart: true

addons:
  # For PgBouncer
  pgbouncer:
    default:
      # ... other settings ...
      autostart: true
  # For etcd members
  etcd:
    m1:
      # ... other settings ...
      autostart: true

Boot Service Behavior

The boot service runs pg start --autostart, which:

  1. Starts all instances with autostart: true
  2. Starts the backup container if backup.autostart: true
  3. Starts PgBouncer services with autostart: true
  4. Starts etcd members with autostart: true (start-only; see above)

If no auto-start targets are configured, the service exits successfully (no error).

Each manager (PostgreSQL, backup, PgBouncer, etcd) self-heals stale rootless podman state at startup — after a reboot the pause-process record is dead, so the service transparently runs podman system migrate before touching containers. This means boot works even when only addons (no PG instance) are marked for auto-start.

Troubleshooting

Service Failed to Start

Check the boot service logs:

Linux (systemd):

journalctl --user -u pgcli-autostart-<hash>.service

macOS (launchd):

cat ~/Library/Logs/pgcli-autostart-<hash>.log

Linux: “XDG_RUNTIME_DIR is not set”

This error occurs when systemd user units are not available. Ensure you have a proper user session:

  • SSH sessions should support systemd –user by default
  • Terminal sessions in desktop environments support systemd –user
  • Cron jobs and other non-interactive contexts do not support systemd –user

Linux: Auto-start Only Works After Login

Run loginctl enable-linger <your-username> to allow rootless podman to start services at boot time.

macOS: Auto-start Only Works After Login

This is expected behavior. macOS LaunchAgents cannot run before user login due to rootless podman constraints.

Examples

Enable auto-start for a complete production setup:

# Enable the default instance
pg autostart enable -i default

# Enable the backup container
pg autostart enable --backup

# Enable PgBouncer for the default instance
pg autostart enable --pgbouncer -i default

# Enable etcd members m1 and m2 (names from pg addon list / pg.yaml)
pg autostart enable --etcd --name m1
pg autostart enable --etcd --name m2

# Check the status
pg autostart status

After the next reboot, all these services will start automatically.