Search This Blog

Saturday, August 2, 2014

Ubuntu 14.04 LTSP Docker Container

Just finished creating a redundant LTSP server as a Docker container.  Using a Dockerfile, we can now build portable LTSP servers to host both thick and thin client PCs. This of course depends on the LAN having at least DHCP and DNS already provided.  DHCP is used to support the PXE boot process, while DNS is used by the Dockerfile to resolve Ubuntu APT Repository package host IPs.  Thus, an Internet connection is also needed.

In this scenario, the container is running on the "" CentOS 6.5 server.  LTSP ports were forwarded through the "" VLAN Gateway (Zentyal server with two ethernet cards) to the docker01 host.  This allows clients on the normal domain LAN to hit the docker01 host behind the gateway on the VLAN.  The container running LTSP then has the gateway's forwarded ports mapped to the docker01 host so the clients can access the LTSP services.

Port 69/udp - TFTPD, serves the PXE boot configuration to clients referred by DHCPd.
Port 10809/tcp - Network Block Device daemon (NBDd), serves the base chroot up as a block device for the client. The external port is 10809 as well.
Port 22/tcp - SSH, serves the authentication and home folder via "SSHFS".  The external port is 2222 so that it does not conflict with the default SSH port 22 on the docker01 host.

Initially had some trouble with SSHFS due to custom security configurations of the 'Dockerhub' provided Ubuntu 14.04 image.  Essentially my SSH connections were being closed by the server as soon as authentication was completed.  I speculated a PAM configuration, but didnt want to dig through all the undocumented changes.  So, I performed a fresh install of Ubuntu 14.04 Server edition (~900MB) on a VM and exported the file system as a gzipped tarball, excluding /sys and /proc.  I then imported the file system in to a new docker container.

FROM champion:ubuntu-base #custom ubuntu 14.04 image

RUN apt-get update

RUN apt-get install -y ltsp-server
RUN ltsp-build-client --arch="amd64" --fat-client
RUN ltsp-config lts.conf

Mannually Update lts.conf:
Port 22 would likely conflict with the docker host's SSH port. So manually add 'SSH_OVERRIDE_PORT=2222' below the [Default] tag inside /var/lib/tftpdboot/ltsp/amd64/lts.conf.  Also add 'SERVER=' so that the client hits the docker host w/ mapped ports, since it can't see the container's resolved host that is used by default.  The value should be the IP of your Docker container's host.

Run Command:
$ docker run -h ltsp -it -p 2222:22 -p 10809:10809 -p 69:69/udp -v /data/ltsp-home/:/home/ -v /data/ltsp-opt/:/opt/ --privileged=true cott:ltsp /bin/bash

-h Sets the hostname to 'ltsp', although this does not really matter, it helps to know what container your attached to.
-p Maps specific ports. (Uppercase P will use the docker range, check docker run usage)
-v The first mount point specified is the docker host path, the second mount point (after the colon) is the mount point inside the container.
--privileged=true Gives the container permissions to access kernel parameters and other information from /proc, this is definitely needed when you build the LTSP fat client.  I left it on during run time as well, but may not be needed.

Once the container has started and you're at the bash prompt, here you just needed to fire up the daemons:

$ service ssh start
$ service tftpd-hpa start
$ service nbd-server start

Press Ctrl+P, Q to drop from the container's bash prompt w/o killing the container's root bash process.  Ultimately you would want these service calls in a custom bash script with the 'wait' command at the end, and specify it in your Dockerfile as the default command.  But for sanity's sake, above it is a manual process to get the gist of what needs to happen.

[user@docker01 ~]$ docker ps -a
CONTAINER ID        IMAGE                                      COMMAND                CREATED             STATUS              PORTS                                                                                                NAMES
2c09964e1882        champion:ltsp                                  /bin/bash              2 hours ago         Up 2 hours>69/udp,>22/tcp,>10809/tcp                                   ltsp_server

LTSP Client Login Screen

Ultimately the configuration needs to be adjusted so that the fat/thin client connects to the docker container's host, with ALL LTSP required ports (69, 10809, 22) mapped to the container using the -p options with the docker 'run' command, and modifications to the client's tftpd provided ltsp configuration (/var/lib/tftpboot/ltsp/amd64/lts.conf) to support the changed SSHFS port, which is modified to 2222 in this post.


  1. Hello,

    We followed the tutorial but can't make the login. You know why?

    1. What is happening when you log in? Does the screen just flash and go back to the login prompt? Usually this is a sign of problems with SSHFS, I would ensure you can just 'ssh' to the ltsp server with the account before attempting to log in your first thick/thin client.

  2. This comment has been removed by the author.

  3. Hello, I try to install ltsp in docker but impossible this one creates an
    W: Failure trying to run: chroot /opt/ltsp/amd64 mount -t proc proc
    W: See /opt/ltsp/amd64/debootstrap/debootstrap.log for details error:
    LTSP client installation ended abnormally The command '/bin/sh -c
    ltsp-build-client' returned a non-zero code: 1
    Do you have a solution? Or a functional dockerfile?


    1. that chroot commands i believe comes from `ltsp-build-client --arch="amd64" --fat-client` which is maintained by the guys over at #ltsp on IRC.

      If I remember correctly, this has something to do with /proc and /sys needing mounted to build the client filesystem image. Docker has had many changes since I worked on this. I recall that docker used to just pass the /proc /sys paths straight through to the host, but I'm not sure what has changed in regard to security, etc.

      Maybe try running a docker container privileged,

      Good luck! sorry i can't be of more help