Skip to content

Commit

Permalink
move modify app into their own pages
Browse files Browse the repository at this point in the history
  • Loading branch information
jesseshieh committed May 31, 2020
1 parent 4afc137 commit 77e9120
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 417 deletions.
394 changes: 0 additions & 394 deletions docs/source/getting-started-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -229,398 +229,4 @@ What's Next?
- :ref:`remote observer`
- :ref:`hot-upgrade`

.. _`make your existing app work on Gigalixir`:
.. _`modifying existing app`:

Modifying an Existing App to Run on Gigalixir
=============================================

Whether you have an existing app or you just ran :bash:`mix phx.new`, the goal of this guide is to get your app ready for deployment on Gigalixir. We assume that you are using Phoenix here. If you aren't, feel free to :ref:`contact us<help>` for help. As long as your app is serving HTTP traffic on :bash:`$PORT`, you should be fine.

Important: If you have an umbrella app, be sure to *also* see :ref:`umbrella`.

.. _`mix vs distillery`:

Mix vs Distillery vs Elixir Releases
------------------------------------

Probably the hardest part of deploying Elixir is choosing which method of deploying you prefer. We typically recommend Distillery because it has the most features, but Mix is much simpler and Elixir releases give you a bit of both. Here is a comparison table to help you choose. Any features not in the table are available for all three.

======================= =================== ======================= ===========
Feature Mix Elixir Releases Distillery
======================= =================== ======================= ===========
Hot Upgrades YES
Remote Observer YES YES
Mix Tasks YES
Included with Elixir YES YES
Easy Configuration YES
======================= =================== ======================= ===========

If you choose mix, see :ref:`modifying existing app with mix`.

If you choose distillery, see :ref:`modifying existing app with distillery`.

If you choose Elixir releases, see :ref:`modifying existing app with Elixir releases`.

.. _`modifying existing app with mix`:

Using Mix
---------

For an example app that uses mix and works on gigalixir, see https://github.com/gigalixir/gigalixir-getting-started/tree/js/mix

Configuration and Secrets
^^^^^^^^^^^^^^^^^^^^^^^^^

Then append something like the following in :bash:`prod.exs`. Don't replace what you already have, just add this to the bottom.

.. code-block:: elixir
config :gigalixir_getting_started, GigalixirGettingStartedWeb.Endpoint,
http: [port: {:system, "PORT"}], # Possibly not needed, but doesn't hurt
url: [host: System.get_env("APP_NAME") <> ".gigalixirapp.com", port: 80],
secret_key_base: Map.fetch!(System.get_env(), "SECRET_KEY_BASE"),
server: true
config :gigalixir_getting_started, GigalixirGettingStarted.Repo,
adapter: Ecto.Adapters.Postgres,
url: System.get_env("DATABASE_URL"),
ssl: true,
pool_size: 2 # Free tier db only allows 4 connections. Rolling deploys need pool_size*(n+1) connections where n is the number of app replicas.
1. Replace :elixir:`:gigalixir_getting_started` with your app name e.g. :elixir:`:my_app`
2. Replace :elixir:`GigalixirGettingStartedWeb.Endpoint` with your endpoint module name. You can find your endpoint module name by running something like

.. code-block:: bash
grep -R "defmodule.*Endpoint" lib/
Phoenix 1.2, 1.3, and 1.4 give different names so this is a common source of errors.
3. Replace :elixir:`GigalixirGettingStarted.Repo` with your repo module name e.g. :elixir:`MyApp.Repo`

You don't have to worry about setting your :bash:`SECRET_KEY_BASE` config because we generate one and set it for you.

Don't forget to commit your changes

.. code-block:: bash
git add config/prod.exs
git commit -m "setup production deploys"
Verify
^^^^^^

Let's make sure everything works.

.. code-block:: bash
APP_NAME=foo SECRET_KEY_BASE="$(mix phx.gen.secret)" MIX_ENV=prod DATABASE_URL="postgresql://user:pass@localhost:5432/foo" PORT=4000 mix phx.server
Check it out.

.. code-block:: bash
curl localhost:4000
If everything works, continue to :ref:`set up deploys`.

Specify Buildpacks (optional)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

We rely on buildpacks to compile and build your release. We auto-detect a variety of buildpacks so you probably don't need this, but if you want
to specify your own buildpacks create a :bash:`.buildpacks` file with the buildpacks you want. For example,

.. code-block:: bash
https://github.com/HashNuke/heroku-buildpack-elixir
https://github.com/gjaldon/heroku-buildpack-phoenix-static
https://github.com/gigalixir/gigalixir-buildpack-mix.git
:bash:`heroku-buildpack-phoenix-static` is optional if you do not have Phoenix static assets. For more information about buildpacks, see :ref:`life of a deploy`.

Note, that the command that gets run in production depends on what your last buildpack is.

- If the last buildpack is :bash:`gigalixir-buildpack-mix`, then the command run will be something like :bash:`elixir --name $MY_NODE_NAME --cookie $MY_COOKIE -S mix phx.server`.
- If the last buildpack is :bash:`heroku-buildpack-phoenix-static`, then the command run will be :bash:`mix phx.server`.
- If the last buildpack is :bash:`heroku-buildpack-elixir`, then the command run will be :bash:`mix run --no-halt`.

If your command is :bash:`mix run --no-halt`, but you are running Phoenix (just not the assets pipeline), make sure you set :elixir:`server: true` in :bash:`prod.exs`.

We highly recommend keeping :bash:`gigalixir-buildpack-mix` last so that your node name and cookie are set properly. Without those, remote_console, ps:migrate, observer, etc won't work.

.. _`modifying existing app with distillery`:

Using Distillery
----------------

For an example app that uses distillery and works on gigalixir, see https://github.com/gigalixir/gigalixir-getting-started

Install Distillery to Build Releases
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In short, you'll need to add something like this to the :elixir:`deps` list in :bash:`mix.exs`

.. code-block:: elixir
{:distillery, "~> 2.1"}
Important: If you are running Elixir 1.9, then you *must* use distillery 2.1 or greater. Elixir 1.9 and distillery below 2.1 both use `mix release` and Elixir's always takes precedence. Distillery 2.1 renames the task to `mix distillery.release`.

Then, run

.. code-block:: bash
mix deps.get
mix distillery.init
# if you are running distillery below version 2.1, you'll want to run `mix release.init` instead
Don't forget to commit

.. code-block:: bash
git add mix.exs mix.lock rel/
git commit -m 'install distillery'
.. _`Distillery installation instructions`: https://hexdocs.pm/distillery/introduction/installation.html

Configuration and Secrets
^^^^^^^^^^^^^^^^^^^^^^^^^

Add something like the following in :bash:`prod.exs`

.. code-block:: elixir
config :gigalixir_getting_started, GigalixirGettingStartedWeb.Endpoint,
server: true, # Without this line, your app will not start the web server!
load_from_system_env: true, # Needed for Phoenix 1.3. Doesn't hurt for other versions
http: [port: {:system, "PORT"}], # Needed for Phoenix 1.2 and 1.4. Doesn't hurt for 1.3.
secret_key_base: "${SECRET_KEY_BASE}",
url: [host: "${APP_NAME}.gigalixirapp.com", port: 443],
cache_static_manifest: "priv/static/cache_manifest.json",
version: Mix.Project.config[:version] # To bust cache during hot upgrades
config :gigalixir_getting_started, GigalixirGettingStarted.Repo,
adapter: Ecto.Adapters.Postgres,
url: "${DATABASE_URL}",
database: "", # Works around a bug in older versions of ecto. Doesn't hurt for other versions.
ssl: true,
pool_size: 2 # Free tier db only allows 4 connections. Rolling deploys need pool_size*(n+1) connections where n is the number of app replicas.
:elixir:`server: true` **is very important and is commonly left out. Make sure you have this line.**

1. Replace :elixir:`:gigalixir_getting_started` with your app name e.g. :elixir:`:my_app`
2. Replace :elixir:`GigalixirGettingStartedWeb.Endpoint` with your endpoint module name. You can find your endpoint module name by running something like

.. code-block:: bash
grep -R "defmodule.*Endpoint" lib/
Phoenix 1.2, 1.3, and 1.4 give different names so this is a common source of errors.
3. Replace :elixir:`GigalixirGettingStarted.Repo` with your repo module name e.g. :elixir:`MyApp.Repo`

You don't have to worry about setting your :bash:`SECRET_KEY_BASE` config because we generate one and set it for you. If you don't use a gigalixir managed postgres database, you'll have to set the :bash:`DATABASE_URL` yourself.

Verify
^^^^^^

Let's make sure everything works.

First, try generating building static assets

.. code-block:: bash
mix deps.get
# generate static assets
cd assets
npm install
npm run deploy
cd ..
mix phx.digest
and building a Distillery release locally

.. code-block:: bash
MIX_ENV=prod mix distillery.release --env=prod
# if you are running distillery below 2.1, you'll want to run this instead: MIX_ENV=prod mix release --env=prod
and running it locally

.. code-block:: bash
MIX_ENV=prod APP_NAME=gigalixir_getting_started SECRET_KEY_BASE="$(mix phx.gen.secret)" DATABASE_URL="postgresql://user:pass@localhost:5432/foo" MY_HOSTNAME=example.com MY_COOKIE=secret REPLACE_OS_VARS=true MY_NODE_NAME=foo@127.0.0.1 PORT=4000 _build/prod/rel/gigalixir_getting_started/bin/gigalixir_getting_started foreground
Don't forget to replace :bash:`gigalixir_getting_started` with your own app name. Also, change/add the environment variables as needed.

Commit the changes

.. code-block:: bash
git add config/prod.exs assets/package-lock.json
git commit -m 'distillery configuration'
Check it out.

.. code-block:: bash
curl localhost:4000
If that didn't work, the first place to check is :bash:`prod.exs`. Make sure you have :elixir:`server: true` somewhere and there are no typos.

Also check out :ref:`troubleshooting`.

If it still doesn't work, don't hesitate to :ref:`contact us<help>`.

If everything works, continue to :ref:`set up deploys`.

.. _`buildpacks`:

Specify Buildpacks (optional)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

We rely on buildpacks to compile and build your release. We auto-detect a variety of buildpacks so you probably don't need this, but if you want
to specify your own buildpacks create a :bash:`.buildpacks` file with the buildpacks you want. For example,

.. code-block:: bash
https://github.com/HashNuke/heroku-buildpack-elixir
https://github.com/gjaldon/heroku-buildpack-phoenix-static
https://github.com/gigalixir/gigalixir-buildpack-distillery.git
:bash:`heroku-buildpack-phoenix-static` is optional if you do not have Phoenix static assets. For more information about buildpacks, see :ref:`life of a deploy`.

Note, that the command that gets run in production depends on what your last buildpack is.

- If the last buildpack is :bash:`gigalixir-buildpack-distillery`, then the command run will be :bash:`/app/bin/foo foreground`.
- If the last buildpack is :bash:`heroku-buildpack-phoenix-static`, then the command run will be :bash:`mix phx.server`.
- If the last buildpack is :bash:`heroku-buildpack-elixir`, then the command run will be :bash:`mix run --no-halt`.

If your command is :bash:`mix run --no-halt`, but you are running Phoenix (just not the assets pipeline), make sure you set :elixir:`server: true` in :bash:`prod.exs`.

Set up Node Clustering with Libcluster (optional)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you want to cluster nodes, you should install libcluster. For more information about installing libcluster, see :ref:`cluster your nodes`.

.. _`Mix`: https://hexdocs.pm/mix/Mix.html

Set Up Hot Upgrades with Git v2.9.0
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

To run hot upgrades, you send an extra http header when running :bash:`git push gigalixir master`. Extra HTTP headers are only supported in git 2.9.0 and above so make sure you upgrade if needed. For information on how to install the latest version of git on Ubuntu, see `this stackoverflow question <http://stackoverflow.com/questions/19109542/installing-latest-version-of-git-in-ubuntu>`_. For information on running hot upgrades, see :ref:`hot-upgrade` and :ref:`life-of-a-hot-upgrade`.

.. _`modifying existing app with Elixir releases`:

Using Elixir Releases
---------------------

Configuration and Secrets
^^^^^^^^^^^^^^^^^^^^^^^^^

Gigalixir auto-detects that you want to use Elixir Releases if you have a :bash:`config/releases.exs` file, so let's create one.

.. code-block:: bash
echo "import Config" > config/releases.exs
The only configuration change we really need to do now is make sure the web server is started. Add the following to your :bash:`releases.exs`.

.. code-block:: bash
config :gigalixir_getting_started, GigalixirGettingStartedWeb.Endpoint,
server: true,
http: [port: {:system, "PORT"}], # Needed for Phoenix 1.2 and 1.4. Doesn't hurt for 1.3.
url: [host: System.get_env("APP_NAME") <> ".gigalixirapp.com", port: 443]
1. Replace :elixir:`:gigalixir_getting_started` with your app name e.g. :elixir:`:my_app`
2. Replace :elixir:`GigalixirGettingStartedWeb.Endpoint` with your endpoint module name. You can find your endpoint module name by running something like

.. code-block:: bash
grep -R "defmodule.*Endpoint" lib/
Phoenix 1.2, 1.3, and 1.4 give different names so this is a common source of errors.

If you're using a free tier database, be sure to also set your pool size to 2 in :bash:`prod.exs`.

You don't have to worry about setting your :bash:`SECRET_KEY_BASE` config because we generate one and set it for you.

Verify
^^^^^^

Let's make sure everything works.

First, try generating building static assets

.. code-block:: bash
mix deps.get
# generate static assets
cd assets
npm install
npm run deploy
cd ..
mix phx.digest
and building a release locally

.. code-block:: bash
export SECRET_KEY_BASE="$(mix phx.gen.secret)"
export DATABASE_URL="postgresql://user:pass@localhost:5432/foo"
MIX_ENV=prod mix release
and running it locally

.. code-block:: bash
MIX_ENV=prod APP_NAME=gigalixir_getting_started PORT=4000 _build/prod/rel/gigalixir_getting_started/bin/gigalixir_getting_started start
Don't forget to replace :bash:`gigalixir_getting_started` with your own app name. Also, change/add the environment variables as needed.

Check it out.

.. code-block:: bash
curl localhost:4000
If that didn't work, the first place to check is :bash:`prod.exs`. Make sure you have :elixir:`server: true` somewhere and there are no typos.

Also check out :ref:`troubleshooting`.

If it still doesn't work, don't hesitate to :ref:`contact us<help>`.

If everything works, commit the changes

.. code-block:: bash
git add config/prod.exs assets/package-lock.json config/releases.exs
git commit -m 'releases configuration'
Continue to :ref:`set up deploys`.

Specify Buildpacks (optional)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

We rely on buildpacks to compile and build your release. We auto-detect a variety of buildpacks so you probably don't need this, but if you want
to specify your own buildpacks create a :bash:`.buildpacks` file with the buildpacks you want. For example,

.. code-block:: bash
https://github.com/HashNuke/heroku-buildpack-elixir
https://github.com/gjaldon/heroku-buildpack-phoenix-static
https://github.com/gigalixir/gigalixir-buildpack-releases.git
:bash:`heroku-buildpack-phoenix-static` is optional if you do not have Phoenix static assets. For more information about buildpacks, see :ref:`life of a deploy`.

Note, that the command that gets run in production depends on what your last buildpack is.

- If the last buildpack is :bash:`gigalixir-buildpack-releases`, then the command run will be :bash:`/app/bin/foo start`.
- If the last buildpack is :bash:`heroku-buildpack-phoenix-static`, then the command run will be :bash:`mix phx.server`.
- If the last buildpack is :bash:`heroku-buildpack-elixir`, then the command run will be :bash:`mix run --no-halt`.

If your command is :bash:`mix run --no-halt`, but you are running Phoenix (just not the assets pipeline), make sure you set :elixir:`server: true` in :bash:`prod.exs`.

0 comments on commit 77e9120

Please sign in to comment.