ecaddy Docs Getting Started

Getting Started

From zero to https://fishme.localhost in five steps. The first two are once-per-machine; the rest are once-per-project.

Requirements

  • macOS with Homebrew installed
  • Ruby 3.2 or newer
  • A foreman-style process manager (foreman, overmind, hivemind, or bin/dev in Rails 7+)
Why macOS-only? ecaddy setup installs Caddy via brew install and runs it under brew services. The rest of the gem (fragment composition, conflict detection, registry) is portable, but the bootstrap helper is mac-specific.

Step 1 — Install the gem

gem install easy_caddy

That installs the ecaddy executable on your $PATH. Verify it:

ecaddy version
# ecaddy 0.1.0

Step 2 — Bootstrap Caddy

ecaddy setup

This is a one-time machine bootstrap. Every step is idempotent — running ecaddy setup a second time is a no-op for anything already in place.

  1. Installs Caddy via Homebrew if not already present.
  2. Scaffolds ~/.config/caddy/{sites,disabled}/.
  3. Writes the global Caddyfile (with import sites/*.caddy).
  4. Symlinks it into /opt/homebrew/etc/Caddyfile so brew services picks it up.
  5. Runs caddy trust to install the local CA in your system keychain — makes https://*.localhost green in browsers.
  6. Starts Caddy as a brew services background service.

Step 3 — Write your project Caddyfile

Put a Caddyfile in your project root. Write it however you need — ecaddy treats it as read-only source. The only automatic transform on copy: relative output file log paths are rewritten to absolute paths, so Caddy (running as a background service detached from your project directory) can actually write the log files.

# Caddyfile (in your Rails project root)

fishme.localhost {
  handle /vite-dev/* {
    reverse_proxy localhost:3054
  }

  reverse_proxy localhost:3104
  tls internal

  log {
    level INFO
    output file log/caddy.log {
      roll_size 2mb
      roll_keep 5
      roll_keep_for 48h
    }
  }
}

vite.fishme.localhost {
  reverse_proxy localhost:3054
  tls internal
}

Pick unique ports across your projects. A common pattern:

ProjectApp portVite port
fishme31043054
letly31003050
traiderb31063056
Pick a site name Every ecaddy command that touches a project uses a site name — a short identifier you choose, like fishme. It determines the fragment filename (sites/fishme.caddy) and is how up, down, edit, and remove target the project. The name is not read from the Caddyfile — you supply it explicitly with --site fishme (short: -s fishme).

Step 4 — Add a Procfile line

# Procfile.dev

web:   bin/rails server -p 3104
js:    yarn dev
caddy: ecaddy run --config ./Caddyfile --site fishme

When foreman (or overmind) starts, ecaddy run copies your Caddyfile into the global config and reloads Caddy. When you press Ctrl-C, it removes the fragment and reloads again — the domain disappears cleanly. No orphan registrations.

Step 5 — Allow .localhost in Rails

# config/environments/development.rb

config.hosts << /.*\.localhost/

Without this, Rails will reject the request with "Blocked host: fishme.localhost".

Step 6 — Start your project

bin/dev

Visit https://fishme.localhost — done. The browser shows a green padlock because caddy trust seeded the local CA in step 2.

Repeat per project

For every additional project, only steps 3 – 6 apply. Re-running ecaddy setup is unnecessary.

Without a Procfile

If you don't want a foreground Caddy process attached to your dev loop, use the one-shot variant:

ecaddy ensure --config ./Caddyfile --site fishme

This copies the Caddyfile, reloads Caddy, and exits. The registration persists across restarts (Caddy is a system service). Use ecaddy down fishme to disable it later, or ecaddy remove fishme to delete it entirely.

Next steps

ecaddy v0.1.0 · MIT License · GitHub