Skip to content

Commit 6d241a1

Browse files
committed
s3: add minio in docker-compose.yaml
Signed-off-by: hmoazzem <[email protected]>
1 parent e16b837 commit 6d241a1

14 files changed

+196
-31
lines changed

README.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
edge configures and manages:
88

99
* [PostgreSQL](https://www.postgresql.org/): The world's most advanced open source database
10-
* [ZITADEL](https://github.com/zitadel/zitadel) - Centralized identity provider (OIDC)
11-
* [SeaweedFS](https://github.com/seaweedfs/seaweedfs) - S3-compatible object storage
12-
* [edgeflare/pgo](https://github.com/edgeflare/pgo) - PostgREST-compatible API and Debezium-compatible CDC
13-
* [NATS](https://nats.io) - Message streaming platform
14-
* [envoyproxy](https://github.com/envoyproxy/envoy) - Cloud-native high-performance edge/middle/service proxy
10+
* [ZITADEL](https://github.com/zitadel/zitadel): Centralized identity provider (OIDC)
11+
* [MinIO](https://github.com/minio/minio) / [SeaweedFS](https://github.com/seaweedfs/seaweedfs): S3-compatible object storage
12+
* [NATS](https://nats.io): Message streaming platform
13+
* [envoy](https://github.com/envoyproxy/envoy): Cloud-native high-performance edge/middle/service proxy
14+
* [edgeflare/pgo](https://github.com/edgeflare/pgo): PostgREST-compatible API and Debezium-compatible CDC
1515

1616
for a unified backend - similar to Firebase, Supabase, Pocketbase etc. And with scaling capabilities.
1717

@@ -54,7 +54,7 @@ docker compose up -d
5454

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

57-
Configure ZITADEL. Adjust the domain in env vars, and in `internal/util/envoy/config.yaml`
57+
Configure ZITADEL. Adjust the domain in env vars, and in `internal/stack/envoy/config.yaml`
5858

5959
```sh
6060
export ZITADEL_HOSTNAME=iam.192-168-0-121.sslip.io
@@ -65,14 +65,14 @@ export ZITADEL_JWK_URL=http://$ZITADEL_HOSTNAME/oauth/v2/keys
6565
```
6666

6767
```sh
68-
go run ./internal/util/configure/...
68+
go run ./internal/stack/configure/...
6969
```
7070

7171
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.
7272

7373
Once ZITADEL is configured, revert the ports (use 80 for envoy), and `docker compose down && docker compose up -d`
7474

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`
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/stack/pgo/config.yaml` with the values. Again, `docker compose down && docker compose up -d`
7676

7777
#### `pgo rest`: PostgREST-compatible REST API
7878

docker-compose.yaml

+55-5
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ services:
7676
envoy-controlplane:
7777
build:
7878
context: "."
79-
dockerfile: "./internal/util/envoy/Containerfile"
79+
dockerfile: "./internal/stack/envoy/Containerfile"
8080
entrypoint: /envoy-controlplane
8181
ports:
8282
- 18000:18000 # xds-server
@@ -92,8 +92,8 @@ services:
9292
- 9901:9901 # admin
9393
- 80:10080 # http-proxy
9494
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
95+
# - $PWD/internal/stack/envoy/bootstrap.yaml:/etc/bootstrap.yaml:rw,Z # when used with envoy-controlplane
96+
- $PWD/internal/stack/envoy/config.yaml:/etc/config.yaml:rw,Z # hard-coded config
9797
depends_on:
9898
- envoy-controlplane
9999

@@ -103,7 +103,7 @@ services:
103103
ports:
104104
- 8080:8080
105105
volumes:
106-
- $PWD/internal/util/pgo/config.yaml:/rest/config.yaml:rw,Z
106+
- $PWD/internal/stack/pgo/config.yaml:/rest/config.yaml:rw,Z
107107
depends_on:
108108
app-db:
109109
condition: service_healthy
@@ -114,13 +114,48 @@ services:
114114
image: ghcr.io/edgeflare/pgo
115115
command: [pipeline, --config, /pipeline/config.yaml]
116116
volumes:
117-
- $PWD/internal/util/pgo/config.yaml:/pipeline/config.yaml:rw,Z
117+
- $PWD/internal/stack/pgo/config.yaml:/pipeline/config.yaml:rw,Z
118118
depends_on:
119119
auth-db:
120120
condition: service_healthy
121121
app-db:
122122
condition: service_healthy
123123

124+
minio:
125+
image: quay.io/minio/minio
126+
command: [server, --console-address, ":9001"]
127+
environment:
128+
MINIO_ROOT_USER: minioadmin
129+
MINIO_ROOT_PASSWORD: minio-secret-key-change-me
130+
MINIO_VOLUMES: /mnt/data
131+
MINIO_BROWSER_REDIRECT_URL: http://minio.127-0-0-1.sslip.io
132+
# OIDC
133+
MINIO_IDENTITY_OPENID_CLIENT_ID: "311219429557993516"
134+
MINIO_IDENTITY_OPENID_CLIENT_SECRET: "PdcOM6b3h2pcdAVc3es83PY62EVLATiMjQrela1IYChAhTbkr1RX5MNqCvMMLauw"
135+
MINIO_IDENTITY_OPENID_DISPLAY_NAME: "Login with SSO"
136+
MINIO_IDENTITY_OPENID_CONFIG_URL: http://iam.192-168-0-121.sslip.io/.well-known/openid-configuration
137+
MINIO_IDENTITY_OPENID_CLAIM_NAME: policy_minio
138+
MINIO_IDENTITY_OPENID_REDIRECT_URI_DYNAMIC: on
139+
MINIO_IDENTITY_OPENID_CLAIM_USERINFO: on
140+
MINIO_IDENTITY_OPENID_COMMENT: "OIDC Identity Provider"
141+
# notify postgres
142+
MINIO_NOTIFY_POSTGRES_ENABLE: on
143+
MINIO_NOTIFY_POSTGRES_CONNECTION_STRING: "host=app-db port=5432 user=postgres password=postgrespw dbname=main sslmode=prefer"
144+
MINIO_NOTIFY_POSTGRES_FORMAT: namespace
145+
MINIO_NOTIFY_POSTGRES_ID: minioevents
146+
MINIO_NOTIFY_POSTGRES_TABLE: minioevents
147+
volumes:
148+
- minio:/mnt/data
149+
ports:
150+
- 9000:9000
151+
- 9001:9001
152+
depends_on:
153+
app-db:
154+
condition: service_healthy
155+
iam-zitadel:
156+
condition: service_healthy
157+
# should also wait for initdb, zitadel client creation
158+
124159
init-app-db:
125160
image: docker.io/bitnami/postgresql:17
126161
environment:
@@ -167,11 +202,26 @@ services:
167202
END IF;
168203
GRANT anon TO authn;
169204
GRANT authn to pgo;
205+
IF NOT EXISTS (
206+
SELECT 1
207+
FROM pg_roles
208+
WHERE rolname = 'minio'
209+
) THEN
210+
CREATE ROLE minio WITH LOGIN PASSWORD 'miniopw';
211+
END IF;
170212
END
171213
\$\$;
214+
215+
CREATE TABLE IF NOT EXISTS public.minioevents (
216+
key CHARACTER VARYING PRIMARY KEY
217+
);
218+
219+
GRANT USAGE ON SCHEMA public to minio;
220+
GRANT ALL PRIVILEGES ON TABLE public.minioevents TO minio;
172221
"
173222
restart: on-failure
174223

175224
volumes:
176225
app-db:
177226
auth-db:
227+
minio:

internal/util/configure/main.go internal/stack/configure/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package main
22

33
import (
4-
"github.com/edgeflare/edge/internal/util/zitadel"
4+
"github.com/edgeflare/edge/internal/stack/zitadel"
55
)
66

77
func main() {
File renamed without changes.

internal/util/envoy/Containerfile internal/stack/envoy/Containerfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ COPY ./go.mod go.mod
88
COPY ./go.sum go.sum
99
RUN go mod download
1010

11-
COPY ./internal/util/envoy internal/util/envoy
11+
COPY ./internal/stack/envoy internal/stack/envoy
1212

13-
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o envoy-controlplane ./internal/util/envoy
13+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o envoy-controlplane ./internal/stack/envoy
1414

1515
# runtime image
1616
FROM gcr.io/distroless/static:nonroot
File renamed without changes.

internal/util/envoy/config.yaml internal/stack/envoy/config.yaml

+68-3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,38 @@ static_resources:
5353
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
5454
max_age: "1728000"
5555
expose_headers: custom-header-1,grpc-status,grpc-message
56+
- name: minio_console_service
57+
domains: ["minio.127-0-0-1.sslip.io"]
58+
routes:
59+
- match: { prefix: "/" }
60+
route:
61+
cluster: minio_console_service
62+
timeout: 0s
63+
max_stream_duration:
64+
grpc_timeout_header_max: 0s
65+
cors:
66+
allow_origin_string_match:
67+
- prefix: "*"
68+
allow_methods: GET, PUT, DELETE, POST, OPTIONS
69+
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
70+
max_age: "1728000"
71+
expose_headers: custom-header-1,grpc-status,grpc-message
72+
- name: minio_s3_service
73+
domains: ["s3.127-0-0-1.sslip.io"]
74+
routes:
75+
- match: { prefix: "/" }
76+
route:
77+
cluster: minio_s3_service
78+
timeout: 0s
79+
max_stream_duration:
80+
grpc_timeout_header_max: 0s
81+
cors:
82+
allow_origin_string_match:
83+
- prefix: "*"
84+
allow_methods: GET, PUT, DELETE, POST, OPTIONS
85+
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
86+
max_age: "1728000"
87+
expose_headers: custom-header-1,grpc-status,grpc-message
5688
http_filters:
5789
- name: envoy.filters.http.grpc_web
5890
typed_config:
@@ -72,7 +104,6 @@ static_resources:
72104
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
73105
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
74106
explicit_http_config:
75-
# http_protocol_options: {}
76107
http2_protocol_options: {}
77108
lb_policy: round_robin
78109
load_assignment:
@@ -84,7 +115,6 @@ static_resources:
84115
socket_address:
85116
address: iam-zitadel
86117
port_value: 8080
87-
88118
- name: pgo_rest_service
89119
connect_timeout: 0.25s
90120
type: LOGICAL_DNS
@@ -93,7 +123,6 @@ static_resources:
93123
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
94124
explicit_http_config:
95125
http_protocol_options: {}
96-
# http2_protocol_options: {}
97126
lb_policy: round_robin
98127
load_assignment:
99128
cluster_name: pgo_rest_cluster
@@ -104,3 +133,39 @@ static_resources:
104133
socket_address:
105134
address: pgo-rest
106135
port_value: 8080
136+
- name: minio_console_service
137+
connect_timeout: 0.25s
138+
type: LOGICAL_DNS
139+
typed_extension_protocol_options:
140+
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
141+
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
142+
explicit_http_config:
143+
http_protocol_options: {}
144+
lb_policy: round_robin
145+
load_assignment:
146+
cluster_name: minio_console_cluster
147+
endpoints:
148+
- lb_endpoints:
149+
- endpoint:
150+
address:
151+
socket_address:
152+
address: minio
153+
port_value: 9001
154+
- name: minio_s3_service
155+
connect_timeout: 0.25s
156+
type: LOGICAL_DNS
157+
typed_extension_protocol_options:
158+
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
159+
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
160+
explicit_http_config:
161+
http_protocol_options: {}
162+
lb_policy: round_robin
163+
load_assignment:
164+
cluster_name: minio_s3_cluster
165+
endpoints:
166+
- lb_endpoints:
167+
- endpoint:
168+
address:
169+
socket_address:
170+
address: minio
171+
port_value: 9000

internal/util/envoy/develop.md internal/stack/envoy/develop.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
set xds_cluster socket_address to `address: 0.0.0.0` in `internal/util/envoy/bootstrap.yaml`
1+
set xds_cluster socket_address to `address: 0.0.0.0` in `internal/stack/envoy/bootstrap.yaml`
22

33
```sh
4-
envoy --config-path internal/util/envoy/bootstrap.yaml --base-id 1
4+
envoy --config-path internal/stack/envoy/bootstrap.yaml --base-id 1
55
```
66

77
```sh
8-
go run ./internal/util/envoy
8+
go run ./internal/stack/envoy
99
```
1010

1111
```sh

internal/util/envoy/main.go internal/stack/envoy/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"flag"
66
"os"
77

8-
"github.com/edgeflare/edge/internal/util/envoy/controlplane"
8+
"github.com/edgeflare/edge/internal/stack/envoy/controlplane"
99
"github.com/envoyproxy/go-control-plane/pkg/cache/v3"
1010
"github.com/envoyproxy/go-control-plane/pkg/server/v3"
1111
"github.com/envoyproxy/go-control-plane/pkg/test/v3"
File renamed without changes.

internal/util/zitadel/configure.go internal/stack/zitadel/configure.go

+58-8
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@ import (
2525

2626
var (
2727
logger *zap.Logger
28-
issuer = cmp.Or(os.Getenv("ZITADEL_ISSUER"), "http://iam.example.local")
29-
api = cmp.Or(os.Getenv("ZITADEL_API"), "iam.example.local:80")
28+
issuer = cmp.Or(os.Getenv("ZITADEL_ISSUER"), "http://iam.127-0-0-1.sslip.io")
29+
api = cmp.Or(os.Getenv("ZITADEL_API"), "iam.127-0-0-1.sslip.io:80")
3030
keyPath = cmp.Or(os.Getenv("ZITADEL_KEY_PATH"), "__zitadel-machinekey/zitadel-admin-sa.json")
3131
)
3232

3333
const (
3434
EDGE_PROJECT_NAME = "edge"
3535
OIDC_CLIENT_EDGE = "edge-ui"
3636
OIDC_CLIENT_OAUTH2PROXY = "oauth2-proxy"
37-
// OIDC_CLIENT_S3 = "seaweedfs"
37+
OIDC_CLIENT_MINIO = "minio"
38+
OIDC_CLIENT_S3 = "seaweedfs"
3839
)
3940

4041
func init() {
@@ -89,11 +90,11 @@ func Configure() {
8990
}
9091
logger.Info("ensured OAuth2 Proxy app", zap.Any("app", oauth2ProxyApp))
9192

92-
// minioClientApp, err := ensureMinioClientApp(ctx, client, createdProject.Id)
93-
// if err != nil {
94-
// logger.Fatal("failed to ensure MinIO client app", zap.Error(err))
95-
// }
96-
// logger.Info("ensured MinIO client app", zap.Any("app", minioClientApp))
93+
minioClientApp, err := ensureMinioClientApp(ctx, client, createdProject.Id)
94+
if err != nil {
95+
logger.Fatal("failed to ensure MinIO client app", zap.Error(err))
96+
}
97+
logger.Info("ensured MinIO client app", zap.Any("app", minioClientApp))
9798
}
9899

99100
func createZitadelClient(issuer, api string) (*management.Client, error) {
@@ -450,6 +451,55 @@ func setTriggers(ctx context.Context, client *management.Client, actionIds []str
450451
return nil
451452
}
452453

454+
func ensureMinioClientApp(ctx context.Context, client *management.Client, projectID string) (*app.App, error) {
455+
apps, err := listApps(ctx, client, projectID)
456+
if err != nil {
457+
return nil, err
458+
}
459+
460+
for _, app := range apps {
461+
if app.Name == OIDC_CLIENT_MINIO {
462+
return app, nil
463+
}
464+
}
465+
466+
// Create OIDC app for MinIO
467+
createdMinioApp, err := client.AddOIDCApp(ctx, &managementpb.AddOIDCAppRequest{
468+
ProjectId: projectID,
469+
Name: OIDC_CLIENT_MINIO,
470+
RedirectUris: []string{
471+
// TODO: don't hardcode
472+
"http://127.0.0.1:9001/oauth_callback",
473+
"http://minio.127-0-0-1.sslip.io/oauth_callback",
474+
},
475+
ResponseTypes: []app.OIDCResponseType{app.OIDCResponseType_OIDC_RESPONSE_TYPE_CODE},
476+
GrantTypes: []app.OIDCGrantType{
477+
app.OIDCGrantType_OIDC_GRANT_TYPE_AUTHORIZATION_CODE,
478+
app.OIDCGrantType_OIDC_GRANT_TYPE_REFRESH_TOKEN,
479+
},
480+
AppType: app.OIDCAppType_OIDC_APP_TYPE_WEB,
481+
482+
AuthMethodType: app.OIDCAuthMethodType_OIDC_AUTH_METHOD_TYPE_BASIC,
483+
})
484+
if err != nil {
485+
return nil, err
486+
}
487+
488+
createdApp, err := client.GetAppByID(ctx, &managementpb.GetAppByIDRequest{
489+
ProjectId: projectID,
490+
AppId: createdMinioApp.AppId,
491+
})
492+
if err != nil {
493+
return nil, err
494+
}
495+
496+
if err != nil {
497+
return nil, err
498+
}
499+
500+
return createdApp.App, nil
501+
}
502+
453503
/*
454504
// setPasswordChangeRequired sets ChangeRequired=false for the admin user
455505
func setPasswordChangeRequired(ctx context.Context, client *userv2.Client) (*user.SetPasswordResponse, error) {

0 commit comments

Comments
 (0)