# Podman Quadlet Production Standards

## Canonical Locations

| Item | Path |
|------|------|
| System quadlets | `/etc/containers/systemd/` |
| User quadlets | `~/.config/containers/systemd/` |
| Config (FHS) | `/etc/<app>/` |
| Variable data (FHS) | `/var/lib/<app>/` |
| Secrets | `podman secret` (not env files) |

**Note**: See `fhs-directory-standards` memory for detailed FHS rules.

## Required Quadlet Sections

### Minimum Production Template

```ini
[Unit]
Description=App Container %i
After=local-fs.target network-online.target
Wants=network-online.target

[Container]
Image=ghcr.io/org/app:tag
Network=host
Environment=PORT=%i
EnvironmentFile=/var/lib/app/.env-%i
Volume=/etc/app/config.yaml:/app/config.yaml:ro

# Health check (adjust endpoint)
HealthCmd=curl -sf http://localhost:%i/health || exit 1
HealthInterval=30s
HealthTimeout=10s
HealthRetries=3
HealthStartPeriod=60s

[Service]
Restart=on-failure
RestartSec=5
TimeoutStartSec=300
StartLimitIntervalSec=500
StartLimitBurst=5
MemoryMax=1G
CPUQuota=200%

[Install]
WantedBy=multi-user.target
```

## Common Gaps (Checklist)

- [ ] `[Service]` section with `Restart=on-failure`
- [ ] `RestartSec=` to prevent rapid restart loops
- [ ] `TimeoutStartSec=300` for image pulls
- [ ] `StartLimitIntervalSec/Burst` to cap restart attempts
- [ ] `HealthCmd` with appropriate endpoint
- [ ] `MemoryMax` and `CPUQuota` resource limits
- [ ] Secrets via `podman secret`, not env files

## Network Mode Tradeoffs

| Mode | Use When |
|------|----------|
| `host` | Performance-critical, single-tenant host, unique ports per instance |
| `bridge` | Multi-tenant, isolation required, port mapping acceptable |

## Scaling Limits (Quadlet Approach)

| Instances | Assessment |
|-----------|------------|
| 1-20 | Comfortable |
| 20-50 | Add deployment automation (Ansible) |
| 50-100 | Manageable, manual ops tedious |
| 100+ | Step change: Kubernetes/Nomad |

## Config Pattern (12-Factor)

- **Config file**: Structure, features, static settings
- **Environment variables**: Instance overrides, deployment context
- **Secrets**: `podman secret create` + `Secret=name,type=env,target=VAR`

## Commands Reference

```bash
# Secret management
echo "value" | podman secret create secret_name -
podman secret ls
podman secret rm secret_name

# Quadlet reload
sudo systemctl daemon-reload

# Service lifecycle
sudo systemctl start app@7143
sudo systemctl status app@7143
journalctl -u app@7143 -f
```
