Mikkel Høgh

Coding the web since 1999

05 Apr 2012

Deploying LedgerSMB with nginx and Plack on FreeBSD

I have recently been looking at LedgerSMB for Drupal Danmark’s accounting needs, but I’ve struggled getting it set up, since it is a classic CGI app, which is not something we usually run on our servers, especiallty since we use nginx on our servers, at it does not support classic CGI. It does support FastCGI, so we need some sort of wrapper around LedgerSMB to get it running.

Fortunately, the wonderful Perl commnuty has a solution for that, namely Plack.

After digging around a bit and getting helpful tips from the LedgerSMB mailing list, I managed to get a working solution together:

  1. Preamble

    Since we use FreeBSD in this example, I’m going to use the ports collection to install the required CPAN packages for this to work. Here we assumbe that you have LedgerSMB and its dependencies installed already.

  2. Installation

    The installation is as simple as running this command:

    # portmaster www/p5-Plack www/p5-CGI-Emulate-PSGI www/p5-CGI-Compile

    This will install Plack and its dependencies.

  3. Starting the Plack server

    This is fairly simple, in fact. Just proceed to the folder where you have LedgerSMB installed and run the following command:

    % plackup -MPlack::App::CGIBin -e 'Plack::App::CGIBin->new(root => "/usr/local/ledgersmb", exec_cb => sub { 1 })->to_app'

    Make sure you adjust the root path in the command to point to your LedgerSMB folder.

    Unless you have added the LedgerSMB folder to your Perl library path, you need to run this command from that folder.

  4. Configuring nginx

    This is very similar to what we do for our PHP-FPM apps, and it seems to work as it should:

    server {
      listen       443;
      server_name  ledger.example.com;
      keepalive_timeout 300;
      ssl                  on;
      ssl_certificate      /etc/ssl/ledger.example.com.crt;
      ssl_certificate_key  /etc/ssl/ledger.example.com.key;
      root   /usr/local/ledgersmb;
      # Serve the login page at the root.
      location = / {
        rewrite ^ /login.pl redirect;
      location ~ \.pl$ {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Port 443; #this is important for Catalyst Apps!
        proxy_pass http://localhost:5000; #changed from http://localhost:5000/ which was causing double forward slash problems in the url
      # Deny access to configuration and other nasty places.
      location ~ \.conf$ { deny all; }
      location /users { deny all; }
      location /bin { deny all; }
      location /utils { deny all; }
      location /spool { deny all; }
      location /templates { deny all; }
      location /LedgerSMB { deny all; }
  5. Profit

    This setup has worked very well for me so far. Hit me up in the comments below if you have any improvements :)