bonfire-app/docs/DEPLOY.md

378 lines
16 KiB
Markdown
Raw Normal View History

2022-03-29 22:02:21 +00:00
# Deployment guide
2021-05-22 18:41:36 +00:00
2022-03-25 16:45:47 +00:00
### WARNING: Bonfire is still under active development and deployment is only recommended for development and testing purposes!
2021-05-22 18:41:36 +00:00
_These instructions are for setting up Bonfire in production. If you want to run the backend in development, please refer to our [Developer Guide](./HACKING.md)!_
2022-03-25 16:45:47 +00:00
## Security Warning
We recommend only granting an account to people you trust to minimise the attack surface.
Accordingly, Bonfire ships with public registration disabled, please
keep it that way. The admin panel has an `invite` facility.
2021-05-22 18:41:36 +00:00
---
## Step 0 - Configure your database
2022-03-25 16:45:47 +00:00
You must provide a postgresql database for data storage. We require postgres 12 or above.
2021-05-22 18:41:36 +00:00
If you are running in a restricted environment such as Amazon RDS, you will need to execute some sql against the database:
```
CREATE EXTENSION IF NOT EXISTS citext;
```
2021-06-15 10:00:18 +00:00
## Step 1 - Download and configure the app
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
1. Install dependencies. You will need to install [just](https://github.com/casey/just#packages), and other requirements such as Docker (check the exact list of requirements based on the option you choose in step 2.)
2. Clone this repository and change into the directory:
2021-05-22 18:41:36 +00:00
2021-06-15 10:00:18 +00:00
```sh
$ git clone https://github.com/bonfire-networks/bonfire-app.git bonfire
$ cd bonfire
```
2022-05-23 02:20:39 +00:00
3. Specify that you want to run in production:
`export MIX_ENV=prod`
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
The first thing to do is choose what flavour of Bonfire you want to deploy, as each flavour uses different Docker images and set of configs. For example if you want to run the `classic` flavour (you may want to use direnv or something similar to persist this):
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
`just config classic`
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
This will initialise some default config (a .env file which won't be checked into git)
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
5. Edit the config (especially the secrets) for the selected flavour in `./.env`
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
These are the config keys you should especially pay attention to:
2021-06-17 09:41:40 +00:00
- SECRET_KEY_BASE
- SIGNING_SALT
- ENCRYPTION_SALT
- POSTGRES_PASSWORD
- MEILI_MASTER_KEY
2022-05-23 02:20:39 +00:00
You can use `just secrets` to generate some random secret keys to use.
2021-06-17 09:41:40 +00:00
And in public.env:
- HOSTNAME
- PUBLIC_PORT
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
You can just registrations on your instance invite-only by setting `INVITE_ONLY=true`.
2021-12-21 02:27:32 +00:00
2022-05-23 02:20:39 +00:00
`MAIL_DOMAIN` and `MAIL_KEY` are needed to configure transactional email, you can for example sign up at [Mailgun](https://www.mailgun.com/) and then configure the domain name and key.
2021-12-21 02:27:32 +00:00
2021-06-15 10:00:18 +00:00
### Further information on config
2022-05-23 02:20:39 +00:00
The app needs some environment variables to be configured in order to work. The easy way to manage that is whit the `just` commands which take care of loading the environment for you.
2021-06-15 10:00:18 +00:00
2022-05-23 02:20:39 +00:00
In the `./config/` (which is a symbolic link to the config of the flavour you choose to run) directory of the codebase, there are following config files:
2021-05-22 18:41:36 +00:00
- `config.exs`: default base configuration, which itself loads many other config files, such as one for each installed Bonfire extension.
- `prod.exs`: default extra configuration for `MIX_ENV=prod`
- `runtime.exs`: extra configuration which is loaded at runtime (vs the others which are only loaded once at compile time, i.e. when you build a release)
2021-06-15 10:00:18 +00:00
- `bonfire_*.exs`: configs specific to different extensions, which are automatically imported by `config.exs`
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
You should *not* have to modify the files above. Instead, overload any settings from the above files using env variables or in `./.env`.
2021-05-22 18:41:36 +00:00
## Step 2 - Install
2022-05-23 02:20:39 +00:00
### Option A - Install using Co-op Cloud (recommended)
[https://coopcloud.tech](https://coopcloud.tech) is an alternative to corporate clouds built by tech co-ops, and provides very useful tools for setting up and managing many self-hosted free software tools using ready-to-use "recipes".
If you're interested in hosting Bonfire alongside other open and/or federated projects, we recommend installing [Abra](https://docs.coopcloud.tech/abra/), [setting up a co-op cloud server](https://docs.coopcloud.tech/operators/) and using the [Bonfire recipe](https://recipes.coopcloud.tech/bonfire) to set up an instance.
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
### Option B - Install using Docker containers (easy mode)
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
The easiest way to launch the docker image is using the just commands.
2021-06-15 12:03:33 +00:00
The `docker-compose.release.yml` uses `config/prod/public.env` and `config/prod/secrets.env` to launch a container with the necessary environment variables along with its dependencies, currently that means an extra postgres container, along with a reverse proxy (Caddy server, which you may want to replace with nginx or whatever you prefer).
2021-05-22 18:41:36 +00:00
#### Install with docker-compose
2022-05-23 02:20:39 +00:00
Make sure you have [Docker](https://www.docker.com/), a recent [docker-compose](https://docs.docker.com/compose/install/#install-compose) (which supports v3 configs), and [just](https://github.com/casey/just#packages) installed:
2021-05-22 18:41:36 +00:00
```sh
$ docker version
Docker version 18.09.1-ce
$ docker-compose -v
docker-compose version 1.23.2
2022-05-23 02:20:39 +00:00
$ just --version
just 1.1.3
2021-05-22 18:41:36 +00:00
...
```
2021-12-12 04:44:14 +00:00
Now that your tooling is set up, you have the choice of using pre-built images or building your own. For example if your flavour does not have a prebuilt image on Docker Hub, or if you want to customise any of the extensions, you can build one yourself - see option A2 below.
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
#### Option B1 - Using pre-built Docker images (recommend to start with)
2021-12-12 04:44:14 +00:00
2021-12-12 06:01:44 +00:00
- The `image` entry in `docker-compose.release.yml` will by default use the image on Docker Hub which corresponds to your chosen flavour (see step 1 above for choosing your flavour).
2021-12-12 04:44:14 +00:00
You can see the images available per flavour, version (we currently recommend using the `latest` tag), and architecture at https://hub.docker.com/r/bonfirenetworks/bonfire/tags
- Start the docker containers with docker-compose:
2021-05-22 18:41:36 +00:00
2021-06-15 10:00:18 +00:00
```
2022-05-23 02:20:39 +00:00
just rel.run
2021-06-15 10:00:18 +00:00
```
2021-05-22 18:41:36 +00:00
2022-01-25 20:54:25 +00:00
Run this at the prompt:
`bin/bonfire remote` to enter Elixir's iex environment
2022-05-13 20:23:04 +00:00
`EctoSparkles.Migrator.migrate` to initialise your database
2022-01-25 20:54:25 +00:00
2021-06-15 10:00:18 +00:00
The backend should now be running at [http://localhost:4000/](http://localhost:4000/).
2021-05-23 08:23:53 +00:00
2021-12-12 04:44:14 +00:00
- If that worked, start the app as a daemon next time:
2021-05-22 18:41:36 +00:00
2021-06-15 10:00:18 +00:00
```
2022-05-23 02:20:39 +00:00
just rel.run.bg
2021-05-22 18:41:36 +00:00
```
2021-06-15 10:00:18 +00:00
#### Docker-related handy commands
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
- `just update` to update to the latest release of Bonfire
- `just rel.run` Run the app in Docker, in the foreground
- `just rel.run.bg` Run the app in Docker, and keep running in the background
- `just rel.stop` Stop the running release
- `just rel.shell` Runs a simple shell inside of the container, useful to explore the image
2021-05-22 18:41:36 +00:00
2021-06-15 10:00:18 +00:00
Once in the shell, you can run `bin/bonfire` with the following commands:
Usage: `bonfire COMMAND [ARGS]`
2021-05-22 18:41:36 +00:00
2021-06-15 10:00:18 +00:00
The known commands are:
2021-06-15 10:05:19 +00:00
- `start` Starts the system
- `start_iex` Starts the system with IEx attached
- `daemon` Starts the system as a daemon
- `daemon_iex` Starts the system as a daemon with IEx attached
- `eval "EXPR"` Executes the given expression on a new, non-booted system
- `rpc "EXPR"` Executes the given expression remotely on the running system
- `remote` Connects to the running system via a IEx remote shell
- `restart` Restarts the running system via a remote command
- `stop` Stops the running system via a remote command
- `pid` Prints the operating system PID of the running system via a remote command
- `version` Prints the release name and version to be booted
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
There are some useful database-related release tasks under `EctoSparkles.Migrator.` that can be run in an `iex` console (which you get to with `just rel.shell` followed by `bin/bonfire remote`, assuming the app is already running):
2021-05-22 18:41:36 +00:00
- `migrate` runs all up migrations
- `rollback(step)` roll back to step X
- `rollback_to(version)` roll back to a specific version
- `rollback_all` rolls back all migrations back to zero (caution: this means loosing all data)
2022-02-12 03:51:23 +00:00
You can also directly call some functions in the code from the command line, for example:
2022-05-13 20:23:04 +00:00
- to migrate: `docker exec bonfire_web bin/bonfire rpc 'EctoSparkles.Migrator.migrate'`
2022-05-23 02:20:39 +00:00
- to just yourself an admin: `docker exec bonfire_web bin/bonfire rpc 'Bonfire.Me.Users.make_admin("my_username")'`
2022-02-12 03:51:23 +00:00
2022-05-23 02:20:39 +00:00
#### Option B2 - Building your own Docker image
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
`Dockerfile.release` uses the [multistage build](https://docs.docker.com/develop/develop-images/multistage-build/) feature to just the image as small as possible. It generates the OTP release which is later copied into the final image packaged in an Alpine linux container.
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
There is a `justfile` with relevant commands (make sure set the `MIX_ENV=prod` env variable):
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
- `just rel.build` which builds the docker image
- `just rel.tag.latest` adds the "latest" tag to your last build, so that it will be used when running
- `just rel.push` if you want to push your latest build to Docker Hub
2021-12-12 04:44:14 +00:00
2021-12-12 06:01:44 +00:00
Once you've built and tagged your image, you may need to update the `image` name in `docker-compose.release.yml` to match (either your local image name if running on the same machine you used for the build, or a remote image on Docker Hub if you pushed it) and then follow the same steps as for option A1.
2021-12-12 04:44:14 +00:00
For production, we recommend to set up a CI workflow to automate this, for an example you can look at the one [we currently use](../github/workflows/release.yaml).
2021-05-22 18:41:36 +00:00
---
2022-05-23 02:20:39 +00:00
### Option C - Manual installation (without Docker)
2021-05-22 18:41:36 +00:00
#### Dependencies
2021-05-23 08:23:53 +00:00
- Postgres (or Postgis) version 12 or newer
2022-05-23 02:20:39 +00:00
- [just](https://github.com/casey/just#packages)
- Elixir version 1.13 with OTP 24 (or newer). If your distribution only has an old version available, check [Elixir's install page](https://elixir-lang.org/install.html) or use a tool like [asdf](https://github.com/asdf-vm/asdf) (run `asdf install` in this directory).
2021-05-22 18:41:36 +00:00
2022-05-23 02:20:39 +00:00
#### C-1. Building the release
2021-05-22 18:41:36 +00:00
- Make sure you have erlang and elixir installed (check `Dockerfile` for what version we're currently using)
2021-05-23 08:23:53 +00:00
- Run `mix deps.get --only prod` to install elixir dependencies.
2022-05-23 02:20:39 +00:00
- Prepare assets with `just js.deps.get`, `just assets.release` and `mix phx.digest`
2021-05-23 08:23:53 +00:00
2021-05-22 18:41:36 +00:00
- Run `mix release` to create an elixir release. This will create an executable in your `_build/prod/rel/bonfire` directory. We will be using the `bin/bonfire` executable from here on.
2022-05-23 02:20:39 +00:00
#### C-2. Running the release
2021-05-22 18:41:36 +00:00
2021-05-23 08:23:53 +00:00
- `cd _build/prod/rel/bonfire/`
2021-05-22 18:41:36 +00:00
2022-05-13 20:23:04 +00:00
- Create a database and run the migrations with `bin/bonfire eval 'EctoSparkles.Migrator.migrate()'`.
2021-05-22 18:41:36 +00:00
- If youre using RDS or some other locked down DB, you may need to run `CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;` on your database with elevated privileges.
2021-05-23 08:23:53 +00:00
* You can check if your instance is configured correctly by running it with `bin/bonfire start`
2021-05-22 18:41:36 +00:00
2021-05-23 08:23:53 +00:00
* To run the instance as a daemon, use `bin/bonfire start daemon`.
2021-05-22 18:41:36 +00:00
---
2022-05-23 02:20:39 +00:00
### Option D - with Nix
2021-07-03 08:04:49 +00:00
2021-07-04 06:00:22 +00:00
This repo is a Flake and includes a Nix module.
2021-07-02 07:49:03 +00:00
Here are the detailed steps to deploy it:
2021-07-02 06:09:11 +00:00
2021-07-02 07:49:03 +00:00
- run a recent version of Nix or NixOS: https://nixos.wiki
- enable Flakes: https://nixos.wiki/wiki/Flakes#Installing_flakes
2021-07-04 06:00:22 +00:00
- add `sandbox = false` in your nix.conf
- fetch and build the app and dependencies: `nix run github:bonfire-networks/bonfire-app start_iex`
2021-07-02 06:09:11 +00:00
- add it as an input to your system flake.
2022-05-23 02:20:39 +00:00
- add an overlay to just the package available
2021-07-02 06:09:11 +00:00
- add the required configuration in your system
2021-07-02 07:49:03 +00:00
Your `flake.nix` file would look like the following. Remember to replace `myHostName` with your actual hostname or however your deployed system is called.
2021-07-02 06:09:11 +00:00
```nix
{
inputs.bonfire.url = "github:happysalada/bonfire-app/main";
outputs = { self, nixpkgs, bonfire }: {
overlay = final: prev: with final;{
# a package named bonfire already exists on nixpkgs so we put it under a different name
elixirBonfire = bonfire.defaultPackage.x86_64-linux;
};
nixosConfigurations.myHostName = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
{
environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ];
nixpkgs.overlays = [ self.overlay ];
}
./myHostName.nix
bonfire.nixosModules.bonfire
];
};
};
}
```
2021-07-02 07:49:03 +00:00
Then your `myHostName.nix` would look like the following:
2021-07-02 06:09:11 +00:00
2021-07-02 07:49:03 +00:00
TODO: add caddy reverse proxy config
2021-07-02 06:09:11 +00:00
```nix
{ config, lib, pkgs, ... }:
{
services.bonfire = {
2021-07-02 07:49:03 +00:00
# you will additionally need to expose bonfire with a reverse proxy, for example caddy
2021-07-02 06:09:11 +00:00
port = 4000;
package = pkgs.elixirBonfire;
dbName = "bonfire";
# the environment should contain a minimum of
# SECRET_KEY_BASE
# SIGNING_SALT
# ENCRYPTION_SALT
# RELEASE_COOKIE
# have a look into nix/module.nix for more details
# the way to deploy secrets is beyond this readme, but I would recommend agenix
environmentFile = "/run/secrets/bonfireEnv";
dbSocketDir = "/var/run/postgresql";
};
# this is uniquely for database backup purposes
# replace myBackupUserName with the user name that will do the backups
# if you want to do backups differently, feel free to remove this part of the config
services.postgresql = {
ensureDatabases = [ "bonfire" ];
ensureUsers = [{
name = "myBackupUserName";
ensurePermissions = { "DATABASE bonfire" = "ALL PRIVILEGES"; };
}];
};
}
```
### Option C with nixos
this repo is a flake and includes a nixos module.
2021-07-03 08:04:49 +00:00
Here are the detailed steps to deploy it.
- add it as an input to your system flake.
2022-05-23 02:20:39 +00:00
- add an overlay to just the package available
2021-07-03 08:04:49 +00:00
- add the required configuration in your system
Your flake.nix file would look like the following. Remember to replace myHostName with your actual hostname or however your deployed system is called.
```nix
{
inputs.bonfire.url = "github:happysalada/bonfire-app/main";
outputs = { self, nixpkgs, bonfire }: {
overlay = final: prev: with final;{
# a package named bonfire already exists on nixpkgs so we put it under a different name
elixirBonfire = bonfire.defaultPackage.x86_64-linux;
};
nixosConfigurations.myHostName = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
{
environment.systemPackages = [ agenix.defaultPackage.x86_64-linux ];
nixpkgs.overlays = [ self.overlay ];
}
./myHostName.nix
bonfire.nixosModules.bonfire
];
};
};
}
```
then in myHostName.nix would look like the following
TODO: add the caddy config
```nix
{ config, lib, pkgs, ... }:
{
services.bonfire = {
# you will need to expose bonfire with a reverse proxy, for example caddy
port = 4000;
package = pkgs.elixirBonfire;
dbName = "bonfire";
# the environment should contain a minimum of
# SECRET_KEY_BASE
# SIGNING_SALT
# ENCRYPTION_SALT
# RELEASE_COOKIE
# have a look into nix/module.nix for more details
# the way to deploy secrets is beyond this readme, but I would recommend agenix
environmentFile = "/run/secrets/bonfireEnv";
dbSocketDir = "/var/run/postgresql";
};
# this is uniquely for database backup purposes
# replace myBackupUserName with the user name that will do the backups
# if you want to do backups differently, feel free to remove this part of the config
services.postgresql = {
ensureDatabases = [ "bonfire" ];
ensureUsers = [{
name = "myBackupUserName";
ensurePermissions = { "DATABASE bonfire" = "ALL PRIVILEGES"; };
}];
};
}
```
2021-05-22 18:41:36 +00:00
## Step 3 - Run
By default, the backend listens on port 4000 (TCP), so you can access it on http://localhost:4000/ (if you are on the same machine). In case of an error it will restart automatically.
Once you've signed up, you will automatically be an instance admin if you were the first to register.
2021-06-15 12:03:33 +00:00
---
#### Step 4 - Adding HTTPS
The common and convenient way for adding HTTPS is by using a reverse proxy like Nginx or Caddyserver (the latter of which is bundled as part of the docker-compose setup).
2022-03-25 16:45:47 +00:00
Caddyserver and other servers can handle generating and setting up HTTPS certificates automatically, but if you need TLS/SSL certificates for nginx, you can look get some for free with [letsencrypt](https://letsencrypt.org/). The simplest way to obtain and install a certificate is to use [Certbot.](https://certbot.eff.org). Depending on your specific setup, certbot may be able to get a certificate and configure your web server automatically.