snapframework/snap

Rule of thumb for deployment

slabko opened this issue · 4 comments

Lately I tried to deploy my new snap based web application. The app included heist, session and auth snaplets. The simplest way to do that was to copy the binary file to webserver and then copy all the resources in the same directory. When I run the app from the directory where all the resources were located, everything worked fine.

To be clear, here is directory, where I deployed the app:

snapapp/
  |-- snaplets/
    |-- heist/
      |-- templates/
        |-- *bunch of tpl files*
  |-- static/
    |-- style.css
  |-- snapapp

I did: cd snapapp && ./snapapp and it worked perfectly.

However, while reading "Filesystem data and automatic installation" from Snaplets tutorial, I though, that there must have been a better way. So I tried to dig it out:

  1. Created a resources directory where I copied snaplets and static directories.
  2. Set path to makeSnaplet to `Just ((</> "/resources/") <$> getDataDir)
  3. Added all resources to cabal's data-files and checked, that files are really exist in getDataDir location

And... nothing. The app just ignored all my actions and still tried to find everything in the current dir. Furthermore I tried to understand makeSnaplet behaviour and found out, that it takes _scFilePath of SnapletConfig which is sort of non-public deal. So I'm stuck, and I'm not even sure if this is the way to deploy the app.

So the question actually (or rather two questions): What is the best way to deploy the snap app using standard tools, reducing number of manual work? And if passing a path to makeSnaplet is not intended to deploy the app, what is the actual intention of that parameter?

Thank you very much in advance, I'll appreciate any help.

I wouldn't recommend using the getSnapletDataDir argument to makeSnaplet as a way to set up for deployment. I suppose you could do that, but if you did you would not want to change the directory like you did with </> "resources".

Deployment and devops is a really big topic and there are so many different situations that it's hard for us as framework authors to come up with any kind of recommended process. One possibility might be to deploy your app in a Docker container. Another might be to have your CI server copy the build artifacts to S3 and then make a deployment script that downloads your compiled builds from S3, copies them into place, and then runs the app.

Thank you Duog for your raplay.

But what is an idea of having a path parameter in makeSnaplet?

It allows reusable snaplets to ship with filesystem resources. This makes it possible to build, say, a wiki snaplet that works nicely out of the box by installing all its own templates while still allowing 100% customization because the user can then modify those templates as much as necessary. Here is an example that ships a config file with reasonable defaults for the end user.

https://github.com/mightybyte/snaplet-postgresql-simple/blob/master/src/Snap/Snaplet/PostgresqlSimple.hs#L283

I shouldn't have ignored all the part about configuration files :)

Thank you very much, Doug, I really appreciate you help!