Skip to content

Commit 6d94943

Browse files
authored
Merge pull request #5 from PostHog/docs/update-readme
Update README with new features
2 parents 90a322e + 2e8a88c commit 6d94943

1 file changed

Lines changed: 138 additions & 28 deletions

File tree

‎README.md‎

Lines changed: 138 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ A PostgreSQL wire protocol compatible server backed by DuckDB. Connect with any
55
## Features
66

77
- **PostgreSQL Wire Protocol**: Full compatibility with PostgreSQL clients
8+
- **TLS Encryption**: Required TLS connections with auto-generated self-signed certificates
89
- **Per-User Databases**: Each authenticated user gets their own isolated DuckDB database file
9-
- **Simple Password Authentication**: Username/password authentication (cleartext)
10-
- **Extended Query Protocol**: Support for prepared statements and parameterized queries
11-
- **SQL Compatibility**: Run most SQL queries that DuckDB supports
10+
- **Password Authentication**: MD5 password authentication
11+
- **Extended Query Protocol**: Support for prepared statements, binary format, and parameterized queries
12+
- **DuckDB Extensions**: Configurable extension loading (ducklake enabled by default)
13+
- **DuckLake Integration**: Auto-attach DuckLake catalogs for lakehouse workflows
14+
- **Rate Limiting**: Built-in protection against brute-force attacks
15+
- **Flexible Configuration**: YAML config files, environment variables, and CLI flags
1216

1317
## Quick Start
1418

@@ -24,39 +28,137 @@ go build -o duckgres .
2428
./duckgres
2529
```
2630

27-
The server starts on port 5432 by default. Database files are stored in `./data/`.
31+
The server starts on port 5432 by default with TLS enabled. Database files are stored in `./data/`. Self-signed certificates are auto-generated in `./certs/` if not present.
2832

2933
### Connect
3034

3135
```bash
32-
# Using psql
33-
PGPASSWORD=postgres psql -h localhost -p 5432 -U postgres
36+
# Using psql (sslmode=require is needed for TLS)
37+
PGPASSWORD=postgres psql "host=localhost port=5432 user=postgres sslmode=require"
3438

3539
# Or with any PostgreSQL driver
3640
```
3741

3842
## Configuration
3943

40-
Configuration is currently done in `main.go`:
41-
42-
```go
43-
cfg := server.Config{
44-
Host: "0.0.0.0",
45-
Port: 5432,
46-
DataDir: "./data",
47-
Users: map[string]string{
48-
"postgres": "postgres",
49-
"alice": "alice123",
50-
"bob": "bob123",
51-
},
52-
}
44+
Duckgres supports three configuration methods (in order of precedence):
45+
1. CLI flags (highest priority)
46+
2. Environment variables
47+
3. YAML config file
48+
4. Built-in defaults (lowest priority)
49+
50+
### YAML Configuration
51+
52+
Create a `duckgres.yaml` file (see `duckgres.example.yaml` for a complete example):
53+
54+
```yaml
55+
host: "0.0.0.0"
56+
port: 5432
57+
data_dir: "./data"
58+
59+
tls:
60+
cert: "./certs/server.crt"
61+
key: "./certs/server.key"
62+
63+
users:
64+
postgres: "postgres"
65+
alice: "alice123"
66+
67+
extensions:
68+
- ducklake
69+
- httpfs
70+
71+
ducklake:
72+
metadata_store: "postgres:dbname=ducklake"
73+
data_path: "s3://my-bucket/ducklake-data/"
74+
75+
rate_limit:
76+
max_failed_attempts: 5
77+
failed_attempt_window: "5m"
78+
ban_duration: "15m"
79+
max_connections_per_ip: 100
80+
```
81+
82+
Run with config file:
83+
84+
```bash
85+
./duckgres --config duckgres.yaml
86+
```
87+
88+
### Environment Variables
89+
90+
| Variable | Description | Default |
91+
|----------|-------------|---------|
92+
| `DUCKGRES_CONFIG` | Path to YAML config file | - |
93+
| `DUCKGRES_HOST` | Host to bind to | `0.0.0.0` |
94+
| `DUCKGRES_PORT` | Port to listen on | `5432` |
95+
| `DUCKGRES_DATA_DIR` | Directory for DuckDB files | `./data` |
96+
| `DUCKGRES_CERT` | TLS certificate file | `./certs/server.crt` |
97+
| `DUCKGRES_KEY` | TLS private key file | `./certs/server.key` |
98+
| `DUCKGRES_DUCKLAKE_METADATA_STORE` | DuckLake metadata store | - |
99+
| `DUCKGRES_DUCKLAKE_DATA_PATH` | DuckLake data path | - |
100+
101+
### CLI Flags
102+
103+
```bash
104+
./duckgres --help
105+
106+
Options:
107+
-config string Path to YAML config file
108+
-host string Host to bind to
109+
-port int Port to listen on
110+
-data-dir string Directory for DuckDB files
111+
-cert string TLS certificate file
112+
-key string TLS private key file
113+
```
114+
115+
## DuckDB Extensions
116+
117+
Extensions are automatically installed and loaded when a user's database is first opened. The `ducklake` extension is enabled by default.
118+
119+
```yaml
120+
extensions:
121+
- ducklake # Default - DuckLake lakehouse format
122+
- httpfs # HTTP/S3 file system access
123+
- parquet # Parquet file support (built-in)
124+
- json # JSON support (built-in)
125+
- postgres # PostgreSQL scanner
53126
```
54127
55-
### Users
128+
## DuckLake Integration
56129
57-
Each user in the `Users` map gets:
58-
- Their own DuckDB database file at `./data/{username}.db`
59-
- Complete isolation from other users' data
130+
DuckLake provides a SQL-based lakehouse format. When configured, the DuckLake catalog is automatically attached on connection:
131+
132+
```yaml
133+
ducklake:
134+
# Metadata store (required to enable DuckLake catalog)
135+
metadata_store: "postgres:host=localhost dbname=ducklake"
136+
# Data path for table files
137+
data_path: "s3://my-bucket/ducklake-data/"
138+
```
139+
140+
This runs the equivalent of:
141+
```sql
142+
ATTACH 'ducklake:postgres:host=localhost dbname=ducklake' (DATA_PATH 's3://my-bucket/ducklake-data/')
143+
```
144+
145+
See [DuckLake documentation](https://ducklake.select/docs/stable/duckdb/usage/connecting) for more details.
146+
147+
## Rate Limiting
148+
149+
Built-in rate limiting protects against brute-force authentication attacks:
150+
151+
- **Failed attempt tracking**: Bans IPs after too many failed auth attempts
152+
- **Connection limits**: Limits concurrent connections per IP
153+
- **Auto-cleanup**: Expired records are automatically cleaned up
154+
155+
```yaml
156+
rate_limit:
157+
max_failed_attempts: 5 # Ban after 5 failures
158+
failed_attempt_window: "5m" # Within 5 minutes
159+
ban_duration: "15m" # Ban lasts 15 minutes
160+
max_connections_per_ip: 100 # Max concurrent connections
161+
```
60162
61163
## Usage Examples
62164
@@ -90,7 +192,7 @@ GROUP BY name;
90192
│ PostgreSQL │
91193
│ Client (psql) │
92194
└────────┬────────┘
93-
│ PostgreSQL Wire Protocol
195+
│ PostgreSQL Wire Protocol (TLS)
94196
▼
95197
┌─────────────────┐
96198
│ Duckgres │
@@ -101,12 +203,15 @@ GROUP BY name;
101203
┌─────────────────┐
102204
│ DuckDB │
103205
│ (per-user db) │
206+
│ + Extensions │
207+
│ + DuckLake │
104208
└─────────────────┘
105209
```
106210

107-
## Supported SQL Commands
211+
## Supported Features
108212

109-
- `SELECT` - Full query support
213+
### SQL Commands
214+
- `SELECT` - Full query support with binary result format
110215
- `INSERT` - Single and multi-row inserts
111216
- `UPDATE` - With WHERE clauses
112217
- `DELETE` - With WHERE clauses
@@ -115,10 +220,15 @@ GROUP BY name;
115220
- `ALTER TABLE`
116221
- `BEGIN/COMMIT/ROLLBACK` (DuckDB transaction support)
117222

223+
### PostgreSQL Compatibility
224+
- Extended query protocol (prepared statements)
225+
- Binary and text result formats
226+
- MD5 password authentication
227+
- Basic `pg_catalog` system tables for client compatibility
228+
- `\dt`, `\d`, and other psql meta-commands
229+
118230
## Limitations
119231

120-
- **No SSL/TLS**: Connections are unencrypted
121-
- **Text Format Only**: Results are returned in text format (no binary protocol)
122232
- **Single Process**: Each user's database is opened in the same process
123233
- **No Replication**: Single-node only
124234
- **Limited System Catalog**: Some `pg_*` system tables are not available

0 commit comments

Comments
 (0)