Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

You'll have to forgive me, as I'm relatively new at doing something like this, but I need to do the following and I know that it has and can be done.

Basically, a few friends and me are assembling some lightweight machines with the express purpose of displaying a single web page over a large screen. I need the machine to essentially boot up as lightweight and as quickly as possible and essentially have it run a browser (WebKit?) in full screen, loading one page which will be controlled dynamically by JavaScript. I'll be using an Intel D525 dual-core processor with integrated GPU, so I shouldn't need to set up any proprietary graphics drivers. Once I get one of these machines set up properly, I should just be able to dd the hard drive onto my computer and then dump it onto each new machine.

As I've never done this before (but have used Linux for quite some time now), I have the following questions:

  1. How can I create a "distribution" which includes only what I need? I suppose I'll need the kernel (;]), X, and a web browser of some sort, but not really too much else. Could I take something like Ubuntu Server and simply install X Server and find a way to have the machine automatically log in, start X, and start the web browser, no questions asked? Is there a book I can read or an article or something?

  2. What can I use for a nice, stripped-down web browser that essentially runs a "chromeless Chromium?" These machines won't be accepting user input at all. If I need to manage them, I'll use SSH.

share|improve this question
add comment

8 Answers 8

up vote 10 down vote accepted

Many distributions have some facility for a minimal install; essentially where you manually select only those packages that you explicitly wish to install. Debian has this ability and would be a better choice, in your situation, than the other obvious minimal contender, Arch Linux.

Arch's rolling release status may provide a level of ongoing complexity that you wish to eschew. Debian would provide the simple, minimal base you are looking for plus offer stability. There is a blog post on using Debian as a kiosk that may offer some helpful tips.

For a browser, as beav_35 suggests, Uzbl is a good choice. My recommendation would be Vimprobable, a WebKit browser that is scriptable, keyboard driven and can be controlled effectively over SSH.

As a window manager, I would recommend dwm: at less than 2000 SLOC, it is extremely lightweight and can be easily configured for a kiosk-type setup.

share|improve this answer
    
dwm looks great for this purpose, and I'm much more familiar with Debian-based systems anyway, so I'll probably use Debian. How small do you think I can get the OS down to? And how can I build a Debian distribution? –  Naftuli Tzvi Kay Aug 1 '11 at 17:56
    
As you proceed through the installation, when you reach the select packages step, instead of Laptop, Standard, etc, choose "Manual" and only select those packages (like X) you need for a bare minimium: start here debian.org/CD/netinst/#businesscard-stable –  jasonwryan Aug 1 '11 at 18:29
add comment

First of all, you might not want to reinvent the wheel... There are several kiosk-focused distributions. One of those might save you a lot of work.

Second, if you are familiar with Kickstart on Fedora and RHEL(or CentOS or Scientific Linux), you can use the Fedora tools to make your own spin of any of those distributions. The documentation is a bit scattered, but start here.

share|improve this answer
    
Debian/Ubuntu equivalent: FAI (Fully Automatic Installation) –  Gilles Aug 1 '11 at 21:44
add comment

Start with a minimal distro such as Arch Linux, then install the packages you need. For a simple web browser try Uzbl.

share|improve this answer
    
uzbl is awesome. +1 –  Naftuli Tzvi Kay Aug 1 '11 at 17:39
add comment

This is a pretty involved question, and since your project isn't entirely clear some of these suggestions may be off-mark, but consider them things to evaluate.

  • You may not need a web browser on ever computer that is part of the display array. If you are trying to show one single page across many screens, chances are you are going to want to use some kind of mass display technology. There are several variants of Xorg that specialize in generating one large display out of video devices on several machines.

  • Even if you use separate X servers on each machine, you can use X-forwarding to send display data from one or more other computers, so the browsers still wouldn't have to run locally.

  • You will want to either use no window manager at all and use geometry specifications to launch your app full screen, or use a configurable tile or framework window manager (such as awesome) to manage the windows on each X display. These make it easy to sort and control full screen windows and are highly scriptable.

  • As for a browser, I think uzbl is likely the clear choice.

  • This might be a good application for network booting. You can setup server with a netbook kernel available via TFTP and a file system available via nfs. All your clients need to do is use a netboot capable NIC to contact this server, download their kernel and go. No hard drive involved! And easy maintenance. All the machines can potentially boot the same image.

  • Your "distro" should probably consist of two things. 1) A package set and 2) a set of configuration files. The package set is a list of packages that need to be installed. This can usually be assembled in a text file and then you can use most distro's package managers to install this list of packages to a target (either a hard drive or a directory that will be your nfs mount point). The configuration files should probably be kept in git or another source control system and contain a few scripts and whatever config mods need to be made to the base system installed with the package set. Building a new system then becomes:

    • Mount drive or target directory
    • package_manager --install-distro --package-set=/path/packagelist.txt --target=/path
    • cd /target/path
    • git clone /path/to/repo (or otherwise checkout your config code to the system root)
    • Install bootloader if drive or add PXE config if netboot
    • boot.

What distro you use as a base should depend on what you are most comfortable with. I would use PLD-Linux for myself, but probably recommend ArchLinux as a similar but better documented system for a newbie to work with. There is no reason Debian, Fedora, or Gentoo would not work for this.

share|improve this answer
    
on net booting: that sounds AWESOME and would make things so much easier to maintain. However, each machine needs to load a different URL, as they'll be fetching information unique to the machine. Is that doable? Everything else would ostensibly stay the same, though I might configure each machine to use a different user/password for HTTP-Basic authentication as a little means of security. –  Naftuli Tzvi Kay Aug 1 '11 at 18:02
    
on "You may not need a web browser on every computer that is part of the display array": I think I will, actually. Each one of these machines will be in a different location, driving one display over VGA or HDMI, displaying a unique webpage for that machine. (although we could serve a single URL which varies content on user/password). –  Naftuli Tzvi Kay Aug 1 '11 at 18:07
    
on window managers: I'd probably just use a really lightweight one like dwm or awesome. How can I tell a window manager to start an application without the title-bar in full screen mode? –  Naftuli Tzvi Kay Aug 1 '11 at 18:08
    
on what distro should consist of: so all I'd really need is to create a git repo, keep a package list and configuration files, and then create an ISO somehow. How do I get the tiniest Debian distro and then work up from there? How do I take these config files and make a burnable ISO? I'd be using apt-get or aptitude on Debian. –  Naftuli Tzvi Kay Aug 1 '11 at 18:11
    
on X-forwarding: it shouldn't really be necessary, as I'll be driving one display per machine. I'll probably have to find a way to have the machine issue a reverse SSH connection so my computer would be able to connect to it, but there might be a way to automate this. Is there a way to have a computer A open a TCP connection to computer B and then have computer B connect over that connection to computer A via SSH? Otherwise, I'd have to get dynamic DNS names for each router: not fun/easy. –  Naftuli Tzvi Kay Aug 1 '11 at 18:14
show 5 more comments

For a system like this I'd recommend Puppy.

While you can build you distro using any version of Linux, Puppy makes it very easy to build custom bootable images, is designed to be compact and has great overlay file system support.

I should just be able to dd the hard drive

No - I'd recommand building a bootable image which you can sensibly maintain - the approach you suggest will come back and bite you.

share|improve this answer
    
The thing is, I'll be running the operating system on a thumb drive. I won't even potentially have a disk drive with which to install the OS. –  Naftuli Tzvi Kay Aug 1 '11 at 18:35
add comment
  • Several people mentioned uzbl and I agree it is a nice choice - but you might find luakit even better.

  • As Caleb already mentioned, you do not really need any window manager. Here's an example script that I crafted to run a WM-less Xorg server with maximized luakit browser:

    #!/bin/sh
    XDCMD="xdotool search --class luakit windowsize %3 100% 100%"
    while [ 1 ]
    do
        ( sleep 0.5; $XDCMD || sleep 0.2 && $XDCMD || sleep 5 && $XDCMD ) &
        /usr/bin/luakit $@
    done
    

    It uses the xdotool to maximize the window just after luakit has started. Maybe there is a better solution to that though...

  • For the base of such system, I'd definitely recommend Gentoo. That's not only because I know it best ;) but also because it uses a rather unique approach of globally managing the build-time options of all the installed software. I mean the USE flags. Using those, you determine the set of features/libraries/standards that are used by all programs that support them - so, for instance, if you want your programs to use ALSA and not need additional audio backends like esd, jack or pulseaudio, you put alsa -jack -esd -pulseaudio amongst your USE flags. After that, each piece of software you build that can use additional audio backends apart from ALSA will be built without the support for those. Since this happens at configuration/build level, you end up with significantly thiner software. So this is a philosophy of building up (while respecting all the dependencies) instead of stripping down (which can end up being buggy and very hard to maintain).

share|improve this answer
add comment

I'll mention this because I'm surprised no one else has.

Linux from Scratch is a book (pdf) that walks you through the creation of your own Linux distribution. It might be overkill for what you're trying to accomplish (actually, it is seeing as you already have the tools you need), but it can prove to be an invaluable tool in understanding how a system works. It's really not that hard and there's no programming involved.

share|improve this answer
add comment

I have written a little bash script once that takes an Arch Linux ISO and generates a new ISO with a modified root image which does a fully automated install. This includes partitioning as well as setting up and configuring the system with Xorg, FVWM, and Chromium. The installed system will login automatically and start Chromium. Just put the new ISO on a USB flash drive and lean back. ;-)

Disclaimer: the script is provided as-is, no warranty given. I haven’t used it in a while, so it might need a tweak here or there. Modify as needed.

#!/bin/bash
# Helpful pages:
#
#   * [ArchWiki topic][1] that explains the options of an AIF configuration
#     file.
#
#   * [Status of automated installation][2], a topic in the Arch Linux Forums
#     that contains the original basic install script by *mhertz*.
#
# [1]: https://wiki.archlinux.org/index.php/AIF_Configuration_File
# [2]: https://bbs.archlinux.org/viewtopic.php?id=111925

TMP_DIR=/tmp/arch-install

# Read command line parameters for input and output ISO files.
if [ -z "$1" ]; then
    echo 'No input file specified, aborting.'
    exit 1
elif [ ! -f "$1" ]; then
    echo 'Input file "'$INPUT_ISO'" not found, aborting.'
    exit 1
elif [ -z "$2" ]; then
    echo 'No output file specified, aborting.'
    exit 1
elif [ -f "$2" ]; then
    echo 'Output file "'$OUTPUT_ISO'" already exists, aborting.'
    exit 1
fi

# Determine full paths to input and output ISO files.
INPUT_ISO=$(readlink -f "$1")
OUTPUT_ISO=$(readlink -f "$2")

# Set some variables for convenience.
SOURCE_DIR=$TMP_DIR/source
DEST_DIR=$TMP_DIR/dest
ROOT_DIR=$TMP_DIR/squashfs-root
BOOT_CFG=$DEST_DIR/boot/isolinux/isolinux.cfg

# Extract ISO image and root image.
mkdir -p $SOURCE_DIR
mount -o loop "$INPUT_ISO" $SOURCE_DIR
cp -a $SOURCE_DIR $DEST_DIR
umount $SOURCE_DIR
rmdir $SOURCE_DIR
unsquashfs -d $ROOT_DIR $DEST_DIR/root-image.sqfs
rm $DEST_DIR/root-image.sqfs

# Modify the root image as needed.
cat >> $ROOT_DIR/etc/aif.conf <<EOF
SOURCE=cd
FILE_URL=file:///src/core/pkg
SYNC_URL=http://ftp.tu-chemnitz.de/pub/linux/archlinux/\$repo/os/\$arch
HARDWARECLOCK=UpTC
TIMEZONE=Europe/Vienna
RUNTIME_REPOSITORIES=
RUNTIME_PACKAGES=
TARGET_GROUPS=base
TARGET_PACKAGES_EXCLUDE=
TARGET_PACKAGES='openssh xorg xcursor-vanilla-dmz-aa'

worker_runtime_network () {
    dhcpcd eth0
}

worker_configure_system () {
    prefill_configs
    sed -i '/^HOSTNAME/ s/"myhost"/"arch"/' \$var_TARGET_DIR/etc/rc.conf
    sed -i '/^password/ s/pam_permit\.so/pam_unix.so md5 shadow/' \$var_TARGET_DIR/etc/pam.d/chpasswd
    sed -i '\|Server = http://ftp\.tu-chemnitz\.de/| s/^#//' \$var_TARGET_DIR/etc/pacman.d/mirrorlist
    sed -i '/id:3:initdefault:/ s/^/#/' \$var_TARGET_DIR/etc/inittab
    sed -i '/id:5:initdefault:/ s/^#//' \$var_TARGET_DIR/etc/inittab
    sed -i '\|x:5:respawn:/usr/bin/xdm| s/^/#/' \$var_TARGET_DIR/etc/inittab
    echo "x:5:respawn:/bin/su -l -c '/usr/bin/startx </dev/null >/dev/null 2>&1' myuser" >> \$var_TARGET_DIR/etc/inittab
    sed -i 's/^timeout .*$/timeout 0/' \$var_TARGET_DIR/boot/grub/menu.lst
    cp /etc/rc.local.firstboot \$var_TARGET_DIR/etc/rc.local
}

# Mandatory variables.
GRUB_DEVICE=/dev/sda
PARTITIONS='/dev/sda 20:ext2:+ 512:swap 2500:xfs *:xfs'
BLOCKDATA='/dev/sda1 raw no_label ext2;yes;/boot;target;no_opts;no_label;no_params
/dev/sda2 raw no_label swap;yes;no_mountpoint;target;no_opts;no_label;no_params
/dev/sda3 raw no_label xfs;yes;/;target;no_opts;no_label;no_params
/dev/sda4 raw no_label xfs;yes;/home;target;no_opts;no_label;no_params'
EOF

cat >> $ROOT_DIR/etc/rc.local <<EOF
aif -p automatic -c /etc/aif.conf
reboot
EOF

cat >> $ROOT_DIR/etc/rc.local.firstboot <<EOF
echo root:rootpassword | chpasswd
useradd -m myuser
echo myuser:myuser | chpasswd
cat >> /home/myuser/.xinitrc <<EOT
#!/bin/sh
exec fvwm2
EOT
cat >> /home/myuser/.Xdefaults <<EOT
Xcursor.theme: Vanilla-DMZ-AA
EOT
mkdir -p /home/myuser/.fvwm
cat >> /home/myuser/.fvwm/config <<EOT
DeskTopSize 1x1
DesktopName 0 Main
DestroyFunc StartFunction
AddToFunc StartFunction
 + I Test (Init) Exec exec xsetroot -solid '#303030'
 + I Test (Init) Exec exec chromium 'http://www.stackoverflow.com'
DestroyMenu RootMenu
AddToMenu RootMenu "Menu" Title
 + "Terminal" Exec exec xterm
 + "Browser" Exec exec chromium 'https://www.stackoverflow.com'
 + "" Nop
 + "Log off" Quit
 + "Reboot" Exec exec sudo /sbin/reboot
 + "Shutdown" Exec exec sudo /sbin/halt
OpaqueMoveSize unlimited
Style * ClickToFocus, ResizeOpaque
Style chromium !Title, !Border, !Handles
CursorStyle root top_left_arrow
CursorStyle stroke hand2
IgnoreModifiers L25
Key Help R A -
Key F1 R A -
Key Tab A M -
Key Escape A MC -
Mouse 1 R A -
Mouse 1 T A Move
Mouse 1 FS A Resize
Mouse 1 I A Iconify Off
Mouse 2 FST A -
Mouse 3 R A Menu RootMenu Nop
EOT
mkdir -p /home/myuser/.config/chromium/Default
touch /home/myuser/.config/chromium/First\ Run
cat >> /home/myuser/.config/chromium/Default/Preferences <<EOT
{
   "alternate_error_pages": {
      "enabled": false
   },
   "autofill": {
      "enabled": false
   },
   "browser": {
      "custom_chrome_frame": true,
      "enable_spellchecking": false
   },
   "default_search_provider": {
       "enabled": true,
       "encodings": "UTF-8",
       "icon_url": "about:blank",
       "id": "2",
       "instant_url": "",
       "keyword": "google.com",
       "name": "Google",
       "prepopulate_id": "1",
       "search_url": "{google:baseURL}search?ie={inputEncoding}&q={searchTerms}",
       "suggest_url": ""
   },
   "devtools": {
      "disabled": true
   },
   "dns_prefetching": {
      "enabled": false
   },
   "download": {
      "directory_upgrade": true
   },
   "extensions": {
      "chrome_url_overrides": {
         "bookmarks": [ "chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html" ]
      }
   },
   "geolocation": {
      "default_content_setting": 2
   },
   "google": {
      "services": {
         "username": ""
      }
   },
   "homepage": "https://www.stackoverflow.com",
   "homepage_is_newtabpage": false,
   "intl": {
      "accept_languages": "en",
      "charset_default": "ISO-8859-1"
   },
   "ntp": {
      "pref_version": 3
   },
   "profile": {
      "clear_site_data_on_exit": true,
      "content_settings": {
         "pref_version": 1
      },
      "default_content_settings": {
         "plugins": 1
      },
      "exited_cleanly": true,
      "notifications_default_content_setting": 2,
      "password_manager_enabled": false
   },
   "safebrowsing": {
      "enabled": false
   },
   "search": {
      "suggest_enabled": false
   },
   "tabs": {
      "use_vertical_tabs": false
   },
   "translate": {
      "enabled": false
   }
}
EOT
chown -R myuser:myuser /home/myuser
pacman -Sy
pacman -S --noconfirm pacman
pacman -S --noconfirm fvwm-devel chromium sudo
echo 'myuser arch=NOPASSWD: /sbin/halt,/sbin/reboot' > /etc/sudoers.d/start_stop
chmod 0440 /etc/sudoers.d/start_stop
rm /etc/rc.local
EOF

# Create the new root image.
mksquashfs $TMP_DIR/squashfs-root $TMP_DIR/dest/root-image.sqfs
rm -rf $TMP_DIR/squashfs-root

# Configure the boot loader.
sed -i 's/TIMEOUT 3000/TIMEOUT 100/' $BOOT_CFG
sed -i '/APPEND hd0 0/d' $BOOT_CFG
sed -i 's/archisolabel=[^ ]*/archisolabel=ARCH/' $BOOT_CFG

# Create the new ISO image.
genisoimage -l -R -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \
    -no-emul-boot -boot-load-size 4 -boot-info-table -V ARCH \
    -o "$OUTPUT_ISO" $DEST_DIR
rm -rf $TMP_DIR
isohybrid "$OUTPUT_ISO"
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.