diff --git a/cmd/caddygat/pgbouncer_spilo.go b/cmd/caddygat/pgbouncer_spilo.go
deleted file mode 100644
index 306615d9316975b90b1925975c993ecb4d782f44..0000000000000000000000000000000000000000
--- a/cmd/caddygat/pgbouncer_spilo.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package main
-
-import (
-	"time"
-
-	"github.com/caddyserver/caddy/v2"
-	"github.com/caddyserver/caddy/v2/caddyconfig"
-	caddycmd "github.com/caddyserver/caddy/v2/cmd"
-
-	"gfx.cafe/gfx/pggat/lib/gat"
-	"gfx.cafe/gfx/pggat/lib/gat/handlers/pgbouncer_spilo"
-	"gfx.cafe/gfx/pggat/lib/util/dur"
-
-	"gfx.cafe/util/go/gun"
-)
-
-func init() {
-	caddycmd.RegisterCommand(caddycmd.Command{
-		Name:  "pgbouncer-spilo",
-		Short: "Runs in pgbouncer-spilo compatibility mode",
-		Func:  runPgbouncerSpilo,
-	})
-}
-
-func runPgbouncerSpilo(flags caddycmd.Flags) (int, error) {
-	caddy.TrapSignals()
-
-	var config pgbouncer_spilo.Config
-	gun.Load(&config)
-
-	var pggat gat.Config
-	pggat.StatLogPeriod = dur.Duration(1 * time.Minute)
-
-	var server gat.ServerConfig
-	server.Listen = config.Listen()
-	server.Routes = append(server.Routes, gat.RouteConfig{
-		Handle: caddyconfig.JSONModuleObject(
-			pgbouncer_spilo.Module{
-				Config: config,
-			},
-			"handler",
-			"pgbouncer_spilo",
-			nil,
-		),
-	})
-	pggat.Servers = append(pggat.Servers, server)
-
-	caddyConfig := caddy.Config{
-		AppsRaw: caddy.ModuleMap{
-			"pggat": caddyconfig.JSON(pggat, nil),
-		},
-	}
-
-	if err := caddy.Run(&caddyConfig); err != nil {
-		return caddy.ExitCodeFailedStartup, err
-	}
-
-	select {}
-}
diff --git a/go.mod b/go.mod
index ac588dfd480eff2336b20d7f6cc84ebc1b9b8816..706ee3ef0a02205ea95d65c8de93efd4799b8496 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,6 @@ go 1.20
 
 require (
 	gfx.cafe/ghalliday1/scram v0.0.2
-	gfx.cafe/util/go/gun v0.0.0-20230721185457-c559e86c829c
 	github.com/caddyserver/caddy/v2 v2.7.4
 	github.com/digitalocean/godo v1.102.1
 	github.com/google/uuid v1.3.0
@@ -23,8 +22,6 @@ require (
 	github.com/caddyserver/certmagic v0.19.2 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
-	github.com/cristalhq/aconfig v0.18.3 // indirect
-	github.com/cristalhq/aconfig/aconfigdotenv v0.17.1 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/emicklei/go-restful/v3 v3.9.0 // indirect
 	github.com/go-logr/logr v1.2.4 // indirect
@@ -48,7 +45,6 @@ require (
 	github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
 	github.com/imdario/mergo v0.3.12 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
-	github.com/joho/godotenv v1.4.0 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/klauspost/cpuid/v2 v2.2.5 // indirect
diff --git a/go.sum b/go.sum
index ba1b8f2a7d3ec5723452673eda401e89cbac9272..91e67319bb9289efbb9802a3f740a5306fbb6e00 100644
--- a/go.sum
+++ b/go.sum
@@ -37,8 +37,6 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
 gfx.cafe/ghalliday1/scram v0.0.2 h1:uuScaL7DUEP/lKWJnA5kKHq5RJev26q8DMbP3gKviAg=
 gfx.cafe/ghalliday1/scram v0.0.2/go.mod h1:qt6+WJoFcX2id67G5w+/dktBJ56Se0sZAa7WjqfNNu0=
-gfx.cafe/util/go/gun v0.0.0-20230721185457-c559e86c829c h1:4XxKaHfYPam36FibTiy1Te7ycfW4+ys08WYyDih5VmU=
-gfx.cafe/util/go/gun v0.0.0-20230721185457-c559e86c829c/go.mod h1:zxq7FdmfdrI4oGeze0MPJt9WqdkFj3BDDSAWRuB63JQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -76,11 +74,6 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
 github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
 github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cristalhq/aconfig v0.17.0/go.mod h1:NXaRp+1e6bkO4dJn+wZ71xyaihMDYPtCSvEhMTm/H3E=
-github.com/cristalhq/aconfig v0.18.3 h1:Or12LIWIF+2mQpcGWA2PQnNc55+WiHFAqRjYh/pQNtM=
-github.com/cristalhq/aconfig v0.18.3/go.mod h1:NXaRp+1e6bkO4dJn+wZ71xyaihMDYPtCSvEhMTm/H3E=
-github.com/cristalhq/aconfig/aconfigdotenv v0.17.1 h1:HG2ql5fGe4FLL2fUv6o+o0YRyF1mWEcYkNfWGWD82k4=
-github.com/cristalhq/aconfig/aconfigdotenv v0.17.1/go.mod h1:gQIKkh+HkVcODvMNz/cLbH65Pk9b0r4tfolCOsI8G9I=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -215,8 +208,6 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
 github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
 github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
-github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
diff --git a/lib/gat/gatcaddyfile/handler.go b/lib/gat/gatcaddyfile/handler.go
index 316b80ea616630a9a09cf88f00720ddbcbf9fa55..cc8d4255e2d6fcd41204d3ed4acef570f6dc8ba2 100644
--- a/lib/gat/gatcaddyfile/handler.go
+++ b/lib/gat/gatcaddyfile/handler.go
@@ -1,6 +1,8 @@
 package gatcaddyfile
 
 import (
+	"gfx.cafe/gfx/pggat/lib/gat/handlers/pgbouncer_spilo"
+	"strconv"
 	"strings"
 	"time"
 
@@ -245,6 +247,121 @@ func init() {
 			}
 		}
 
+		return &module, nil
+	})
+	RegisterDirective(Handler, "pgbouncer_spilo", func(d *caddyfile.Dispenser, warnings *[]caddyconfig.Warning) (caddy.Module, error) {
+		module := pgbouncer_spilo.Module{}
+
+		if !d.NextBlock(d.Nesting()) {
+			return nil, d.ArgErr()
+		}
+
+		for {
+			if d.Val() == "}" {
+				break
+			}
+
+			directive := d.Val()
+			switch directive {
+			case "host":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				module.Host = d.Val()
+			case "port":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				var err error
+				module.Port, err = strconv.Atoi(d.Val())
+				if err != nil {
+					return nil, d.WrapErr(err)
+				}
+			case "user":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				module.User = d.Val()
+			case "schema":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				module.Schema = d.Val()
+			case "password":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				module.Password = d.Val()
+			case "mode":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				module.Mode = d.Val()
+			case "default_size":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				var err error
+				module.DefaultSize, err = strconv.Atoi(d.Val())
+				if err != nil {
+					return nil, d.WrapErr(err)
+				}
+			case "min_size":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				var err error
+				module.MinSize, err = strconv.Atoi(d.Val())
+				if err != nil {
+					return nil, d.WrapErr(err)
+				}
+			case "reserve_size":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				var err error
+				module.ReserveSize, err = strconv.Atoi(d.Val())
+				if err != nil {
+					return nil, d.WrapErr(err)
+				}
+			case "max_client_conn":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				var err error
+				module.MaxClientConn, err = strconv.Atoi(d.Val())
+				if err != nil {
+					return nil, d.WrapErr(err)
+				}
+			case "max_db_conn":
+				if !d.NextArg() {
+					return nil, d.ArgErr()
+				}
+
+				var err error
+				module.MaxDBConn, err = strconv.Atoi(d.Val())
+				if err != nil {
+					return nil, d.WrapErr(err)
+				}
+			default:
+				return nil, d.ArgErr()
+			}
+
+			if !d.NextLine() {
+				return nil, d.EOFErr()
+			}
+		}
+
 		return &module, nil
 	})
 }
diff --git a/lib/gat/handlers/pgbouncer_spilo/config.go b/lib/gat/handlers/pgbouncer_spilo/config.go
index 81dc370759448d31b433483a8df6f8a92cd0d5ba..f303c6eb99b7091d81e6ded8b1ddfabf6e399a53 100644
--- a/lib/gat/handlers/pgbouncer_spilo/config.go
+++ b/lib/gat/handlers/pgbouncer_spilo/config.go
@@ -1,44 +1,15 @@
 package pgbouncer_spilo
 
-import (
-	"strconv"
-
-	"github.com/caddyserver/caddy/v2/caddyconfig"
-
-	"gfx.cafe/gfx/pggat/lib/gat"
-	"gfx.cafe/gfx/pggat/lib/gat/ssl/servers/x509_key_pair"
-)
-
 type Config struct {
-	Host                string `json:"host" env:"PGHOST"`
-	Port                int    `json:"port" env:"PGPORT"`
-	User                string `json:"user" env:"PGUSER"`
-	Schema              string `json:"schema" env:"PGSCHEMA"`
-	Password            string `json:"password" env:"PGPASSWORD"`
-	PoolerPort          int    `json:"pooler_port" env:"CONNECTION_POOLER_PORT"`
-	PoolerMode          string `json:"pooler_mode" env:"CONNECTION_POOLER_MODE"`
-	PoolerDefaultSize   int    `json:"pooler_default_size" env:"CONNECTION_POOLER_DEFAULT_SIZE"`
-	PoolerMinSize       int    `json:"pooler_min_size" env:"CONNECTION_POOLER_MIN_SIZE"`
-	PoolerReserveSize   int    `json:"pooler_reserve_size" env:"CONNECTION_POOLER_RESERVE_SIZE"`
-	PoolerMaxClientConn int    `json:"pooler_max_client_conn" env:"CONNECTION_POOLER_MAX_CLIENT_CONN"`
-	PoolerMaxDBConn     int    `json:"pooler_max_db_conn" env:"CONNECTION_POOLER_MAX_DB_CONN"`
-}
-
-func (T Config) Listen() []gat.ListenerConfig {
-	ssl := caddyconfig.JSONModuleObject(
-		x509_key_pair.Server{
-			CertFile: "/etc/ssl/certs/pgbouncer.crt",
-			KeyFile:  "/etc/ssl/certs/pgbouncer.key",
-		},
-		"provider",
-		"x509_key_pair",
-		nil,
-	)
-
-	return []gat.ListenerConfig{
-		{
-			Address: ":" + strconv.Itoa(T.PoolerPort),
-			SSL:     ssl,
-		},
-	}
+	Host          string `json:"host"`
+	Port          int    `json:"port"`
+	User          string `json:"user"`
+	Schema        string `json:"schema"`
+	Password      string `json:"password"`
+	Mode          string `json:"mode"`
+	DefaultSize   int    `json:"default_size"`
+	MinSize       int    `json:"min_size"`
+	ReserveSize   int    `json:"reserve_size"`
+	MaxClientConn int    `json:"max_client_conn"`
+	MaxDBConn     int    `json:"max_db_conn"`
 }
diff --git a/lib/gat/handlers/pgbouncer_spilo/module.go b/lib/gat/handlers/pgbouncer_spilo/module.go
index 5a80a19bf9a7a1a8b1d3e48e55123fd6bb79c43a..dc41720b5b91196e3dd19d2f6d636d5dc5412f23 100644
--- a/lib/gat/handlers/pgbouncer_spilo/module.go
+++ b/lib/gat/handlers/pgbouncer_spilo/module.go
@@ -42,9 +42,7 @@ func (T *Module) Provision(ctx caddy.Context) error {
 		Port:     T.Port,
 		AuthUser: T.User,
 	}
-	pgb.PgBouncer.PoolMode = pgbouncer.PoolMode(T.PoolerMode)
-	pgb.PgBouncer.ListenPort = T.PoolerPort
-	pgb.PgBouncer.ListenAddr = "*"
+	pgb.PgBouncer.PoolMode = pgbouncer.PoolMode(T.Mode)
 	pgb.PgBouncer.AuthType = "md5"
 	pgb.PgBouncer.AuthFile = pgbouncer.AuthFile{
 		T.User: T.Password,
@@ -66,10 +64,10 @@ func (T *Module) Provision(ctx caddy.Context) error {
 	pgb.PgBouncer.LogConnections = 0
 	pgb.PgBouncer.LogDisconnections = 0
 
-	pgb.PgBouncer.DefaultPoolSize = T.PoolerDefaultSize
-	pgb.PgBouncer.ReservePoolSize = T.PoolerReserveSize
-	pgb.PgBouncer.MaxClientConn = T.PoolerMaxClientConn
-	pgb.PgBouncer.MaxDBConnections = T.PoolerMaxDBConn
+	pgb.PgBouncer.DefaultPoolSize = T.DefaultSize
+	pgb.PgBouncer.ReservePoolSize = T.ReserveSize
+	pgb.PgBouncer.MaxClientConn = T.MaxClientConn
+	pgb.PgBouncer.MaxDBConnections = T.MaxDBConn
 	pgb.PgBouncer.IdleTransactionTimeout = 600
 	pgb.PgBouncer.ServerLoginRetry = 5
 
diff --git a/presets/pgbouncer_spilo.Caddyfile b/presets/pgbouncer_spilo.Caddyfile
new file mode 100644
index 0000000000000000000000000000000000000000..b481eff38e34108537ab61fe698fc049ec950f0f
--- /dev/null
+++ b/presets/pgbouncer_spilo.Caddyfile
@@ -0,0 +1,18 @@
+:{$CONNECTION_POOLER_PORT:5432} {
+    ssl x509_key_pair /etc/ssl/certs/pgbouncer.crt /etc/ssl/certs/pgbouncer.key
+    require_ssl
+
+    pgbouncer_spilo {
+        host {$PGHOST}
+        port {$PGPORT}
+        user {$PGUSER}
+        schema {$PGSCHEMA}
+        password {$PGPASSWORD}
+        mode {$CONNECTION_POOLER_MODE}
+        default_size {$CONNECTION_POOLER_DEFAULT_SIZE}
+        min_size {$CONNECTION_POOLER_MIN_SIZE}
+        reserve_size {$CONNECTION_POOLER_RESERVE_SIZE}
+        max_client_conn {$CONNECTION_POOLER_MAX_CLIENT_CONN}
+        max_db_conn {$CONNECTION_POOLER_MAX_DB_CONN}
+    }
+}
\ No newline at end of file