diff --git a/pkg/abstractions/output/output.go b/pkg/abstractions/output/output.go
index 7f227338b..a493e2b8a 100644
--- a/pkg/abstractions/output/output.go
+++ b/pkg/abstractions/output/output.go
@@ -215,7 +215,7 @@ func SetPublicURL(ctx context.Context, config types.AppConfig, backendRepo repos
 		return "", err
 	}
 
-	return fmt.Sprintf("%v/output/id/%v", config.GatewayService.ExternalURL, outputId), nil
+	return fmt.Sprintf("%v/output/id/%v", config.GatewayService.HTTP.GetExternalURL(), outputId), nil
 }
 
 func GetTaskOutputRootPath(workspaceName string, task *types.TaskWithRelated) string {
diff --git a/pkg/api/v1/stub.go b/pkg/api/v1/stub.go
index 9afaaa8b3..00fb25e57 100644
--- a/pkg/api/v1/stub.go
+++ b/pkg/api/v1/stub.go
@@ -115,7 +115,7 @@ func (g *StubGroup) GetURL(ctx echo.Context) error {
 
 	// Get URL for Serves
 	if stub.Type.IsServe() {
-		invokeUrl := common.BuildServeURL(g.config.GatewayService.ExternalURL, filter.URLType, stub)
+		invokeUrl := common.BuildServeURL(g.config.GatewayService.HTTP.GetExternalURL(), filter.URLType, stub)
 		return ctx.JSON(http.StatusOK, map[string]string{"url": invokeUrl})
 	}
 
@@ -134,6 +134,6 @@ func (g *StubGroup) GetURL(ctx echo.Context) error {
 		return HTTPInternalServerError("Failed to lookup deployment")
 	}
 
-	invokeUrl := common.BuildDeploymentURL(g.config.GatewayService.ExternalURL, filter.URLType, stub, &deployment.Deployment)
+	invokeUrl := common.BuildDeploymentURL(g.config.GatewayService.HTTP.GetExternalURL(), filter.URLType, stub, &deployment.Deployment)
 	return ctx.JSON(http.StatusOK, map[string]string{"url": invokeUrl})
 }
diff --git a/pkg/common/config.default.yaml b/pkg/common/config.default.yaml
index a6a4791bd..bcca17ef2 100644
--- a/pkg/common/config.default.yaml
+++ b/pkg/common/config.default.yaml
@@ -33,13 +33,18 @@ storage:
     bufferSize: 300
 gateway:
   host: beta9-gateway
-  externalURL: http://localhost:1994
   invokeURLType: path
   grpc:
+    externalHost: localhost
+    externalPort: 1993
+    tls: false
     port: 1993
     maxRecvMsgSize: 1024
     maxSendMsgSize: 1024
   http:
+    externalHost: localhost
+    externalPort: 1994
+    tls: false
     port: 1994
     enablePrettyLogs: true
     cors:
diff --git a/pkg/gateway/gateway.go b/pkg/gateway/gateway.go
index f647f9987..26369fd04 100644
--- a/pkg/gateway/gateway.go
+++ b/pkg/gateway/gateway.go
@@ -185,7 +185,7 @@ func (g *Gateway) initHttp() error {
 		AllowHeaders: g.Config.GatewayService.HTTP.CORS.AllowedHeaders,
 		AllowMethods: g.Config.GatewayService.HTTP.CORS.AllowedMethods,
 	}))
-	e.Use(gatewayMiddleware.Subdomain(g.Config.GatewayService.ExternalURL, g.BackendRepo, g.RedisClient))
+	e.Use(gatewayMiddleware.Subdomain(g.Config.GatewayService.HTTP.GetExternalURL(), g.BackendRepo, g.RedisClient))
 	e.Use(middleware.Recover())
 
 	// Accept both HTTP/2 and HTTP/1
diff --git a/pkg/gateway/services/stub.go b/pkg/gateway/services/stub.go
index 3fa6bc2b7..b8bf9b9d0 100644
--- a/pkg/gateway/services/stub.go
+++ b/pkg/gateway/services/stub.go
@@ -222,7 +222,7 @@ func (gws *GatewayService) DeployStub(ctx context.Context, in *pb.DeployStubRequ
 	}
 
 	// TODO: Remove this field once `pkg/api/v1/stub.go:GetURL()` is used by frontend and SDK version can be force upgraded
-	invokeUrl := common.BuildDeploymentURL(gws.appConfig.GatewayService.ExternalURL, common.InvokeUrlTypePath, stub, deployment)
+	invokeUrl := common.BuildDeploymentURL(gws.appConfig.GatewayService.HTTP.GetExternalURL(), common.InvokeUrlTypePath, stub, deployment)
 
 	go gws.eventRepo.PushDeployStubEvent(authInfo.Workspace.ExternalId, &stub.Stub)
 
@@ -257,7 +257,7 @@ func (gws *GatewayService) GetURL(ctx context.Context, in *pb.GetURLRequest) (*p
 
 	// Get URL for Serves
 	if stub.Type.IsServe() {
-		invokeUrl := common.BuildServeURL(gws.appConfig.GatewayService.ExternalURL, in.UrlType, stub)
+		invokeUrl := common.BuildServeURL(gws.appConfig.GatewayService.HTTP.GetExternalURL(), in.UrlType, stub)
 		return &pb.GetURLResponse{
 			Ok:  true,
 			Url: invokeUrl,
@@ -280,7 +280,7 @@ func (gws *GatewayService) GetURL(ctx context.Context, in *pb.GetURLRequest) (*p
 		}, nil
 	}
 
-	invokeUrl := common.BuildDeploymentURL(gws.appConfig.GatewayService.ExternalURL, in.UrlType, stub, &deployment.Deployment)
+	invokeUrl := common.BuildDeploymentURL(gws.appConfig.GatewayService.HTTP.GetExternalURL(), in.UrlType, stub, &deployment.Deployment)
 	return &pb.GetURLResponse{
 		Ok:  true,
 		Url: invokeUrl,
diff --git a/pkg/scheduler/pool_external.go b/pkg/scheduler/pool_external.go
index f7fcbc450..3c8522da3 100644
--- a/pkg/scheduler/pool_external.go
+++ b/pkg/scheduler/pool_external.go
@@ -402,7 +402,7 @@ func (wpc *ExternalWorkerPoolController) getWorkerEnvironment(workerId, machineI
 		},
 		{
 			Name:  "BETA9_GATEWAY_HOST",
-			Value: wpc.config.GatewayService.ExternalHost,
+			Value: wpc.config.GatewayService.GRPC.ExternalHost,
 		},
 		{
 			Name:  "BETA9_GATEWAY_PORT",
diff --git a/pkg/scheduler/pool_local.go b/pkg/scheduler/pool_local.go
index 725759c8f..bba7521cf 100644
--- a/pkg/scheduler/pool_local.go
+++ b/pkg/scheduler/pool_local.go
@@ -409,7 +409,7 @@ func (wpc *LocalKubernetesWorkerPoolController) getWorkerEnvironment(workerId st
 		envVars = append(envVars, []corev1.EnvVar{
 			{
 				Name:  "BETA9_GATEWAY_HOST",
-				Value: wpc.config.GatewayService.ExternalHost,
+				Value: wpc.config.GatewayService.GRPC.ExternalHost,
 			},
 			{
 				Name:  "BETA9_GATEWAY_PORT",
diff --git a/pkg/types/config.go b/pkg/types/config.go
index 84585b97d..c4adad172 100644
--- a/pkg/types/config.go
+++ b/pkg/types/config.go
@@ -1,6 +1,7 @@
 package types
 
 import (
+	"fmt"
 	"time"
 
 	blobcache "github.com/beam-cloud/blobcache-v2/pkg"
@@ -69,15 +70,35 @@ type PostgresConfig struct {
 }
 
 type GRPCConfig struct {
-	Port           int `key:"port" json:"port"`
-	MaxRecvMsgSize int `key:"maxRecvMsgSize" json:"max_recv_msg_size"`
-	MaxSendMsgSize int `key:"maxSendMsgSize" json:"max_send_msg_size"`
+	ExternalPort   int    `key:"externalPort" json:"external_port"`
+	ExternalHost   string `key:"externalHost" json:"external_host"`
+	TLS            bool   `key:"tls" json:"tls"`
+	Port           int    `key:"port" json:"port"`
+	MaxRecvMsgSize int    `key:"maxRecvMsgSize" json:"max_recv_msg_size"`
+	MaxSendMsgSize int    `key:"maxSendMsgSize" json:"max_send_msg_size"`
 }
 
 type HTTPConfig struct {
+	ExternalPort     int        `key:"externalPort" json:"external_port"`
+	ExternalHost     string     `key:"externalHost" json:"external_host"`
+	TLS              bool       `key:"tls" json:"tls"`
+	Port             int        `key:"port" json:"port"`
 	EnablePrettyLogs bool       `key:"enablePrettyLogs" json:"enable_pretty_logs"`
 	CORS             CORSConfig `key:"cors" json:"cors"`
-	Port             int        `key:"port" json:"port"`
+}
+
+func (h *HTTPConfig) GetExternalURL() string {
+	baseUrl := "http"
+	if h.TLS {
+		baseUrl += "s"
+	}
+	baseUrl += "://" + h.ExternalHost
+
+	if h.Port != 80 && h.Port != 443 {
+		baseUrl += fmt.Sprintf(":%d", h.Port)
+	}
+
+	return baseUrl
 }
 
 type CORSConfig struct {
@@ -94,8 +115,6 @@ type StubLimits struct {
 
 type GatewayServiceConfig struct {
 	Host            string        `key:"host" json:"host"`
-	ExternalHost    string        `key:"externalHost" json:"external_host"`
-	ExternalURL     string        `key:"externalURL" json:"external_url"`
 	InvokeURLType   string        `key:"invokeURLType" json:"invoke_url_type"`
 	GRPC            GRPCConfig    `key:"grpc" json:"grpc"`
 	HTTP            HTTPConfig    `key:"http" json:"http"`