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

# Hosting

> Deploy AgentLogs with the official GHCR image or standalone binary

# Hosting AgentLogs

AgentLogs server is available in two production-ready formats:

* Official Docker image: `ghcr.io/agentlogs/agentlogs`
* Official standalone binary: `agentlogs-server` for Linux, macOS, and Windows

Both run the same server runtime and support embedded migrations.

<Note>You must configure at least one OAuth provider. AgentLogs currently supports GitHub and GitLab login.</Note>

## Deploy

### Docker

Pull and run the official image:

```bash theme={null}
docker run -d \
  --name agentlogs \
  -p 3000:3000 \
  -v agentlogs-data:/app/.data \
  -e BETTER_AUTH_SECRET=... \
  -e WEB_URL=https://logs.example.com \
  -e GITHUB_CLIENT_ID=... \
  -e GITHUB_CLIENT_SECRET=... \
  ghcr.io/agentlogs/agentlogs:latest
```

Replace the GitHub variables with GitLab variables if you want GitLab-only login, or provide both sets if you want both providers enabled.

<Note>Mount `/app/.data` to persist both SQLite data and uploaded transcript blobs.</Note>

### Standalone Binary

Download a matching binary from the GitHub Releases page (`server-vX.Y.Z` tags), then run:

```bash theme={null}
chmod +x ./agentlogs-server
./agentlogs-server
```

* By default, the binary runs embedded migrations, then starts the server
* `--no-migrations` skips startup migrations
* `--only-migrations` runs migrations and exits

## Environment Variables

Before you deploy, make sure you have:

* `BETTER_AUTH_SECRET`
* `WEB_URL` set to your public hostname in production
* GitHub login: `GITHUB_CLIENT_ID` and `GITHUB_CLIENT_SECRET`, or GitLab login: `GITLAB_CLIENT_ID` and `GITLAB_CLIENT_SECRET`
* `GITLAB_ISSUER` if you use self-managed GitLab
* An AI summary backend if you want transcript titles generated automatically

### Authentication

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>BETTER\_AUTH\_SECRET</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>

      <td>
        Required. Generate with <code>openssl rand -base64 32</code>. Used to sign auth state and sessions.
      </td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>WEB\_URL</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>[http://localhost:3000](http://localhost:3000)</code>
      </td>

      <td>
        Public base URL of your app. Used for OAuth callbacks, auth origins, and browser redirects. Set this to your
        real public hostname in production.
      </td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>WAITLIST\_ENABLED</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>true</code>
      </td>

      <td>
        When enabled, new users default to the <code>waitlist</code> role. Set it to <code>false</code> to make new
        users regular users immediately.
      </td>
    </tr>
  </tbody>
</table>

### OAuth Providers

At least one provider must be configured.

If both GitHub and GitLab are configured, AgentLogs currently prefers GitHub for provider-agnostic login redirects such as browser login and device authorization.

#### GitHub

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>GITHUB\_CLIENT\_ID</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Required if GitHub login is enabled. GitHub OAuth app client ID.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>GITHUB\_CLIENT\_SECRET</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Required if GitHub login is enabled. GitHub OAuth app client secret.</td>
    </tr>
  </tbody>
</table>

#### GitLab

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>GITLAB\_CLIENT\_ID</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Required if GitLab login is enabled. GitLab OAuth/OIDC app client ID.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>GITLAB\_CLIENT\_SECRET</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Required if GitLab login is enabled. GitLab OAuth/OIDC app client secret.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>GITLAB\_ISSUER</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>[https://gitlab.com](https://gitlab.com)</code>
      </td>

      <td>Set this to your self-managed GitLab instance URL when not using gitlab.com.</td>
    </tr>
  </tbody>
</table>

### Storage

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>DB\_LOCAL\_PATH</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>.data/db.sqlite</code>
      </td>

      <td>SQLite database path.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>STORAGE\_DIR</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>.data/storage</code>
      </td>

      <td>Local blob storage directory for uploaded transcript assets.</td>
    </tr>
  </tbody>
</table>

### Email

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>RESEND\_API\_KEY</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Enables transactional email delivery.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>EMAIL\_SENDER</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>Philipp from AgentLogs \<[philipp@agentlogs.ai](mailto:philipp@agentlogs.ai)></code>
      </td>

      <td>Overrides the default transactional sender.</td>
    </tr>
  </tbody>
</table>

### AI Features

AgentLogs can generate short transcript titles during ingest. You can configure one of two backends:

* `AI_BASE_URL` and `AI_MODEL` for any OpenAI-compatible endpoint such as Ollama, vLLM, or LiteLLM
* `OPENROUTER_API_KEY` for the default hosted path through OpenRouter

If both `AI_BASE_URL` and `AI_MODEL` are set, AgentLogs prefers the OpenAI-compatible endpoint. If no AI backend is configured, summary generation falls back to a generic placeholder title.

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>OPENROUTER\_API\_KEY</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Enables AI-generated summaries through OpenRouter when no custom AI endpoint is configured.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>AI\_BASE\_URL</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>

      <td>
        Base URL for an OpenAI-compatible API. Typical values end in <code>/v1</code>.
      </td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>AI\_MODEL</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>

      <td>
        Required with <code>AI\_BASE\_URL</code>. Model identifier sent to the compatible endpoint.
      </td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>AI\_API\_KEY</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>unset</td>
      <td>Optional API key for the compatible endpoint. Leave blank for local providers that do not require auth.</td>
    </tr>
  </tbody>
</table>

#### OpenAI-compatible endpoints

Use these variables when you want AgentLogs to keep summary generation inside your own infrastructure:

```bash theme={null}
AI_BASE_URL=http://localhost:11434/v1
AI_MODEL=llama3.2
AI_API_KEY=
```

* For Docker deployments that call an Ollama server running on the host, use `http://host.docker.internal:11434/v1`
* For gateways like LiteLLM or vLLM, set `AI_MODEL` to the model name that gateway exposes

#### OpenRouter

Use OpenRouter when you want a hosted default without running your own model server:

```bash theme={null}
OPENROUTER_API_KEY=...
```

### Runtime

<table>
  <thead>
    <tr>
      <th>Variable</th>
      <th>Default</th>
      <th>Notes</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>HOST</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>0.0.0.0</code>
      </td>

      <td>HTTP bind host for the standalone server runtime.</td>
    </tr>

    <tr>
      <td style={{ whiteSpace: "nowrap" }}>
        <code>PORT</code>
      </td>

      <td style={{ whiteSpace: "nowrap" }}>
        <code>3000</code>
      </td>

      <td>HTTP port for the standalone server runtime.</td>
    </tr>
  </tbody>
</table>

## Configure Authentication Providers

### GitHub OAuth App

Create an OAuth app at [github.com/settings/developers](https://github.com/settings/developers):

* **Homepage URL**: `${WEB_URL}`
* **Authorization callback URL**: `${WEB_URL}/api/auth/callback/github`

Example for production:

* Homepage: `https://logs.example.com`
* Callback: `https://logs.example.com/api/auth/callback/github`

### GitLab OAuth / OIDC App

Create an OAuth application in your GitLab instance:

* **Redirect URI**: `${WEB_URL}/api/auth/oauth2/callback/gitlab`
* **Scopes**: `openid`, `profile`, `email`

Example for production:

* Issuer: `https://gitlab.com`
* Redirect URI: `https://logs.example.com/api/auth/oauth2/callback/gitlab`

For self-managed GitLab, set `GITLAB_ISSUER` to your instance base URL, for example `https://gitlab.company.internal`.

## Connect Your CLI And Plugins

Authenticate your CLI against your host:

```bash theme={null}
npx agentlogs login logs.example.com
```

Use your public hostname without `https://` so your local CLI and plugins upload to your own instance.

## Upgrade

When upgrading, deploy a newer image or binary and start it again:

* Docker: restart the container with the new tag; embedded migrations run on startup by default
* Binary: replace the binary and run `./agentlogs-server`
