On writing my first snaps, and keeping my passwords secure everywhere

I’ve been writing snaps for a year, more or less. But all the snaps I had written were a one-time thing to reproduce a bug, automate a scenario, or explore a specific code path. A few months ago I decided to write one snap that I would use day-to-day. The application I use the most by far is keepass, so that seemed like a good place to start.


With kpcli I access my password database from the command line. It’s just one big perl script, but not as ugly as it sounds :) That was a great first experiment because I haven’t tried perl in a snap before, and it would let me access the passwords from my beagle bone black in a secure and confined way.

Because it is a script, I just need to copy it into the snap. Of course, there’s a plugin for that! snapcraft is a meta-packaging tool to generate snaps. It comes with plugins for many packaging tools, copy being the most simple of them. Run:

  $ sudo apt install snapcraft
  $ snapcraft help copy

The next step is to look at the dependencies. Luckily, they are right there in the README file, in the form of Ubuntu packages. snapcraft calls them stage-packages, and they will be installed into the snap during the build.

Now I have almost all the difficult details to make the snap, and it was surprisingly easy. With this information, I wrote a part (read more about parts):

    source: https://github.com/alecsammon/kpcli.git
    plugin: copy
      kpcli.pl: scripts/kpcli.pl
      - perl-base
      - libcrypt-rijndael-perl
      - libterm-readkey-perl
      - libsort-naturally-perl
      - libfile-keepass-perl
      - libterm-shellui-perl
      - libterm-readline-gnu-perl
      - libclone-perl

I am just missing a way to tell the command where to find the perl libraries that I am bundling inside the snap. There is work in progress to make it easier to set up environment variables before launching the command; but for my first simple snap, quick and easy will do. I wrote a wrapper script:


  $SNAP/usr/bin/perl -I $SNAP/usr/share/perl/5.22 -I $SNAP/usr/lib/x86_64-linux-gnu/perl/5.22 -I $SNAP/usr/lib/x86_64-linux-gnu/perl5/5.22 -I $SNAP/usr/share/perl5 $SNAP/scripts/kpcli.pl

and the corresponding part:

    plugin: copy
      run.sh: scripts/run.sh

Finally, I added details about the name, version, summary and description of the snap, and defined the kpcli app. You can download the source of this snapcraft.yaml, put it in a directory and run snapcraft in there to generate it yourself. Or try mine installing it from the store:

  $ sudo snap install kpcli-elopio
  $ kpcli-elopio.kpcli


Ok, that solves command line access, but I also want some eye-candy, sometimes. KeepassX gives me access to the same passwords database through a GUI. By the time I finished my CLI snap I saw work from kyrofa, sergiusens and dpm to make it easy to snap desktop apps and use them in Ubuntu classic. I also was at a sprint sitting next to attente, who knows everything I didn’t know about the desktop, so it was a great time to enter the world of collaborative snapping.

Let me digress here for a moment to talk about collaboration. snapcraft and snapd are free software, and a lot of their design is based on the idea that the system can be extended and improved through the shared work of many and diverse developers. snapcraft aims to be the universal packaging tool, and plugins are the way we integrate the wild variety of build systems into the lifecycle to generate a snap. KeepassX is more complex than the CLI client, and it uses cmake to generate the executable. Well, guess what? There’s a plugin for that! :) (see the source of the cmake plugin). Also, this application uses the QT5 UI libraries. Just like with the kpcli snap, that means I will require to set up some environment variables and a launcher; but somebody else already did that and we have a way to share and reuse parts. Run:

  $ snapcraft update
  $ snapcraft search qt5
  $ snapcraft define qt5conf

There’s a part for that!! And when this application is running, I would like it to be integrated with unity7, if available. That means I would need a few extra permissions for my isolated app to access the unity7 services and libraries installed in a classic Ubuntu system. I’m a lucky guy because there’s an interface for that!!! (see the source of the unity7 interface) By default, snaps will be fully confined and won’t be able to access anything they don’t provide by themselves. Through interfaces, we allow snaps to get extra permissions to consume services, access devices and directories, and do anything that you could do in a classic unconfined Linux system; but now in a controlled manner with the explicit acknowledgement of the user for sensitive stuff. Run:

  $ snap interfaces

We have plugins, parts and interfaces for the most common cases of the most common apps. But the fun is just starting, and there are lots and lots of apps out there that would benefit from the controlled dependencies, usable security and transactional updates of snaps. We celebrate when we get new people into the team, so if you want to participate and influence the future of this shiny project, we can help you getting started in the playpen.

One last detail about collaboration is the relation with upstreams and distribution maintainers. Snapping free software projects is a pleasure because the source is available for us to inspect and decide on the best strategy to build the snap. Then we spread the apps to more people, we get more feedback and in many cases we end up sending patches to improve the upstream project. And I already mentioned the use of Ubuntu packages during the build of the snaps. With this we bootstrap from the awesome work that the Debian and Ubuntu communities are doing, and we’ll keep benefitting from both sides as we need debs to build some snaps, and the two play nicely together.

Aaaand back on track, because with all the work shared by the community this KeepassX snap is almost done by itself, but not quite.

I start by creating a new snapcraft.yaml file an defining the snap details:

  name: keepassx-elopio
  version: "2.0.2"
  summary: KeePassX is a cross platform password safe
  description: |
    KeePassX is an application for people with extremly high demands on secure
    personal data management. It has a light interface, is cross platform and
    published under the terms of the GNU General Public License.

Next, the app:

      command: qt5-launch keepassx
      plugs: [unity7, opengl]

Take a look at that qt5-launch, which is provided from the shared qt part that I will reference in a few lines. keepassx is a binary that lives inside the snap, and that we will compile using a snapcraft plugin. Also look at those plugs. That’s how we tell the system that a snap wants to consume an interface slot of the same name.

Followed by the parts:

      source: https://github.com/keepassx/keepassx.git
      source-tag: 2.0.2
      plugin: cmake
        - g++
        - qtbase5-dev
        - libqt4-dev
        - libqt5x11extras5-dev
        - qttools5-dev
        - qttools5-dev-tools
        - libgcrypt20-dev
        - zlib1g-dev
        - libgtk2.0-0
        - libqt5gui5
        - unity-gtk2-module
        - appmenu-qt5
        - dconf-gsettings-backend
      after: [qt5conf]

Note the new build-packages section. Those packages will not end up in the snap, they are only used during the compilation so they will be installed in the host where you are running snapcraft. I already discussed about the stage-packages, nothing new to see there. Now the after keyword is where a lot of the collaboration magic happens. It means that my keepassx part depends on the qt5conf part. But I don’t define the qt5conf part in my yaml file, so snapcraft will bring it from the pool of shared parts (see the source of the qt5conf part). I love this because I didn’t have to write any of the qt complications, and when a qt expert makes a change to improve it, I just need to run snapcraft again and my snap will be better with no effort. This is where the qt5-launch I used in the apps section comes from.

I finish my yaml adding a last part:

      plugin: copy
        gschemas.compiled: usr/share/glib-2.0/schemas/gschemas.compiled
        giomodule.cache: usr/lib/x86_64-linux-gnu/gio/modules/giomodule.cache

This is required to save the KeepassX settings. It’s currently not a nice way to include the compiled files in the snap, and we are discussing about how to improve it, so I won’t dig too much here. It shows how simple yet flexible snaps are: you can put anything into the snap, it doesn’t matter how you got it. But it also shows that we have things to improve, so let me insist on my invitation for you to join our project. If there’s something you hate, this is the right time to change it. If there’s something you like, there’s always room to improve it. We have cookies.

Punto final, café con tamal. Give it a try:

  $ sudo snap install keepassx-elopio
  $ keepassx-elopio.keepassx


Autotools básico


Crear paquetes de código fuente utilizando las herramientas de construcción de GNU (Autoconf, Automake y Libtool) a partir de uno o más ficheros de código fuente y los ficheros configure.ac y Makefile.am.

Esta guía muestra cómo a partir de un fichero fuente holamundo.c y el par de ficheros mencionados anteriormente se generará un archivo llamado holamundo-1.0.0.tar.gz que una vez desempaquetado se pueda compilar e instalar con el típico "./configure && make && sudo make install".


  • Portabilidad, permite generar makefiles compatibles con diferentes implementaciones de Make, múltiples compiladores e intérpretes y generar scripts compatibles con múltiples shell.

  • Multiplataforma, los scripts generados facilitan las comprobaciones y configuraciones necesarias para generar una compilación cruzada, por ejemplo generar binarios para otra arquitectura agregando pocos parámetros.


  • autoconf, se encarga de generar el script configure a partir del fichero configure.ac.

  • automake, genera el fichero Makefile.in a partir del fichero Makefile.am.

  • libtool, gestiona la creación de librerías estáticas y dinámicas, y también la carga (en tiempo de ejecución) de librerías dinámicas.

Dentro del paquete autoconf hay otras herramientas relevantes como aclocal y autoheader. En este ejemplo básico se ejecutan de forma automática todas las herramientas mencionadas utilizando la herramienta autoreconf.

Herramientas relacionadas

  • make, procesa archivos Makefile. Existen varias implementaciones (GNU Make, BSD Make...) con algunas incompatibilidades que autotools solventa.

  • pkg-config, facilita información sobre la mayoría de las librerías instaladas en el sistema (ubicación, dependencias, versión, etc.).

¡Hola, Autotools!

Para crear el ejemplo básico de paquete es conveniente disponer de una carpeta de trabajo para tenerlo mejor organizado.

  • Crear una carpeta holamundo con una subcarpeta src para el código fuente y a continuación ubicarse en la carpeta de trabajo:
mkdir -p holamundo/src
cd holamundo


  • Crear un fichero de código fuente C en src/holamundo.c:
#include <stdio.h>

int main() {
    printf("Hola Mundo!\n");

    return 0;


  • Crear un fichero Makefile.am:
bin_PROGRAMS = holamundo
holamundo_SOURCES = src/holamundo.c


  • Ejecutar la herramienta autoscan en la carpeta de trabajo. Creará un fichero llamado configure.scan que hay que renombrar a configure.ac:
mv configure.scan configure.ac

Nos habrá generado un fichero configure.ac parecido al siguiente:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.


# Checks for programs.

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

  • Modificar la macro AC_INIT del fichero configure.ac para mostrar el nombre del paquete, versión y dirección para avisar sobre errores (correo electrónico o web):
AC_INIT([holamundo], [1.0.0], [https://github.com/JaquerEspeis/webespeis/issues])
  • Agregar la macro AM_INIT_AUTOMAKE en el fichero configure.ac para poder generar los Makefiles. Un buen lugar sería después de la línea de AC_CONFIG_HEADERS:
AM_INIT_AUTOMAKE([foreign subdir-objects])

Una vez modificado el fichero configure.ac debería ser parecido al siguiente:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_INIT([holamundo], [1.0.0], [fran@fran.cr])
AM_INIT_AUTOMAKE([foreign subdir-objects])

# Checks for programs.

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.


Generar configure y Makefile.in

  • Ejecutar:
autoreconf -i

Generar Makefile


Generar paquete ("tarball")

make dist

Se habrá generado holamundo-1.0.0.tar.gz

Instalación genérica del paquete

  • Descomprimir:
tar xf holamundo-1.0.0.tar.gz
  • Entrar en la carpeta comprimida:
cd holamundo-1.0.0
  • Generar Makefile:
  • Construir:
  • Instalar:
sudo make install

Detalles de los ficheros creados


bin_PROGRAMS indica la lista de programas (binarios en este caso) que va a crearse. En este caso se va a crear un binario llamado holamundo.

holamundo_SOURCES indica que nuestro holamundo tiene un listado de _SOURCES (ficheros fuente). En este ejemplo solamente hay uno (src/holamundo.c). Si el proyecto tuviera más ficheros de código fuente para crear el programa se separan con espacios. Si se desea poner un fichero por línea para hacer el mantenimiento de Makefile.am más limpio se puede utilizar \ al final de la línea para indicar que continúa en la siguiente, por lo tanto:

holamundo_SOURCES = \
    fichero1.c \
    fichero2.c \

es lo mismo que:

holamundo_SOURCES = fichero1.c fichero2.c fichero3.c


foreign indica que se está creando un paquete GNU estándar (no exigirá la existencia de los ficheros ChangeLog, COPYING, NEWS y README para funcionar).

subdir-objects indica que se está usando el modo recursivo, es decir, no se van a usar múltiples ficheros Makefile.am para cada carpeta con objetivos a procesar.

AC_PREREQ indica la versión mínima de autoconf requerida para funcionar con el archivo de configuración.

AC_CONFIG_SRCDIR comprueba que el código fuente existe en la carpeta indicada mediante la comprobación de algún fichero fuente de la misma.

AC_CONFIG_HEADERS indica el nombre que tendrá el archivo de configuración de código fuente generado. Esto permite crear definiciones (por ejemplo, #define LOQUESEA 1) en el archivo indicado (por defecto, config.h) que podrá ser incluido en el código fuente. Estas definiciones podrían variar según lo que compruebe el script configure, resultando muy útil por ejemplo para verificar si el programa se ha compilado con o sin soporte de una característica en particular, por ejemplo para dependencias opcionales de librerías o comprobaciones de funcionalidad del compilador o de un sistema operativo en tiempo de compilación.

AC_PROG_CC comprueba la existencia de un compilador de C. Como autoscan ha detectado código fuente en C se ha agregado esta macro automáticamente.

AC_CONFIG_FILES recibe en el primer parámetro una lista de ficheros separados con espacios. (en este caso solo Makefile, que generará a partir de Makefile.in). Los ficheros con extensión .in se utilizan para sustituir los valores de las variables que contienen y generar el archivo de salida, normalmente con el mismo nombre sin el .in. Este proceso lo realiza la macro AC_OUTPUT.

Algunos parámetros del script configure

El parámetro --prefix permite indicar el directorio base de instalación, que por defecto suele ser /usr/local. Por ejemplo el programa holamundo se copiaría por defecto a la carpeta /usr/local/bin si no se cambia el --prefix. Las distribuciones suelen usar en sus paquetes --prefix=/usr. Si se quiere instalar un paquete y no se tienen permisos de superusuario se podría indicar una ruta dentro de la $HOME donde usualmente se suelen tener permisos de escritura.

./configure --help muestra información detallada de los parámetros.

Compilación cruzada con el script configure

El parámetro --host permite utilizar de forma sencilla toolchains para compilación cruzada, por ejemplo en una máquina Intel con Ubuntu e instalando el paquete gcc-arm-linux-gnueabihf proporciona el toolchain para ARMv7 (hard float) y puede realizarse esto:

./configure --host=arm-linux-gnueabihf

A continuación podemos verificar que el ejecutable holamundo es un ELF para arquitectura ARM y no para Intel mediante:

file holamundo

por lo que podremos comprobar que efectivamente se utilizaron las herramientas del toolchain sin tener que prefijar individualmente compilador, enlazador y demás ejecutables.

Más información

Sharing the Wi-Fi connection through Ethernet

My apartment was clearly not designed for the Internet of Things. I have a weird set up to connect all my devices: there’s ADSL, Ethernet, Wi-Fi, powerline networking, 4G from a free promotion until I download 3GB and then 3G for the rest of the month... It’s crazy, and getting crazier as I have to test more and more devices for snappy. When I was about to throw a cable from the kitchen to the office I found about sharing the network (thanks Luis!). Now let me repeat a slightly modified version of part of Luis’ answer to show how I share my wireless connection through an ethernet cable with my test board.

  1. Open the network indicator.

  2. Click Edit Connections....


  3. On the Network Connections dialog, click the Add button.


  4. On the Choose a Connection Type dialog, select Ethernet.


  5. On the Editing dialog, enter a name for the connection.

  6. Go to the IPv4 Settings tab.

  7. Select the Method Shared to other computers.


  8. Click the Save button.

What’s left is to connect an Ethernet cable from your laptop to the board, give power to the board and wait for it to finish booting.

To get the IP of the board you can run the arp command (Thanks to Alex for the tip). It will show you the addresses of the neighbour machines. The one of your board will be like 10.42.0.?. Now you can ssh into the board using the default credentials (username ubuntu, password ubuntu) or the ones you configured.


This also proved to be useful during our first snappy maker night, when we had to connect many boards to play with the system.

Pro tip: If you are having problems connecting through ssh, you can connect through the serial console to check for errors.



En este momento de la historia, en la mayoría de los casos el consumidor no conoce el origen de los productos. Con una plataforma que brinde la posibilidad de compartir información entre productores y consumidores, se pueden solucionar varios problemas que presenta esta cadena de consumo.


Una plataforma, diseñada para compartir información entre productores, proveedores y consumidores, fue creada en Australia por la fundación Open Food Network.

Esta plataforma permite conocer el origen de los productos, la situación del productor, métodos de producción y otros factores que pueden tener alto impacto en la decisión del consumidor de orientarse a un producto o a otro.



Por el momento lo que hemos logrado:

  • Comprar el dominio
  • Configurar ofn en ubuntu 14.04
  • Necesitamos alguien con experiencia en ruby y rails para que revise
  • Tenemos un ambiente de pruebas


Ambiente de Producción

  1. Agregar el "Host" a la configuración de la Base de datos en config/database.yml:
  adapter: postgresql
  encoding: unicode
  database: open_food_network_prod
  pool: 5
  host: localhost
  username: ofn_user
  password: toor
  1. Crear la base de datos:
/opt/openfoodnetwork/www# RAILS_ENV=production rake db:schema:load db:seed
  1. Precompilar los activos en el ambiente de producción:
/opt/openfoodnetwork/www# RAILS_ENV=production rake assets:clean
/opt/openfoodnetwork/www# RAILS_ENV=production rake assets:precompile
  1. Correr Unicorn en producción manualmente
 cd /opt/openfoodnetwork/www && bundle exec unicorn -c ../shared/config/unicorn.rb -E production -D

Solucion de Problemas

  • Información del Log de Unicorn:
$ tail -f /opt/openfoodnetwork/shared/log/unicorn.log
  • Encontrar la ubicación del Unix Socket en /opt/openfoodnetwork/shared/config/unicorn.rb

  • Verificar que el Unix socket se encuentre creado:

$ ls -lah /tmp/unicorn.openfoodnetwork.sock
  • Verificar que Unicorn esté corriendo:
$ ps aux | grep unicorn


(1) http://teotti.com/use-of-rails-environments/ (2) https://www.digitalocean.com/community/tutorials/how-to-deploy-a-rails-app-with-unicorn-and-nginx-on-ubuntu-14-04

Utilizar Nikola por primera vez


La forma mas simple de instalar Nikola es con pip y virtual, también se podría utilizar uno de los paquetes de la distribución que se este utilizando, en si son usuarios de Linux.

En el directorio del repositorio del sitio

virtualenv --python=python3 .env
source .env/bin/activate
pip3 install --upgrade "Nikola[extras]"

Primeros usos

En este momento se tiene el sistema instalado, ahora hay que crear el contenido del primer sitio de prueba, estando en el directorio que va a mantener el código, se ejecuta el comando nikola init --demo ., luego se debe de construir el sitio con el comando nikola build.

El siguiente paso es ver el sitio, para lo que va a utilizar el comando nikola serve -b, pero es mucho mas fácil utilizar nikola auto -b para reconstrucciones automáticas.

Utilizar markdown

Para utilizar markdown para crear los post se debe usar uno de los múltiples lenguajes de marcado ligero soportado, para eso se debe de editar el archivo config.py en la raíz del sitio en Nikola.

Primero se debe de verificar que este en la estructura COMPILERS

# 'rest' is reStructuredText
# 'markdown' is MarkDown
# 'html' assumes the file is HTML and just copies it
    "rest": ('.rst', '.txt'),
    "markdown": ('.md', '.mdown', '.markdown'),
    "textile": ('.textile',),
    "txt2tags": ('.t2t',),
    "bbcode": ('.bb',),
    #"wiki": ('.wiki',),
    "ipynb": ('.ipynb',),
    "html": ('.html', '.htm'),
    # PHP files are rendered the usual way (i.e. with the full templates).
    # The resulting files have .php extensions, making it possible to run
    # them without reconfiguring your server to recognize them.
    "php": ('.php',),
    # Pandoc detects the input from the source filename
    # but is disabled by default as it would conflict
    # with many of the others.
    # "pandoc": ('.rst', '.md', '.txt'),

Luego se debe de agregar a la estructura del tipo de entrada, en el ejemplo de abajo se agregó la linea, ("posts/*.md", "posts", "post.tmpl") a los dos tipos de entras POST y PAGES.

    ("posts/*.rst", "posts", "post.tmpl"),
    ("posts/*.txt", "posts", "post.tmpl"),
    ("posts/*.md", "posts", "post.tmpl"),
    ("stories/*.rst", "stories", "story.tmpl"),
    ("stories/*.txt", "stories", "story.tmpl"),
    ("stories/*.md", "stories", "story.tmpl"),

Utilizar locales para Costa Rica

Este proceso debería funcionar para la mayoría de idiomas.

  1. Generar el locale necesario con `locale-get
  2. Definir cual es el locale que debe de utilizar Nikola por defecto.
# What is the default language?

# What other languages do you have?
# The format is {"translationcode" : "path/to/translation" }
# the path will be used as a prefix for the generated pages location
    DEFAULT_LANG: "es_CR",
    # Example for another language:
    # "es": "./es",
    "es": "./",
    "en": "./en",
  1. Definir el locale que se va a utilizar para es, por defecto es es_ES.

El locale a utilizar puede ser probado, importando locale import locale y llamando al locale necesario locale.setlocale(locale.LC_ALL, 'es_CR.utf-8')

Conectarse a Snappy a través de la consola serial

Estoy trabajando en Snappy Ubuntu con un BeagleBone Black Rev C y un Raspberry Pi 2. Es posible conectarse a los dispositivos a través de la consola serial para monitorear errores durante el arranque y para controlar el sistema. Luego de mi primer cable quemado, decidí escribir las instrucciones para conectar los cables y así reducir la probabilidad de que mis dispositivos prendan fuego.

Lo primero, por supuesto, es instalar snappy en la tarjeta SD. Luego, comprar uno de estos cables FTDI que convierten de USB a serial. Este cable se puede usar en ambos dispositivos porque tiene los conectores separados. El cable negro es tierra (GND), el cable blanco es para recibir datos en el puerto USB, el cable verde es para transmitir datos desde el puerto USB ye el cable rojo es de corriente eléctrica de 5V.

BeagleBone Black

El BeagleBone Black Rev C tiene 6 pines. Hay un punto blanco al lado del primer pin. Conecte el cable negro GND al primer pin, el cable verde al cuarto pin y el cable blanco al quinto pin. En el BeagleBoneNUNCA conecte el cable rojo.



Raspberry Pi

El Raspberry Pi 2 Model B tiene 40 pines. Aquí hay un bonito dibujo del pinout con los números y las funciones de los pines.

Conecte el cable negro GND al sexto pin, el cable blanco al octavo pin y el cable verde al décimo pin. De forma opcional puede darle corriente al Raspberry conectando el cable rojo al segundo pin, pero si hace esto NO conecte el cable de poder USB porque no es posible usar ambas fuentes de poder.



Consola serial

Instale screen:

  sudo apt-get install screen

Conecte el otro extremo del cable a un puerto USB de su computadora y busque el nombre del dispositivo tty:

  ls /dev/ttyUSB*

Inicie la sesión de screen en la terminal serial, reemplazando /dev/ttyUSB? con el número de su dispositivo.

  sudo screen {/dev/ttyUSB?} 115200

Por último, inserte la tarjeta SD y conecte el cable de poder de su dispositivo. Ahora podrá ver los mensajes de arranque en la termina, y al final snappy le permitirá inciar la sesión. El usuario predeterminado es ubuntu y la contraseña predeterminada también es ubuntu.


Snappy tiene un servidor SSH preinstalado. Una vez que el arranque ha sido exitoso, se puede iniciar sesión a través de SSH, lo que nos da una mejor experiencia. Esta terminal serial se puede usar para obtener la dirección IP del dispositivo:

  ip addr show

Y desde una terminal diferente, reemplazando ip con la dirección IP del dispositivo:

  ssh ubuntu@{ip}

Ahora estamos listos para empezar a jugar con snappy en el dispositivo. No se pierdan del tour.

Para salir de la consola serial, presione CTRL+a y luego k.

Más información sobre los cables y la consola serial