Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,14 @@ Requires Python 3.13+.
uv tool install authsome
```

By default, the CLI talks to hosted Authsome at `https://api.authsome.ai`. To use a local or self-hosted daemon instead, set `AUTHSOME_BASE_URL`:

```bash
export AUTHSOME_BASE_URL=http://127.0.0.1:7998
```

You only need `AUTHSOME_CALLBACK_BASE_URL` when you operate a self-hosted server or run a local daemon on a non-default host or port. Set it to the URL users can open in their browser for claim and OAuth callback links.

## Self-hosting

Run a persistent daemon in Docker — no Python required on the host:
Expand Down
6 changes: 3 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ services:
- authsome-data:/data/authsome
environment:
AUTHSOME_HOME: /data/authsome
# Set this to the public URL of this server so OAuth callbacks resolve correctly.
# Example: AUTHSOME_SERVER_BASE_URL: https://auth.example.com
AUTHSOME_SERVER_BASE_URL: ""
# Self-hosted servers need this public URL so OAuth callbacks resolve correctly.
# Example: AUTHSOME_CALLBACK_BASE_URL: https://auth.example.com
AUTHSOME_CALLBACK_BASE_URL: http://localhost:7998
# Encryption mode: "local_key" (default) or "keyring"
AUTHSOME_ENCRYPTION_MODE: local_key
AUTHSOME_LOG_LEVEL: info
Expand Down
9 changes: 6 additions & 3 deletions docs/guides/self-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,23 @@ curl http://localhost:7998/health

The daemon is now available at `http://localhost:7998`.

Point agents at it by setting:
Authsome clients use hosted Authsome by default. Point agents at this self-hosted daemon by setting:

```bash
export AUTHSOME_BASE_URL=http://localhost:7998
```

Because this is a self-hosted server, set `AUTHSOME_CALLBACK_BASE_URL` to the URL users can open in their browser for claim, input, and OAuth callback links. The Docker Compose quick start sets it to `http://localhost:7998`. Change it only when you bind the daemon to a different host or port, or put it behind a reverse proxy.

## Environment variables

| Variable | Default | Description |
|---|---|---|
| `AUTHSOME_HOME` | `/data/authsome` | Root directory for credentials, keys, and the database |
| `AUTHSOME_HOST` | `0.0.0.0` | Interface the daemon binds to inside the container |
| `AUTHSOME_PORT` | `7998` | TCP port |
| `AUTHSOME_BASE_URL` | _(derived from host:port)_ | Public URL used to build OAuth callback URLs. **Must be set when behind a reverse proxy.** On client machines, set this to point the CLI at a remote daemon. |
| `AUTHSOME_BASE_URL` | `https://api.authsome.ai` | Client runtime target. On client machines, set this to point the CLI and proxy at a local or self-hosted daemon. |
| `AUTHSOME_CALLBACK_BASE_URL` | `http://127.0.0.1:7998` | Server public URL used to build claim, input, and OAuth callback links. Set this only for self-hosted servers or local daemons running on a non-default browser-facing host or port. |
| `AUTHSOME_ENCRYPTION_MODE` | `local_key` | `local_key` stores the master key on disk; `keyring` uses the OS keyring (not available in containers) |
| `AUTHSOME_LOG_LEVEL` | `info` | Uvicorn log level (`debug`, `info`, `warning`, `error`) |
| `AUTHSOME_ANALYTICS` | `1` | Set to `0` to disable telemetry |
Expand Down Expand Up @@ -83,7 +86,7 @@ services:
expose:
- "7998"
environment:
AUTHSOME_BASE_URL: https://auth.example.com
AUTHSOME_CALLBACK_BASE_URL: https://auth.example.com
volumes:
- authsome-data:/data/authsome

Expand Down
2 changes: 1 addition & 1 deletion docs/site/concepts/the-daemon.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ icon: "server"
keywords: ["authsome daemon", "AUTHSOME_BASE_URL", "AUTHSOME_BASE_URL", "authsome dashboard"]
---

Authsome operates as a persistent local daemon (by default running on `127.0.0.1:7998`). The CLI and the injection proxy act as thin clients that communicate with this daemon.
Authsome can operate against a persistent local daemon, usually running on `127.0.0.1:7998`. Hosted Authsome is the default client target; set `AUTHSOME_BASE_URL=http://127.0.0.1:7998` when you want the CLI and injection proxy to use a local daemon. You only need `AUTHSOME_CALLBACK_BASE_URL` for self-hosted servers or local daemons running on a non-default browser-facing host or port.

## Concept and motivation

Expand Down
6 changes: 5 additions & 1 deletion docs/site/installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ Authsome runs on Python 3.13 or newer. It ships as a single PyPI package with no
</Tab>
</Tabs>

<Note>
Authsome clients use hosted Authsome at `https://api.authsome.ai` by default. Set `AUTHSOME_BASE_URL` only when you want the CLI and proxy to use a local or self-hosted Authsome server.
</Note>

<Note>
Every command in the docs is written as `authsome <subcommand>` and assumes you ran `uv tool install authsome` (or `pip install authsome`). If you skipped install and prefer one-off runs, prefix every command with `uvx authsome@latest` instead of `authsome`.
</Note>
Expand All @@ -83,7 +87,7 @@ If `doctor` reports failures, see [Diagnose with doctor](/troubleshooting/doctor

## First-run initialization

On `authsome init`, authsome initializes its home directory at `~/.authsome/`, creates a generated identity handle and Ed25519 DID, and registers that identity with the local daemon:
On `authsome init`, authsome initializes its home directory at `~/.authsome/`, creates a generated identity handle and Ed25519 DID, and registers that identity with the configured Authsome server:

```text
~/.authsome/
Expand Down
4 changes: 4 additions & 0 deletions docs/site/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ This page covers both. Pick the one that matches how you will actually use it.
- Python 3.13 or newer
- A graphical browser on the same machine (for the initial login). For SSH or CI, see [Headless setup](/guides/headless-device-code).

<Note>
The CLI targets hosted Authsome by default. For local development or self-hosted deployments, set `AUTHSOME_BASE_URL` before running `authsome` commands.
</Note>

## Verify the install

```bash
Expand Down
2 changes: 1 addition & 1 deletion docs/site/reference/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ All commands support `--json` for machine-readable output, `--quiet` to suppress
| `connections` | Inspect and manage stored provider connections. |
| `daemon` | Manage the local Authsome daemon. |
| `doctor` | Run health checks on directory layout and encryption. |
| `init` | Initialize local storage and register a fresh profile. |
| `init` | Create a local identity and register it with the configured Authsome server. |
| `log` | View structured audit entries or the raw client debug log. |
| `login <provider>` | Authenticate with PROVIDER using the configured flow. |
| `logout <provider>` | Log out of the specified PROVIDER connection. |
Expand Down
27 changes: 21 additions & 6 deletions docs/site/reference/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,41 @@ Authsome interacts with environment variables in three roles: **inputs** that ch

| Variable | Purpose |
|----------|---------|
| `AUTHSOME_BASE_URL` | The daemon URL. On client machines, set this to point the CLI and proxy at a remote daemon instead of auto-starting one locally. On the daemon host, set this to the public URL when behind a reverse proxy — authsome uses it to build OAuth callback URLs such as `/auth/callback/oauth`. Defaults to `http://127.0.0.1:7998`. |
| `AUTHSOME_BASE_URL` | Client runtime target. Defaults to `https://api.authsome.ai`. Set this on client machines to point the CLI and proxy at a local or self-hosted daemon. |
| `AUTHSOME_CALLBACK_BASE_URL` | Server public URL used to build claim, input, device, success, and OAuth callback links. If unset, the server falls back to the default local daemon URL, `http://127.0.0.1:7998`. Set this only when you operate a self-hosted server or run a local daemon on a non-default browser-facing host or port. |
| `AUTHSOME_HOME` | Override the default `~/.authsome` directory. Useful for tests, ephemeral environments, and per-project vaults. |
| `HTTP_PROXY` / `HTTPS_PROXY` | Honored by authsome's own outbound HTTP requests (token endpoints, device flow polling). The proxy started by `authsome run` is **set** as these variables in the child process; it does not chain through them. |

### `AUTHSOME_BASE_URL` for remote daemons
### Runtime target and callback URL

For remote daemon deployments:

- set `AUTHSOME_BASE_URL` to the full daemon URL on client machines
- set `AUTHSOME_BASE_URL` to the public-facing URL on the daemon host when behind a reverse proxy
- set `AUTHSOME_CALLBACK_BASE_URL` on the daemon host only when you are self-hosting, such as behind a reverse proxy
- when `AUTHSOME_BASE_URL` points at a non-local host, the CLI will not attempt to manage daemon state

Example:
Client example:

```bash
export AUTHSOME_BASE_URL=https://authsome.internal.example.com
uv run authsome list
authsome provider list
```

When running the daemon locally, you typically do not need to set `AUTHSOME_BASE_URL`.
Server example:

```bash
export AUTHSOME_CALLBACK_BASE_URL=https://authsome.internal.example.com
authsome daemon serve
```

For local daemon mode, set `AUTHSOME_BASE_URL` explicitly:

```bash
export AUTHSOME_BASE_URL=http://127.0.0.1:7998
authsome login github
```

The default local daemon address, `http://127.0.0.1:7998`, does not need `AUTHSOME_CALLBACK_BASE_URL`. If you run the local daemon on a custom host or port, also set `AUTHSOME_CALLBACK_BASE_URL` to the browser-facing URL. Authsome does not infer callback URLs from custom daemon bind flags.

### Provider-specific input variables

Expand Down
7 changes: 4 additions & 3 deletions docs/site/troubleshooting/daemon-issues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Common root causes:

## CLI can't find the daemon

The CLI looks at `AUTHSOME_BASE_URL` first, then falls back to `http://127.0.0.1:7998`.
The CLI looks at `AUTHSOME_BASE_URL` first, then falls back to hosted Authsome at `https://api.authsome.ai`. Set `AUTHSOME_BASE_URL=http://127.0.0.1:7998` for local daemon mode.

```bash
echo $AUTHSOME_BASE_URL
Expand All @@ -63,7 +63,7 @@ echo $AUTHSOME_BASE_URL
If it's set to a hosted URL that's currently unreachable:

```bash
unset AUTHSOME_BASE_URL
export AUTHSOME_BASE_URL=http://127.0.0.1:7998
authsome whoami
```

Expand All @@ -72,7 +72,8 @@ The CLI will start a local daemon and verify it's reachable.
If you do want a hosted daemon and it's unreachable, the fix is on the daemon host. Check that:

- The daemon process is running there.
- `AUTHSOME_BASE_URL` on the daemon matches the URL you're calling.
- `AUTHSOME_BASE_URL` on the client matches the URL you're calling.
- if this is self-hosted, `AUTHSOME_CALLBACK_BASE_URL` on the daemon host matches the browser-facing URL used for claim and OAuth callback links.
- Ingress is allowed from your client's network (private VPC, VPN, or whatever the team uses).


Expand Down
11 changes: 6 additions & 5 deletions src/authsome/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
"""
Authsome — A portable local authentication library for AI agents and developer tools.
Authsome — A hosted-by-default authentication library for AI agents and developer tools.

Provides credential management for third-party services with support for:
- OAuth2 (PKCE, Device Code, DCR + PKCE)
- API key management
- Encrypted local storage (OS keyring or local file)
- Encrypted credential storage

Usage:
Run `authsome login openai` to start the local daemon and connect a
provider, then use `authsome run ...` to inject credentials through the
local proxy.
Run `authsome login openai` to connect a provider through the configured
Authsome server, then use `authsome run ...` to inject credentials through
the local proxy. Set `AUTHSOME_BASE_URL` to opt into a local or self-hosted
Authsome server.
"""

from importlib.metadata import PackageNotFoundError as _PkgNotFoundError
Expand Down
2 changes: 1 addition & 1 deletion src/authsome/cli/commands/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ async def run(ctx_obj: ContextObj, command: tuple[str]) -> None:
@click.command()
@auth_command
async def init(ctx_obj: ContextObj) -> None:
"""Initialize local storage and register a fresh profile."""
"""Create a local identity and register it with the configured Authsome server."""
home = get_authsome_config().home
RuntimeIdentity.ensure_local(home)

Expand Down
5 changes: 3 additions & 2 deletions src/authsome/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@
@common_options
@click.pass_context
def cli(ctx: click.Context, verbose: bool, log_file: str) -> None:
"""Authsome: Portable local authentication library for AI agents and tools.
"""Authsome: Credential broker for AI agents and tools.

Securely manage credentials and API keys for third-party providers from your terminal.
Uses hosted Authsome by default. Set AUTHSOME_BASE_URL to use a local daemon
or self-hosted Authsome server.
"""
resolved = Path(log_file) if log_file else None
setup_logging(verbose=verbose, log_file=resolved)
Expand Down
4 changes: 3 additions & 1 deletion src/authsome/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from authsome import __version__

DEFAULT_BASE_URL = "https://api.authsome.ai"


class AuthsomeConfig(BaseSettings):
"""Shared Authsome configuration resolved from environment variables."""
Expand All @@ -15,7 +17,7 @@ class AuthsomeConfig(BaseSettings):

version: str = __version__
home: Path = Field(default=Path.home() / ".authsome")
base_url: str = Field(default="http://127.0.0.1:7998")
base_url: str = Field(default=DEFAULT_BASE_URL)

@property
def client_home(self) -> Path:
Expand Down
1 change: 1 addition & 0 deletions src/authsome/server/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class ServerConfig(AuthsomeConfig):
# Network
host: str = "127.0.0.1"
port: int = 7998
callback_base_url: str | None = None

# Store
database_url: str | None = Field(default=None, validation_alias="DATABASE_URL")
Expand Down
6 changes: 4 additions & 2 deletions src/authsome/server/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@

# Invariant: must match the OAuth callback route declared in routes/auth.py.
DEFAULT_CALLBACK_PATH = "/api/auth/callback/oauth"
DEFAULT_LOCAL_SERVER_BASE_URL = "http://127.0.0.1:7998"


def build_server_base_url() -> str:
"""Return the canonical external base URL for the daemon."""
return get_server_config().base_url
config = get_server_config()
return config.callback_base_url or DEFAULT_LOCAL_SERVER_BASE_URL


def _base_url(base_url: str | None = None) -> str:
return (base_url or get_server_config().base_url).rstrip("/")
return (base_url or build_server_base_url()).rstrip("/")


def build_callback_url(base_url: str | None = None) -> str:
Expand Down
Loading