/lxc-haskell-env

A mirror of https://gitlab.com/mdimjasevic/lxc-haskell-env

Introduction

These instructions are for setting up a privileged LXC container with a Haskell development environment. The container runs Debian GNU/Linux 10 (code-named Buster). One can connect to the container via SSH and VNC. When connected via VNC, the clipboard is shared between the container and the host machine thanks to the autocutsel tool.

Prerequisites

LXC (Linux Containers) is a virtualization method specific to operating systems based on the Linux kernel. Therefore, you need to have a Linux-based operating system to follow these instructions. Furthermore, the instructions are written for the GNU/Linux Debian Buster operating system, though they should be applicable to other GNU/Linux distributions (possibly with minor modifications).

Instructions

These are instructions for LXC 3.0.3 in Debian GNU/Linux Buster. Follow the steps tagged “(LVM)” only if you use Logical Volume Management (LVM), in which case you should skip steps tagged (DIR).

  1. Choose a name for the LXC container. In this running example buster-2 will be used:
    export CNAME=buster-2
        
  2. Create a list of Debian packages to install. The list is stored in an environment variable:
    export PKGS=sudo,emacs,xfonts-base,tightvncserver,xfce4,xfce4-goodies,xfce4-pulseaudio-plugin,pavucontrol,x11-xserver-utils,dbus-x11,haskell-platform,haskell-stack,elpa-haskell-mode,elpa-smex,firefox-esr,xserver-xorg-core,curl,autocutsel,git,unar,rsync,bzip2,wget,hlint
        
  3. (LVM) Choose an LVM volume group (set to the group you have on your host machine):
    export VGNAME=howard-vg
        
  4. (LVM) Choose an LVM volume:
    export LVNAME=$CNAME
        
  5. (LVM) Choose the size of the container’s root file system:
    export FSSIZE=50G
        
  6. (LVM) To create a privileged container named “buster-2” with several things installed, where the root file system is stored in an LVM volume:
    sudo lxc-create --name $CNAME --bdev lvm --lvname $LVNAME --vgname $VGNAME --fssize $FSSIZE --template debian -- --release buster --package $PKGS
        
  7. (DIR) To create a privileged container with several things installed, where the root file system is stored in a directory:
    sudo lxc-create --name $CNAME --template debian -- --release buster --package $PKGS
        
  8. Start the container:
    sudo lxc-start --name $CNAME
        
  9. Set a password for the root user:
    sudo lxc-attach --name $CNAME passwd
        
  10. Install the packages given bz the PKGS variable:
    sudo lxc-attach --name $CNAME -- apt install $(echo $PKGS | tr "," " ")
        
  11. Add a user dev to the container:
    sudo lxc-attach --name $CNAME -- useradd -m -s /bin/bash dev
        
  12. Set the password for the dev user:
    sudo lxc-attach --name $CNAME -- passwd dev
        
  13. Add dev to the sudo group for the root privileges:
    sudo lxc-attach --name $CNAME -- usermod -a -G sudo dev
        
  14. (Something here is missing about TTY; it is resolved by adding the dev user via visudo).
  15. Copy the public SSH key of your user on the host machine to the dev user in the container:
    ssh-copy-id -i ~/.ssh/id_rsa.pub dev@192.168.122.195
        
  16. Start the VNC server as the dev user:
    sudo lxc-attach --name $CNAME -- su - dev -c vncserver
        

    This will ask for a password so create one.

  17. Kill the VNC server:
    sudo lxc-attach --name $CNAME -- su - dev -c "vncserver -kill :1"
        
  18. Put the following in ~/.vnc/xstartup in the container:
    	#!/bin/bash
    	xrdb $HOME/.Xresources
    	autocutsel -fork
    	startxfce4 &
        
  19. Create a systemd service in /etc/systemd/system/vncserver@1.service in the container:
    	[Unit]
    	Description=Remote desktop service (VNC)
    	After=syslog.target network.target
    
    	[Service]
    	Type=forking
    	User=dev
    
    	# Clean any existing files in /tmp/.X11-unix environment
    	ExecStartPre=/bin/bash -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
    	ExecStart=/usr/bin/vncserver -geometry 2320x1305
    	ExecStop=/usr/bin/vncserver -kill %i
    
    	[Install]
    	WantedBy=multi-user.target
        
  20. Reload a service daemon, enable the service and start it:
    sudo systemctl daemon-reload
    sudo systemctl enable vncserver@1.service
    sudo systemctl start vncserver@1.service
        
  21. Install a VNC viewer on the host machine. I recommend Remmina, though others will work. GNOME’s Remote Desktop Viewer captures certain keystrokes such as Ctrl+W, which means they cannot be used in the VNC session; this is why I decided to go with another VNC viewer, namely Remmina.
    sudo apt-get install remmina remmina-plugin-vnc
        
  22. Start a VNC viewer on the host machine. Provide the container’s IP address and a port (the port is typically 5901).

Installing Nix (an unfinished section)

One might want to install the Nix package manager because a number of Haskell projects use it as a build system. Unfortunately, there is no official Debian binary package for Nix. Therefore, we will build the package ourselves from an unofficial Debian source package. To install the Nix package manager in the LXC container:

  1. Install git-buildpackage on the host:
    sudo apt-get install git-buildpackage
        
  2. Create a Debian GNU/Linux Buster image that will be used for building the package for Nix:
    DIST=buster git-pbuilder create
        
  3. Get the unofficial Debian source package from a Git repository:
    git clone https://github.com/KaiHa/nix-debian.git
    cd nix-debian
        
  4. Build a Debian binary package for Nix:
    gbp buildpackage --git-pbuilder --git-dist=buster
        
  5. Find two Debian packages in ../nix.deb-export/. My host machine is the amd64 architecture, so for Nix 2.2.1 the packages are nix_2.2.1-1_amd64.deb and nix-dbgsym_2.2.1-1_amd64.deb.
  6. Copy the nix_2.2.1-1_amd64.deb package to the LXC container:
    rsync -a --progress *deb dev@192.168.122.142:/tmp/
        
  7. In the LXC container install dependencies for the binary package for Nix:
    sudo lxc-attach --name $CNAME -- su - dev -c "sudo apt-get install -y libdbd-sqlite3-perl libwww-curl-perl libboost-context1.67.0 libbrotli1 libreadline7 libsodium23 perl-dbdabi-94 readline-common"
        
  8. Finally install the nix_2.2.1-1_amd64.deb package:
    sudo lxc-attach --name $CNAME -- su - dev -c "sudo dpkg -i /tmp/nix_2.2.1-1_amd64.deb"
        
  9. Add the following to /etc/nix/nix.conf in the container (create the file if it does not exist):
    build-use-sandbox = false
        
  10. To have nixpkgs working properly, run the following in the container:
    nix-channel --add https://nixos.org/channels/nixpkgs-unstable
    nix-channel --update
        
  11. Stop the container. On the host machine add the following line to /etc/sysctl.d/80-lxc-userns.conf (create the file if it does not exist):
    kernel.unprivileged_userns_clone=1
        
  12. Restart sysctl on the host:
    sudo sysctl --system
        
  13. Start the LXC container:
    sudo lxc-start --name $CNAME
        

To be done

See semi-official Debian source package for Nix

Create LXC containers with a disk stored in LVM

  • The default is a 20 GB root partition /, which can be too little, especially when Nix is used. When creating a container with lxc-create, there is an option --bdev that can take “lvm” as a value and further arguments can be provided, as explained in the man pages of lxc-create.
    • [2019-08-28 wed]: I am not completely sure, but it might be the case that I have to create LVM logical volumes via a live boot from USB. When booted regularly from the disk, I attempted to run sudo lvcreate -L 50G -n buster-2 howard-vg, but I get this:
      Insufficient free space: 12800 extents needed, but only 0 available
              

      yet there is 173 GB of free space in the volume group according to the output of sudo vgdisplay.

      • On [2019-10-23 sri] I confirmed this is really the case: I had to boot a live USB to create a new logical volume.

Share the camera, microphone and speaker devices with the container

Set up xmonad

Decrease the display lag

  • Maybe there is something to configure in /etc/X11 as generated by the gtf tool from the xserver-xorg-core package with ModeLine and a dummy driver.

Copyright

To the extent possible under law, Marko Dimjašević has waived all copyright and related or neighboring rights to this project (CC0).