diff --git a/README.md b/README.md index 346138d5..07bfc0c7 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/docker-compose.yml b/docker-compose.yml index 08fe4cf1..15c239f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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 diff --git a/docs/guides/self-hosting.md b/docs/guides/self-hosting.md index f174b850..9d1d164f 100644 --- a/docs/guides/self-hosting.md +++ b/docs/guides/self-hosting.md @@ -18,12 +18,14 @@ 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 | @@ -31,7 +33,8 @@ export AUTHSOME_BASE_URL=http://localhost:7998 | `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 | @@ -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 diff --git a/docs/site/concepts/the-daemon.mdx b/docs/site/concepts/the-daemon.mdx index 1ed50aa2..7ee0ce17 100644 --- a/docs/site/concepts/the-daemon.mdx +++ b/docs/site/concepts/the-daemon.mdx @@ -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 diff --git a/docs/site/installation.mdx b/docs/site/installation.mdx index eaebaf15..2268ffac 100644 --- a/docs/site/installation.mdx +++ b/docs/site/installation.mdx @@ -66,6 +66,10 @@ Authsome runs on Python 3.13 or newer. It ships as a single PyPI package with no + + 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. + + Every command in the docs is written as `authsome ` 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`. @@ -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/ diff --git a/docs/site/quickstart.mdx b/docs/site/quickstart.mdx index 69579a30..af9443ca 100644 --- a/docs/site/quickstart.mdx +++ b/docs/site/quickstart.mdx @@ -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). + + The CLI targets hosted Authsome by default. For local development or self-hosted deployments, set `AUTHSOME_BASE_URL` before running `authsome` commands. + + ## Verify the install ```bash diff --git a/docs/site/reference/cli.mdx b/docs/site/reference/cli.mdx index 78cf8a17..be7cae77 100644 --- a/docs/site/reference/cli.mdx +++ b/docs/site/reference/cli.mdx @@ -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 ` | Authenticate with PROVIDER using the configured flow. | | `logout ` | Log out of the specified PROVIDER connection. | diff --git a/docs/site/reference/environment-variables.mdx b/docs/site/reference/environment-variables.mdx index e659afac..d7ca4b2f 100644 --- a/docs/site/reference/environment-variables.mdx +++ b/docs/site/reference/environment-variables.mdx @@ -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 diff --git a/docs/site/troubleshooting/daemon-issues.mdx b/docs/site/troubleshooting/daemon-issues.mdx index 71462732..587e3309 100644 --- a/docs/site/troubleshooting/daemon-issues.mdx +++ b/docs/site/troubleshooting/daemon-issues.mdx @@ -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 @@ -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 ``` @@ -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). diff --git a/src/authsome/__init__.py b/src/authsome/__init__.py index ae168d79..98e5bf42 100644 --- a/src/authsome/__init__.py +++ b/src/authsome/__init__.py @@ -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 diff --git a/src/authsome/cli/commands/core.py b/src/authsome/cli/commands/core.py index 668615dc..f51d3412 100644 --- a/src/authsome/cli/commands/core.py +++ b/src/authsome/cli/commands/core.py @@ -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) diff --git a/src/authsome/cli/main.py b/src/authsome/cli/main.py index 6e95b9b5..19f558c3 100644 --- a/src/authsome/cli/main.py +++ b/src/authsome/cli/main.py @@ -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) diff --git a/src/authsome/config.py b/src/authsome/config.py index c5bb3997..3000cd7f 100644 --- a/src/authsome/config.py +++ b/src/authsome/config.py @@ -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.""" @@ -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: diff --git a/src/authsome/server/config.py b/src/authsome/server/config.py index 746aa9b8..2e1d0322 100644 --- a/src/authsome/server/config.py +++ b/src/authsome/server/config.py @@ -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") diff --git a/src/authsome/server/urls.py b/src/authsome/server/urls.py index a9786188..3a194a59 100644 --- a/src/authsome/server/urls.py +++ b/src/authsome/server/urls.py @@ -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: