I have never tried this, but since it seems you're still looking and haven't gotten an answer in almost a month, I'll tell you where I'd start.
This how-to is ancient, but the general outline seems sound. You don't have to do everything exactly the same. It does focus on using a web browser as the centerpiece but that is mostly irrelevant here (i.e., relax, it's not another "web-kiosk").
It refers to /etc/inittab
, which most linux distros don't use anymore, but it so happens that debian wheezy (raspbian) does. The idea is you are going to use runlevel 4 as the kiosk and make it the default. You can do that or just use whatever is currently the default (2 or 3, I think). The raspbian I have running right now has been modified by me, so I am not sure what the original differences were between the /etc/rc[N].d
directories -- which correspond to the 7 runlevels. You want to either use one that doesn't start the graphical login (lightdm
) or else to remove lightdm
from that runlevel. You might as well do that kind of thing the right way (see man update-rc.d
).
Then, following this part of the how-to, you want to create your own boot service (aka. init) script for starting X and your app without a login. Don't do it quite that way, however; you need to conform to debian, so see /etc/init.d/README
. Also, you don't have to use a window manager at all (although fvwm
is still great, methinks particularly for this kind of thing, so keep it in mind if you do), because an .xinitrc
like this:
#!/bin/sh
myApp
Will run just your app in plain X -- which is very very plain: no menus, no titlebars, no toolbars, etc, or a way for the user to start another application or get a shell. It just provides a cursor.
An issue with this is that if you go straight to a desktop from boot, that will be a superuser desktop. Actually, X instances always have a uid of 0, but the applications run from the xinitrc run as the user that started X -- in this case X was started by init, so the user will be root (although technically root is not logged in). Hence the above xinitrc would be better with:
su -c myApp pi
Which will run your app as the pi user instead (who is also technically not logged in).
Since technically no one is logged in, even if the kiosk user kills X (e.g. via ctrl-alt-delete
) they will just be left at a login prompt. The how-to goes beyond that such that the service init script starts X (see NOTE below) in the foreground so that when it exits, the service script continues and runs shutdown -r now
.
Remember that someone who has physical access to a (normal) machine can always circumvent whatever security you implement, so all you are really trying to do here is not make it too easy and to prevent nasty accidents.
Also remember that since your boot service will be doing this in the foreground, no other services will run after it, so make sure it is the absolute last one. Very important! You could, in fact, use /etc/rc.local
instead, since that is normally guaranteed to be last ;) That will save you some time.
NOTE: Actually in the how-to it's another script, /root/kiosk
, from this section. Notice that's just one line which references the .xinitrc
script shown in the section above (3.4). Just put a line like that in your boot script directly. Your (preliminary) xinitrc, as already described, will be much simpler.
An Alternative to Staying Foregrounded with init...
The purpose of leaving the X invocation foregrounded is just to block the execution of the init script until X exits, so that the next line in the script (shutdown
) will run:
startx
shutdown -r now
Here I've used startx
instead of the how-to's /usr/X11R6/bin/xinit /root/kiosk.xinitrc ....
line. This will use $HOME/.xinitrc
, and $HOME would be /root
. Pretty sure startx is also a blocking call, so until X exits, shutdown
won't run. If instead you did this:
startx &
shutdown -r now
X would run, but then shutdown would run too, right away (obviously pointless).
You don't have to use that trick if you don't care about having shutdown come in -- as mentioned the user will just end up with a login prompt. But it does seem like a useful idea, since then you can just turn it off with ctrl-alt-backspace
. Another idea, if your app is closeable, would be to use startx &
in the init script, which backgrounds it and allows init to continue normally (this is fine; X will still be running and have control of the display -- "backgrounded" is a maybe a confusing term). Instead of in the init script, put shutdown
in the xinitrc instead:
#!/bin/sh
#/root/.xinitrc
su -c myApp pi
shutdown -r now
Same trick, different place. Now when someone closes myApp
, shutdown will happen (but if they kill X, it won't). You could also do it both ways, but I actually like this one better because it means you can exit X and get a login, which may be useful sometimes, and you can also easily turn the system off from the GUI.
Don't background (&
) myApp in the .xinitrc even if there is no shutdown after it though, because when the .xinitrc is done X exits ;) The last call there has to persist in the foreground (normally, it's a DE or window manager).
Init scripts and .xinitrc
are similar concepts. One is run by init
, which is process 1 on linux (it's the only process started by the kernel). The other is run by the X server. Note that there are .xinitrc files and an xinitrc command (they're related but not the same).