about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEmery Hemingway <emery@vfemail.net>2014-03-26 18:12:00 -0400
committerEmery Hemingway <emery@vfemail.net>2014-03-29 15:31:37 -0400
commit6c77690b2898aa8a12184ca8f3c113a11c957e50 (patch)
treecfee74fab8daa89079e3787367ae44dc07da01f7
parent22c04a2fe121edfdc7950fea293c0ed2eea769e7 (diff)
downloadnixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.tar
nixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.tar.gz
nixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.tar.bz2
nixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.tar.lz
nixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.tar.xz
nixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.tar.zst
nixlib-6c77690b2898aa8a12184ca8f3c113a11c957e50.zip
rippled: initial pkg and module expressions
rippled is the Ripple P2P payment network reference server
https://ripple.com
-rw-r--r--lib/maintainers.nix1
-rw-r--r--nixos/modules/misc/ids.nix1
-rw-r--r--nixos/modules/module-list.nix1
-rw-r--r--nixos/modules/services/misc/rippled.nix326
-rw-r--r--pkgs/servers/rippled/default.nix32
-rw-r--r--pkgs/servers/rippled/scons-env.patch46
-rw-r--r--pkgs/top-level/all-packages.nix2
7 files changed, 409 insertions, 0 deletions
diff --git a/lib/maintainers.nix b/lib/maintainers.nix
index 938e1ed54550..1e3b9a32a529 100644
--- a/lib/maintainers.nix
+++ b/lib/maintainers.nix
@@ -28,6 +28,7 @@
   coroa = "Jonas Hörsch <jonas@chaoflow.net>";
   edwtjo = "Edward Tjörnhammar <ed@cflags.cc>";
   eelco = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
+  emery = "Emery Hemingawy <emery@vfemail.net>";
   ertes = "Ertugrul Söylemez <es@ertes.de>";
   falsifian = "James Cook <james.cook@utoronto.ca>";
   garbas = "Rok Garbas <rok@garbas.si>";
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 9c413e36d568..f03aeed7f65d 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -123,6 +123,7 @@
       ngircd = 112;
       btsync = 113;
       minecraft = 114;
+      rippled = 115;
 
       # When adding a uid, make sure it doesn't match an existing gid.
 
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index 652a99e7c5a6..79c071087e42 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -132,6 +132,7 @@
   ./services/misc/nix-gc.nix
   ./services/misc/nix-ssh-serve.nix
   ./services/misc/nixos-manual.nix
+  ./services/misc/rippled.nix
   ./services/misc/rogue.nix
   ./services/misc/svnserve.nix
   ./services/misc/synergy.nix
diff --git a/nixos/modules/services/misc/rippled.nix b/nixos/modules/services/misc/rippled.nix
new file mode 100644
index 000000000000..7d339a48b976
--- /dev/null
+++ b/nixos/modules/services/misc/rippled.nix
@@ -0,0 +1,326 @@
+# configuration building is commented out until better tested.
+
+{ config, pkgs, ... }:
+
+with pkgs.lib;
+
+let
+  cfg = config.services.rippled;
+
+  rippledStateCfgFile = "/var/lib/rippled/rippled.cfg";
+
+  rippledCfg = ''
+    [node_db]
+    type=HyperLevelDB
+    path=/var/lib/rippled/db/hyperldb
+
+    [debug_logfile]
+    /var/log/rippled/debug.log
+
+  ''
+  /*
+  + optionalString (cfg.ips != null) ''
+    [ips]
+    ${concatStringsSep "\n" cfg.ips}
+
+  ''
+  + optionalString (cfg.ipsFixed != null) ''
+    [ips_fixed]
+    ${concatStringsSep "\n" cfg.ipsFixed}
+
+  ''
+  */
+  + optionalString (cfg.peerIp != null) ''
+    [peer_ip]
+    ${cfg.peerIp}
+
+    [peer_port]
+    ${toString cfg.peerPort}
+
+  ''
+  + cfg.extraConfig;
+
+  rippledCfgFile = pkgs.writeText "rippled.cfg" rippledCfg;
+    
+in
+
+{
+
+  ###### interface
+
+  options = {
+
+    services.rippled = {
+
+      enable = mkOption {
+        default = false;
+	description = "Whether to enable rippled";
+      };
+
+      /*
+      ips = mkOption {
+        default = [ "r.ripple.com 51235" ];
+	example = [ "192.168.0.1" "192.168.0.1 3939" "r.ripple.com 51235" ];
+	description = ''
+	  List of hostnames or ips where the Ripple protocol is served.
+	  For a starter list, you can either copy entries from: 
+	  https://ripple.com/ripple.txt or if you prefer you can let it
+	   default to r.ripple.com 51235
+
+	  A port may optionally be specified after adding a space to the 
+	  address. By convention, if known, IPs are listed in from most 
+	  to least trusted.
+	'';
+      };
+
+      ipsFixed = mkOption {
+        default = null;
+	example = [ "192.168.0.1" "192.168.0.1 3939" "r.ripple.com 51235" ];
+	description = ''
+	  List of IP addresses or hostnames to which rippled should always 
+	  attempt to maintain peer connections with. This is useful for 
+	  manually forming private networks, for example to configure a 
+	  validation server that connects to the Ripple network through a 
+	  public-facing server, or for building a set of cluster peers.
+
+	  A port may optionally be specified after adding a space to the address
+	'';
+      };
+      */
+
+      peerIp = mkOption {
+        default = null;
+	example = "0.0.0.0";
+	description = ''
+	  IP address or domain to bind to allow external connections from peers.
+	  Defaults to not binding, which disallows external connections from peers.
+        '';
+      };
+
+      peerPort = mkOption {
+	default = 51235;
+	description = ''
+	  If peerIp is supplied, corresponding port to bind to for peer connections.
+	'';
+      };
+
+      /*
+      peerPortProxy = mkOption {
+        type = types.int;
+	example = 51236;
+	description = ''
+	  An optional, additional listening port number for peers. Incoming
+	  connections on this port will be required to provide a PROXY Protocol
+	  handshake, described in this document (external link):
+
+	    http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
+
+	  The PROXY Protocol is a popular method used by elastic load balancing
+	  service providers such as Amazon, to identify the true IP address and
+	  port number of external incoming connections.
+
+	  In addition to enabling this setting, it will also be required to
+	  use your provider-specific control panel or administrative web page
+	  to configure your server instance to receive PROXY Protocol handshakes,
+	  and also to restrict access to your instance to the Elastic Load Balancer.
+	'';
+      };
+
+      peerPrivate = mkOption {
+        default = null;
+	example = 0;
+	description = ''
+	 0: Request peers to broadcast your address. Normal outbound peer connections [default]
+	 1: Request peers not broadcast your address. Only connect to configured peers.
+       '';
+     };
+
+     peerSslCipherList = mkOption {
+       default = null;
+       example = "ALL:!LOW:!EXP:!MD5:@STRENGTH";
+       description = ''
+         A colon delimited string with the allowed SSL cipher modes for peer. The
+	 choices for for ciphers are defined by the OpenSSL API function
+	 SSL_CTX_set_cipher_list, documented here (external link):
+
+	  http://pic.dhe.ibm.com/infocenter/tpfhelp/current/index.jsp?topic=%2Fcom.ibm.ztpf-ztpfdf.doc_put.cur%2Fgtpc2%2Fcpp_ssl_ctx_set_cipher_list.html
+
+	The default setting of "ALL:!LOW:!EXP:!MD5:@STRENGTH", which allows
+	non-authenticated peer connections (they are, however, secure).
+      '';
+    };
+
+    nodeSeed = mkOption {
+      default = null;
+      example = "RASH BUSH MILK LOOK BAD BRIM AVID GAFF BAIT ROT POD LOVE";
+      description = ''
+        This is used for clustering. To force a particular node seed or key, the
+	key can be set here.  The format is the same as the validation_seed field.
+	To obtain a validation seed, use the rippled validation_create command.
+      '';
+    };
+
+    clusterNodes = mkOption {
+      default = null;
+      example = [ "n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5" ];
+      description = ''
+        To extend full trust to other nodes, place their node public keys here.
+	Generally, you should only do this for nodes under common administration.
+	Node public keys start with an 'n'. To give a node a name for identification
+	place a space after the public key and then the name.
+      '';
+    };
+
+    sntpServers = mkOption {
+      default = null;
+      example = [ "time.nist.gov" "pool.ntp.org" ];
+      description = ''
+        IP address or domain of NTP servers to use for time synchronization.
+      '';
+    };
+
+    # TODO: websocket options
+
+    rpcAllowRemote = mkOption {
+      default = false;
+      description = ''
+        false: Allow RPC connections only from 127.0.0.1. [default]
+	true:  Allow RPC connections from any IP.
+      '';
+    };
+
+    rpcAdminAllow = mkOption {
+      example = [ "10.0.0.4" ];
+      description = ''
+        List of IP addresses allowed to have admin access.
+      '';
+    };
+
+    rpcAdminUser = mkOption {
+      type = types.str;
+      description = ''
+        As a server, require this as the admin user to be specified.  Also, require
+	rpc_admin_user and rpc_admin_password to be checked for RPC admin functions.
+	The request must specify these as the admin_user and admin_password in the
+	request object.
+      '';
+    };
+
+    rpcAdminPassword = mkOption {
+      type = types.str;
+      description = ''
+        As a server, require this as the admin pasword to be specified.  Also,
+	require rpc_admin_user and rpc_admin_password to be checked for RPC admin
+	functions.  The request must specify these as the admin_user and
+	admin_password in the request object.
+      '';
+    };
+
+      rpcIp = mkOption {
+        type = types.str;
+	description = ''
+	  IP address or domain to bind to allow insecure RPC connections.
+	  Defaults to not binding, which disallows RPC connections.
+	'';
+      };
+
+      rpcPort = mkOption {
+        type = types.int;
+        description = ''
+          If rpcIp is supplied, corresponding port to bind to for peer connections.
+        '';
+      };
+
+      rpcUser = mkOption {
+        type = types.str;
+	description = ''
+	  Require a this user to specified and require rpcPassword to
+	  be checked for RPC access via the rpcIp and rpcPort. The user and password
+	  must be specified via HTTP's basic authentication method.
+	  As a client, supply this to the server via HTTP's basic authentication
+	  method.
+	'';
+      };
+
+      rpcPassword = mkOption {
+        type = types.str;
+	description = ''
+	  Require a this password to specified and require rpc_user to
+	  be checked for RPC access via the rpcIp and rpcPort. The user and password
+	  must be specified via HTTP's basic authentication method.
+	  As a client, supply this to the server via HTTP's basic authentication
+	  method.
+	'';
+      };
+
+      rpcStartup = mkOption {
+        example = [ ''"command" : "log_level"'' ''"partition" : "ripplecalc"'' ''"severity" : "trace"'' ];
+	description = "List of RPC commands to run at startup.";
+      };
+
+      rpcSecure = mkOption {
+        default = false;
+	description = ''
+	  false: Server certificates are not provided for RPC clients using SSL [default]
+	  true:  Client RPC connections wil be provided with SSL certificates.
+
+	  Note that if rpc_secure is enabled, it will also be necessasry to configure the
+	  certificate file settings located in rpcSslCert, rpcSslChain, and rpcSslKey
+	'';
+      };
+      */
+
+      extraConfig = mkOption {
+        default = "";
+	description = ''
+	  Extra lines to be added verbatim to the rippled.cfg configuration file.
+	'';
+      };
+
+    };
+
+  };
+
+
+  ###### implementation
+
+  config = mkIf cfg.enable {
+
+    environment = {
+      etc = singleton
+        { source = rippledStateCfgFile;
+	  target = "rippled";
+	};
+	
+	# users can attempt to send RPC commands to the server.
+	systemPackages = [ pkgs.rippled ];
+    };
+
+    users.extraUsers = singleton
+      { name = "rippled";
+        description = "Ripple server user";
+        uid = config.ids.uids.rippled;
+	home = "/var/lib/rippled";
+      };
+
+    systemd.services.rippled = {
+      path = [ pkgs.rippled ];
+
+      after = [ "network.target" ];
+      wantedBy = [ "multi-user.target" ];
+
+      serviceConfig = {
+        ExecStart = "${pkgs.rippled}/bin/rippled --fg -q --conf ${rippledStateCfgFile}";
+	WorkingDirectory = "/var/lib/rippled";
+      };
+    };
+
+    networking.firewall.allowedTCPPorts = mkIf (cfg.peerIp != null) [ cfg.peerPort ];
+
+    system.activationScripts.rippled = ''
+      mkdir -p /var/{lib,log}/rippled
+      chown -R rippled /var/{lib,log}/rippled
+      ln -sf ${rippledCfgFile} ${rippledStateCfgFile}
+    '';
+  };
+}
diff --git a/pkgs/servers/rippled/default.nix b/pkgs/servers/rippled/default.nix
new file mode 100644
index 000000000000..66a0743b367f
--- /dev/null
+++ b/pkgs/servers/rippled/default.nix
@@ -0,0 +1,32 @@
+{ stdenv, fetchurl, scons, pkgconfig, openssl, protobuf, boost155, zlib}:
+
+stdenv.mkDerivation rec {
+  name = "rippled-${version}";
+  version = "0.23.0";
+
+  src = fetchurl {
+    url = "https://github.com/ripple/rippled/archive/${version}.tar.gz";
+    sha256 = "0js734sk11jn19fyp403mk6p62azlc6s9kyhr5jfg466fiak537p";
+  };
+
+  patches = [ ./scons-env.patch ];
+
+  buildInputs = [ scons pkgconfig openssl protobuf boost155 zlib ];
+
+  RIPPLED_BOOST_HOME = boost155.out;
+  RIPPLED_ZLIB_HOME = zlib.out;
+  buildPhase = "scons build/rippled";
+
+  installPhase = ''
+    mkdir -p $out/bin    
+    cp build/rippled $out/bin/
+  '';
+
+  meta = {
+    description = "Ripple P2P payment network reference server";
+    homepage = "https://ripple.com";
+    maintainers = stdenv.lib.maintainers.emery;
+    license = stdenv.lib.licenses.isc;
+    platforms = stdenv.lib.platforms.linux;
+  };
+}
\ No newline at end of file
diff --git a/pkgs/servers/rippled/scons-env.patch b/pkgs/servers/rippled/scons-env.patch
new file mode 100644
index 000000000000..5b80e77bb2e0
--- /dev/null
+++ b/pkgs/servers/rippled/scons-env.patch
@@ -0,0 +1,46 @@
+diff --git a/SConstruct b/SConstruct
+index 8ba8bbd..95eab3b 100644
+--- a/SConstruct
++++ b/SConstruct
+@@ -24,6 +24,8 @@ USING_CLANG = OSX or os.environ.get('CC', None) == 'clang'
+ #
+ BOOST_HOME = os.environ.get("RIPPLED_BOOST_HOME", None)
+ 
++ZLIB_HOME = os.environ.get("RIPPLED_ZLIB_HOME", None)
++
+ 
+ if OSX or Ubuntu or Debian or Archlinux:
+     CTAGS = 'ctags'
+@@ -36,7 +38,7 @@ else:
+ # scons tools
+ #
+ 
+-HONOR_ENVS = ['CC', 'CXX', 'PATH']
++HONOR_ENVS = ['CC', 'CXX', 'PATH', 'PKG_CONFIG_PATH']
+ 
+ env = Environment(
+     tools = ['default', 'protoc'],
+@@ -156,8 +158,8 @@ INCLUDE_PATHS = [
+     'build/proto'
+     ]
+ 
+-# if BOOST_HOME:
+-#     INCLUDE_PATHS.append(BOOST_HOME)
++if BOOST_HOME:
++    INCLUDE_PATHS.append("%s/include" % BOOST_HOME)
+ 
+ #-------------------------------------------------------------------------------
+ #
+@@ -261,7 +263,11 @@ env.Append(
+ # such, as installed into `/usr/lib/`
+ if BOOST_HOME is not None:
+     env.Prepend(
+-        LIBPATH = ["%s/stage/lib" % BOOST_HOME])
++        LIBPATH = ["%s/lib" % BOOST_HOME])
++
++if ZLIB_HOME is not None:
++    env.Prepend(
++        LIBPATH = ["%s/lib" % ZLIB_HOME])
+ 
+ if not OSX:
+     env.Append(LINKFLAGS = [
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index da2edad1e60d..8a9228d15a2b 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -6528,6 +6528,8 @@ let
 
   rethinkdb = callPackage ../servers/nosql/rethinkdb { };
 
+  rippled = callPackage ../servers/rippled { };
+
   spamassassin = callPackage ../servers/mail/spamassassin {
     inherit (perlPackages) HTMLParser NetDNS NetAddrIP DBFile
       HTTPDate MailDKIM LWP IOSocketSSL;