Notes to self

Reading Kamal configuration

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!

Check out my book
Learn how to use Kamal to deploy your web applications with Kamal Handbook. Visualize Kamal's concepts, understand Kamal's configuration, and deploy practical life examples.
by Josef Strzibny
RSS