From fcac8d19d756077c4cb10d78ed9b9b8fca52b628 Mon Sep 17 00:00:00 2001 From: omer-topal Date: Tue, 10 Mar 2026 15:12:38 +0300 Subject: [PATCH] fix: separate HTTP bind host from gRPC gateway target host --- docs/setting-up/configuration.mdx | 8 ++++++++ example.config.yaml | 2 ++ internal/config/config.go | 8 +++++--- internal/config/config_test.go | 6 ++++++ internal/servers/server.go | 4 ++-- pkg/cmd/config.go | 4 ++++ pkg/cmd/flags/serve.go | 14 ++++++++++++++ pkg/cmd/serve.go | 2 ++ 8 files changed, 43 insertions(+), 5 deletions(-) diff --git a/docs/setting-up/configuration.mdx b/docs/setting-up/configuration.mdx index a20ee7ee3..00e70b1ad 100644 --- a/docs/setting-up/configuration.mdx +++ b/docs/setting-up/configuration.mdx @@ -23,10 +23,12 @@ docker run -p 3476:3476 -p 3478:3478 ghcr.io/permify/permify --help # including whether or not TLS is enabled and the certificate and # key file locations. server: + host: "" rate_limit: 100 http: enabled: true port: 3476 + grpc_target_host: 127.0.0.1 tls: enabled: true cert: /etc/letsencrypt/live/yourdomain.com/fullchain.pem @@ -137,10 +139,12 @@ Server options to run Permify. (`grpc` and `http` available for now.) ``` ├── server + ├── host ├── rate_limit ├── (`grpc` or `http`) │ ├── enabled │ ├── port + │ ├── grpc_target_host │ └── tls │ ├── enabled │ ├── cert @@ -151,10 +155,12 @@ Server options to run Permify. (`grpc` and `http` available for now.) | Required | Argument | Default | Description | |----------|---------------------------|---------|---------------------------------------------------------------------| +| [ ] | host | "" | host/interface to bind the HTTP server. | | [ ] | rate_limit | 100 | the maximum number of requests the server should handle per second. | | [x] | [ server_type ] | - | server option type can either be `grpc` or `http`. | | [ ] | enabled (for server type) | true | switch option for server. | | [x] | port | - | port that server run on. | +| [ ] | grpc_target_host (HTTP) |127.0.0.1| host the HTTP gateway uses to connect to the local gRPC server. | | [x] | tls | - | transport layer security options. | | [ ] | enabled (for tls) | false | switch option for tls | | [ ] | cert | - | tls certificate path. | @@ -164,6 +170,7 @@ Server options to run Permify. (`grpc` and `http` available for now.) | Argument | ENV | Type | |---------------------------|-----------------------------------|--------------| +| server-host | PERMIFY_SERVER_HOST | string | | rate_limit | PERMIFY_RATE_LIMIT | int | | grpc-port | PERMIFY_GRPC_PORT | string | | grpc-tls-enabled | PERMIFY_GRPC_TLS_ENABLED | boolean | @@ -171,6 +178,7 @@ Server options to run Permify. (`grpc` and `http` available for now.) | grpc-tls-cert-path | PERMIFY_GRPC_TLS_CERT_PATH | string | | http-enabled | PERMIFY_HTTP_ENABLED | boolean | | http-port | PERMIFY_HTTP_PORT | string | +| http-grpc-target-host | PERMIFY_HTTP_GRPC_TARGET_HOST | string | | http-tls-key-path | PERMIFY_HTTP_TLS_KEY_PATH | string | | http-tls-cert-path | PERMIFY_HTTP_TLS_CERT_PATH | string | | http-cors-allowed-origins | PERMIFY_HTTP_CORS_ALLOWED_ORIGINS | string array | diff --git a/example.config.yaml b/example.config.yaml index 8a94d9663..ceead8e9c 100644 --- a/example.config.yaml +++ b/example.config.yaml @@ -4,10 +4,12 @@ account_id: "" # including whether or not TLS is enabled and the certificate and # key file locations. server: + host: "" rate_limit: 100 http: enabled: true port: 3476 + grpc_target_host: 127.0.0.1 tls: enabled: false cert: /etc/letsencrypt/live/yourdomain.com/fullchain.pem diff --git a/internal/config/config.go b/internal/config/config.go index 692131f9e..683b18ece 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -38,6 +38,7 @@ type ( HTTP struct { Enabled bool `mapstructure:"enabled"` // Whether the HTTP server is enabled Port string `mapstructure:"port"` // Port for the HTTP server + GRPCTargetHost string `mapstructure:"grpc_target_host"` // Host the HTTP gateway uses to reach the local gRPC server TLSConfig TLSConfig `mapstructure:"tls"` // TLS configuration for the HTTP server CORSAllowedOrigins []string `mapstructure:"cors_allowed_origins"` // List of allowed origins for CORS CORSAllowedHeaders []string `mapstructure:"cors_allowed_headers"` // List of allowed headers for CORS @@ -284,10 +285,11 @@ func DefaultConfig() *Config { AccountID: "", Server: Server{ NameOverride: "", - Host: "127.0.0.1", + Host: "", HTTP: HTTP{ - Enabled: true, - Port: "3476", + Enabled: true, + Port: "3476", + GRPCTargetHost: "127.0.0.1", TLSConfig: TLSConfig{ Enabled: false, }, diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 0db550462..2bc2394f2 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -18,7 +18,9 @@ func TestNewConfig_FileNotFound(t *testing.T) { assert.NotNil(t, cfg) // Check if default values are applied correctly + assert.Equal(t, "", cfg.Server.Host) assert.Equal(t, "3476", cfg.Server.HTTP.Port) + assert.Equal(t, "127.0.0.1", cfg.Server.HTTP.GRPCTargetHost) assert.Equal(t, "3478", cfg.Server.GRPC.Port) assert.Equal(t, "info", cfg.Log.Level) } @@ -59,6 +61,8 @@ logger: assert.Equal(t, "debug", cfg.Log.Level) // Check if default values are applied correctly + assert.Equal(t, "", cfg.Server.Host) + assert.Equal(t, "127.0.0.1", cfg.Server.HTTP.GRPCTargetHost) assert.False(t, cfg.Server.HTTP.TLSConfig.Enabled) assert.False(t, cfg.Server.GRPC.TLSConfig.Enabled) assert.False(t, cfg.Profiler.Enabled) @@ -131,6 +135,8 @@ database: assert.Equal(t, "postgres://user:password@localhost/dbname", cfg.Database.URI) // Check if default values are applied correctly + assert.Equal(t, "", cfg.Server.Host) + assert.Equal(t, "127.0.0.1", cfg.Server.HTTP.GRPCTargetHost) assert.Equal(t, "3478", cfg.Server.GRPC.Port) assert.False(t, cfg.Server.HTTP.TLSConfig.Enabled) assert.False(t, cfg.Server.GRPC.TLSConfig.Enabled) diff --git a/internal/servers/server.go b/internal/servers/server.go index 0519418ce..6c7fa525f 100644 --- a/internal/servers/server.go +++ b/internal/servers/server.go @@ -269,8 +269,8 @@ func (s *Container) Run( options = append(options, grpc.WithTransportCredentials(insecure.NewCredentials())) } - targetAddr := net.JoinHostPort(srv.Host, srv.GRPC.Port) // gRPC server address - conn, err := grpc.NewClient(targetAddr, options...) // Create gRPC client connection + targetAddr := net.JoinHostPort(srv.HTTP.GRPCTargetHost, srv.GRPC.Port) + conn, err := grpc.NewClient(targetAddr, options...) // Create gRPC client connection if err != nil { return err } diff --git a/pkg/cmd/config.go b/pkg/cmd/config.go index e35b5a8c5..512f3a63b 100644 --- a/pkg/cmd/config.go +++ b/pkg/cmd/config.go @@ -30,12 +30,14 @@ func NewConfigCommand() *cobra.Command { f.Bool("http-enabled", conf.Server.HTTP.Enabled, "switch option for HTTP server") f.String("account-id", conf.AccountID, "account id") f.Int64("server-rate-limit", conf.Server.RateLimit, "the maximum number of requests the server should handle per second") + f.String("server-host", conf.Server.Host, "host/interface to bind the HTTP server") f.String("server-name-override", conf.Server.NameOverride, "server name override") f.String("grpc-port", conf.Server.GRPC.Port, "port that GRPC server run on") f.Bool("grpc-tls-enabled", conf.Server.GRPC.TLSConfig.Enabled, "switch option for GRPC tls server") f.String("grpc-tls-key-path", conf.Server.GRPC.TLSConfig.KeyPath, "GRPC tls key path") f.String("grpc-tls-cert-path", conf.Server.GRPC.TLSConfig.CertPath, "GRPC tls certificate path") f.String("http-port", conf.Server.HTTP.Port, "HTTP port address") + f.String("http-grpc-target-host", conf.Server.HTTP.GRPCTargetHost, "host the HTTP gateway uses to connect to the local gRPC server") f.Bool("http-tls-enabled", conf.Server.HTTP.TLSConfig.Enabled, "switch option for HTTP tls server") f.String("http-tls-key-path", conf.Server.HTTP.TLSConfig.KeyPath, "HTTP tls key path") f.String("http-tls-cert-path", conf.Server.HTTP.TLSConfig.CertPath, "HTTP tls certificate path") @@ -154,12 +156,14 @@ func conf() func(cmd *cobra.Command, args []string) error { // Return config han data = append(data, []string{"account_id", cfg.AccountID, getKeyOrigin(cmd, "account-id", "PERMIFY_ACCOUNT_ID")}, // SERVER + []string{"server.host", cfg.Server.Host, getKeyOrigin(cmd, "server-host", "PERMIFY_SERVER_HOST")}, []string{"server.name_override", fmt.Sprintf("%v", cfg.Server.NameOverride), getKeyOrigin(cmd, "server-name-override", "PERMIFY_NAME_OVERRIDE")}, []string{"server.rate_limit", fmt.Sprintf("%v", cfg.Server.RateLimit), getKeyOrigin(cmd, "server-rate-limit", "PERMIFY_RATE_LIMIT")}, []string{"server.grpc.port", cfg.Server.GRPC.Port, getKeyOrigin(cmd, "grpc-port", "PERMIFY_GRPC_PORT")}, []string{"server.grpc.tls.enabled", fmt.Sprintf("%v", cfg.Server.GRPC.TLSConfig.Enabled), getKeyOrigin(cmd, "grpc-tls-enabled", "PERMIFY_GRPC_TLS_ENABLED")}, []string{"server.grpc.tls.cert", cfg.Server.GRPC.TLSConfig.CertPath, getKeyOrigin(cmd, "grpc-tls-cert-path", "PERMIFY_GRPC_TLS_CERT_PATH")}, []string{"server.http.enabled", fmt.Sprintf("%v", cfg.Server.HTTP.Enabled), getKeyOrigin(cmd, "http-enabled", "PERMIFY_HTTP_ENABLED")}, + []string{"server.http.grpc_target_host", cfg.Server.HTTP.GRPCTargetHost, getKeyOrigin(cmd, "http-grpc-target-host", "PERMIFY_HTTP_GRPC_TARGET_HOST")}, []string{"server.http.tls.enabled", fmt.Sprintf("%v", cfg.Server.HTTP.TLSConfig.Enabled), getKeyOrigin(cmd, "http-tls-enabled", "PERMIFY_HTTP_TLS_ENABLED")}, []string{"server.http.tls.key", HideSecret(cfg.Server.HTTP.TLSConfig.KeyPath), getKeyOrigin(cmd, "http-tls-key-path", "PERMIFY_HTTP_TLS_KEY_PATH")}, []string{"server.http.tls.cert", HideSecret(cfg.Server.HTTP.TLSConfig.CertPath), getKeyOrigin(cmd, "http-tls-cert-path", "PERMIFY_HTTP_TLS_CERT_PATH")}, diff --git a/pkg/cmd/flags/serve.go b/pkg/cmd/flags/serve.go index 596f78203..97e885018 100644 --- a/pkg/cmd/flags/serve.go +++ b/pkg/cmd/flags/serve.go @@ -29,6 +29,13 @@ func RegisterServeFlags(flags *pflag.FlagSet) { panic(err) } + if err = viper.BindPFlag("server.host", flags.Lookup("server-host")); err != nil { + panic(err) + } + if err = viper.BindEnv("server.host", "PERMIFY_SERVER_HOST"); err != nil { + panic(err) + } + if err = viper.BindPFlag("server.name_override", flags.Lookup("server-name-override")); err != nil { panic(err) } @@ -80,6 +87,13 @@ func RegisterServeFlags(flags *pflag.FlagSet) { panic(err) } + if err = viper.BindPFlag("server.http.grpc_target_host", flags.Lookup("http-grpc-target-host")); err != nil { + panic(err) + } + if err = viper.BindEnv("server.http.grpc_target_host", "PERMIFY_HTTP_GRPC_TARGET_HOST"); err != nil { + panic(err) + } + if err = viper.BindPFlag("server.http.tls.enabled", flags.Lookup("http-tls-enabled")); err != nil { panic(err) } diff --git a/pkg/cmd/serve.go b/pkg/cmd/serve.go index 64169aa3e..78f000c52 100644 --- a/pkg/cmd/serve.go +++ b/pkg/cmd/serve.go @@ -60,12 +60,14 @@ func NewServeCommand() *cobra.Command { f.Bool("http-enabled", conf.Server.HTTP.Enabled, "switch option for HTTP server") f.String("account-id", conf.AccountID, "account id") f.Int64("server-rate-limit", conf.Server.RateLimit, "the maximum number of requests the server should handle per second") + f.String("server-host", conf.Server.Host, "host/interface to bind the HTTP server") f.String("server-name-override", conf.Server.NameOverride, "server name override") f.String("grpc-port", conf.Server.GRPC.Port, "port that GRPC server run on") f.Bool("grpc-tls-enabled", conf.Server.GRPC.TLSConfig.Enabled, "switch option for GRPC tls server") f.String("grpc-tls-key-path", conf.Server.GRPC.TLSConfig.KeyPath, "GRPC tls key path") f.String("grpc-tls-cert-path", conf.Server.GRPC.TLSConfig.CertPath, "GRPC tls certificate path") f.String("http-port", conf.Server.HTTP.Port, "HTTP port address") + f.String("http-grpc-target-host", conf.Server.HTTP.GRPCTargetHost, "host the HTTP gateway uses to connect to the local gRPC server") f.Bool("http-tls-enabled", conf.Server.HTTP.TLSConfig.Enabled, "switch option for HTTP tls server") f.String("http-tls-key-path", conf.Server.HTTP.TLSConfig.KeyPath, "HTTP tls key path") f.String("http-tls-cert-path", conf.Server.HTTP.TLSConfig.CertPath, "HTTP tls certificate path")