If you configured your config/deploy.yml
file for Kamal, you might thought about working with this very configuration outside Kamal. Here’s how.
TIP: Checkout Kamal Handbook, my new book on Kamal.
Kamal config
Reading Kamal’s configuration from Ruby is pretty straight-forward. We just initialize Kamal::Configuration
object from a passed config file:
config_file = Pathname.new(File.expand_path("config/deploy.yml"))
config = Kamal::Configuration.create_from(config_file: config_file)
puts config.inspect
Now we can access the whole YAML configuration as Kamal sees it:
> config.image
=> "strzibnyj/template"
> config.service
=> "template"
Registry
Registry is a Hash of username and password as you would expect:
> config.registry
=> {"username"=>"strzibnyj", "password"=>["KAMAL_REGISTRY_PASSWORD"]}
SSH
The SSH configuration can be accessed at config.ssh
. Here’s how to read the SSH user:
> config.ssh
=> #<Kamal::Configuration::Ssh:0x0000000107688f28 @config={"user"=>"app"}>
> config.ssh.user
=> "app"
Traefik
Traefik configuration is under config.traefik
and is just a Hash
:
> config.traefik
=>
{"options"=>{"publish"=>["443:443"], "volume"=>["/letsencrypt/acme.json:/letsencrypt/acme.json"], "network"=>"private"},
"args"=>
{"entryPoints.web.address"=>":80",
"entryPoints.websecure.address"=>":443",
"certificatesResolvers.letsencrypt.acme.email"=>"info@template.com",
"certificatesResolvers.letsencrypt.acme.storage"=>"/letsencrypt/acme.json",
"certificatesResolvers.letsencrypt.acme.httpchallenge"=>true,
"certificatesResolvers.letsencrypt.acme.httpchallenge.entrypoint"=>"web"}}
Servers and roles
Same for servers:
> config.servers.first
=>
["web",
{"hosts"=>["170.64.149.226"],
"labels"=>
{"traefik.http.routers.template.rule"=>"Host(`app.template.com`)",
"traefik.http.routers.template.entrypoints"=>"web",
"traefik.http.routers.template_secure.entrypoints"=>"websecure",
"traefik.http.routers.template_secure.rule"=>"Host(`app.template.com`)",
"traefik.http.routers.template_secure.tls"=>true,
"traefik.http.routers.template_secure.tls.certresolver"=>"letsencrypt"},
"options"=>{"network"=>"private"},
"port"=>"3000:3000"}]
To get IP addresses for out web
and job
roles we can do:
> config.servers["web"]["hosts"]
=> ["150.64.149.221"]
We can also work with servers as roles:
> config.roles.first
=>
#<Kamal::Configuration::Role:0x0000000107db2a38
@config=
#<Kamal::Configuration:0x0000000107db34d8
@accessories=
[#<Kamal::Configuration::Accessory:0x0000000106f7d5f8
@config=#<Kamal::Configuration:0x0000000107db34d8 ...>,
@name="postgres",
@specifics=
{"image"=>"postgres:15",
"host"=>"...",
ENVs
The list of environments are under config.env
:
> config.env
=>
{"clear"=>
{"HOST"=>"app.template.com",
"REDIS_URL"=>"redis://:someuniquepass453@template-redis:6379/1",
"DB_HOST"=>"170.64.149.226",
"RAILS_SERVE_STATIC_FILES"=>true,
"RAILS_LOG_TO_STDOUT"=>true,
"ENABLE_FREE_PLAN"=>true},
"secret"=>["RAILS_MASTER_KEY", "POSTGRES_PASSWORD"]}
Accessories
You can access accessories under config.accessories
. You’ll get an array of the Kamal::Configuration::Accessor
objects. Here’s an example:
> accessory = config.accessories.first
> accessory.name
=> "postgres"
> config.accessories.first.specifics
=>
{"image"=>"postgres:15",
"host"=>"170.64.149.226",
"port"=>5432,
"env"=>{"clear"=>{"POSTGRES_USER"=>"template", "POSTGRES_DB"=>"template_production"}, "secret"=>["POSTGRES_PASSWORD"]},
"files"=>["config/init.sql:/docker-entrypoint-initdb.d/setup.sql"],
"directories"=>["data:/var/lib/postgresql/data"],
"options"=>{"network"=>"private"}}
Volumes
Perhaps surprisingly, volumes are different. There is no config.volumes
. Instead, we can ask for the volume arguments:
> config.volume_args
=> ["--volume", "/storage:/rails/storage"]
Hope that helped!