I’m currently testing the waters with NixOS, and want to deploy a Rails app on a NixOS.
At first I thought I could just specify as user packages things like ruby zlib etc, but I’ve fallen into the trap that pkg-config does not find it in this case.
Now, I’ve since learned that I should create a .nix file and use nix-shell to get access to the libraries I need to build my webapp.
So far so good, it works in the nix-shell. However I now have trouble unifying it with my preferred deployment pattern:
(If you know mina/capistrano it is pretty much exactly that)
You run mina deploy and this happens on the remote server:
Each new release creates a new folder, and the running release gets symlinked to ‘current’
You have a set of shared folders, which get symlinked into the ‘current’ release
The shared folders are never deleted or touched between upgrades
To me it sounds very similar to what NixOS does on its own already, and I think I am just missing some techniques and ways to get a similar idea working.
I’ve tried to play around with profiles, but that didn’t get me much further. I then thought of creating a service file for my webapp, but it is unclear to me how it would be structured for a rails app.
I had so far no trouble creating a custom systemd service.
I’d love some help and learn how this could be achieved! Thank you for any pointers
You could use mina deploy and wrap your application in nix-shell but this might end up in garbage collecting the libraries if you run nix-collect-garbage at some point on your server. A better approach is to package your gems with bundix from your existing Gemfile. This allows you to use the same setup for both development and deployment. The nice thing about bundix is that for many gems we already know the native dependencies and put them in place automatically. You can checkout this file to see what gems are already covered by this: nixpkgs/default.nix at master · NixOS/nixpkgs · GitHub. In the wiki we also have a tutorial and a bit in our manual.
nixops also has a quite similar feel to it. It would require to wrap the application is a package, declare the service as a systemd unit, write a configuration.nix for the target machine and finally attach it to the nixosp config. Then nixops deploy would have a similar effect as mina deploy except that the whole system configuration is also included with it. nixops also supports rollbacks.
Usually services have a way to specify the “data” dir that contains mutable data. So you would also declare a user for the service and then point the service to the user’s home. Unfortunately rails has this insane notion of mixing code and mutable data in the same directory so that might make things a bit more difficult. The 12factor-rails gem tries to fix this so it might come in handy. Otherwise I would recommend to create symlinks from ./log to /var/myapp/log for example.
Install direnv and then create a .envrc with use nix as the content.
Is it possible to configure the upload folder? As long as it’s possible to pass a custom target directory to rails it’s fine. The goal is to move away from relative to absolute paths. ./uploads to /var/myapp/uploads