--- warning: DO NOT CHANGE THIS MANUALLY, THIS IS GENERATED BY https://github.com/duckdb/community-extensions repository, check README there title: harbor excerpt: | DuckDB Community Extensions Client/server DuckDB over one HTTP port — web UI, JSON /sql, and native ATTACH (TYPE harbor) extension: name: harbor description: Client/server DuckDB over one HTTP port — web UI, JSON /sql, and native ATTACH (TYPE harbor) version: 0.4.0 language: C++ build: cmake license: MIT maintainers: - shreeve repo: github: shreeve/duckdb-harbor ref: 70a86f05775908e78b4479944c5beb40aac3e685 docs: hello_world: | -- Load the extension and start the server in the background. -- harbor_serve returns once the server is accepting connections; -- harbor_wait keeps the process alive in daemon mode (containers, -- systemd). LOAD harbor; CALL harbor_serve(bind := '127.0.0.1', port := 9494); -- ┌─────────────────────────────────┐ -- │ token │ -- ├─────────────────────────────────┤ -- │ a1b2c3d4e5f6... │ -- └─────────────────────────────────┘ -- Hit it from another shell: -- curl http://127.0.0.1:9494/health -- curl -H "Authorization: Bearer " \ -- -X POST http://127.0.0.1:9494/sql \ -- -H 'Content-Type: application/json' \ -- -d '{"sql":"SELECT 42 AS the_answer"}' -- -- {"ok":true,"kind":"select","columns":[{"name":"the_answer","duckdbType":"INTEGER","lossless":true}], -- "data":[[42]],"rowCount":1,"timeMs":0} -- Browser users open http://127.0.0.1:9494/ — the harbor login -- page asks for the token once, sets a HttpOnly SameSite=Strict -- cookie, then proxies the official DuckDB UI through. -- A second DuckDB attaches the server's catalog natively — catalog -- discovery and table scans both ride /sql, so multi-table JOINs, -- projection pushdown, and CLI autocomplete all work: -- LOAD harbor; -- ATTACH 'harbor:127.0.0.1:9494' AS h (TYPE harbor, TOKEN ''); -- SELECT * FROM h.main.orders o JOIN h.main.customers c USING (customer_id); -- Stop the server: CALL harbor_stop(); extended_description: | `harbor` is a single DuckDB extension. When loaded, your DuckDB instance turns into a client/server database on one HTTP port: | Surface | Endpoints | What it gives you | |---------------|----------------------------------------|---------------------------------------------------------------------------| | JSON SQL | `POST /sql`, `/sql/sessions/*` | NDJSON streaming + one-shot JSON, prepared params (incl. `LIST`/`STRUCT`/`MAP`), principal-owned sessions, `harbor_query_timeout_s` enforcement | | Native attach | client-side `ATTACH 'harbor:host' (TYPE harbor)` | Browse and query the server's catalog from any DuckDB — multi-table JOINs, projection pushdown, and CLI autocomplete; catalog + scans both ride `/sql` (read-only) | | DuckDB UI | `GET /`, `/ddb/*`, `/localEvents` | Cookie-gated proxy to the official DuckDB UI; CSP+nonce on the login page | | Admin | `/health`, `/whoami`, `/tables`, `/schema/:db/:t`, `/checkpoint`, `/sessions`, `/interrupt` | Centralized `__HARBOR_ADMIN__:resource:action` default-deny + `harbor_allow_admin_without_authz` operator opt-in | | Auth | `/auth/login`, `/auth/logout` | Bearer / X-Harbor-Token / HMAC-signed `harbor_session` cookie | All on the same port, against the same in-process DuckDB, with the same session pool and auth model. **Use cases:** - Operate one DuckDB process and let users hit it via whatever interface fits their tool: browser (UI), DuckDB CLI/clients (`ATTACH ... TYPE harbor`), backend code (`/sql`). - Bridge between SQL clients and apps without standing up a separate database server. - Container-native deployments — `harbor_wait()` blocks until SIGTERM so harbor runs cleanly under systemd / Docker / Kubernetes. **Status:** v0.4 release, tested across the DuckDB community-extension matrix (linux_amd64/arm64, osx_amd64/arm64, windows_amd64/_mingw, wasm_mvp/eh/threads). Source, design spec, contributor guide, full release notes: [github.com/shreeve/duckdb-harbor](https://github.com/shreeve/duckdb-harbor). Vendors the official `duckdb-ui`; targets DuckDB v1.5.3. extension_star_count: 12 extension_star_count_pretty: 12 extension_download_count: 817 extension_download_count_pretty: 817 image: '/images/community_extensions/social_preview/preview_community_extension_harbor.png' layout: community_extension_doc --- ### Installing and Loading ```sql INSTALL {{ page.extension.name }} FROM community; LOAD {{ page.extension.name }}; ``` {% if page.docs.hello_world %} ### Example ```sql {{ page.docs.hello_world }}``` {% endif %} {% if page.docs.extended_description %} ### About {{ page.extension.name }} {{ page.docs.extended_description }} {% endif %} ### Added Functions
| function_name | function_type | description | comment | examples | |--------------------------|---------------|-------------|---------|----------| | harbor_check_token | scalar | NULL | NULL | | | harbor_identify | table | NULL | NULL | | | harbor_nop_authorization | scalar | NULL | NULL | | | harbor_serve | table | NULL | NULL | | | harbor_stop | table | NULL | NULL | | | harbor_version | scalar | NULL | NULL | | | harbor_wait | table | NULL | NULL | | | whoami | table_macro | NULL | NULL | | ### Overloaded Functions
This extension does not add any function overloads. ### Added Types
This extension does not add any types. ### Added Settings
| name | description | input_type | scope | aliases | |----------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|--------|---------| | harbor_allow_admin_without_authz | When true AND no custom harbor_authorization_function is set, admin endpoints (__HARBOR_ADMIN__:*) bypass the internal default-deny rule. Off by default; harbor_serve logs a loud WARN at startup when the combination is in effect. | BOOLEAN | GLOBAL | [] | | harbor_auth_cookie_ttl_s | TTL in seconds for HMAC-signed harbor_session cookies issued by /auth/login (default 12h) | UBIGINT | GLOBAL | [] | | harbor_authentication_function | Name of a Harbor callback function for authentication | VARCHAR | GLOBAL | [] | | harbor_authorization_function | Name of a Harbor callback function for authorization | VARCHAR | GLOBAL | [] | | harbor_cors_origins | Comma-separated allow-list of origins for cross-origin /auth/*, /sql, /info (empty = no cross-origin permitted; '*' is rejected) | VARCHAR | GLOBAL | [] | | harbor_loaded_at_us | Epoch microseconds at extension load | BIGINT | GLOBAL | [] | | harbor_max_request_body_bytes | Maximum POST body size for /sql JSON requests; larger requests return 413 PAYLOAD_TOO_LARGE (default 256 MiB) | UBIGINT | GLOBAL | [] | | harbor_max_response_rows | Cap on rows returned per /sql request; 0 = unlimited; truncation reflected in the NDJSON end record's truncated:true field (default 0) | UBIGINT | GLOBAL | [] | | harbor_max_sessions | Maximum concurrent DB sessions across all principals; new session creation past this limit returns 429 SESSION_LIMIT (default 1024) | UBIGINT | GLOBAL | [] | | harbor_query_timeout_s | Per-query wall-clock timeout in seconds. 0 disables the timeout. Non-zero values interrupt any Connection::Execute (/sql, /ddb/run, admin transients) that runs longer than the configured limit, returning HTTP 504 with errorCode QUERY_TIMEOUT. Default 0. | UBIGINT | GLOBAL | [] | | harbor_stop_drain_timeout_s | Seconds harbor_stop waits for in-flight request handlers to drain per attempt before re-checking active requests (default 30; 0 = poll without waiting) | UBIGINT | GLOBAL | [] | | ui_polling_interval | UI catalog watcher polling interval in milliseconds (0 disables) | UINTEGER | GLOBAL | [] | | ui_remote_url | Remote URL the UI proxies GET /.* requests to (default ui.duckdb.org) | VARCHAR | GLOBAL | [] | | whoami_hostname | Network hostname / public address | VARCHAR | GLOBAL | [] | | whoami_meta | Provider-specific metadata as JSON | VARCHAR | GLOBAL | [] | | whoami_name | Human-readable name for this node | VARCHAR | GLOBAL | [] | | whoami_provider | Deployment provider (ec2, docker, local, ...) | VARCHAR | GLOBAL | [] | | whoami_region | Deployment region | VARCHAR | GLOBAL | [] | | whoami_started_at | Node start time (ISO-8601 TIMESTAMP) | VARCHAR | GLOBAL | [] |