Elixir/Phoenix Project: Establish Hosting Service
Tags: elixir, tutorial, sideprojects
Published: 2020-10-07 14:24:44

#### Goals:
  - Establish a hosting service
  - Update README with deploy steps
  - Setup custom domain to point to new environment

---

#### Establish a hosting service
A project running locally on my machine is great, but it doesn't mean much if that's the only place it exists. It might seem a bit premature, considering that at this point my entire project is still the default Phoenix splash page. But getting a hosting environment setup early means that new features will be able to go live as soon as they are merged. I started the process by digging around the web to see what others had done (noticing a pattern yet?). And I was a bit surprised that there is a whole service targeted specifically to hosing Elixir/Phoenix projects that I had not heard of: [Gigalixir](https://www.gigalixir.com/). What I was _not_ surprised by was that there is an entire [Deployment](https://hexdocs.pm/phoenix/deployment.html#content) section of the Phoenix hexdocs, and in that section there is a whole subsection of how to [deploy to Gigalixir](https://hexdocs.pm/phoenix/gigalixir.html#content).

But, before I go any further, I'm sure someone out there is thinking "why not Heroku?". In a nutshell, Heroku is not setup to give access to all of the features of an Elixir/Phoenix app, like node clustering. Not being partial to any particular hosting service, I figured why not setup my hosting with a service that is made for Elixir/Phoenix?

I ended up walking through the Gigalixir [Getting Started Guide](https://gigalixir.readthedocs.io/en/latest/getting-started-guide.html), and I have to say, the process was pretty painless. The Gigalixir docs are very detailed, and searchable. Because of the level of detail in their docs, I'm not going to write out my entire process, because I literally just followed the docs through step by step. I will note that I got a bit hung up in the [Specify Versions](https://gigalixir.readthedocs.io/en/latest/getting-started-guide.html#specify-versions) section, because my local versions of `elixir` and `erlang` were newer than what were specified in the docs.

My local: 
`elixir` -> `1.10.4`
`erlang` -> `23`

Docs specs:
`elixir` -> `1.10.3`
`erlang` -> `22.3`

I attempted to declare these new versions in the `elixir_buildpack.config` file that Gigalixir uses to set environment versioning, but when I tried to push up to the service was giving an error stating that those versions couldn't be found. I tinkered with things for a bit, but the only way I could get a push to this new staging environment to be successful was to use the environment specs given in the docs. It's definitely less than desirable to have a local version be different than in a staging environment, but it's a minor version difference, and I know that my next step in this app is to dockerize everything, and there I will take the steps to ensure the versions match.

Another thing to note is that while setting up my Github repository I switched my primary branch name from `master` to `main`. It seems that Gigalixir has not quite caught up with this optional change, and in the [Deploy](https://gigalixir.readthedocs.io/en/latest/getting-started-guide.html#deploy) step it has this:

`git push gigalixir master`

But, thats basically shorthand, stating that `master` from Github should be pushed to `master` in the staging environment. Since I don't have a `master` branch, I get the following error:

{% gist https://gist.github.com/noelworden/10c83478a2a1db48bba4a68c570e27c0 %}

The fix is pretty simple, it just requires a more verbose command:

`git push gigalixir main:master`

That command is stating that the `main` branch of Github should be pushed to the `master` branch of staging

One last note that was not noted in the Getting Started Guide is that the remote can be renamed. By default Gigalixir named the remote `gigalixir` but I am more used to referencing remotes by their purpose, like `staging` or `production`. So I ran this command to update the name of my remote:

`git remote rename gigalixir staging`

Although there were a few small hiccups, all in all the process to setup a staging environment for the project was relatively painless. I have setup a few Heroku environments back in the day, and this process seems remarkably similar. I would strongly recommend at least skimming through the entirety of the Gigalixir [docs](https://gigalixir.readthedocs.io/en/latest/) as they are chock full of useful information.

#### Update README with deploy steps
In the vein of trying to keep within the ream of best practices I felt like it would be beneficial to document the deploy steps in the README. I've been on more than a few projects where I was the second or third engineer onboarded and there was no documentation on how to perform relatively essential tasks. This is what I included in the project's README:

---

## Deploying to staging
### Hosted by Gigalixir, docs can be found [here](https://gigalixir.readthedocs.io/en/latest/)
  - It should be noted that the docs are _very_ good, and searchable
  - Once the CLI is installed, `gigalixir help` is also very detailed

### Project URLs
  - https://atlas-staging.gigalixirapp.com/
  - https://atlas-production.gigalixirapp.com/

### Install Gigalixir CLI (with homebrew)
  - `brew tap gigalixir/brew && brew install gigalixir`

### Log into Gigalixir
  - `gigalixir login`

### Verify login was successful
  - `gigalixir account`

### Setup git remote
  - Navigate to project folder
  - `gigalixir git:remote atlas-staging`

### Confirm remote
  - `git remote -v`

### If desired, rename remote (which defaulted to `gigalixir`) to `staging`
  - `git remote rename gigalixir staging`

### Push to staging
  - Any branch can be pushed to the staging site
  - Branches need to be pushed to Github before being pushed to staging
    - `git push staging <branch name>:master`

### Main vs Master
  - This project's main branch is named `main`, but Gigalixir is expecting it to be named `master`
    - Because of this, when pushing `main` to staging, it _cannot_ be done with the shorthand:
      `git push staging master`
    - Until a fix is made by Gigalixir, the following syntax must be used to push:
      `git push staging main:master`


## Executing `mix` Commands in Staging
The app is currently setup to be able to run mix commands on the staging environment

### The `run` command
  - This can be used to run a shell command as a job in a separate container
  - `gigalixir run ...`

### Using `run` and `mix`
  - Any `mix` command available locally can be executing on staging utilizing `run`
  - `gigalixir run mix <command here>`

### Executing a migration
  - `gigalixir run mix ecto.migrate`
  - The logs do not automatically show, to view the logs
    - `gigalixir logs`


## Viewing the app
### To open the app in a browser
- `gigalixir open`

---

With this information, along with the slightly tweaked default `Spin up the Project` steps, a new developer _should_ be able to pull down the project, get it spun up, and push work to staging all from the docs. I don't really plan on anyone besides me working on this in the foreseeable future, but solid documentation should be the goal of all projects, right?

#### Setup custom domain
Before I even started this project I dug around for a domain that I felt would be appropriate. It would be a bummer if I got 3 months into this project and I couldn't acquire a domain that had a name is a similar vein. I was able to purchase `anglingatlas.com`, so I named the project and repo `atlas` (I didn't want to type out `AnglingAtlas` every time I had to reference something in the project). 

Gigalixir makes it pretty easy to assign a custom domain to the staging (or any other) environment. The one-liner can be found [here](https://gigalixir.readthedocs.io/en/latest/domain.html?highlight=domain#how-to-set-up-a-custom-domain). I should also point out that the Gigalixir web interface is pretty user-friendly as well. Now my staging environment can be found at https://staging.theanglingatlas.com/

#### Closing thoughts
I kind of gravitated to all of these devops tasks because it's an aspect of projects that I haven't dealt with directly in quite some time. I was curious what it actually took to get all of this stuff in place. And since I was so far down this road I figured I might as well get it all taken care of. Once this is all squared away, I'll be able to just worry about the features. The last piece of this (I think) is going to be dockerizing the project.

There aren't a ton of changes in the repo since a lot of this section was configuring Gigalixir, but [here](https://github.com/noelworden/atlas/tree/7298c0159e29548ed028614e0b544c0e88c88439) is what it looks like after all of this configuration.

#### References
- https://hexdocs.pm/phoenix/deployment.html#content
- https://www.gigalixir.com/
- https://gigalixir.readthedocs.io/en/latest/faq.html
- https://github.com/git-guides/git-remote

------

This post is part of an ongoing [series](https://dev.to/noelworden/new-side-project-new-blog-series-135h). I encourage any critique, feedback, or suggestions in the comments.