Get loomio server to start

Crashes immediately on hitting any route because vue js stuff is not compiled
yet.
This commit is contained in:
Akshay Mankar 2024-08-24 21:18:34 +02:00
parent b339a30b23
commit 8d707f9a53
Signed by: axeman
GPG key ID: CA08F3AB62369B89
12 changed files with 226 additions and 54 deletions

View file

@ -20,11 +20,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1710889954, "lastModified": 1724334015,
"narHash": "sha256-Pr6F5Pmd7JnNEMHHmspZ0qVqIBVxyZ13ik1pJtm2QXk=", "narHash": "sha256-5sfvc0MswIRNdRWioUhG58rGKGn2o90Ck6l6ClpwQqA=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "7872526e9c5332274ea5932a0c3270d6e4724f3b", "rev": "6d204f819efff3d552a88d0a44b5aaaee172b784",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -19,6 +19,7 @@
system = "x86_64-linux"; system = "x86_64-linux";
modules = [ modules = [
(import ./modules/overlay.nix) (import ./modules/overlay.nix)
./modules/loomio.nix
./hosts/test/configuration.nix ./hosts/test/configuration.nix
]; ];
}; };

View file

@ -19,11 +19,10 @@
users.users.nixosvmtest.group = "nixosvmtest"; users.users.nixosvmtest.group = "nixosvmtest";
users.groups.nixosvmtest = {}; users.groups.nixosvmtest = {};
users.groups.loomio = {}; services.loomio = {
users.users.loomio = { enable = true;
description = "User to run loomio"; encyrptedCredentials = ./loomio-credentials.yml.enc;
group = "loomio"; credentialEncryptionKeyFile = ./loomio-master.key;
isSystemUser = true;
}; };
services.postgresql = { services.postgresql = {
@ -32,23 +31,9 @@
ensureUsers = [{ ensureUsers = [{
name = "loomio"; name = "loomio";
ensureDBOwnership = true; ensureDBOwnership = true;
# ensurePermissions = { "DATABASE loomio" = "ALL PRIVILEGES"; }; ensureClauses.superuser = true;
}]; }];
}; };
systemd.services.loomio = {
enable = true;
after = [ "basic.target" ];
serviceConfig = {
User = "loomio";
Restart = "always";
ExecStart = "${pkgs.loomio}/bin/loomio";
};
environment = {
DATABASE_URL = "postgresql://localhost/loomio";
};
};
system.stateVersion = "23.11"; system.stateVersion = "23.11";
} }

View file

@ -0,0 +1 @@
1LR0cmifVLl04EAAtWPaoBhy85l6u7pGPjiSheUe/vkKbu3S3MK4XV6vBOmGnki4yMrOvdpvpLomnlCxCxEyOYcDRtBh3LkgZ3+9Bx37IcRHfgobzWVG/ik1/ZA4w2zbo8u/oJD6/gtuJNXBTkWNgpo4/WCJddxrzbF1Jo/FawT/ecwPO5898x/VBZn79rMFqcSJ2NKY4noOhOr2+EosFBjEkU7T5QVag64WQDT5/Np2vVhFWPvCgyoXziKTjBpCIUE9dDcA7HFIPgZ5nZXIwdSmVdAN3cA1zDlQMGqA27R4tt9zuRkPCvnfNvfuuVp9FHuok7tUTFPNR6v6NPzvHNceHugUvFF9zu33MAl8tH9j5W3Wd7zPVxuYp9nU8nHPmQF5DlPUoqUERLq/0biF7+F/4KGkNl+DFkZW--EGCnUuZJQoZORDG3--UsPRfjEX4LFxe6ECg8uR9Q==

View file

@ -0,0 +1 @@
dd587169f25e5ed7e391a511da13f491

View file

@ -1,12 +1,116 @@
{lib, ...}: {pkgs, lib, config, ...}:
{ let
cfg = config.services.loomio;
package = pkgs.loomio;
env = {
RAILS_ENV = "production";
BUNDLE_FORCE_RUBY_PLATFORM = "true";
LOOMIO_DATABASE = "loomio";
LOOMIO_ENCRYPTED_CREDENTIALS_PATH = cfg.encyrptedCredentials;
};
cfgService = {
User = "loomio";
Group = "loomio";
WorkingDirectory = package;
StateDirectory = "loomio";
};
in {
imports = []; imports = [];
options = { options = {
enable = lib.mkEnableOption "loomio"; services.loomio = {
enable = lib.mkEnableOption "loomio";
encyrptedCredentials = lib.mkOption {
description = "Credentials required to run loomio";
type = lib.types.path;
};
credentialEncryptionKeyFile = lib.mkOption {
description = "File containing encryption key for the encyptedCredentials";
type = lib.types.path;
};
};
}; };
config = { config = {
users.groups.loomio = {};
users.users.loomio = {
description = "User to run loomio";
group = "loomio";
isSystemUser = true;
};
systemd.services.loomio-init-dirs = {
enable = true;
after = ["network.target" ];
serviceConfig = cfgService // {
Type = "oneshot";
};
script = ''
cat > /var/lib/loomio/.secrets_env <<EOF
RAILS_MASTER_KEY=$(cat ${cfg.credentialEncryptionKeyFile})
EOF
'';
};
systemd.services.loomio-init-db = {
enable = true;
after = ["network.target" "postgresql.service" "loomio-init-dirs.service" ];
requires = [ "postgresql.service" "loomio-init-dirs.service" ];
serviceConfig = cfgService // {
Type = "oneshot";
EnvironmentFile = [ "/var/lib/loomio/.secrets_env" ];
};
environment = env;
path = [package config.services.postgresql.package];
script = ''
#!/usr/bin/env bash
result="$(psql -t --csv -c \
"select count(*) from pg_class c \
join pg_namespace s on s.oid = c.relnamespace \
where s.nspname not in ('pg_catalog', 'pg_toast', 'information_schema') \
and s.nspname not like 'pg_temp%';")" || error_code=$?
if [ "''${error_code:-0}" -ne 0 ]; then
echo "Failure checking if database is seeded. psql gave exit code $error_code"
exit "$error_code"
fi
if [ "$result" -eq 0 ]; then
echo "Seeding database"
SAFETY_ASSURED=1 rails db:schema:load
rails db:seed
else
echo "Migrating database (this might be a noop)"
rails db:migrate
fi
'';
};
systemd.services.loomio = { systemd.services.loomio = {
enable = true; enable = true;
after = [ "network.target" "loomio-init-db.service" ];
requires = [ "loomio.socket" "loomio-init-db.service" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = cfgService // {
Type = "notify";
TimeoutStartSec = 120;
WatchdogSec = 10;
Restart = "always";
ExecStart = "${package}/bin/puma -C config/puma.rb";
EnvironmentFile = [ "/var/lib/loomio/.secrets_env" ];
};
environment = env // {
PORT="3000";
};
};
systemd.sockets.loomio = {
listenStreams = ["0.0.0.0:3000"];
socketConfig = {
NoDelay = true;
ReusePort = true;
Backlog = 1024;
};
}; };
}; };
} }

21
pkg/loomio/creds.patch Normal file
View file

@ -0,0 +1,21 @@
diff --git a/.gitignore b/.gitignore
index 75bb667202..db91658d32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -97,3 +97,5 @@ yarn-error.log*
# Ruby bundle and gems
/vendor
+
+/config/master.key
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 05f46dad87..de8fbf9168 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -95,4 +95,6 @@ Rails.application.configure do
# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false
+
+ config.credentials.content_path = ENV['LOOMIO_ENCRYPTED_CREDENTIALS_PATH']
end

View file

@ -1,8 +1,20 @@
{stdenv, writeText, callPackage, bundlerEnv, ruby_3_2 }: {stdenv,
writeShellScriptBin,
writeText,
symlinkJoin,
callPackage,
bundlerEnv,
ruby_3_2,
postgresql
}:
let let
gemfile-patch = callPackage ./gemfile-patch.nix {}; gemfile-patch = callPackage ./gemfile-patch.nix {};
src = callPackage ./source.nix { patches = [gemfile-patch];}; src = callPackage ./source.nix {
patches = [
gemfile-patch
./creds.patch
];
};
gems = bundlerEnv { gems = bundlerEnv {
name = "loomio-env"; name = "loomio-env";
ruby = ruby_3_2; ruby = ruby_3_2;
@ -12,28 +24,39 @@ let
databaseConfig = writeText "database.yml" '' databaseConfig = writeText "database.yml" ''
production: production:
url: <%= ENV['DATABASE_URL'] %> adapter: postgresql
database: <%= ENV['LOOMIO_DATABASE'] %>
host: /var/run/postgresql
''; '';
in stdenv.mkDerivation { in stdenv.mkDerivation {
name = "loomio"; name = "loomio";
inherit src; inherit src;
nativeBuildInputs = [ gems gems.wrappedRuby ];
buildInputs = [gems ruby_3_2]; buildInputs = [gems ruby_3_2];
buildPhase = ''
runHook preBuild
cp ${databaseConfig} config/database.yml
cp ${./puma.rb} config/puma.rb
export BUNDLE_FORCE_RUBY_PLATFORM=true
${gems}/bin/bundle exec bootsnap precompile --gemfile app/ lib/
patchShebangs bin/
for b in $(ls ${gems}/bin/)
do
if [ ! -f bin/$b ]; then
ln -s ${gems}/bin/$b bin/$b
fi
done
runHook postBuild
'';
installPhase = '' installPhase = ''
mkdir -p $out/{bin,share/loomio} mkdir -p $out
cp -r * $out/share/loomio cp -r * $out
bin=$out/bin/loomio
cp ${databaseConfig} $out/share/loomio/config/database.yml
cat > $bin <<EOF
#!/usr/bin/env bash
set -ex
export BUNDLE_FORCE_RUBY_PLATFORM=true
export RAILS_ENV=production
${gems}/bin/bundle exec rake -f $out/share/loomio/Rakefile db:prepare
${gems}/bin/bundle exec puma -C $out/share/loomio/config/puma.rb
EOF
chmod +x $bin
''; '';
} }

View file

@ -1,6 +1,6 @@
{fetchurl}: {fetchurl}:
fetchurl { fetchurl {
url = "https://github.com/akshaymankar/loomio/commit/528641fd04135a186232568fbf9a4717e2053e86.patch"; url = "https://github.com/akshaymankar/loomio/commit/e8d4c448dd448658aceeaf715b5ea601ee111c03.patch";
hash = "sha256-sg/4U72gZHoTYepZ4dIQlyC4YBjU5+YgIKI/Oj+XlRs="; hash = "sha256-ruONUFWQ/0V+I9x6nV7wNr5xz1QMUPVvLR1xT6gBVRU=";
} }

View file

@ -818,7 +818,7 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["http://rubygems.org"]; remotes = ["http://rubygems.org"];
sha256 = "0szml3n6ql6wzl5fq2rcl1w9iksz4zb68p7cbbwkwc5kkp34ikgx"; sha256 = "07139870npj59jnl8vmk39ja3gdk3fb5z9vc0lf32y2h891hwqsi";
type = "gem"; type = "gem";
}; };
version = "1.17.0"; version = "1.17.0";
@ -991,7 +991,7 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["http://rubygems.org"]; remotes = ["http://rubygems.org"];
sha256 = "00jg44v6az86mmh8gmr5l4lvryjhzla29qs4qi1gcdcqx2b7xlhk"; sha256 = "1mnxzcq8kmyfb9bkzqnp019d1hx1vprip3yzdkkha6b3qz5rgg9r";
type = "gem"; type = "gem";
}; };
version = "3.25.3"; version = "3.25.3";
@ -1045,7 +1045,7 @@
platforms = []; platforms = [];
source = { source = {
remotes = ["http://rubygems.org"]; remotes = ["http://rubygems.org"];
sha256 = "0xkpyc0hmb20xznyh1i1m093r1swni9wfmss0hks67fy6s6kmsr2"; sha256 = "03z8yq0z228g6xxxq6s2mmslpv6psrdmi30dpmhysr4px16d897n";
type = "gem"; type = "gem";
}; };
version = "1.62.0"; version = "1.62.0";
@ -1387,6 +1387,16 @@
}; };
version = "1.1.5"; version = "1.1.5";
}; };
mini_portile2 = {
groups = ["default" "development" "test"];
platforms = [];
source = {
remotes = ["http://rubygems.org"];
sha256 = "1q1f2sdw3y3y9mnym9dhjgsjr72sq975cfg5c4yx7gwv8nmzbvhk";
type = "gem";
};
version = "2.8.7";
};
minitest = { minitest = {
groups = ["default" "development" "test"]; groups = ["default" "development" "test"];
platforms = []; platforms = [];
@ -1503,12 +1513,12 @@
version = "2.7.0"; version = "2.7.0";
}; };
nokogiri = { nokogiri = {
dependencies = ["racc"]; dependencies = ["mini_portile2" "racc"];
groups = ["default" "development" "test"]; groups = ["default" "development" "test"];
platforms = []; platforms = [];
source = { source = {
remotes = ["http://rubygems.org"]; remotes = ["http://rubygems.org"];
sha256 = "1aiz5hg2pfjnk756f2zd0723m3wq30gkmishmc76jwn51yw341v3"; sha256 = "15gysw8rassqgdq3kwgl4mhqmrgh7nk2qvrcqp4ijyqazgywn6gq";
type = "gem"; type = "gem";
}; };
version = "1.16.7"; version = "1.16.7";

26
pkg/loomio/puma.rb Normal file
View file

@ -0,0 +1,26 @@
max_threads_count = ENV['RAILS_MAX_THREADS'] || ENV['MAX_THREADS'] || 5
min_threads_count = ENV['RAILS_MIN_THREADS'] || ENV['MIN_THREADS'] || max_threads_count
threads min_threads_count, max_threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
workers ENV['PUMA_WORKERS'] || ENV['WEB_CONCURRENCY'] || 0
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
preload_app!

View file

@ -99,7 +99,7 @@ in
inherit version; inherit version;
} }
EOF EOF
SOURCE_DIR="$(nix-build --no-out-link -E '(import <nixpkgs> {}).callPackage ./source.nix {}')" SOURCE_DIR="$(nix-build --no-out-link -E 'let pkgs = import <nixpkgs> {}; in pkgs.callPackage ./source.nix { patches = [(pkgs.callPackage ./gemfile-patch.nix {})]; }')"
echo "Creating gemset.nix" echo "Creating gemset.nix"
BUNDLE_FORCE_RUBY_PLATFORM=true bundix --lockfile="$SOURCE_DIR/Gemfile.lock" --gemfile="$SOURCE_DIR/Gemfile" BUNDLE_FORCE_RUBY_PLATFORM=true bundix --lockfile="$SOURCE_DIR/Gemfile.lock" --gemfile="$SOURCE_DIR/Gemfile"