Running Steam in a LXC container

Anyone who met me probably knows that I like to run everything in containers.

A couple of weeks ago, I was attending the Ubuntu Developer Summit in Copenhagen, DK where I demoed how to run OpenGL code from within an LXC container. At that same UDS, all attendees also received a beta key for Steam on Linux.

Yesterday I finally received said key by e-mail and I’ve been experimenting with Steam a bit. Now, my laptop is running the development version of Ubuntu 13.04 and only has 64bit binaries. Steam is 32bit-only and Valve recommends running it on Ubuntu 12.04 LTS.

So I just spent a couple of hours writing a tool called steam-lxc which uses LXC’s new python API and a bunch more python magic to generate an Ubuntu 12.04 LTS 32bit container, install everything that’s needed to run Steam, then install Steam itself and configures some tricks to get direct GPU access and access to pulseaudio for sound.

All in all, it only takes 3 minutes for the script to setup everything I need to run Steam and then start it.

Here’s a (pretty boring) screencast of the script in action:

This script has only been tested with Intel hardware on Ubuntu 13.04 64bit at this point, but the PPA contains builds for Ubuntu 12.04 and Ubuntu 12.10 too.

To get it on your machine just do:

  • sudo apt-add-repository ppa:ubuntu-lxc/stable
  • sudo apt-get update
  • sudo apt-get install steam-lxc
  • sudo mkdir -p /var/lib/lxc /var/cache/lxc

Then once that’s all installed, set it up with sudo steam-lxc create. This can take somewhere from 5 minutes to an hour depending on your internet connection.

And once the environment is all setup, you can start steam with sudo steam-lxc run.

The code can be found at: https://code.launchpad.net/~ubuntu-lxc/lxc/steam-lxc

You can leave your feedback as comment here and if you want to improve the script, merge proposals are more than welcome.
I don’t have any hardware requiring proprietary drivers but I’d expect steam to fail on such hardware as the drivers won’t get properly installed in the container. Adding code to deal with those is pretty easy and I’d love to get some patches for that!

Have fun!

This entry was posted in Canonical voices, Conferences, LXC, Planet Ubuntu and tagged . Bookmark the permalink.

34 Responses to Running Steam in a LXC container

  1. Since this was the first container I created on this system I got “lxc_container: No such file or directory – failed to create container path for elizabeth-steam” and had to: sudo mkdir /var/lib/lxc

    Started up fine I got that done :)

    • Hmm, I really need to track that bug down, /var/lib/lxc and /var/cache/lxc are supposed to be shipped or created by the lxc package…
      I’ll add a mention to the post so that people check that those two exist before running steam-lxc.

      • Neither existed on my system when I ran “create” for the first time, but he cache directory appears to have been created fine eventually, it just failed when /var/lib/lxc wasn’t there.

  2. siretart says:

    12.04.1 fails with:

    sudo steam-lxc run
    Container failed to start.
    25
    Failed to get the container’s ip.

    Do you accept launchpad bugreports, and if yes, where?

    • Hmm, that’s very odd that create succeeded but run didn’t… I assume you tried running that command again?

      If I remember the code well, the code is assuming the container will start within 30s and will then get an IP within the next 30s. That error message indicates that the container wasn’t in state “running” within 30s of the start call being made.

      Can you pastebin /var/log/lxccontainer.log ? that should contain enough information for me to figure out what went wrong in your case and whether it’s a bug in steam-lxc or in lxc itself.

  3. Drake says:

    I’m having the same problem as siretart. Here is the lxccontainer.log http://pastebin.com/nEEJamnQ. Also after I run the ‘steam-lxc run’ command I have three steam-lxc processes still running.

  4. Logan B says:

    When I attempt to create the containter (under Debian Wheezy) I get:

    Failed to create the container
    lxc_container: cgroup is not mounted
    Traceback (most recent call last):
    File “./steam-lxc”, line 337, in
    main()
    File “./steam-lxc”, line 334, in main
    sys.exit(getattr(steam, args.func)() is False)
    File “./steam-lxc”, line 110, in create
    mount_hook = “%s/pre-mount.sh” % “/”.join(rootfs.split(“/”)[:-1])
    AttributeError: ‘bool’ object has no attribute ‘split’

    I compiled lxc from your git repo, so I’m not sure what’s causing it.

    • That’s because you don’t have the cgroup filesystem mounted.
      On Ubuntu, you’d use cgroup-lite to setup that, on Debian, I think the easiest is to mount the cgroup filesystem on /cgroup (mount -t cgroup none /cgroup).

  5. Axel Groll says:

    Dear Stéphane,

    I’m an Linux noob (moved over from Win7 to Kubuntu 12.10 just a few day ago).
    Now I’d like to run my old win apps/games securely seperated with wine inside of an akrose container. Just for test, I used akrose supertuxkart.
    It actually run, but without sound and joystick support.

    Since I’ve seen you mentioning Steam inside Arkose with sound, I figured there might be a solution here.

    Tanks in Advance and a happy 2013, =)
    Axel

    • Axel Groll says:

      Hi Stéphane,

      to make myself a bit clearer:

      I’d like to run linux (or wine) games inside a Arkose ‘sandbox’ with sound and gamepad/joystick support.

      The game (e.g Supertuxkart) itself runs, but (unfortnately) without sound and no gamepad access.

      How do I solve this?

      Thanks for your help!
      Axel

      • Sound should work fine as long as it’s using pulseaudio, otherwise you may need to add some devices to the whitelist.
        Same thing for the gamepad, I guess it’s a separate device and it’s not allowed by arkose by default, passing a –device /dev/… option to the command line should do the trick (assuming you’re using the arkose command line).

        • Axel Groll says:

          Dear Stéphane,

          I switched from alsa to pulseaudio, which works pretty well with e.g. Supertuxkart and wine. ;)

          I then started to test –device /etc/input/js0 . That didn’t work at all.
          user1@arkose-tmp6zMw_o:~$ cd /dev
          user1@arkose-tmp6zMw_o:/dev$ ls
          agpgart audio3 dsp fd kmsg loop3 loop7 midi00 midi1 mixer1 mpu401stat ptmx ram1 ram13 ram2 ram6 random rmidi3 smpte1 stderr tty0 tty4 tty8
          audio audioctl dsp1 full loop0 loop4 mapper midi01 midi2 mixer2 mqueue pts ram10 ram14 ram3 ram7 rmidi0 sequencer smpte2 stdin tty1 tty5 tty9
          audio1 console dsp2 fuse loop1 loop5 mem midi02 midi3 mixer3 null ram ram11 ram15 ram4 ram8 rmidi1 shm smpte3 stdout tty2 tty6 urandom
          audio2 core dsp3 kmem loop2 loop6 midi0 midi03 mixer mpu401data port ram0 ram12 ram16 ram5 ram9 rmidi2 smpte0 sndstat tty tty3 tty7 zero
          user1@arkose-tmp6zMw_o:/dev$ cd /dev/input
          bash: cd: /dev/input: File or directory not found

          -> no joystick devices, not even an according /dev/input dir.

          Then I to update Arkose, but to no avail. There’s no repository for Ubuntu 12.10 yet, right?

          Thanks again, Stéphane for making desktop containg easy to use ;)
          Axel

  6. nick says:

    Running ubuntu 12.10 this failed for me with error:

    Container failed to start.
    Failed to get the container’s ip.

    Here is a copy of lxccontainer.log
    http://pastebin.com/XJPzEiMq

    Could you offer some advice?

    I have a few additional questions. Can this be used or modified to allow for multiple installs / instances of steam? And closely related to this question, can we use / specify alternative directories other than /var/lib/lxc and /var/cache/lxc?

    On my host system, I run the nvidia proprietary drivers, which your post suggests will fail to install. Is there any way to remedy this? I plan to run TF2 in addition to a few other games, and I believe that Tf2 requires the nvidia driver.

    Any advice you can offer is greatly appreciated!

    Best
    Nick

  7. Jim says:

    Hi,
    everything is fine except the audio.

    When launching, I got a:
    17:10:32,358 SteamLXC WARNING b’Home directory /home/jim not ours.’

    which then leads to a:
    17:25:27,268 SteamLXC DEBUG b’AL lib: pulseaudio.c:612: Context did not connect: Access denied’

    Thank you very much

  8. Marco says:

    Hi,
    I have the same problem (no audio when running steam games):

    sudo steam-lxc run
    [sudo] password for marco:
    Home directory /home/marco not ours.
    Connection failure: Connection refused
    pa_context_connect() failed: Connection refused
    Warning: Permanently added ‘x.x.x.x’ (ECDSA) to the list of known hosts.
    Setting up Steam content in /home/marco/.local/share/Steam

    Thank you !

  9. Hawk says:

    Would it be possible to run Steam/TF2 specifically inside of Arkose instead of an lxc container? The furthest I’ve gotten is attempting to run TF2 and running into this error: “NVIDIA: could not open the device file /dev/nvidia0 (No such file or directory).” My needs require something a bit more simple than a full lxc container.

  10. Antonio says:

    I have been trying to run arkose in bodhi, based in ubuntu 12.04, but I get the errors:
    lxc-execute: No such file or directory – failed to mount a new instance of ‘/dev/pts’
    lxc-execute: failed to setup the new pts instance
    lxc-execute: failed to setup the container
    lxc-execute: invalid sequence number 1. expected 2
    lxc-execute: failed to spawn ‘arkose-tmphjrwI0′
    Are there any hope?
    Thanks

  11. peter says:

    Hi,

    running
    sudo steam-lxc create
    on kubuntu 13.10 with kernel 3.12 I’ve encountered:
    ontainer successfuly created
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess
    lxc_container: failed to clone(0x8000): Invalid argument
    lxc_container: Invalid argument – failed to create subprocess

    Looks like problem is in run_command(self, command, env={}, root=False) method, with starting commands in container using
    self.container.attach_wait(
    lxc.attach_run_command, command,
    extra_env_vars=env)

    What should be correct version for this configuration?
    Thank you.
    Regards.
    Peter

  12. ACuriousFellow says:

    Hey Stephane, thanks for the great guide. I’ve actually got everything working with LXC + Steam, including passthrough of an nvidia card.

    The one thing I can’t seem to get working is getting Steam to identify an xboxdrv backed controller. I’ve created device nodes in the container for /dev/input, /dev/bus/usb, /dev/uinput and have even tried bind-mounting /dev and /sys, but haven’t had any luck.

    The controller works in the container otherwise, wine sees it just fine (evtest works and wine control joy.cpl works as well), it just looks like Steam does it’s own thing in this regard.

    Any thoughts? I don’t think I’ll have any luck getting any help anywhere else but here. :)

  13. Alvin says:

    I got some wacko stuff..it is because I already had a steam linux setup?

    sudo steam-lxc create
    Creating configuration directory
    Traceback (most recent call last):
    File “/usr/bin/steam-lxc”, line 335, in
    main()
    File “/usr/bin/steam-lxc”, line 332, in main
    getattr(steam, args.func)()
    File “/usr/bin/steam-lxc”, line 85, in create
    {“release”: “precise”, “arch”: “i386″}):
    File “/usr/lib/python3/dist-packages/lxc/__init__.py”, line 225, in create
    flags=flags, args=tuple(template_args))
    TypeError: an integer is required

    Linux Mint 16 Petra
    HP Pavillion a1310n
    hdml video card

  14. This would have been really awesome, but unfortunately I get a stacktrace.

    fmohr@fmohr-X240:~/Downloads $ sudo python3.4 steam-lxc create
    Traceback (most recent call last):
    File “steam-lxc”, line 334, in
    main()
    File “steam-lxc”, line 331, in main
    getattr(steam, args.func)()
    File “steam-lxc”, line 84, in create
    {“release”: “precise”, “arch”: “i386″}):
    File “/usr/lib/python3/dist-packages/lxc/__init__.py”, line 228, in create
    args=tuple(template_args))
    TypeError: an integer is required (got type dict)

    Anyway, thanks for the script! Maybe someone will find the time to fix this (mayyybe even me – who knows)

  15. panzi says:

    Does the same exist for Fedora/yum based Linux distributions?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>