Skip to content

Commit 4b6061a

Browse files
committed
doc: tmp use static envoy config in docker
Signed-off-by: hmoazzem <[email protected]>
1 parent 68cef4d commit 4b6061a

File tree

4 files changed

+206
-100
lines changed

4 files changed

+206
-100
lines changed

README.md

+29-43
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,36 @@
44
[![CodeQL](https://github.com/edgeflare/edge/actions/workflows/codeql.yml/badge.svg)](https://github.com/edgeflare/edge/actions/workflows/codeql.yml)
55
[![Release](https://github.com/edgeflare/edge/actions/workflows/release.yml/badge.svg)](https://github.com/edgeflare/edge/actions/workflows/release.yml)
66

7-
Edge configures and manages:
7+
edge configures and manages:
8+
9+
* [PostgreSQL](https://www.postgresql.org/): The world's most advanced open source database
810
* [ZITADEL](https://github.com/zitadel/zitadel) - Centralized identity provider (OIDC)
911
* [SeaweedFS](https://github.com/seaweedfs/seaweedfs) - S3-compatible object storage
1012
* [edgeflare/pgo](https://github.com/edgeflare/pgo) - PostgREST-compatible API and Debezium-compatible CDC
1113
* [NATS](https://nats.io) - Message streaming platform
1214
* [envoyproxy](https://github.com/envoyproxy/envoy) - Cloud-native high-performance edge/middle/service proxy
13-
## How it works
1415

15-
Edge launches and configures these components to work together as a unified backend with PostgreSQL - similar to Supabase or Pocketbase. And with scaling capabilities.
16+
for a unified backend - similar to Firebase, Supabase, Pocketbase etc. And with scaling capabilities.
1617

1718
## Deployment options
1819

19-
Edge can run as:
20-
- A single binary (embeds official component binaries)
21-
- [Docker compose](./docker-compose.yaml)
22-
- Kubernetes resources (follow this README)
23-
- Via a Kubernetes CRD named [Project](./example/project.yaml)
24-
25-
This project is in the ideation stage. Edge configures/manages the four underlying tools to create a cohesive system.
20+
- A single binary (embeds official component binaries): WIP
21+
- [Docker compose](./docker-compose.yaml) or Kubernetes resources: follow this README
22+
- Via a Kubernetes CRD: [Project](./example/project.yaml)
2623

27-
Interested in experimenting or contributing? See [CONTRIBUTING.md](./CONTRIBUTING.md).
24+
edge is in very early stage. Interested in experimenting or contributing? See [CONTRIBUTING.md](./CONTRIBUTING.md).
2825

2926
```sh
3027
git clone [email protected]:edgeflare/edge.git && cd edge
3128
```
3229

33-
This uses iam.example.local and api.example.local domains. Ensure they point to the Gateway IP (envoyproxy) eg by adding an entry to `/etc/hosts` like
34-
35-
```sh
36-
127.0.0.1 api.example.local iam.example.local
37-
```
38-
3930
### [docker-compose.yaml](./docker-compose.yaml)
4031

4132
Adjust the docker-compose.yaml
4233

4334
- Free up port 80 from envoy for zitadel's initial configuration via management API which requires end-to-end HTTP/2 support.
44-
envoyproxy config in docker doesn't support (our xds-server incomplete) HTTP/2 yet; on [k8s](https://raw.githubusercontent.com/edgeflare/pgo/refs/heads/main/k8s.yaml) everything works fine.
35+
envoyproxy config in docker doesn't support (we gotta finish xds-server) HTTP/2 yet.
36+
On [k8s](https://raw.githubusercontent.com/edgeflare/pgo/refs/heads/main/k8s.yaml) everything works fine.
4537

4638
```yaml
4739
envoy:
@@ -63,41 +55,28 @@ docker compose up -d
6355

6456
#### Use the centralized IdP for authorization in Postgres via `pgo rest` (PostgREST API)
6557

66-
Any OIDC compliant Identity Provider (eg ZITADEL, Keycloak, Auth0) can be used.
58+
Configure ZITADEL. Adjust the domains in env vars, and in `internal/util/envoy/config.yaml`
6759

6860
```sh
69-
export ZITADEL_ISSUER=http://iam.example.local
70-
export ZITADEL_API=iam.example.local:80
61+
export ZITADEL_ISSUER=http://iam.192-168-0-121.sslip.io
62+
export ZITADEL_API=iam.192-168-0-121.sslip.io:80
7163
export ZITADEL_KEY_PATH=__zitadel-machinekey/zitadel-admin-sa.json
72-
export ZITADEL_JWK_URL=http://iam.example.local/oauth/v2/keys
64+
export ZITADEL_JWK_URL=http://iam.192-168-0-121.sslip.io/oauth/v2/keys
7365
```
7466

75-
Configure components eg create OIDC clients in ZITADEL etc
76-
7767
```sh
7868
go run ./internal/util/configure/...
7969
```
8070

81-
Once done, revert the ports (use 80 for envoy), and `docker compose restart`
82-
83-
#### pgo rest
84-
85-
Visit http://iam.example.local, login and regenerate client-secret for oauth2-proxy client in edge project. Then adjust `internal/util/pgo/config.yaml`
71+
The above go code creates, among others, an OIDC client which pgo uses for authN/authZ. Any OIDC compliant Identity Provider (eg , Keycloak, Auth0) can be used; pgo just needs the client credentials.
8672

87-
> `pgo rest` container fails because of proxy issues. It can be run locally
73+
Once ZITADEL is configured, revert the ports (use 80 for envoy), and `docker compose down && docker compose up -d`
8874

89-
```sh
90-
go install github.com/edgeflare/pgo@latest # or download from release page
91-
```
92-
##### PostgREST-compatible REST API
93-
94-
```sh
95-
pgo rest --config internal/util/pgo/config.yaml --rest.pg_conn_string "host=localhost port=5432 user=pgo password=pgopw dbname=main sslmode=prefer"
96-
```
75+
Visit ZITADEL UI (eg at http://iam.192-168-0-121.sslip.io), login (see docker-compose.yaml) and regenerate client-secret for oauth2-proxy client in edge project. Then update `internal/util/pgo/config.yaml` with the values. Again, `docker compose down && docker compose up -d`
9776

98-
###### realtime/replication eg sync users from auth-db to app-db
77+
#### `pgo rest`: PostgREST-compatible REST API
9978

100-
Create table in sink-db. See pgo repo for more examples
79+
Create a table in app-db for REST and pipeline demo. See pgo repo for more examples
10180

10281
```sh
10382
PGUSER=postgres PGPASSWORD=postgrespw PGHOST=localhost PGDATABASE=main PGPORT=5432 psql
@@ -109,14 +88,22 @@ CREATE SCHEMA IF NOT EXISTS iam;
10988
CREATE TABLE IF NOT EXISTS iam.users (
11089
id TEXT DEFAULT gen_random_uuid()::TEXT PRIMARY KEY
11190
);
91+
92+
-- wide-open for demo. use GRANT and RLS for granular ACL
93+
GRANT USAGE ON SCHEMA iam to anon;
94+
GRANT ALL ON iam.users to anon;
11295
```
11396

114-
Start pipeline
97+
`docker restart edge_pgo-rest_1` to reload schema cache if it bugs. Now we can for example
11598

11699
```sh
117-
pgo pipeline --config internal/util/pgo/config.yaml
100+
curl http://api.127-0-0-1.sslip.io/iam/users
118101
```
119102

103+
##### `pgo pipeline`: Debezium-compatible CDC for realtime-event/replication etc
104+
105+
The demo pgo-pipeline container syncs users from auth-db (in projections.users14 table) to app-db (in iam.users)
106+
120107
### Kubernetes
121108
If you already have a live k8s cluster, great just copy-paste-enter.
122109
For development and lightweight prod, [k3s](https://github.com/k3s-io/k3s) seems a great option.
@@ -143,7 +130,6 @@ export ZITADEL_ADMIN_PW=$(kubectl get secrets example-zitadel-firstinstance -o j
143130

144131
Configure zitadel like in docker-compose. Then apply something like `https://raw.githubusercontent.com/edgeflare/pgo/refs/heads/main/k8s.yaml`
145132

146-
147133
## Cleanup
148134

149135
```sh

docker-compose.yaml

+66-52
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ services:
3434
ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
3535
ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgrespw
3636
ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
37-
ZITADEL_EXTERNALDOMAIN: iam.example.local
37+
ZITADEL_EXTERNALDOMAIN: iam.192-168-0-121.sslip.io # resolves to 192.168.0.121 (gateway/envoy IP). use LAN or accesible IP/hostname
3838
ZITADEL_EXTERNALPORT: 80
3939
ZITADEL_PORT: 8080
4040
ZITADEL_EXTERNALSECURE: false
@@ -73,6 +73,54 @@ services:
7373
timeout: 5s
7474
retries: 5
7575

76+
envoy-controlplane:
77+
build:
78+
context: "."
79+
dockerfile: "./internal/util/envoy/Containerfile"
80+
entrypoint: /envoy-controlplane
81+
ports:
82+
- 18000:18000 # xds-server
83+
environment:
84+
- "DEBUG=true"
85+
86+
envoy:
87+
image: docker.io/envoyproxy/envoy:contrib-v1.33-latest
88+
# command: [envoy, --config-path, /etc/bootstrap.yaml, --base-id, 1] # when used with envoy-controlplane for dynamic config
89+
command: [envoy, --config-path, /etc/config.yaml, --base-id, 1]
90+
privileged: true
91+
ports:
92+
- 9901:9901 # admin
93+
- 80:10080 # http-proxy
94+
volumes:
95+
# - $PWD/internal/util/envoy/bootstrap.yaml:/etc/bootstrap.yaml:rw,Z # when used with envoy-controlplane
96+
- $PWD/internal/util/envoy/config.yaml:/etc/config.yaml:rw,Z # hard-coded config
97+
depends_on:
98+
- envoy-controlplane
99+
100+
pgo-rest:
101+
image: ghcr.io/edgeflare/pgo
102+
command: [rest, --config, /rest/config.yaml]
103+
ports:
104+
- 8080:8080
105+
volumes:
106+
- $PWD/internal/util/pgo/config.yaml:/rest/config.yaml:rw,Z
107+
depends_on:
108+
app-db:
109+
condition: service_healthy
110+
# init-app-db:
111+
# condition: service_completed_successfully # errors
112+
113+
pgo-pipeline:
114+
image: ghcr.io/edgeflare/pgo
115+
command: [pipeline, --config, /pipeline/config.yaml]
116+
volumes:
117+
- $PWD/internal/util/pgo/config.yaml:/pipeline/config.yaml:rw,Z
118+
depends_on:
119+
auth-db:
120+
condition: service_healthy
121+
app-db:
122+
condition: service_healthy
123+
76124
init-app-db:
77125
image: docker.io/bitnami/postgresql:17
78126
environment:
@@ -93,71 +141,37 @@ services:
93141
sleep 2
94142
done
95143
echo "PostgreSQL is up - executing SQL"
96-
97144
psql -c "
98-
DO \$\$
99-
BEGIN
145+
DO \$\$
146+
BEGIN
100147
IF NOT EXISTS (
101-
SELECT 1
102-
FROM pg_roles
103-
WHERE rolname = 'pgo'
148+
SELECT 1
149+
FROM pg_roles
150+
WHERE rolname = 'pgo'
104151
) THEN
105-
CREATE ROLE pgo WITH LOGIN PASSWORD 'pgopw';
152+
CREATE ROLE pgo WITH LOGIN PASSWORD 'pgopw';
106153
END IF;
107154
IF NOT EXISTS (
108-
SELECT 1
109-
FROM pg_roles
110-
WHERE rolname = 'authn'
155+
SELECT 1
156+
FROM pg_roles
157+
WHERE rolname = 'authn'
111158
) THEN
112-
CREATE ROLE authn NOLOGIN;
159+
CREATE ROLE authn NOLOGIN;
113160
END IF;
114161
IF NOT EXISTS (
115-
SELECT 1
116-
FROM pg_roles
117-
WHERE rolname = 'anon'
162+
SELECT 1
163+
FROM pg_roles
164+
WHERE rolname = 'anon'
118165
) THEN
119-
CREATE ROLE anon NOLOGIN;
166+
CREATE ROLE anon NOLOGIN;
120167
END IF;
121168
GRANT anon TO authn;
122-
GRANT authn,anon to pgo;
123-
END
124-
\$\$;
169+
GRANT authn to pgo;
170+
END
171+
\$\$;
125172
"
126173
restart: on-failure
127174

128-
envoy-controlplane:
129-
build:
130-
context: "."
131-
dockerfile: "./internal/util/envoy/Containerfile"
132-
entrypoint: /envoy-controlplane
133-
ports:
134-
- 18000:18000 # xds-server
135-
environment:
136-
- "DEBUG=true"
137-
138-
envoy:
139-
image: docker.io/envoyproxy/envoy:contrib-v1.33-latest
140-
command: [envoy, --config-path, /etc/bootstrap.yaml, --base-id, 1]
141-
privileged: true
142-
ports:
143-
- 9901:9901 # admin
144-
- 80:10080 # http-proxy
145-
volumes:
146-
- $PWD/internal/util/envoy/bootstrap.yaml:/etc/bootstrap.yaml:rw,Z
147-
depends_on:
148-
- envoy-controlplane
149-
150-
pgo-rest:
151-
image: ghcr.io/edgeflare/pgo
152-
command: [rest, --config, /rest/config.yaml]
153-
ports:
154-
- 8080:8080
155-
volumes:
156-
- $PWD/internal/util/pgo/config.yaml:/rest/config.yaml:rw,Z
157-
depends_on:
158-
app-db:
159-
condition: service_healthy
160-
161175
volumes:
162176
app-db:
163177
auth-db:

internal/util/envoy/config.yaml

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
admin:
2+
address:
3+
socket_address:
4+
address: 0.0.0.0
5+
port_value: 9901
6+
7+
static_resources:
8+
listeners:
9+
- name: listener_0
10+
address:
11+
socket_address:
12+
address: 0.0.0.0
13+
port_value: 10080
14+
filter_chains:
15+
- filters:
16+
- name: envoy.filters.network.http_connection_manager
17+
typed_config:
18+
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
19+
codec_type: auto
20+
stat_prefix: ingress_http
21+
route_config:
22+
name: multi_service_route
23+
virtual_hosts:
24+
- name: iam_service
25+
domains: ["iam.127-0-0-1.sslip.io", "iam.192-168-0-121.sslip.io", "iam.example.local", "zitadel.example.local"]
26+
routes:
27+
- match: { prefix: "/" }
28+
route:
29+
cluster: iam_zitadel_service
30+
timeout: 0s
31+
max_stream_duration:
32+
grpc_timeout_header_max: 0s
33+
cors:
34+
allow_origin_string_match:
35+
- prefix: "*"
36+
allow_methods: GET, PUT, DELETE, POST, OPTIONS
37+
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
38+
max_age: "1728000"
39+
expose_headers: custom-header-1,grpc-status,grpc-message
40+
- name: pgo_service
41+
domains: ["api.127-0-0-1.sslip.io", "api.example.local", "pgo.example.local"]
42+
routes:
43+
- match: { prefix: "/" }
44+
route:
45+
cluster: pgo_rest_service
46+
timeout: 0s
47+
max_stream_duration:
48+
grpc_timeout_header_max: 0s
49+
cors:
50+
allow_origin_string_match:
51+
- prefix: "*"
52+
allow_methods: GET, PUT, DELETE, POST, OPTIONS
53+
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
54+
max_age: "1728000"
55+
expose_headers: custom-header-1,grpc-status,grpc-message
56+
http_filters:
57+
- name: envoy.filters.http.grpc_web
58+
typed_config:
59+
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
60+
- name: envoy.filters.http.cors
61+
typed_config:
62+
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
63+
- name: envoy.filters.http.router
64+
typed_config:
65+
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
66+
67+
clusters:
68+
- name: iam_zitadel_service
69+
connect_timeout: 0.25s
70+
type: LOGICAL_DNS
71+
typed_extension_protocol_options:
72+
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
73+
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
74+
explicit_http_config:
75+
# http_protocol_options: {}
76+
http2_protocol_options: {}
77+
lb_policy: round_robin
78+
load_assignment:
79+
cluster_name: iam_zitadel_cluster
80+
endpoints:
81+
- lb_endpoints:
82+
- endpoint:
83+
address:
84+
socket_address:
85+
address: iam-zitadel
86+
port_value: 8080
87+
88+
- name: pgo_rest_service
89+
connect_timeout: 0.25s
90+
type: LOGICAL_DNS
91+
typed_extension_protocol_options:
92+
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
93+
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
94+
explicit_http_config:
95+
http_protocol_options: {}
96+
# http2_protocol_options: {}
97+
lb_policy: round_robin
98+
load_assignment:
99+
cluster_name: pgo_rest_cluster
100+
endpoints:
101+
- lb_endpoints:
102+
- endpoint:
103+
address:
104+
socket_address:
105+
address: pgo-rest
106+
port_value: 8080

0 commit comments

Comments
 (0)