forked from axeman/erpnext-nix
wip: backend works. frontend still has some issues
This commit is contained in:
parent
e39cb5308f
commit
f8346df08f
35
flake.nix
35
flake.nix
|
@ -26,17 +26,26 @@
|
||||||
# propagatedBuildInputs = old.propagatedBuildInputs ++ [python3.pkgs.setuptools];
|
# propagatedBuildInputs = old.propagatedBuildInputs ++ [python3.pkgs.setuptools];
|
||||||
#});
|
#});
|
||||||
assets = pkgs.callPackage ./node/frappe-assets.nix {};
|
assets = pkgs.callPackage ./node/frappe-assets.nix {};
|
||||||
|
# Source: https://github.com/frappe/frappe_docker/blob/main/resources/nginx-template.conf
|
||||||
|
nginx-conf = pkgs.callPackage ./nginx-erpnext-conf.nix {inherit pkgs;};
|
||||||
penv = py.buildEnv.override {
|
penv = py.buildEnv.override {
|
||||||
extraLibs = [ py.pkgs.frappe py.pkgs.erpnext ];
|
extraLibs = [ py.pkgs.frappe py.pkgs.erpnext ];
|
||||||
};
|
};
|
||||||
runErpNext = pkgs.writeShellScriptBin "runErpNext" ''
|
runErpNext = pkgs.writeShellScriptBin "runErpNext" ''
|
||||||
export PYTHON_PATH=${penv}/${py.sitePackages}
|
export PYTHON_PATH=${penv}/${py.sitePackages}
|
||||||
|
# The upstream installer bench CLI wants mysql in its PATH
|
||||||
|
export PATH=${pkgs.mariadb-client}/bin:''$PATH
|
||||||
|
|
||||||
hostname=localhost
|
hostname=localhost
|
||||||
sites=$(mktemp -d)
|
tmp=/tmp/erpnext
|
||||||
|
|
||||||
|
mkdir -p $tmp/apps $tmp/sites $tmp/config/pids $tmp/logs $tmp/env/bin
|
||||||
|
|
||||||
for f in ${assets}/share/sites/*; do
|
for f in ${assets}/share/sites/*; do
|
||||||
ln -s "$f" "$sites/$(basename $f)"
|
ln -s "$f" "$tmp/sites/$(basename $f)"
|
||||||
done
|
done
|
||||||
cat >$sites/common_site_config.json <<EOF
|
|
||||||
|
cat >$tmp/sites/common_site_config.json <<EOF
|
||||||
{
|
{
|
||||||
"db_host": "localhost",
|
"db_host": "localhost",
|
||||||
"db_port": 3306,
|
"db_port": 3306,
|
||||||
|
@ -48,10 +57,21 @@
|
||||||
"socketio_port": 6379
|
"socketio_port": 6379
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
mkdir -p $sites/$hostname/logs
|
|
||||||
ln -s $sites/common_site_config.json $sites/$hostname/site_config.json
|
# The upstream bench CLI installer expects this file
|
||||||
echo "Sites dir: $sites"
|
echo -e "erpnext\nfrappe\n" > $tmp/sites/apps.txt
|
||||||
${penv}/bin/gunicorn --chdir="$sites" --bind=0.0.0.0:9090 --threads=4 --workers=2 --worker-class=gthread --worker-tmp-dir=/dev/shm --timeout=120 --preload frappe.app:application
|
|
||||||
|
cd $tmp
|
||||||
|
ln -s ${py.pkgs.erpnext}/lib/python3.10/site-packages apps/erpnext
|
||||||
|
ln -s ${py.pkgs.frappe}/lib/python3.10/site-packages apps/frappe
|
||||||
|
ln -s ${penv} $tmp/env
|
||||||
|
ln -sf ${nginx-conf} $tmp/nginx-erpnext.conf
|
||||||
|
|
||||||
|
# Upstream initializes the DB with this command
|
||||||
|
${py.pkgs.bench}/bin/bench new-site localhost --mariadb-root-password password --admin-password admin
|
||||||
|
|
||||||
|
echo "Workdir: $tmp"
|
||||||
|
${penv}/bin/gunicorn --chdir="$tmp/sites" --bind=0.0.0.0:9090 --threads=4 --workers=2 --worker-class=gthread --worker-tmp-dir=/dev/shm --timeout=120 --preload frappe.app:application
|
||||||
'';
|
'';
|
||||||
in rec {
|
in rec {
|
||||||
packages = {
|
packages = {
|
||||||
|
@ -64,6 +84,7 @@
|
||||||
inherit pkgs runErpNext assets;
|
inherit pkgs runErpNext assets;
|
||||||
pip2nix = import "${pip2nix}/default.nix" { inherit pkgs; pythonPackages = "python310Packages"; };
|
pip2nix = import "${pip2nix}/default.nix" { inherit pkgs; pythonPackages = "python310Packages"; };
|
||||||
erpnext = py.pkgs.erpnext;
|
erpnext = py.pkgs.erpnext;
|
||||||
|
bench = py.pkgs.bench;
|
||||||
pythonPkgs = py.pkgs;
|
pythonPkgs = py.pkgs;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
157
nginx-erpnext-conf.nix
Normal file
157
nginx-erpnext-conf.nix
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
{ pkgs }:
|
||||||
|
let
|
||||||
|
backend = "localhost:9090";
|
||||||
|
socketio = "0.0.0.0:9000";
|
||||||
|
frappe_site_name_header = "localhost";
|
||||||
|
upstream_real_ip_address = "127.0.0.1";
|
||||||
|
upstream_real_ip_header = "X-Forwarded-For";
|
||||||
|
upstream_real_ip_recursive = "off";
|
||||||
|
client_max_body_size = "50m";
|
||||||
|
proxy_read_timeout = "120";
|
||||||
|
in
|
||||||
|
pkgs.writeText "erpnext.conf" ''
|
||||||
|
user nginx;
|
||||||
|
worker_processes auto;
|
||||||
|
|
||||||
|
error_log /tmp/erpnext/logs/nginx/error.log notice;
|
||||||
|
pid /tmp/erpnext/nginx.pid;
|
||||||
|
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
http {
|
||||||
|
include ${pkgs.nginx}/conf/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||||
|
'$status $body_bytes_sent "$http_referer" '
|
||||||
|
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||||
|
|
||||||
|
access_log /tmp/erpnext/logs/nginx/access.log main;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
#tcp_nopush on;
|
||||||
|
|
||||||
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
#gzip on;
|
||||||
|
|
||||||
|
upstream backend-server {
|
||||||
|
server ${backend} fail_timeout=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
upstream socketio-server {
|
||||||
|
server ${socketio} fail_timeout=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse the X-Forwarded-Proto header - if set - defaulting to $scheme.
|
||||||
|
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
|
||||||
|
default $scheme;
|
||||||
|
https https;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name ${frappe_site_name_header};
|
||||||
|
root /tmp/erpnext/sites;
|
||||||
|
|
||||||
|
proxy_buffer_size 128k;
|
||||||
|
proxy_buffers 4 256k;
|
||||||
|
proxy_busy_buffers_size 256k;
|
||||||
|
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
|
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header Referrer-Policy "same-origin, strict-origin-when-cross-origin";
|
||||||
|
|
||||||
|
set_real_ip_from ${upstream_real_ip_address};
|
||||||
|
real_ip_header ${upstream_real_ip_header};
|
||||||
|
real_ip_recursive ${upstream_real_ip_recursive};
|
||||||
|
|
||||||
|
location /assets {
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ ^/protected/(.*) {
|
||||||
|
internal;
|
||||||
|
try_files /${frappe_site_name_header}/$1 =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /socket.io {
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "upgrade";
|
||||||
|
proxy_set_header X-Frappe-Site-Name ${frappe_site_name_header};
|
||||||
|
proxy_set_header Origin $scheme://${frappe_site_name_header};
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
|
||||||
|
proxy_pass http://socketio-server;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
rewrite ^(.+)/$ $proxy_x_forwarded_proto://${frappe_site_name_header}$1 permanent;
|
||||||
|
rewrite ^(.+)/index\.html$ $proxy_x_forwarded_proto://${frappe_site_name_header}$1 permanent;
|
||||||
|
rewrite ^(.+)\.html$ $proxy_x_forwarded_proto://${frappe_site_name_header}$1 permanent;
|
||||||
|
|
||||||
|
location ~ ^/files/.*.(htm|html|svg|xml) {
|
||||||
|
add_header Content-disposition "attachment";
|
||||||
|
try_files /${frappe_site_name_header}/public/$uri @webserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
try_files /${frappe_site_name_header}/public/$uri @webserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
location @webserver {
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
|
||||||
|
proxy_set_header X-Frappe-Site-Name ${frappe_site_name_header};
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Use-X-Accel-Redirect True;
|
||||||
|
proxy_read_timeout ${proxy_read_timeout};
|
||||||
|
proxy_redirect off;
|
||||||
|
|
||||||
|
proxy_pass http://backend-server;
|
||||||
|
}
|
||||||
|
|
||||||
|
# optimizations
|
||||||
|
sendfile on;
|
||||||
|
keepalive_timeout 15;
|
||||||
|
client_max_body_size ${client_max_body_size};
|
||||||
|
client_body_buffer_size 16K;
|
||||||
|
client_header_buffer_size 1k;
|
||||||
|
|
||||||
|
# enable gzip compression
|
||||||
|
# based on https://mattstauffer.co/blog/enabling-gzip-on-nginx-servers-including-laravel-forge
|
||||||
|
gzip on;
|
||||||
|
gzip_http_version 1.1;
|
||||||
|
gzip_comp_level 5;
|
||||||
|
gzip_min_length 256;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_types
|
||||||
|
application/atom+xml
|
||||||
|
application/javascript
|
||||||
|
application/json
|
||||||
|
application/rss+xml
|
||||||
|
application/vnd.ms-fontobject
|
||||||
|
application/x-font-ttf
|
||||||
|
application/font-woff
|
||||||
|
application/x-web-app-manifest+json
|
||||||
|
application/xhtml+xml
|
||||||
|
application/xml
|
||||||
|
font/opentype
|
||||||
|
image/svg+xml
|
||||||
|
image/x-icon
|
||||||
|
text/css
|
||||||
|
text/plain
|
||||||
|
text/x-component;
|
||||||
|
# text/html is always compressed by HttpGzipModule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
''
|
|
@ -64,6 +64,8 @@ let
|
||||||
cp -r "${erpnextSrc}/erpnext/public" "sites/assets/erpnext"
|
cp -r "${erpnextSrc}/erpnext/public" "sites/assets/erpnext"
|
||||||
cp -r "$src/frappe/public" "sites/assets/frappe"
|
cp -r "$src/frappe/public" "sites/assets/frappe"
|
||||||
|
|
||||||
|
# The upstream esbuild script expects this file and will build assets
|
||||||
|
# for all listed apps
|
||||||
echo -e "erpnext\nfrappe\n" > sites/apps.txt
|
echo -e "erpnext\nfrappe\n" > sites/apps.txt
|
||||||
|
|
||||||
cp -r ${erpnextSrc} apps/erpnext
|
cp -r ${erpnextSrc} apps/erpnext
|
||||||
|
@ -78,6 +80,10 @@ let
|
||||||
cp -r $node_modules apps/frappe/node_modules
|
cp -r $node_modules apps/frappe/node_modules
|
||||||
|
|
||||||
yarn --offline production
|
yarn --offline production
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm sites/apps.txt
|
||||||
|
|
||||||
mv sites deps/
|
mv sites deps/
|
||||||
|
|
||||||
runHook postBuild
|
runHook postBuild
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
pkgs.python3.override {
|
pkgs.python3.override {
|
||||||
packageOverrides = self: super: {
|
packageOverrides = self: super: {
|
||||||
|
bench = self.callPackage ./python/bench.nix {};
|
||||||
erpnext = self.callPackage ./python/erpnext.nix {};
|
erpnext = self.callPackage ./python/erpnext.nix {};
|
||||||
frappe = self.callPackage ./python/frappe.nix {};
|
frappe = self.callPackage ./python/frappe.nix {};
|
||||||
|
|
||||||
email-reply-parser = self.callPackage ./python/email-reply-parser.nix {};
|
email-reply-parser = self.callPackage ./python/email-reply-parser.nix {};
|
||||||
git-url-parse = self.callPackage ./python/git-url-parse.nix {};
|
git-url-parse = self.callPackage ./python/git-url-parse.nix {};
|
||||||
gocardless-pro = self.callPackage ./python/gocardless-pro.nix {};
|
gocardless-pro = self.callPackage ./python/gocardless-pro.nix {};
|
||||||
|
honcho = self.callPackage ./python/honcho.nix {};
|
||||||
jsonobject = self.callPackage ./python/jsonobject.nix {};
|
jsonobject = self.callPackage ./python/jsonobject.nix {};
|
||||||
maxminddb-geolite2 = self.callPackage ./python/maxminddb-geolite2.nix {};
|
maxminddb-geolite2 = self.callPackage ./python/maxminddb-geolite2.nix {};
|
||||||
posthog = self.callPackage ./python/posthog.nix {};
|
posthog = self.callPackage ./python/posthog.nix {};
|
||||||
|
|
39
python/bench.nix
Normal file
39
python/bench.nix
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{ lib
|
||||||
|
, buildPythonPackage
|
||||||
|
, fetchFromGitHub
|
||||||
|
, pythonRelaxDepsHook
|
||||||
|
|
||||||
|
, hatchling
|
||||||
|
|
||||||
|
, click
|
||||||
|
, gitpython
|
||||||
|
, honcho
|
||||||
|
, jinja2
|
||||||
|
, python-crontab
|
||||||
|
, requests
|
||||||
|
, semantic-version
|
||||||
|
, setuptools
|
||||||
|
, tomli
|
||||||
|
}:
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "frappe-bench";
|
||||||
|
version = "5.16.2";
|
||||||
|
format = "pyproject";
|
||||||
|
src = import ../srcs/bench.nix {inherit fetchFromGitHub; };
|
||||||
|
nativeBuildInputs = [ pythonRelaxDepsHook ];
|
||||||
|
pythonRelaxDeps = [ "jinja2" "python-crontab" "semantic-version" ];
|
||||||
|
buildInputs = [
|
||||||
|
hatchling
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
click
|
||||||
|
gitpython
|
||||||
|
honcho
|
||||||
|
jinja2
|
||||||
|
python-crontab
|
||||||
|
requests
|
||||||
|
semantic-version
|
||||||
|
setuptools
|
||||||
|
tomli
|
||||||
|
];
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
{ lib
|
{ lib
|
||||||
, buildPythonPackage
|
, buildPythonPackage
|
||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
, fetchYarnDeps
|
|
||||||
, mkYarnPackage
|
|
||||||
|
|
||||||
, taxjar
|
, taxjar
|
||||||
, gocardless-pro
|
, gocardless-pro
|
||||||
|
@ -34,10 +32,4 @@ buildPythonPackage rec {
|
||||||
python-stdnum
|
python-stdnum
|
||||||
frappe
|
frappe
|
||||||
];
|
];
|
||||||
|
|
||||||
# postInstall = ''
|
|
||||||
# mkdir -p $out/test/frappe $out/test/erpnext
|
|
||||||
# ln -s ${frappe-assets} $out/test/frappe
|
|
||||||
# ln -s ${erpnext-modules} $out/test/erpnext
|
|
||||||
# '';
|
|
||||||
}
|
}
|
||||||
|
|
17
python/honcho.nix
Normal file
17
python/honcho.nix
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
buildPythonPackage,
|
||||||
|
fetchPypi,
|
||||||
|
jinja2,
|
||||||
|
}:
|
||||||
|
buildPythonPackage rec {
|
||||||
|
pname = "honcho";
|
||||||
|
version = "1.1.0";
|
||||||
|
src = fetchPypi {
|
||||||
|
pname = "honcho";
|
||||||
|
inherit version;
|
||||||
|
sha256 = "sha256-xeygve1L72aXojrsBCL9T2UI6jWBl5o0hfxLiTV+sqk=";
|
||||||
|
};
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
jinja2
|
||||||
|
];
|
||||||
|
}
|
7
srcs/bench.nix
Normal file
7
srcs/bench.nix
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{fetchFromGitHub}:
|
||||||
|
fetchFromGitHub {
|
||||||
|
owner = "frappe";
|
||||||
|
repo = "bench";
|
||||||
|
rev = "v5.16.2";
|
||||||
|
sha256 = "sha256-SF/RwY54OKXTDIYz4LsQIR03QoCKPIGey60DO8TdonY=";
|
||||||
|
}
|
Loading…
Reference in a new issue