---
title: Configuration
product: trilio-share-protection
doc_type: guide
version: master
source: git2docs (code-derived, validation-filtered)
canonical: https://git2docs.com/murali-balcha/docs/trilio-share-protection/trilio-share-protection-/configuration
---

# Configuration

_All environment variables, config files, and feature flags_

## Overview

This page describes every configuration option, environment variable, and feature flag that controls Trilio Share Protection (Abacá). Configuration is managed through a single oslo.config file (`abaca.conf`) shared by all Abacá services — `abaca-api`, `abaca-conductor`, and `abaca-worker-agent` — with a small set of environment variable overrides for container and Docker Compose deployments that do not mount a config file. Understanding these settings lets you tune API server binding, database and message-broker connectivity, the conductor's scheduling and reconciliation cadence, the Kopia execution model, and the worker fleet warm-pool behaviour. If any option's default is wrong for your environment, this page tells you exactly what to change and why.

## Prerequisites

Before configuring Abacá, make sure you have:

- **Abacá** installed (services `abaca-api`, `abaca-conductor`, `abaca-worker-agent`, and the CLI tools `abaca-manage` and `abaca-dev`)
- **OpenStack** ≥ 2023.1 (Antelope) or RHOSO 18, with Keystone, Manila, and Barbican reachable
- **OpenShift** ≥ 4.12 (control-plane deployment target)
- **MariaDB** ≥ 10.x or MySQL accessible from the services
- **RabbitMQ** accessible from all services
- **S3-compatible object storage** (AWS S3, MinIO, Ceph RGW, ODF, or Wasabi)
- **Python** ≥ 3.11 (required by `abaca-manage` and `python-abacaclient`)
- **Docker or Podman** — only needed for the local Docker Compose development stack
- `oslo-config-generator` installed (`pip install oslo-config-generator`) if you intend to regenerate the sample config
- The admin OpenStack credentials (`openrc`) available when using the Kolla deployment scripts

## Installation

### 1. Obtain the sample configuration file

The sample file `etc/abaca.conf.sample` ships with the Abacá source tree. Every supported option is listed there with its type, default value, and description. Copy it to the conventional system path:

```bash
cp etc/abaca.conf.sample /etc/abaca/abaca.conf
```

Set ownership and permissions so the service user can read it but unprivileged users cannot:

```bash
chown root:abaca /etc/abaca/abaca.conf
chmod 0640 /etc/abaca/abaca.conf
```

### 2. Edit the file

Open `/etc/abaca/abaca.conf` and uncomment the options you need to change. Every option that keeps its default value can remain commented out — oslo.config applies the default automatically.

At a minimum you almost certainly need to set:

```ini
[DEFAULT]
transport_url = rabbit://abaca:RABBIT_PASSWORD@RABBIT_HOST:5672/abaca

[database]
connection = mysql+pymysql://abaca:DB_PASSWORD@DB_HOST/abaca?charset=utf8mb4

[keystone_authtoken]
www_authenticate_uri = http://KEYSTONE_HOST:5000
auth_url             = http://KEYSTONE_HOST:5000
auth_type            = password
project_domain_name  = Default
user_domain_name     = Default
project_name         = service
username             = abaca
password             = ABACA_SERVICE_PASSWORD

[abaca]
service_user_id   = <uuid from `openstack user show abaca -f value -c id`>
service_user_name = abaca
```

### 3. Pass the config file to each service

Every Abacá console script accepts `--config-file`:

```bash
abaca-api --config-file /etc/abaca/abaca.conf
abaca-conductor --config-file /etc/abaca/abaca.conf
abaca-worker-agent --config-file /etc/abaca/abaca.conf
abaca-manage --config-file /etc/abaca/abaca.conf db_sync
```

When deploying on OpenShift or with Kolla, the config file is mounted into each container at `/etc/abaca/abaca.conf`; oslo.config discovers it automatically via the `project=abaca` convention, so no `--config-file` flag is needed in those environments.

### 4. Run database migrations

After writing a valid `[database]` section, initialise or migrate the schema:

```bash
abaca-manage --config-file /etc/abaca/abaca.conf db_sync
```

### 5. (Optional) Regenerate the sample after code changes

If you modify option definitions in `abaca/common/config.py`, regenerate the checked-in sample so CI does not fail:

```bash
tox -e sample-config          # regenerate in-place
tox -e sample-config-check    # verify the checked-in copy is current
```

## Configuration

Abacá's options are organised into named groups that correspond directly to ini-file sections. The table format below lists each option as `[section] option_name`, its type and default, and what it controls.

---

### `[DEFAULT]` — logging and messaging

This section is provided by oslo.log and oslo.messaging. The most important option for production is `transport_url`.

| Option | Type | Default | Description |
|---|---|---|---|
| `debug` | bool | `false` | Set to `true` to emit DEBUG-level log lines. Hot-reloadable (no restart needed). |
| `log_file` | string | _(stderr)_ | Path for log output. Omit to write to stderr (recommended in containers). |
| `use_json` | bool | `false` | Emit structured JSON log lines — recommended for log aggregators such as Elasticsearch or Loki. |
| `use_journal` | bool | `false` | Send logs to systemd-journald using the native protocol. Useful on RHEL hosts. |
| `transport_url` | string | `rabbit://` | Full RabbitMQ (or other oslo.messaging backend) URL. **Required** — the bare default connects to localhost with no credentials. Override with `ABACA_TRANSPORT_URL` in container environments. |
| `rpc_response_timeout` | int | `60` | Seconds to wait for a synchronous RPC response. Increase on slow or high-latency networks. |

---

### `[abaca]` — service identity

These values are served on the unauthenticated `/v1/service_info` endpoint so tenants can create Keystone trusts to the correct trustee without needing user-list privileges.

| Option | Type | Default | Env override | Description |
|---|---|---|---|---|
| `service_user_id` | string | _(none)_ | `ABACA_SERVICE_USER_ID` | Keystone UUID of the Abacá service account. Populated by the deploy pipeline; tenants read it via `/v1/service_info`. **Required** in production. |
| `service_user_name` | string | `abaca` | `ABACA_SERVICE_USER_NAME` | Keystone username of the service account. |
| `worker_project_id` | string | _(none)_ | `ABACA_WORKER_PROJECT_ID` | Keystone project UUID where worker VMs run. Advertised on `/v1/service_info`. |
| `worker_project_name` | string | `abaca` | `ABACA_WORKER_PROJECT_NAME` | Keystone project name for worker VMs. |

---

### `[api]` — HTTP server

| Option | Type | Default | Description |
|---|---|---|---|
| `bind_host` | string | `0.0.0.0` | IP address the API server binds to. Set to `127.0.0.1` to restrict to localhost (e.g., behind an ingress proxy). |
| `bind_port` | port (int) | `9797` | TCP port the API server listens on. |
| `noauth` | bool | `false` | **Development only.** Bypasses keystonemiddleware and injects a fake admin context. **Never enable in production.** The `enrollment.dispatch=inline` mode also refuses to start unless `noauth=true`, providing a second safety lock. |
| `max_limit` | int | `1000` | Hard upper bound on the `limit` query parameter for list endpoints. |
| `default_limit` | int | `100` | Page size used when the caller omits `limit`. |

---

### `[database]` — persistence

| Option | Type | Default | Env override | Description |
|---|---|---|---|---|
| `connection` | string | `sqlite:///abaca.sqlite` | `ABACA_DATABASE_CONNECTION` | SQLAlchemy connection URL. The SQLite default lets you run a dev stack with no external database; **always set a real MySQL/MariaDB URL in production**. Marked `secret=True` so oslo.config redacts it from log output. |

For production, use:

```ini
[database]
connection = mysql+pymysql://abaca:PASSWORD@DB_HOST/abaca?charset=utf8mb4
```

---

### `[conductor]` — scheduling, reconciliation, and worker fleet

#### Scheduling and reconciliation

| Option | Type | Default | Description |
|---|---|---|---|
| `scheduler_interval` | int | `60` | Seconds between passes over protection policies to trigger scheduled backups. Lower values reduce scheduling latency; higher values reduce database load. |
| `reconciliation_interval` | int | `300` | Seconds between reconciliation loop passes. The loop heals stuck jobs, orphaned workers, and database drift. See also `queued_job_deadline_seconds`. |
| `maintenance_interval_seconds` | int | `604800` (7 days) | How often the conductor enqueues a `kopia maintenance run --full` job per enrolled backup target. This is the only way Kopia reclaims S3 storage from blobs orphaned by retention pruning. Safe to run concurrently with backups. |
| `usage_sample_interval_seconds` | int | `21600` (6 h) | How often the conductor samples `kopia content stats` per enrolled target and persists the result as post-dedup, post-compression bytes on S3. This number is more accurate than summing `Backup.size_bytes` because it accounts for cross-snapshot deduplication. Read-only against the repository; safe to run concurrently. |
| `queued_job_deadline_seconds` | int | `300` | Seconds a job may sit in the `queued` state with no assigned worker before the reconciliation loop re-dispatches it. Guards against dropped RPC casts caused by broker hiccups. |

#### Heartbeat

| Option | Type | Default | Description |
|---|---|---|---|
| `worker_heartbeat_interval_seconds` | int | `10` | How often a running `abaca-worker-agent` sends a heartbeat RPC cast to the conductor. Must be comfortably less than `worker_heartbeat_deadline_seconds`. |
| `worker_heartbeat_deadline_seconds` | int | `60` | Seconds after the last heartbeat before the conductor marks a worker DEAD and reassigns its in-flight job. Increase this only if your network regularly drops heartbeat cycles. |
| `worker_agent_topic` | string | `abaca-worker` | oslo.messaging topic used to address worker agents. Change only if you have a custom RabbitMQ topology. |

#### Worker warm-pool (autoscale floor)

By default (`min_workers = 0`) the warm-pool sweep is **disabled** and operators must boot workers manually using `abaca-dev worker-boot`. When you set `min_workers > 0`, the conductor's reconciliation loop boots new VMs until the ACTIVE worker count reaches the floor.

| Option | Type | Default | Description |
|---|---|---|---|
| `min_workers` | int | `0` | Minimum number of ACTIVE worker VMs to keep running. `0` disables automatic booting. |
| `worker_boot_cooldown_seconds` | int | `180` | Minimum gap between consecutive boot attempts. Cloud-init typically finishes in 30–90 s; 180 s prevents double-booting when the loop ticks before the previous VM registers. |
| `worker_boot_os_cloud` | string | `abaca-service` | `clouds.yaml` entry the conductor uses to authenticate against Nova when booting workers. The file must be mounted at `/etc/openstack/clouds.yaml` inside the conductor container. |
| `worker_boot_image` | string | `abaca-worker-0.23.1` | Glance image to boot. Must carry the `abaca_worker_image=1` property; the fleet manager enforces this. |
| `worker_boot_flavor` | string | `m1.small` | Nova flavor for automatically booted workers. |
| `worker_boot_network` | string | _(none)_ | Neutron network ID or name the warm-pool worker attaches to. Must be reachable from Manila share networks and the RabbitMQ broker. **Required** when `min_workers > 0`; the conductor logs a WARNING and skips booting when unset. |
| `worker_boot_key_name` | string | _(none)_ | Nova keypair injected into automatically booted workers. **Required** when `min_workers > 0`. |

---

### `[kopia]` — backup engine

| Option | Type | Default | Env override | Description |
|---|---|---|---|---|
| `binary` | string | `kopia` | — | Path to the Kopia CLI binary inside the worker image. Override if your image places `kopia` outside `$PATH`. |
| `require_fips_profile` | bool | `true` | — | Refuse to create a Kopia repository unless the FIPS 140-approved cryptographic profile can be applied. This is a supported, validated production configuration; **do not set to `false`** unless you have explicitly accepted the compliance implications. |
| `subprocess_timeout` | int | `3600` | — | Maximum seconds a single Kopia subprocess may run before the agent kills it. Increase for very large shares or slow S3 endpoints. |
| `executor` | string | `worker_rpc` | `ABACA_KOPIA_EXECUTOR` | How Kopia commands are executed. `worker_rpc` (production) dispatches to a worker VM via oslo.messaging — the conductor never holds tenant credentials. `ephemeral_container` is a **development-only** mode that runs Kopia in a throwaway container on the conductor host; in this mode the conductor briefly holds tenant credentials. **Do not use `ephemeral_container` in production.** |
| `image` | string | `abaca-kopia:0.23.1` | `ABACA_KOPIA_IMAGE` | Container image used when `executor=ephemeral_container`. Always pin to an explicit version tag; never use `:latest`. |
| `container_engine` | string | `docker` | `ABACA_KOPIA_CONTAINER_ENGINE` | Container engine (`docker` or `podman`) for the ephemeral executor. The argument vector is podman-compatible. |
| `container_network` | string | `host` | `ABACA_KOPIA_CONTAINER_NETWORK` | Docker/Podman network for ephemeral containers. Use `host` on Kolla controllers. On a Compose stack, use the Compose network name so MinIO is reachable by service DNS. |

---

### `[worker]` — worker-agent runtime

| Option | Type | Default | Description |
|---|---|---|---|
| `mount_base` | string | `/var/lib/abaca/mnt` | Base directory inside a worker VM under which Manila shares are mounted during a job. Each job gets a subdirectory under this path; the directory is cleaned up when the job completes. |

---

### `[enrollment]` — target enrollment behaviour

| Option | Type | Default | Env override | Description |
|---|---|---|---|---|
| `dispatch` | string | `rpc` | `ABACA_ENROLLMENT_DISPATCH` | How enrollment jobs are dispatched. `rpc` (production and functional tests) creates the job row and casts to the conductor via oslo.messaging. `inline` is a **unit-test harness only** — it drives the state machine in-process with no broker. The API refuses to start with `dispatch=inline` unless `api.noauth=true`, preventing accidental use on real clusters. |

---

### `[keystone_authtoken]` — Keystone middleware

This section is provided by `keystonemiddleware`. The options most commonly set in Abacá deployments are:

```ini
[keystone_authtoken]
www_authenticate_uri         = http://KEYSTONE_VIP:5000
auth_url                     = http://KEYSTONE_VIP:5000
memcached_servers            = MEMCACHE_HOST:11211
auth_type                    = password
project_domain_name          = Default
user_domain_name             = Default
project_name                 = service
username                     = abaca
password                     = ABACA_SERVICE_PASSWORD
service_token_roles          = service
service_token_roles_required = true
region_name                  = RegionOne
```

Refer to the [keystonemiddleware documentation](https://docs.openstack.org/keystonemiddleware/latest/) for the full option reference.

---

### Environment variable overrides

A subset of options can be set via environment variables, which is the intended mechanism for Docker Compose and other container deployments that do not mount a config file.

| Environment variable | Overrides | Notes |
|---|---|---|
| `ABACA_DATABASE_CONNECTION` | `[database] connection` | Full SQLAlchemy URL |
| `ABACA_TRANSPORT_URL` | `[DEFAULT] transport_url` | Full oslo.messaging URL |
| `ABACA_SERVICE_USER_ID` | `[abaca] service_user_id` | Keystone user UUID |
| `ABACA_SERVICE_USER_NAME` | `[abaca] service_user_name` | Keystone username |
| `ABACA_WORKER_PROJECT_ID` | `[abaca] worker_project_id` | Keystone project UUID |
| `ABACA_WORKER_PROJECT_NAME` | `[abaca] worker_project_name` | Keystone project name |
| `ABACA_KOPIA_EXECUTOR` | `[kopia] executor` | `worker_rpc` or `ephemeral_container` |
| `ABACA_KOPIA_IMAGE` | `[kopia] image` | Container image for ephemeral executor |
| `ABACA_KOPIA_CONTAINER_ENGINE` | `[kopia] container_engine` | `docker` or `podman` |
| `ABACA_KOPIA_CONTAINER_NETWORK` | `[kopia] container_network` | Network name/mode |
| `ABACA_ENROLLMENT_DISPATCH` | `[enrollment] dispatch` | `rpc` or `inline` |

When a config file is present, its values take precedence over environment variables for all options **except** `transport_url`, where the environment variable is set as the oslo.config default before file parsing and is therefore overridden by an explicit `transport_url =` line in the file.

## Usage

### Production: config file on OpenShift or Kolla

In a production deployment the config file lives at `/etc/abaca/abaca.conf` and is mounted into each container. The Kolla deploy script `deploy/kolla/06-config.sh` renders and installs separate files for the API and conductor:

- `/etc/kolla/abaca-api/abaca.conf` — includes the `[api]` section
- `/etc/kolla/abaca-conductor/abaca.conf` — includes the `[conductor]` section

Both files share the same `[DEFAULT]`, `[database]`, `[keystone_authtoken]`, `[abaca]`, `[enrollment]`, and `[kopia]` sections. You do not need to pass `--config-file` when oslo.config can find the file via the `project=abaca` convention.

### Development: Docker Compose without a config file

The Docker Compose development stack uses environment variables instead of a mounted config file. Set them in your shell or in a `.env` file that Compose picks up automatically:

```bash
export ABACA_DATABASE_CONNECTION="mysql+pymysql://abaca:dev@localhost/abaca?charset=utf8mb4"
export ABACA_TRANSPORT_URL="rabbit://abaca:dev@localhost:5672/abaca"
export ABACA_KOPIA_EXECUTOR="ephemeral_container"
export ABACA_KOPIA_IMAGE="abaca-kopia:0.23.1"
export ABACA_KOPIA_CONTAINER_ENGINE="docker"
export ABACA_KOPIA_CONTAINER_NETWORK="abaca_default"
```

Also set `[api] noauth = true` (via the file) or pass it on the command line when you want to bypass Keystone during local development:

```bash
abaca-api --config-file /etc/abaca/abaca.conf --config-option api.noauth=true
```

> **Warning:** `noauth=true` disables all authentication. Never run this in an environment that handles real tenant data.

### Tuning the conductor's scheduling cadence

If you have many protection policies and the scheduler is consuming noticeable database CPU, increase `scheduler_interval`. If you need backups to start more promptly after their scheduled time, decrease it. The reconciliation loop interval (`reconciliation_interval`) should remain at or below the `worker_heartbeat_deadline_seconds` value so that dead workers are detected within one loop pass.

A safe starting set of conductor values for a medium-sized deployment:

```ini
[conductor]
scheduler_interval              = 60
reconciliation_interval         = 300
worker_heartbeat_deadline_seconds = 60
worker_heartbeat_interval_seconds = 10
queued_job_deadline_seconds     = 300
maintenance_interval_seconds    = 604800
usage_sample_interval_seconds   = 21600
```

### Enabling the warm-pool autoscale floor

To keep a standing pool of worker VMs ready (rather than relying on manual `abaca-dev worker-boot`):

```ini
[conductor]
min_workers                  = 2
worker_boot_cooldown_seconds = 180
worker_boot_os_cloud         = abaca-service
worker_boot_image            = abaca-worker-0.23.1
worker_boot_flavor           = m1.small
worker_boot_network          = abaca-worker-net
worker_boot_key_name         = abaca-deploy-key
```

Make sure `/etc/openstack/clouds.yaml` is mounted into the conductor container with an entry named `abaca-service` that has credentials sufficient to call Nova.

### FIPS mode

FIPS 140 compliance is the default (`[kopia] require_fips_profile = true`). Worker VMs run RHEL in FIPS mode and Kopia is configured to use only FIPS-approved algorithms. You do not need to set any additional option to enable FIPS — it is on unless you explicitly disable it. Do not disable it in regulated environments.

## Examples

### Example 1 — Minimal production config (API service)

A complete, working config for the `abaca-api` service on a Kolla-managed controller. Replace placeholder values with your actual hosts and passwords.

```ini
[DEFAULT]
debug         = false
use_stderr    = true
transport_url = rabbit://abaca:RABBIT_PASSWORD@rabbit.internal:5672/abaca

[database]
connection = mysql+pymysql://abaca:DB_PASSWORD@db.internal/abaca?charset=utf8mb4

[keystone_authtoken]
www_authenticate_uri         = http://keystone.internal:5000
auth_url                     = http://keystone.internal:5000
memcached_servers            = keystone.internal:11211
auth_type                    = password
project_domain_name          = Default
user_domain_name             = Default
project_name                 = service
username                     = abaca
password                     = ABACA_SERVICE_PASSWORD
service_token_roles          = service
service_token_roles_required = true
region_name                  = RegionOne

[abaca]
service_user_id     = a1b2c3d4-e5f6-7890-abcd-ef1234567890
service_user_name   = abaca
worker_project_id   = f0e1d2c3-b4a5-6789-fedc-ba0987654321
worker_project_name = abaca

[api]
bind_host = 0.0.0.0
bind_port = 9797
noauth    = false

[enrollment]
dispatch = rpc

[kopia]
executor           = worker_rpc
require_fips_profile = true
```

Start the API:

```bash
abaca-api --config-file /etc/abaca/abaca.conf
```

Expected: the service logs startup at INFO level and binds to `0.0.0.0:9797`.

---

### Example 2 — Conductor config with warm-pool enabled

```ini
[DEFAULT]
debug         = false
use_stderr    = true
transport_url = rabbit://abaca:RABBIT_PASSWORD@rabbit.internal:5672/abaca

[database]
connection = mysql+pymysql://abaca:DB_PASSWORD@db.internal/abaca?charset=utf8mb4

[keystone_authtoken]
www_authenticate_uri = http://keystone.internal:5000
auth_url             = http://keystone.internal:5000
auth_type            = password
project_domain_name  = Default
user_domain_name     = Default
project_name         = service
username             = abaca
password             = ABACA_SERVICE_PASSWORD
service_token_roles          = service
service_token_roles_required = true

[abaca]
service_user_id     = a1b2c3d4-e5f6-7890-abcd-ef1234567890
service_user_name   = abaca
worker_project_id   = f0e1d2c3-b4a5-6789-fedc-ba0987654321
worker_project_name = abaca

[enrollment]
dispatch = rpc

[conductor]
scheduler_interval               = 60
reconciliation_interval          = 300
worker_heartbeat_deadline_seconds = 60
worker_heartbeat_interval_seconds = 10
queued_job_deadline_seconds      = 300
maintenance_interval_seconds     = 604800
usage_sample_interval_seconds    = 21600
min_workers                      = 2
worker_boot_cooldown_seconds     = 180
worker_boot_os_cloud             = abaca-service
worker_boot_image                = abaca-worker-0.23.1
worker_boot_flavor               = m1.small
worker_boot_network              = abaca-worker-net
worker_boot_key_name             = abaca-deploy-key

[kopia]
executor             = worker_rpc
require_fips_profile = true
```

Start the conductor:

```bash
abaca-conductor --config-file /etc/abaca/abaca.conf
```

Expected: the conductor logs that it is starting the scheduler loop (every 60 s), the reconciliation loop (every 300 s), and the warm-pool sweep. Within one reconciliation cycle it boots worker VMs until the ACTIVE count reaches 2.

---

### Example 3 — Local Docker Compose dev stack (environment variables only)

No config file is needed. Export environment variables, then start the services:

```bash
export ABACA_DATABASE_CONNECTION="sqlite:///abaca-dev.sqlite"
export ABACA_TRANSPORT_URL="rabbit://guest:guest@localhost:5672/"
export ABACA_SERVICE_USER_NAME="abaca"
export ABACA_KOPIA_EXECUTOR="ephemeral_container"
export ABACA_KOPIA_IMAGE="abaca-kopia:0.23.1"
export ABACA_KOPIA_CONTAINER_ENGINE="docker"
export ABACA_KOPIA_CONTAINER_NETWORK="host"
export ABACA_ENROLLMENT_DISPATCH="rpc"

# Run the database migration first
abaca-manage db_sync

# Start the API with noauth for local testing
abaca-api --config-option api.noauth=true
```

Expected: the API starts on `0.0.0.0:9797` and accepts unauthenticated requests with a fake admin context injected. All Kopia commands run in ephemeral Docker containers on the local host.

---

### Example 4 — Regenerating the sample config after adding an option

After editing `abaca/common/config.py` to add or modify an option:

```bash
# Regenerate in-place
tox -e sample-config

# Verify the checked-in copy matches (CI runs this step)
tox -e sample-config-check
```

Expected output of `sample-config-check` when the sample is current:

```
sample-config-check: commands succeeded
```

If the check fails, it means the checked-in `etc/abaca.conf.sample` has drifted from the code — run `tox -e sample-config` and commit the result.

## Troubleshooting

### Issue 1 — Service fails to start: `NoValidConnection` or `OperationalError` connecting to the database

**Symptom:** `abaca-api` or `abaca-conductor` exits immediately with a SQLAlchemy `OperationalError` or a connection refused error referencing `sqlite:///abaca.sqlite` (or your configured URL).

**Likely cause:** The `[database] connection` option is unset (falling back to the SQLite default) or points to a host/port that is not reachable from the container.

**Fix:**
1. Check the effective value: `abaca-manage --config-file /etc/abaca/abaca.conf config_file` (or inspect the `[database]` section of your config).
2. Set `connection` to the correct MySQL/MariaDB URL, or export `ABACA_DATABASE_CONNECTION`.
3. Make sure the database host is reachable from within the container and that the credentials are correct.
4. Run `abaca-manage --config-file /etc/abaca/abaca.conf db_sync` to confirm connectivity before starting the service.

---

### Issue 2 — Service fails to start: `MessagingTimeout` or `kombu.exceptions.OperationalError` for RabbitMQ

**Symptom:** The conductor or API logs a RabbitMQ connection error and exits, or hangs at startup.

**Likely cause:** `[DEFAULT] transport_url` is the bare default `rabbit://` (connects to localhost with no credentials) or points to a host that is not reachable.

**Fix:**
1. Set `transport_url` in `[DEFAULT]` to the full URL: `rabbit://USER:PASSWORD@HOST:5672/VHOST`.
2. Alternatively, export `ABACA_TRANSPORT_URL` before starting the service.
3. Verify connectivity: `python3 -c "import kombu; kombu.Connection('amqp://USER:PASSWORD@HOST:5672/VHOST').ensure_connection()"`.

---

### Issue 3 — API returns 401 Unauthorized for all requests

**Symptom:** Every API call returns `401 Unauthorized` with a `WWW-Authenticate` header pointing at Keystone.

**Likely cause:** The `[keystone_authtoken]` section is missing or has incorrect `auth_url`, `username`, or `password` values, causing keystonemiddleware to reject the service token validation.

**Fix:**
1. Confirm the `abaca` service user exists in Keystone and its password matches `[keystone_authtoken] password`.
2. Check `www_authenticate_uri` and `auth_url` point to a reachable Keystone endpoint.
3. If you are running a local dev stack and want to skip Keystone, set `[api] noauth = true` — but **never in production**.

---

### Issue 4 — `noauth=true` is set but enrollment fails with `dispatch=inline refused`

**Symptom:** The API starts with `noauth=true` but enrollment calls return an error saying `dispatch=inline is refused`.

**Likely cause:** `[enrollment] dispatch` is set to `inline` (the unit-test harness), but this mode is only permitted when `api.noauth=true`. Check whether both are set consistently.

**Fix:** For a real development stack, use `dispatch = rpc` (the default) and make sure RabbitMQ and the conductor are running. Only set `dispatch = inline` in pure unit-test contexts where no broker or conductor exists.

---

### Issue 5 — Kopia repository creation fails: `FIPS profile cannot be applied`

**Symptom:** Enrollment jobs fail with an error indicating the FIPS cryptographic profile cannot be applied.

**Likely cause:** The worker VM is not running in RHEL FIPS mode, or the Kopia binary in the worker image does not support the FIPS profile.

**Fix:**
1. Verify the worker image was built with FIPS mode enabled (RHEL FIPS mode, Kopia ≥ 0.23.1).
2. Confirm the Glance image carries the `abaca_worker_image=1` property.
3. If you are in a non-regulated environment and deliberately want to skip FIPS, set `[kopia] require_fips_profile = false` — but document and approve this exception explicitly.

---

### Issue 6 — Warm-pool sweep boots no workers despite `min_workers > 0`

**Symptom:** The conductor logs a WARNING and the worker count does not rise to `min_workers`.

**Likely cause:** `worker_boot_network` or `worker_boot_key_name` is unset; the sweep no-ops and logs a warning when either is missing.

**Fix:**
1. Set `[conductor] worker_boot_network` to the Neutron network ID or name that is reachable from Manila share networks and the RabbitMQ broker.
2. Set `[conductor] worker_boot_key_name` to a valid Nova keypair name.
3. Confirm `[conductor] worker_boot_os_cloud` matches an entry in `/etc/openstack/clouds.yaml` that is mounted into the conductor container.
4. Confirm the Glance image named in `worker_boot_image` exists and has the `abaca_worker_image=1` property.

---

### Issue 7 — The sample config file is out of date in CI

**Symptom:** The `sample-config-check` CI job fails with a diff showing the checked-in `etc/abaca.conf.sample` does not match a fresh generation.

**Likely cause:** Someone added or modified an option in `abaca/common/config.py` without regenerating the sample.

**Fix:**
```bash
tox -e sample-config
git add etc/abaca.conf.sample
git commit -m "regen sample config"
```
