summary refs log blame commit diff
path: root/modules/services/databases/postgresql.nix
blob: 6d58b757421c65ab404de87c01b784424e620c4b (plain) (tree)
1
2
3
4
5
6
7
8


                      
 

   

                                   




















                                                                          
 
                                                             
 
                                        
 







                                                                     
  
 



































                                        


                                        
                                                          




                                                   
                                                                  


           

                           
                        
                                                                  
















                                                                              




                                                                      

                                                                           
                                                                 
                                                                                





                                                                              



      
 
 




                                                   

                                               
        
 

                                 
 
                                              
 






                                                               
                     
                                          
 
                                                              
 



                                      
 

                  
                                      


                                                
                                                            
                                           
              

                                                                




                                                                   
                                                                             
 



                                                                      

                       
                  
 



                                                             
        
 
    
  
 
{ config, pkgs, ... }:

with pkgs.lib;

let

  cfg = config.services.postgresql;

  # see description of extraPlugins
  postgresqlAndPlugins = pg:
    if cfg.extraPlugins == [] then pg
    else pkgs.runCommand "postgresql-and-plugins" {
      inherit (pkgs) perl;
      inherit pg;
      # used by env builder:
      paths = [ pg ] ++ cfg.extraPlugins;
      pathsToLink = "/";
      ignoreCollisions = 0;
      manifest = null;
    }
      ''
        perlScript=${pkgs.buildEnvScript}
        mkdir -p $out/bin
        $perl/bin/perl $perlScript
        rm $out/bin/{pg_config,postgres,pg_ctl}
        cp --target-directory=$out/bin $pg/bin/{postgres,pg_config,pg_ctl}
      '';

  postgresql = postgresqlAndPlugins pkgs.postgresql;

  run = "${pkgs.su}/bin/su -s ${pkgs.stdenv.shell} postgres";

  flags = optional cfg.enableTCPIP "-i";

  # The main PostgreSQL configuration file.
  configFile = pkgs.writeText "postgresql.conf"
    ''
      hba_file = '${pkgs.writeText "pg_hba.conf" cfg.authentication}'
      ident_file = '${pkgs.writeText "pg_ident.conf" cfg.identMap}'
      log_destination = 'syslog'
    '';  

in

{

  ###### interface
  
  options = {
  
    services.postgresql = {
    
      enable = mkOption {
        default = false;
        description = ''
          Whether to run PostgreSQL.
        '';
      };
      
      port = mkOption {
        default = "5432";
        description = ''
          Port for PostgreSQL.
        '';
      };
      
      logDir = mkOption {
        default = "/var/log/postgresql";
        description = ''
          Log directory for PostgreSQL.
        '';
      };
      
      dataDir = mkOption {
        default = "/var/db/postgresql";
        description = ''
          Data directory for PostgreSQL.
        '';
      };
      
      authentication = mkOption {
        default = ''
          # Generated file; do not edit!
          local all mediawiki        ident mediawiki-users
          local all all              ident sameuser
          host  all all 127.0.0.1/32 md5
          host  all all ::1/128      md5
        '';
        description = ''
          Defines how users authenticate themselves to the server.
        '';
      };
      
      identMap = mkOption {
        default = "";
        description = ''
          Defines the mapping from system users to database users.
        '';
      };
      
      authMethod = mkOption {
        default = " ident sameuser ";
        description = ''
          How to authorize users. 
          Note: ident needs absolute trust to all allowed client hosts.
        '';
      };
      
      enableTCPIP = mkOption {
        default = false;
        description = ''
          Whether to run PostgreSQL with -i flag to enable TCP/IP connections.
        '';
      };

      extraPlugins = mkOption {
        default = [];
        example = "pkgs.postgis"; # of course don't use a string here!
        description = ''
          When this list contains elements a new store path is created.
          PostgreSQL and the elments are symlinked into it. Then pg_config,
          postgres and pc_ctl are copied to make them use the new
          $out/lib directory as pkglibdir. This makes it possible to use postgis
          without patching the .sql files which reference $libdir/postgis-1.5.
        '';
        # Note: the duplication of executables is about 4MB size.
        # So a nicer solution was patching postgresql to allow setting the
        # libdir explicitely.
      };
      
    };

  };


  ###### implementation
  
  config = mkIf config.services.postgresql.enable {

    users.extraUsers = singleton
      { name = "postgres";
        description = "PostgreSQL server user";
      };

    users.extraGroups = singleton
      { name = "postgres"; };

    environment.systemPackages = [postgresql];

    # !!! This should be be in the mediawiki module, obviously.
    services.postgresql.identMap =
      ''
        mediawiki-users root   mediawiki
        mediawiki-users wwwrun mediawiki
      '';

    jobs.postgresql =
      { description = "PostgreSQL server";

        startOn = "started network-interfaces and filesystem";

        environment =
          { TZ = config.time.timeZone;
            PGDATA = cfg.dataDir;
          };

        preStart =
          ''
            # Initialise the database.
            if ! test -e ${cfg.dataDir}; then
                mkdir -m 0700 -p ${cfg.dataDir}
                chown -R postgres ${cfg.dataDir}
                ${run} -c '${postgresql}/bin/initdb -U root'
                rm -f ${cfg.dataDir}/*.conf
            fi

            ln -sfn ${configFile} ${cfg.dataDir}/postgresql.conf

            # We'd like to use the `-w' flag here to wait until the
            # database is up, but it requires a `postgres' user to
            # exist.  And we can't call `createuser' before the
            # database is running.
            ${run} -c '${postgresql}/bin/pg_ctl start -o "${toString flags}"'

            # So wait until the server is up.  `pg_ctl status' doesn't
            # work (apparently, it just checks whether the server is
            # running), so try to connect with psql.
            while ! ${postgresql}/bin/psql postgres -c ""; do
                sleep 1
            done
          ''; # */

        postStop =
          ''
            ${run} -c '${postgresql}/bin/pg_ctl stop -m fast'
          '';
      };

  };
  
}