Creating Jails in FreeBSD is very easy. It takes few minutes to follow the official handbook and voilĂ ! We’ve a dedicated container. But what can we do with it?

A very common use pattern on FreeBSD desktop is to use Jails to encapsulate dependencies, so they don’t pollute the main OS. Don’t want that pesky Pyton? Straight to Jail. Java? Straight to jail!

Simple jail - Ltex-Ls

I am not a native speaker, so my English skills are far from perfect. My terrible typing skills don’t add anything good into the mix. Therefore, I am in need of a good grammar and spell checker. There is Grammarly, but it’s closed source and cloud based. We don’t want that.

Luckily an alternative exist - LanguageTool. It is quite good and can run locally! I use it via an LSP - Ltex-Ls. Technically it’s aimed at Latex, but it can work with any filetype.

The problem with ltex-ls is that is runs on JVM. I really don’t need that on my system. Let’s lock it in a jail and allow our NeoVim1 to use it.

First, let’s create a Jail and call it `ltex`. For now we can allow it access to the internet, as we will download some files.

ltex {
      ip4 = inherit;
      interface = em0;
}

We will remove network access after we are done with the setup. We don’t want any of our writings to leak to the web.

Then, let’s log into the jail

doas jexec ltex /bin/sh

and add the dreaded java

pkg install openjdk-jre

then, let’s fetch our latex-ls

cd /root
wget https://github.com/valentjn/ltex-ls/releases/download/16.0.0/ltex-ls-16.0.0.tar.gz
tar -xvf ltex-ls-16.0.0.tar.gz

for ease of use, let’s remove the version number from the directory

mv ltex-ls-16.0.0/ ltex

And our jail is ready, so let’s leave it (either `exit` or the good, old Ctrl+d). We can now open our nvim config file. This is not a guide about this part, so let’s just assume you have LSP and LSP-Config intalled.

Our config will look like this:

lspconfig.ltex.setup{
  on_attach = on_attach,
  cmd = { "doas",
    "jexec",
    "ltex",
    "/root/ltex/bin/ltex-ls" },
-- rest of config omitted
}

Notice, that we now run the command as root inside the Jail. It would make sense to allow passwordless-doas to our user due to `doas`. I will update this guide if I figure out if we can commit this security nightmare here.

But let’s go a step further. Ltex-Ls allows to use machine learning based grammar check based on ngram data. We can add it to our jail. Let’s log back in

doas jexec ltex /bin/sh

Next we need to fetch the ngram data (you can find it on LanguageTool website. We need to have a `ngrams` folder which contains `en` (as the language shortcut). The ngrams should be inside the `en`.

I propose you move the files to `/var/ngrams/en` inside the Jail.

We can now tell `NeoVim` to inform the `ltex-ls` runtime to use the ngrams.

-- our old config
lspconfig.ltex.setup{
  on_attach = on_attach,
  cmd = { "doas",
    "jexec",
    "ltex",
    "/root/ltex/bin/ltex-ls" },
  -- ngram settings added
  settings = {
    ltex = {
      additionalRules = {
        languageModel = '/var/ngrams/',
      },
    },
  },
  -- rest of config still omitted

Note that we instructed the LSP to use /var/ngrams folder. For program running inside a Jail, the Jail is full system. Even though we can access the ngram data on the host OS under /jail/containers/ltex/var/ngrams (depending on your config), for Jail, the /jail/containers/ltex/ prefix doesn’t exist as it points to root for the jail.

We can now remove networking from the jail, so our Jail config just defines the existence of the jail

ltex {
}

And boom. We’ve got machine language grammar checking which is completely offline and does not pollute our primary system. Our tinfoil friends will be proud of us.

[this article will be expanded with more examples in the near future]


  1. I can, of course, run in any other editor which supports the LSP standard, be it Emacs or some bad one. ↩︎