1. Introduction

In the following tutorial, we'll learn how to use the packaging and deployment tools that can help you deploy your application on a production server.

Deploying your web application on a remote server is a crucial part

2. Packaging your web application

2.1 What's an application package ?

What we call package is a single compressed file containing everything needed to run your application. Packages are platform dependent: if you build your package on Linux, you'll get a package that can only be deployed on other Linux systems.

Crails application packages consist of five elements:

2.2 Package command

The Crails Command Line Interface comes with a tool to package your application in a single step:

$ crails package

What this command does is, it first builds your application (like crails build), then creates a compressed archive (by default: application.tar.gz) which we call a package.

The package command has several option, the first of which being:

$ crails package --mode Release

This is what you want to do when you're about to deploy a package meant for a production environment. The Release build will be safer and lighter.

You can check out other options for the package command by running $ crails package -h.

3. Deploying your web application

We know how to package our application, and that's great ! But the purpose of a package is to be deployed, so let's see how to do that !

First things first, deployments are performed through ssh, so make sure you've got it installed on your system.

3.1 Manual deployment

Deploying a crails package is pretty simple. The first step is to send the package to your server, which can be done using scp:

$ scp application.tar.gz user@127.0.0.1:/tmp/application.tar.gz
$ ssh user@127.0.0.1

Where 127.0.0.1 is the IP of the server you're trying to reach, and user the name of the user with which you want to use to connect to that server.

Now that we're connected, we need to get root access, which can typically be done through:

$ sudo su

Then, we extract our archive at the root of the machine:

$ cd /
$ tar xf /tmp/application.tar.gz

And voilĂ  ! You may now start your application with the following command:

$ /usr/local/bin/application_name/start.sh

Where application_name is the name you've given to your application when creating it with the crails new command (which you can customize by changing the name variable in the .crails file at the root of your project).

Of course, the application will stop as soon as you leave the terminal. To have your application run in the background, we need to deploy it as a service... which is precisely the purpose of the next chapter.

3.2 Using the deploy command

If you have direct ssh access to your machine, then you can make your life simpler by just using the deploy command, such as:

$ crails deploy \
  --hostname 127.0.0.1 \
  --deploy-user user \
  --sudo \
  --pubkey \
  --user webapp \
  --group www

Wow, that was a lot of options ! Let's go over what those do:

The deploy command will first package your application, then deploy it. So once you are done developping, you're always just one command away to send your application live.

Note that if the user and group specified in your options don't already exist on your production environment, they will be created by the deploy command.

The deploy command requies the libssh development files to be available on your system to build, so if you didn't have it prepped when you last installed crails, the deploy command won't be available.

3.3 Environment

Your deployed application might require environment variables to define some instance-specific settings. That is probably the best way to define your database settings, for instance.

You can optionally provide your own environment files or variables, which will be compiled to a single file and uploaded to /usr/share/crails-deploy (the filename being your application name).

Use the --env option to add environment variables:

$ crails deploy [options] --env VARIABLE1=example VARIABLE2=example

Or environment files:

$ crails deploy [options] --env example1.env example2.env ...

The environment file will be loaded when you start your application as a service (using systemctl start my_application on Linux, for instance).

Environment files should define variables using the following format:

DATABASE_URL="postgresql://user:password@localhost:5432/app"
REDIS_URL="redis://localhost:5379"

3.4 FreeBSD jails

If you're using a FreeBSD server, you may want to deploy your application in a jail. That's a great idea ! And good for you, the deploy command can help you with that !

Once you've created a jail, just use the --jail-path option to deploy to a jail:

$ crails deploy \
  --hostname 127.0.0.1 \
  --deploy-user user \
  --sudo --pubkey \
  --jailpath /var/jails/webapp

When using jails, the --user and --group options will be relative to the jail, and only the service file will be deployed outside of the jail.

3.5 Deploying pre-built packages

The methods we've seen before are all-in-one: they build, package and deploy your application all at once. What if you already have a packaged application at hand, and just want to deploy that package ?

In this case, we don't use the crails command anymore, and switch to crails-deploy:

$ crails-deploy \
  --app-name application_name \
  --package my_package.tar.gz \
  --hostname 127.0.0.1 \
  --sudo --pubkey \
  --start /usr/local/bin/package_name/start.sh \
  --stop /usr/local/bin/package_name/stop.sh

The option are the same as the ones for crails deploy, except you must:

Note that the same package can be deployed several time with different app-name, and thus, different services, environment, logs and runtime directories. This means you can deploy several instances of the same package on the same machine.

crails-deploy is framework agnostic, and can work for projects even outside of the crails framework. Check out the project's README at crails-deploy's github page to learn more about this tool.

4. Packaging with Docker

It is best to ensure your packaging environment is the same as your production environment: it's a good way to avoid the linking issues that could happen in cases where a system library (such as the C++ standard library, or the openssl library) is provided by your production environment in a different version than on your packaging environment.

With Linux, this result is pretty simple to achieve, using Docker to locally replicate your production environment.

Which is why Crails comes with a set of tools to help you package your application using docker. Let's take a look ! Firstly, make sure that the docker service is installed and running on your machine.

Then, go to the diretory of one of your crails project, and install the docker plugin:

$ crails plugins docker install

This will set you up by creating the following files:

File/Folder Purpose
docker/ Where your docker machine are run and configured.
docker/base/Dockerfile Docker configuration using the debian:sid image.
docker/base/build-build2.sh Build2 is the build manager for crails. This scripts will install build2 on your docker machine.
docker/base/build-crails.sh This script will build the crails framework libraries used by your application.
docker/base/build-environment.sh This file sets some build options used by the build-crails.sh script.
docker/base/build-odb-compiler.sh Optional: present when you're using the odb plugin.
docker/base/build-comet.sh Optional: present when you're using the comet plugin.

The base configuration is meant as an example: we can't really guesstimate what your own production environment will look like, so it should serve as a template for the configurations you will create for your servers.

4.1 Machine creation

Speaking of which, now that the docker plugin is installed, you can scaffold new docker machine configurations with the following command:

$ crails plugins docker new --name my_machine --image ubuntu:22.04

Your new machine configuration will be created in docker/my_machine.

4.2 Running a machine

While you should be perfectly able to build and run those docker machines, the Crails CLI comes with a bunch of tool to do it for you.

4.2.1 Opening a shell

This is pretty useful for debugging and tinkering around: the shell command allows you to launch your docker machine, and opens a shell to interact with its contents:

$ crails plugins docker shell --dockerfile my_machine

If it hasn't already been done, this command will need to build the docker machine first. That might take a while, so be patient ! You can also use the -v option to see the output of docker as it builds the machine.

4.2.2 Running your application

For some reasons that are your own, you might prefer to run your application from a docker machine rather than directly from your own system. There's a command for that:

$ crails plugins docker run --dockerfile my_machine --port 3001

4.2.3 Packaging your application

Lastly, the main purpose of the docker plugin: packaging your application for your target environment.

You can use the following command to create a package from a specific docker machine:

$ crails plugins docker package \
  --dockerfile my_machine \
  --output my_machine.tar.gz

The options of the crails package command are all also available with this comannd.

4.2.4 Deploying your application

Similarly to the package command, you can also use the deploy command with the docker plugin, such as:

$ crails plugins docker deploy \
  --dockerfile my_machine \
  --hostname 192.168.0.15 \
  --deploy-user user

The options of the crails deploy command are all also available with this command.