> ## Documentation Index
> Fetch the complete documentation index at: https://docs.infraudit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting Your Self-Hosted InfraAudit Deployment

> Fixes for common self-hosting issues: containers that won't start, Supabase authentication errors, missing cloud resources, and scans that don't run.

This page covers the most common issues encountered when deploying and running InfraAudit. Issues are organized by symptom. If you don't find your issue here, check the [FAQ](/resources/faq) or open a [GitHub issue](https://github.com/pratik-mahalle/infraudit-go/issues).

## Container startup issues

<AccordionGroup>
  <Accordion title="SUPABASE_JWT_SECRET is required">
    The API validates the Supabase JWT secret at startup and will not boot without it.

    **Fixes:**

    * Check that `SUPABASE_JWT_SECRET` is set in your `.env` file.
    * Verify you copied it from **Project Settings → API → JWT Settings** in Supabase — not the `anon` key or `service_role` key.
    * Make sure the variable name is spelled exactly right, with no trailing spaces or quotes around the value.
  </Accordion>

  <Accordion title="failed to connect to database">
    ```
    api_1  | FATAL: failed to connect to database: dial tcp postgres:5432: connect: connection refused
    ```

    **Fixes:**

    * The Postgres container may still be starting. Wait 10–15 seconds and run `docker compose up -d` again — it's idempotent.
    * Check that `DB_HOST`, `DB_PORT`, `DB_USER`, and `DB_PASSWORD` in `.env` match your Postgres configuration.
    * For Docker Compose, `DB_HOST` should be `postgres` (the service name), not `localhost`.
  </Accordion>

  <Accordion title="Port 8080 already in use">
    ```
    Error: listen tcp :8080: bind: address already in use
    ```

    **Fix:** Change `SERVER_PORT` in `.env` to an available port and update the port mapping in `docker-compose.yml`:

    ```yaml theme={null}
    ports:
      - "9090:9090"  # left side is the host port
    ```
  </Accordion>

  <Accordion title="Migration failure at startup">
    ```
    api_1  | migration 0012_add_anomaly_table.up.sql: ERROR: column "threshold" already exists
    ```

    A migration was partially applied. To reset:

    1. Drop the migration tracking table (this marks all migrations as unapplied):

    ```bash theme={null}
    docker compose exec postgres psql -U infraudit infraudit \
      -c "DROP TABLE IF EXISTS schema_migrations;"
    ```

    2. Restart the API — it will re-run all migrations.

    If the error is a conflict (column already exists) from a specific migration, you can mark that migration as applied without re-running it:

    ```bash theme={null}
    docker compose exec postgres psql -U infraudit infraudit \
      -c "INSERT INTO schema_migrations (version, dirty) VALUES (12, false);"
    ```
  </Accordion>
</AccordionGroup>

## Authentication errors

<AccordionGroup>
  <Accordion title="401 Unauthorized on all API requests">
    **Fixes:**

    * Verify that `SUPABASE_URL` and `SUPABASE_JWT_SECRET` in `.env` match the values in your Supabase project under **Settings → API**.
    * Check that the frontend and API are configured to use the **same** Supabase project. A common mistake is running the frontend against a different Supabase project than the API.
    * If you recently rotated the JWT secret in Supabase, update `SUPABASE_JWT_SECRET` in `.env` and restart the API.
  </Accordion>

  <Accordion title="Cannot log in — redirect errors in the browser">
    **Fixes:**

    * In your Supabase project, go to **Authentication → URL Configuration** and set the **Site URL** to your frontend URL (e.g. `http://localhost:5173`).
    * Add your frontend URL to the **Redirect URLs** allowlist in the same section.
    * If you've changed `FRONTEND_URL` in `.env`, make sure the new URL is also added to Supabase.
  </Accordion>
</AccordionGroup>

## Resources not appearing

<AccordionGroup>
  <Accordion title="No resources appear after connecting a provider">
    The initial resource sync runs in the background after you connect a provider. For small accounts it takes under a minute; for large accounts with 1,000 or more resources, it can take up to 10 minutes.

    **Check the sync status:**

    In the InfraAudit UI, go to **Cloud Providers** and look at the provider's status:

    * `syncing` — the sync is in progress, wait for it to complete
    * `synced` — the sync finished; resources should be visible
    * `error` — the sync failed; click the provider to see the error message

    If the status shows `error`, the most likely cause is invalid credentials or missing IAM permissions. See the relevant integration guide for required permissions:

    * [AWS integration](/integrations/aws)
    * [GCP integration](/integrations/gcp)
    * [Azure integration](/integrations/azure)
  </Accordion>

  <Accordion title="Drift detection returns zero findings after first setup">
    This is expected behavior. InfraAudit captures baselines during the initial resource sync. The drift scanner compares live state against those baselines, so on the very first scan there is nothing to compare against.

    To see drift findings:

    1. Make a change in your cloud account (add a tag, modify a security group rule, etc.)
    2. Wait for or manually trigger a resource sync.
    3. Run drift detection — the change will appear as a finding.
  </Accordion>
</AccordionGroup>

## Scans not running

<AccordionGroup>
  <Accordion title="Scheduled scans are not executing">
    **Fixes:**

    * Check the `JOB_*_SCHEDULE` variables in your `.env`. The defaults use standard cron syntax — verify the expressions are valid.
    * Check the API logs for job scheduler errors: `docker compose logs api | grep -i "job\|scheduler\|cron"`.
    * Check `JOB_TIMEOUT_SECONDS` — if the previous job run timed out, the scheduler may be waiting for it to complete. The default is `300` seconds.
    * If using the `LOG_LEVEL=debug` setting, scheduler activity is logged at startup.
  </Accordion>

  <Accordion title="Scans time out on large accounts">
    For accounts with many resources, scans may exceed the default 5-minute timeout.

    **Fix:** Increase `JOB_TIMEOUT_SECONDS` in `.env`:

    ```env theme={null}
    JOB_TIMEOUT_SECONDS=900
    ```

    Restart the API for the change to take effect.
  </Accordion>
</AccordionGroup>

## Performance issues

<AccordionGroup>
  <Accordion title="High memory usage">
    Memory usage spikes during large vulnerability scans and compliance assessments — this is expected. If memory stays elevated after a job finishes, restart the API container:

    ```bash theme={null}
    docker compose restart api
    ```

    If memory consistently exceeds 1 GB during normal operation (not during scans), increase `DB_MAX_IDLE_CONNS` and reduce `DB_MAX_OPEN_CONNS` in your `.env` to reduce connection pool overhead.
  </Accordion>
</AccordionGroup>

## Viewing logs

```bash theme={null}
# Follow live API logs
docker compose logs -f api

# Show Postgres logs
docker compose logs postgres

# Show all containers
docker compose logs
```

Set `LOG_LEVEL=debug` in `.env` for verbose output. Remember to set it back to `info` when you're done — debug logging significantly increases log volume.

## Filing a GitHub issue

If you can't resolve an issue with this page, open an issue at [github.com/pratik-mahalle/infraudit-go/issues](https://github.com/pratik-mahalle/infraudit-go/issues). Include:

1. Your InfraAudit version: `docker compose exec api ./infraudit-api --version`
2. Your deployment method (Docker Compose, Kubernetes, or binary)
3. The full error log output
4. Your `.env` file contents with all secrets redacted
