diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..5f7f4be1 --- /dev/null +++ b/.env.example @@ -0,0 +1,38 @@ +############ +# Database +############ + +POSTGRES_HOST=localhost +POSTGRES_USER=postgres +POSTGRES_PASSWORD="" +POSTGRES_PORT=5432 + +############ +# Dev Container Environement Variables +############ +DEV_SERVER_IP=127.0.0.1 +DEV_SECRET_KEY_BASE=k/B2/h3nrn+XIwYaLZcc7cIAKfUihj9gLwm/IrtzNhx6daOLRax2xAzDCRoiHCNuH1iPOlMhp9aD91HJ +DEV_DATABASE_URL=ecto://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/animina_dev +DEV_PHX_HOST=dev.animina.de +DEV_PORT=4300 +DEV_FILE_VOLUME_PATH=/etc/animina/dev/ +DEV_CONTAINER_IMAGE="animina/animina-dev" + +############ +# Prod Container Environement Variables +############ +PROD_SERVER_IP=127.0.0.1 +PROD_SECRET_KEY_BASE=l8m2Yg9DmUzyC/onSZuzd2yR0UZbPTw3a8fRwMLDZqyhF1TuPdPys5pv/7rAo8xN12ZtuOW46kVEWBpy +PROD_DATABASE_URL=ecto://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/animina +PROD_PHX_HOST=animina.de +PROD_PORT=4310 +PROD_FILE_VOLUME_PATH=/etc/animina/prod/ +PROD_CONTAINER_IMAGE="animina/animina-prod" + +############ +# Shared Environement Variables +############ +DISABLE_ML_FEATURES="true" +KAMAL_REGISTRY_USERNAME="animina" +KAMAL_REGISTRY_PASSWORD="" +REMOTE_BUILDER_SSH_URL="ssh://root@$DEV_SERVER_IP" \ No newline at end of file diff --git a/README.md b/README.md index 460a8be4..a135d2fe 100644 --- a/README.md +++ b/README.md @@ -171,15 +171,74 @@ Follow these installation [steps](https://kamal-deploy.org/docs/installation/) t ### Configure environment variables -Create a .env file in the root of the project and add the following +Create a .env file in the root of the project and then copy the contents of .env.examnple to it. +To configure the database edit the following env variables ``` +POSTGRES_HOST=localhost +POSTGRES_USER=postgres +POSTGRES_PASSWORD="" +POSTGRES_PORT=5432 +``` + +Kamal requires a registry where it can upload and cache the docker containers. This project uses github registry. +To configure the registry, create a github [token](https://github.com/settings/tokens/new) and grant it the `write:packages` access rights. +Copy the token and paste it in your .env file under the `KAMAL_REGISTRY_PASSWORD` key. +``` +KAMAL_REGISTRY_USERNAME= KAMAL_REGISTRY_PASSWORD= -SECRET_KEY_BASE= -DATABASE_URL=[dogenerated] -PHX_HOST=[yourdomain] ``` +The rest of the environment variables are similar but prefixed with the target deployment. To cnfigure for prod deployments, edit the variables with +`PROD_` prefix, for dev `DEV_` prefix. + +``` +*_SERVER_IP= +*_SECRET_KEY_BASE= //Use `mix phx.gen.secret 80` to generate this +*_DATABASE_URL= +*_PHX_HOST= +*_PORT= +*_FILE_VOLUME_PATH= +*_CONTAINER_IMAGE= //Should start with your github username, followed by the container name +``` + +For example, here's a config for a prod environment +``` +PROD_SERVER_IP=127.0.0.1 +PROD_SECRET_KEY_BASE=9GGCyEor8pAYi1CncIsZx9opAwhD7+7/zMbrs9NN05/oEH3PXU0AfQ7ESodoXsHg00S07ATBkGKcFbFJ +PROD_DATABASE_URL=ecto://$POSTGRES_USER:$POSTGRES_PASSWORD@$POSTGRES_HOST:$POSTGRES_PORT/animina +PROD_PHX_HOST=animina.de +PROD_PORT=4310 +PROD_FILE_VOLUME_PATH=/etc/animina/prod/ +PROD_CONTAINER_IMAGE="animina/animina-prod" +``` + +### Initialize kamal +Run the following command to setup kamal both on your local instance and the remote host. You will be prompted to enter the password +of the remote host. This command will check if Docker is installed and, if not, it will attempt to install it on your host server. + +``` +kamal server bootstrap +``` + +### Deploy the application +To deploy the application, run `kamal deploy`. You will need to set the destinations flag `-d` followed by the destination name. +For example to deploy to prod, run +``` +kamal deploy -d prod +``` +To deploy to dev, run +``` +kamal deploy -d dev +``` + +The above command logins into the docker registry, builds the docker images locally, pushes the build artifacts to the registry and finally deploys the docker images to your host. Read more about `kamal deploy` [here](https://kamal-deploy.org/docs/commands/deploy/) + +To redeploy running `kamal deploy` will result in an error as our container is already running and bound to a port on the host. This is due to how kamal 2 works as seen in this github issue [here](https://github.com/basecamp/kamal/issues/1133). + +To get around this, first run `kamal app stop` and then run `kamal deploy`. Be sure to specify the destinations using the `-d` flag. + + ## Submiting Code Please read the [CONTRIBUTING.md](CONTRIBUTING.md) file. diff --git a/config/deploy.prod.yml b/config/deploy.prod.yml index eab854ce..2e0d2fda 100644 --- a/config/deploy.prod.yml +++ b/config/deploy.prod.yml @@ -33,11 +33,11 @@ env: clear: PORT: 4000 MIX_ENV: prod - DATABASE_URL: <%= ENV["PROD_DATABASE_URL"] %> secret: - SECRET_KEY_BASE - PHX_HOST - DISABLE_ML_FEATURES + - DATABASE_URL ssh: user: root diff --git a/config/deploy.yml b/config/deploy.yml new file mode 100644 index 00000000..c6a44006 --- /dev/null +++ b/config/deploy.yml @@ -0,0 +1,48 @@ +# Name of your application. Used to uniquely configure containers. +service: animina + +<% require "dotenv"; Dotenv.load(".env") %> + +# Name of the container image. +image: animina/animina + +# Deploy to these servers. +servers: + web: + hosts: + - <%= ENV["PROD_SERVER_IP"] %> + options: + publish: <%= ENV["PROD_PORT"] %>:4000 + proxy: false + +# Credentials for your image host. +registry: + server: ghcr.io + username: + - KAMAL_REGISTRY_USERNAME + # Always use an access token rather than real password (pulled from .kamal/secrets). + password: + - KAMAL_REGISTRY_PASSWORD + + +builder: + arch: amd64 + +# Inject ENV variables into containers (secrets come from .kamal/secrets). +env: + clear: + PORT: 4000 + MIX_ENV: prod + secret: + - DATABASE_URL + - SECRET_KEY_BASE + - PHX_HOST + - DISABLE_ML_FEATURES + +ssh: + user: root + +# Use a persistent storage volume. +# +volumes: + - "<%= ENV["PROD_FILE_VOLUME_PATH"] %>:/uploads" diff --git a/mix.exs b/mix.exs index 7aa0fc2b..fe535e71 100644 --- a/mix.exs +++ b/mix.exs @@ -11,7 +11,8 @@ defmodule Animina.MixProject do releases: [ animina: [ applications: [ - animina: :permanent + animina: :permanent, + animina_web: :permanent ] ] ],