sitesx

A Phoenix SubDomainer which makes subdomain using DigitalOcean, Cloudflare, etc. API and contains convenient view helper interface along with Plug and Ecto


Keywords
cloudflare, digitalocean, ecto, helper, phoenix, plug, subdomain
License
MIT

Documentation

Sitesx

Build Status Ebert Hex version Inline docs Lisence

A Phoenix SubDomainer which makes subdomain using DigitalOcean, Cloudflare, etc. API and contains convenient view helper interface along with Plug and Ecto

Installation

If available in Hex, the package can be installed as:

  1. Add sitesx to your list of dependencies in mix.exs:
def deps do
  [{:sitesx, "~> 0.10"}]
end
  1. Ensure sitesx is started before your application:
def application do
  [applications: [:sitesx]]
end
  1. Sitesx needs to add a migration:
defmodule MyApp.Repo.Migrations.CreateSite do
  use Ecto.Migration

  def change do
    create table(:sites) do
      add :name, :string
      add :dns, :boolean, default: false

      timestamps()
    end
    create index(:sites, [:name], unique: true)
    create index(:sites, [:dns])

  end
end
  1. After definition, needs to add a model:
defmodule MyApp.Site do
  use MyApp.Web, :model

  schema "sites" do
    field :name, :string
    field :dns, :boolean

    timestamps()
  end

  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:name dns])
    |> validate_required([:name])
    |> unique_constraint(:name)
  end
end

Mix commands mix sitesx.gen.model or mix sitesx.gen.schema will be able to generate No.3 and No.4 instead of define manually.

$ mix sitesx.gen.model   # Until phoenix v1.2.x
$ mix sitesx.gen.schema  # Phoenix v1.3.x
  1. Stores Sitesx model into private on Plug struct.

A Sitesx.Plug module extracts domain information from request URL or sub queryparameter.

Plug in Router

defmodule MyApp.Router do
  use MyApp.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers

    plug Sitesx.Plug
  end
end

or

Plug in Controller

defmodule MyApp.MyController do
  use MyApp.Web, :controller

  plug Sitesx.Plug
end
  1. Configuration

Cloudflare

config :sitesx,
  otp_app: MyApp,
  domain: "example.com",
  ensure_domain_interval: 300,
  dns: [
    provider: :cloudflare,
    auth_email: "mail@example.com",
    auth_key: "hash-key1",
    zone_identifier: "hash-key1",
  ]

Digitalocean

config :sitesx,
  otp_app: MyApp,
  domain: "example.com",
  request_options: [hackney: [pool: :cloudflare]],
  dns: :digitalocean
Sitesx.App, Configuration from mix config and environment variable.

hexdocs: https://hexdocs.pm/sitesx/Sitesx.App.html

Customization

Obviously, those definition are still not enough to work on development. Therefore it will be changed is better that have 1:N relation between one of a model and Site model.

defmodule MyApp.Entry do
  use MyApp.Web, :model

  schema "entries" do
    belongs_to :site, MyApp.Site
    field :title, :string
    field :content, :string

    timestamps()
  end
end

And then

defmodule MyApp.Site do
  use MyApp.Web, :model

  schema "sites" do
    has_many :entries, MyApp.Entry
    field :name, :string
    field :dns, :boolean

    timestamps()
  end
end

Usage

Create a record

Create subdomain1 as CNAME record to DNS Provider which will be stored on Cloudflare or Digitalocean. And also will be stores that into database, too.

{_, site} = Sitesx.Q.get_or_create("subdomain1")
Repo.insert_or_update(entry, %{site_id: site.id})

Generate a URL

Import module

# web/web.ex
defmodule MyApp.Web do
  def view do
    quote do
      use Phoenix.View, root: "web/templates"
      ...
      ...
      ...
      import Sitesx.Helpers
    end
  end
end

Then call function

subdomain_url(@conn, "entry.latest")
#-> Ensured domain: http://subdomain1.example.com/entries/latest
#-> Not ensured domain: http://example.com/entries/latest?sub=subdomain1

subdomain_url("subdomain2", @conn, "page.index")
#-> Ensured domain: http://subdomain2.example.com/entries/latest
#-> Not ensured domain: http://example.com/entries/latest?sub=subdomain2

Documentation

Sitesx.Domain manages DNS record which has detect, extract, create method.

hexdocs: https://hexdocs.pm/sitesx/Sitesx.Domain.html

Sitesx.Helpers. Generate URL with subdomain for controller or templates along with Phoenix.HTML.SimplifiedHelpers.URL

hexdocs: https://hexdocs.pm/sitesx/Sitesx.Helpers.html

Sitesx.Plug. Stores Sitesx model into private on Plug struct.

hexdocs: https://hexdocs.pm/sitesx/Sitesx.Plug.html

Sitesx.Q. Ecto Query Helper along with Sitesx.Plug

hexdocs: https://hexdocs.pm/sitesx/Sitesx.Q.html

Sitesx.App, Configuration from mix config and environment variable.

hexdocs: https://hexdocs.pm/sitesx/Sitesx.App.html

Documentation

hexdocs: https://hexdocs.pm/sitesx