mirror of
https://github.com/bonfire-networks/bonfire-app.git
synced 2024-05-05 10:48:43 +00:00
nix: add initial flake
This commit is contained in:
parent
9ea952d101
commit
b8859a7147
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -55,3 +55,8 @@ deps.path*
|
|||
|
||||
# Dev artifacts
|
||||
.elixir_ls
|
||||
db/
|
||||
.nix-hex/
|
||||
.nix-mix/
|
||||
.direnv/
|
||||
/result
|
||||
|
|
|
@ -5,17 +5,17 @@
|
|||
import Config
|
||||
|
||||
if config_env() == :prod do
|
||||
|
||||
host = System.get_env("HOSTNAME", "localhost")
|
||||
port = String.to_integer(System.get_env("PORT", "4000"))
|
||||
|
||||
System.get_env("RELEASING") || System.get_env("DATABASE_URL") || (System.get_env("POSTGRES_DB") && System.get_env("POSTGRES_PASSWORD")) ||
|
||||
raise """
|
||||
Environment variables for database are missing.
|
||||
For example: DATABASE_URL=ecto://USER:PASS@HOST/DATABASE
|
||||
You can also set POSTGRES_DB and POSTGRES_PASSWORD (required),
|
||||
and POSTGRES_USER (default: postgres) and POSTGRES_HOST (default: localhost)
|
||||
"""
|
||||
System.get_env("RELEASING") || System.get_env("DATABASE_URL") ||
|
||||
(System.get_env("POSTGRES_DB") && System.get_env("POSTGRES_PASSWORD")) ||
|
||||
raise """
|
||||
Environment variables for database are missing.
|
||||
For example: DATABASE_URL=ecto://USER:PASS@HOST/DATABASE
|
||||
You can also set POSTGRES_DB and POSTGRES_PASSWORD (required),
|
||||
and POSTGRES_USER (default: postgres) and POSTGRES_HOST (default: localhost)
|
||||
"""
|
||||
|
||||
if System.get_env("DATABASE_URL") do
|
||||
config :bonfire, Bonfire.Repo,
|
||||
|
@ -28,6 +28,7 @@ if config_env() == :prod do
|
|||
password: System.get_env("POSTGRES_PASSWORD", "postgres"),
|
||||
database: System.get_env("POSTGRES_DB", "bonfire"),
|
||||
hostname: System.get_env("POSTGRES_HOST", "localhost"),
|
||||
socket_dir: System.get_env("POSTGRES_SOCKET_DIR"),
|
||||
pool_size: String.to_integer(System.get_env("POOL_SIZE", "10"))
|
||||
end
|
||||
|
||||
|
@ -38,12 +39,14 @@ if config_env() == :prod do
|
|||
You can generate one by calling: mix phx.gen.secret
|
||||
"""
|
||||
|
||||
signing_salt = System.get_env("RELEASING") || System.get_env("SIGNING_SALT") ||
|
||||
signing_salt =
|
||||
System.get_env("RELEASING") || System.get_env("SIGNING_SALT") ||
|
||||
raise """
|
||||
environment variable SIGNING_SALT is missing.
|
||||
"""
|
||||
|
||||
encryption_salt = System.get_env("RELEASING") || System.get_env("ENCRYPTION_SALT") ||
|
||||
encryption_salt =
|
||||
System.get_env("RELEASING") || System.get_env("ENCRYPTION_SALT") ||
|
||||
raise """
|
||||
environment variable ENCRYPTION_SALT is missing.
|
||||
"""
|
||||
|
@ -73,5 +76,6 @@ if config_env() == :prod do
|
|||
#
|
||||
# Then you can assemble a release by calling `mix release`.
|
||||
# See `mix help release` for more information.
|
||||
end
|
||||
|
||||
end # end prod-only config
|
||||
# end prod-only config
|
||||
|
|
25
flake.lock
Normal file
25
flake.lock
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1622253036,
|
||||
"narHash": "sha256-HSVusps0KHjVayUkWvFPiIZe1JKxT+GeDQBzcpw+MFE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "25bca77c48ddb0bacdb46e7398d948a348d06119",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"id": "nixpkgs",
|
||||
"type": "indirect"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
33
flake.nix
Normal file
33
flake.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
description = "Bonfire!";
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
# taken from https://github.com/ngi-nix/project-template/blob/master/flake.nix
|
||||
# System types to support.
|
||||
supportedSystems = [ "x86_64-linux" "x86_64-darwin" ];
|
||||
|
||||
# Helper function to generate an attrset '{ x86_64-linux = f "x86_64-linux"; ... }'.
|
||||
forAllSystems = f: nixpkgs.lib.genAttrs supportedSystems (system: f system);
|
||||
|
||||
# Nixpkgs instantiated for supported system types.
|
||||
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; overlays = [ self.overlay ]; });
|
||||
in
|
||||
{
|
||||
overlay = final: prev: {
|
||||
bonfire = import ./nix/package.nix { pkgs = final; inherit self; };
|
||||
};
|
||||
packages = forAllSystems (system:
|
||||
{
|
||||
inherit (nixpkgsFor.${system}) bonfire;
|
||||
});
|
||||
defaultPackage = forAllSystems (system: self.packages.${system}.bonfire);
|
||||
nixosModules.bonfire = import ./nix/module.nix;
|
||||
devShell = forAllSystems
|
||||
(system:
|
||||
import ./nix/shell.nix {
|
||||
pkgs = nixpkgsFor.${system};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
102
nix/module.nix
Normal file
102
nix/module.nix
Normal file
|
@ -0,0 +1,102 @@
|
|||
{ pkgs, config, lib, ... }:
|
||||
with lib;
|
||||
let
|
||||
bonfireConfig = config.services.bonfire;
|
||||
in
|
||||
{
|
||||
options.services.bonfire = {
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 4000;
|
||||
description = "port to run the instance on";
|
||||
};
|
||||
package = mkOption {
|
||||
type = types.package;
|
||||
description = "package to run the instance with";
|
||||
};
|
||||
hostname = mkOption {
|
||||
type = types.str;
|
||||
default = "bonfire.cafe";
|
||||
example = "bonfire.cafe";
|
||||
description = ''
|
||||
hostname for which the service will be run
|
||||
'';
|
||||
};
|
||||
dbName = mkOption {
|
||||
type = types.str;
|
||||
default = "bonfire";
|
||||
description = ''
|
||||
name of the database you want to connect to
|
||||
'';
|
||||
};
|
||||
dbSocketDir = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = ''
|
||||
If this is defined, bonfire will connect to postgres
|
||||
with a unix socket and not TCP/IP
|
||||
'';
|
||||
};
|
||||
environmentFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
environment file for secret environment variables
|
||||
should contain
|
||||
SECRET_KEY_BASE
|
||||
SIGNING_SALT
|
||||
ENCRYPTION_SALT
|
||||
RELEASE_COOKIE
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = with bonfireConfig; {
|
||||
services.postgresql = {
|
||||
extraPlugins = with pkgs.postgresql_13.pkgs; [ postgis ];
|
||||
ensureDatabases = [ "bonfire" ];
|
||||
ensureUsers = [{
|
||||
# Same name as the unix user is needed
|
||||
name = "bonfire";
|
||||
ensurePermissions = { "DATABASE bonfire" = "ALL PRIVILEGES"; };
|
||||
}];
|
||||
};
|
||||
|
||||
systemd.services.bonfire = {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "postgresql.service" ];
|
||||
requires = [ "postgresql.service" ];
|
||||
description = "Bonfire!";
|
||||
serviceConfig = {
|
||||
Type = "exec";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
ExecStartPre = "${package}/bin/bonfire eval Bonfire.Repo.ReleaseTasks.migrate";
|
||||
ExecStart = "${package}/bin/bonfire start";
|
||||
ExecStop = "${package}/bin/bonfire stop";
|
||||
|
||||
DynamicUser = true;
|
||||
StateDirectory = "bonfire";
|
||||
|
||||
EnvironmentFile = environmentFile;
|
||||
|
||||
PrivateTmp = true;
|
||||
ProtectSystem = "full";
|
||||
NoNewPrivileges = true;
|
||||
|
||||
ReadWritePaths = "${if dbSocketDir == null then "" else dbSocketDir} /var/lib/bonfire";
|
||||
};
|
||||
environment = {
|
||||
RELEASE_TMP = "/tmp";
|
||||
TZDATA_DIR = "/var/lib/bonfire";
|
||||
LANG = "en_US.UTF-8";
|
||||
PORT = toString port;
|
||||
POSTGRES_USER = "bonfire";
|
||||
POSTGRES_PASSWORD = "unused";
|
||||
POSTGRES_DB = dbName;
|
||||
POSTGRES_SOCKET_DIR = lib.mkIf (dbSocketDir != null) dbSocketDir;
|
||||
HOSTNAME = hostname;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
71
nix/package.nix
Normal file
71
nix/package.nix
Normal file
|
@ -0,0 +1,71 @@
|
|||
{ pkgs, self }:
|
||||
let
|
||||
beamPackages = with pkgs; beam.packagesWith beam.interpreters.erlang;
|
||||
in
|
||||
beamPackages.mixRelease rec {
|
||||
pname = "bonfire";
|
||||
version = "1.0.0";
|
||||
mixEnv = "prod";
|
||||
|
||||
src = self;
|
||||
|
||||
mixFodDeps = beamPackages.fetchMixDeps {
|
||||
pname = "mix-deps-${pname}";
|
||||
inherit src mixEnv version;
|
||||
LANG = "en_US.UTF-8";
|
||||
# override needed here since bonfire dependencies rely on git
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mix deps.get --only ${mixEnv}
|
||||
cp -r --no-preserve=mode,ownership,timestamps $TEMPDIR/deps $out
|
||||
runHook postInstall
|
||||
'';
|
||||
# TODO add sha256
|
||||
# since I didn't know exactly what dependencies where being pulled
|
||||
# I went for the quick hack of not checking for dependency integrity
|
||||
# This has the downside of triggering a rebuild on every deployment
|
||||
sha256 = null;
|
||||
};
|
||||
|
||||
frontendAssets = with pkgs; stdenvNoCC.mkDerivation {
|
||||
pname = "frontend-assets-${pname}";
|
||||
nativeBuildInputs = [ nodejs cacert git ];
|
||||
|
||||
inherit version src;
|
||||
|
||||
configurePhase = ''
|
||||
export HOME=$(mktemp -d)
|
||||
cp -r ${mixFodDeps} ./deps
|
||||
cd assets
|
||||
npm install --quiet
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
npm run deploy
|
||||
cd ..
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
cp -r priv/static $out
|
||||
'';
|
||||
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
# TODO add sha256
|
||||
# since I didn't know exactly what dependencies where being pulled
|
||||
# I went for the quick hack of not checking for dependency integrity
|
||||
# This has the downside of triggering a rebuild on every deployment
|
||||
outputHash = null;
|
||||
|
||||
impureEnvVars = lib.fetchers.proxyImpureEnvVars;
|
||||
};
|
||||
|
||||
nativeBuildInputs = with pkgs; [ rustc cargo gcc ]; # for NIFs
|
||||
|
||||
postBuild = ''
|
||||
cp -r ${frontendAssets} priv/static
|
||||
# digest needs to write files
|
||||
chmod -R u+w priv/static
|
||||
mix phx.digest
|
||||
'';
|
||||
}
|
65
nix/shell.nix
Normal file
65
nix/shell.nix
Normal file
|
@ -0,0 +1,65 @@
|
|||
{ pkgs ? import <nixpkgs> { } }:
|
||||
|
||||
with pkgs;
|
||||
|
||||
let
|
||||
messctl = rustPlatform.buildRustPackage rec {
|
||||
pname = "messctl";
|
||||
version = "0.0.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "bonfire-networks";
|
||||
repo = pname;
|
||||
rev = "8421d5ee91b120f1fe78fe8b123fc0fdf59609ff";
|
||||
sha256 = "sha256-MniXkng8v30xzSC+cIZ+K6DWeJLCFDieXZioAQFU4/s=";
|
||||
};
|
||||
cargoSha256 = "sha256-K4Wq949DK3STwKo0MgaGNsu3r+qg8OqqXK3O4g4FpR0=";
|
||||
};
|
||||
|
||||
# define packages to install with special handling for OSX
|
||||
shellBasePackages = [
|
||||
git
|
||||
beam.packages.erlang.elixir_1_12
|
||||
nodejs-16_x
|
||||
postgresql_13
|
||||
messctl
|
||||
# for NIFs
|
||||
rustfmt
|
||||
clippy
|
||||
];
|
||||
|
||||
shellBuildInputs = shellBasePackages ++ lib.optional stdenv.isLinux inotify-tools
|
||||
++ lib.optionals stdenv.isDarwin
|
||||
(with darwin.apple_sdk.frameworks; [ CoreFoundation CoreServices ]);
|
||||
|
||||
# define shell startup command
|
||||
shellHooks = ''
|
||||
# this allows mix to work on the local directory
|
||||
mkdir -p $PWD/.nix-mix
|
||||
mkdir -p $PWD/.nix-hex
|
||||
export MIX_HOME=$PWD/.nix-mix
|
||||
export HEX_HOME=$PWD/.nix-mix
|
||||
export PATH=$MIX_HOME/bin:$PATH
|
||||
export PATH=$HEX_HOME/bin:$PATH
|
||||
mix local.hex --force
|
||||
export LANG=en_US.UTF-8
|
||||
export ERL_AFLAGS="-kernel shell_history enabled"
|
||||
|
||||
# postges related
|
||||
export PGDATA="$PWD/db"
|
||||
|
||||
# elixir
|
||||
export MIX_ENV=dev
|
||||
export FORK=./forks
|
||||
'';
|
||||
|
||||
in
|
||||
|
||||
mkShell
|
||||
{
|
||||
nativeBuildInputs = [ rustc cargo gcc ]; # for NIFs
|
||||
buildInputs = shellBuildInputs;
|
||||
shellHook = shellHooks;
|
||||
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
|
||||
}
|
||||
|
Loading…
Reference in a new issue