My First Deploy
Tags: dohackathon, elixir
Published: 2020-12-27 20:58:11

So I was a bit curious about how DigitalOcean's App platform worked so I decided to add basic authentication stuff and deploy it, but I wanted to have email confirmation as well so I did a small detour to setup that as well using.

## User authentication

> Rule 1: Never do your own authentication

This is one of those live rules that you just have to trust and besides, why reinvent the wheel? 

For authentication I'm using [Phx.Gen.Auth](https://github.com/aaronrenner/phx_gen_auth) a new authentication system generator for Phoenix. The main difference from authentication libraries you find is that this is a generator and not a library. This means that it generates all the code that it needs and inserts it into your project (as if written by you).

Why use it? Well basically I have two reasons: 1) I wanted to try it out. 2) I always end up having to dive deep into how to customize other libraries workflow because there's an edge case I need to handle so way easier to handle if its just code in my project.

One small modification I had to do was adding the logic to ask for email confirmation before allowing to sign in. Thankfully this was sort of easy thanks to comments like this in the generated code:

```elixir
@doc """
Used for routes that require the user to be authenticated.

If you want to enforce the user email is confirmed before
they use the application at all, here would be a good place.
"""
def require_authenticated_user(conn, _opts) do
  ...
end
```

## Email library

For emailing related stuff I decided to use my usual choice of library [Bamboo](https://github.com/thoughtbot/bamboo). For mail service I decided to give [Postmark](https://postmarkapp.com/) a try after some recommendations (and changes to Mailgun's free trial).

Postmark was a bit extra complicated to setup because it doesn't allow public domains emails such as `@gmail.com` for sign up. I had gotten a free year for a `.tech` domain recently so decided to setup mail forwarding to my email from it and sign up with that. So after that small detour it was about the same as other mail providers I've used.

Bamboo let users create abstractions called `Adapter` to have a common interface. For my non-production environments I'm using [Bamboo.LocalAdapter](https://hexdocs.pm/bamboo/Bamboo.LocalAdapter.html#content) which just prints the email and for production [Bamboo.PostmarkAdapter](https://github.com/pablo-co/bamboo_postmark)

## Deploying

Now to the important part: deploying to App Platform. 

Since neither Elixir nor Phoenix are natively-supported I need to add a Dockerfile to my project so it can run. Also, I had to do some changes to use Elixir's releases and use environment variables at start-time instead of compile time. Thankfully all this (including a demo Dockerfile) is explained in Phoenix's documentation: [Deploy with Releases](https://hexdocs.pm/phoenix/releases.html#content).

Next, still no deploy (sorry), I went ahead and a managed database cluster (1 node ja) so my app could connect to it. Why not use the dev database they offer? Well because the credits they gave out expire in 60 days so no point in not trying all the cool stuff they have.

Now finally I have a deployed app: https://sponsorly.aminarria.tech/

## "Deploy to DO" button

This was very direct:

1. Went into my app's settings in DO and downloaded its spec
1. Created a [deploy.template.yaml](https://github.com/AminArria/sponsorly/blob/main/.do/deploy.template.yaml) following the [documentation](https://www.digitalocean.com/docs/app-platform/how-to/add-deploy-do-button/) and seen what was in my spec.
1. Add the button to my README

Although for this to work properly, mainly because of the Postmark requirement, I made a small change so the Bamboo adapter can be changed to the local one using a environment variable `USE_LOCAL_ADAPTER = "true"`.

And that's it! I have a bare-bones app deployed and that you can deploy with the click of a button (and some config of environment variables)