Git Product home page Git Product logo

raspberry-pi-turnkey's Introduction

Raspberry Pi Turnkey

Have you ever wanted to setup a Raspberry Pi without having to SSH or attach a keyboard to add your WiFi credentials? This is particularly useful when you are making a Raspberry Pi that needs to be deployed somewhere where supplying the credentials via SSH or attaching a keyboard isn't an option. Or it could be useful if you take your Pi to a friend's house and they don't have ethernet cables or extra keyboards+monitors to put your friend's WiFi credentials onto the Pi. With this image base you don't ever need to modify a wpa_supplicant with SSH/terminal/PiBakery again!

You can follow the instructions below to create a turnkey image, or you can just download my latest one at raspberry-pi-turnkey.schollz.com/2018-06-25-turnkey-1.3.zip (v1.3.0, 982MB) and follow the typical flashing instructions.

Support

Usage

Once you boot the Pi with this image, wait about 10 minutes for the Pi to reformat the drive and start up the web server. Then you will see a WiFi AP named "ConnectToConnect" (password same). Connect to it and your browser should automatically redirect you to a sign-in page. If not, navigate to 192.168.4.1 where you'll see a login form.

When the WiFi credentials are entered onto the login form, the Pi will modify its internal wpa_supplicant to conform to them so that it will be connected to the net. The Pi will then reboot itself using those WiFi credentials. If the credentials are not correct, then the Pi will reboot back into the AP mode to allow you to re-enter them again.

Once connected, you can recieve a message with the LAN IP for your Pi at https://snaptext.live (the specific URL will be given to you when you enter in the credentials to the form).

Note: The Raspberry Pi is not a fast computer. When you see the AP and connect to it, it may take up to a minute for the page at 192.168.4.1 to appear. Also, if you enter the wrong WiFi credentials, it will have to reboot twice to reset the Pi to allow you to enter the credentials again. So try to enter them right the first time!

How does it work?

When the Pi starts up it runs a Python script, startup.py. This script first checks if the Pi is online (by looking for an SSID in iwconfig wlan0). If the Pi is online, the script sets the status as "connected" (saved to disk in status.json).

If the Pi is not online, it will check the status. The initial status is "disconnected". When "disconnected" the Pi will uncomment the configuration files for hostapd and dnsmasq. The access point configuration is nearly identical to as outlined in this tutorial. Then the Pi sets the status as "hostapd" and reboots itself.

When the status is "hostapd" then the script will bind to port 80 and serve a web form at 192.168.4.1. Once you connect to the AP this web form will be available and it will recieve input. Once the server recieves input, it sets the credentials in wpa_supplicant.conf and comments out the configuration file for hostapd and dnsmasq so that the AP doesn't interfere, and then reboots. When it reboots it will see if it gets online and set the status as "connected" or "disconnected". Then it repeats the steps above (i.e. doing nothing if connected, or restarting the AP if disconnected).

Instructions to create image

The following are the step-by-step instructions for how I create the turnkey image. If you don't want to download the image I created above (I don't blame you), then follow these to make one exactly the same.

These instructions assume you are using Ubuntu. You can use Windows/OS X for most of these steps, except step #4 which requires resizing.

1. Flash Raspbian Stretch Lite

Starting from version Raspbian Stretch Lite version 2017-11-29.

$ sudo dd bs=4M if=2017-11-29-raspbian-stretch-lite.img of=/dev/mmcblk0 conv=fsync status=progress

Change /dev/mmcblk0 to whatever your SD card is (find it using fdisk -l).

After flashing, for the first time use, just plug in ethernet and you can SSH into the Pi. To activate SSH on boot just do

$ touch /media/YOURUSER/boot/ssh

2. Install libraries onto the Raspberry Pi

SSH into your Pi using Ethernet, as you will have to disable the WiFi connection when you install hostapd.

Basic libraries

$ sudo apt-get update
$ sudo apt-get dist-upgrade -y
$ sudo apt-get install -y dnsmasq hostapd vim python3-flask python3-requests git

Install node (optional)

$ wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-linux-armv6l.tar.xz
$ sudo mkdir /usr/lib/nodejs
$ sudo tar -xJvf node-v8.9.4-linux-armv6l.tar.xz -C /usr/lib/nodejs 
$ rm -rf node-v8.9.4-linux-armv6l.tar.xz
$ sudo mv /usr/lib/nodejs/node-v8.9.4-linux-armv6l /usr/lib/nodejs/node-v8.9.4
$ echo 'export NODEJS_HOME=/usr/lib/nodejs/node-v8.9.4' >> ~/.profile
$ echo 'export PATH=$NODEJS_HOME/bin:$PATH' >> ~/.profile
$ source ~/.profile

Install Go (optional)

$ wget https://dl.google.com/go/go1.10.linux-armv6l.tar.gz
$ sudo tar -C /usr/local -xzf go*gz
$ rm go*gz
$ echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' >>  ~/.profile
$ echo 'export GOPATH=$HOME/go' >>  ~/.profile
$ source ~/.profile

Install turnkey

$ git clone https://github.com/schollz/raspberry-pi-turnkey.git

Install Hostapd

$ sudo systemctl stop dnsmasq && sudo systemctl stop hostapd

$ echo 'interface wlan0
static ip_address=192.168.4.1/24' | sudo tee --append /etc/dhcpcd.conf

$ sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig  
$ sudo systemctl daemon-reload
$ sudo systemctl restart dhcpcd

$ echo 'interface=wlan0
dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h' | sudo tee --append /etc/dnsmasq.conf

$ echo 'interface=wlan0
driver=nl80211
ssid=ConnectToConnect
hw_mode=g
channel=7
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=ConnectToConnect
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP' | sudo tee --append /etc/hostapd/hostapd.conf

$ echo 'DAEMON_CONF="/etc/hostapd/hostapd.conf"' | sudo tee --append /etc/default/hostapd

$ sudo systemctl start hostapd && sudo systemctl start dnsmasq

Add pi to sudoers

Add pi to the sudoers, so that you can run sudo commands without having to be root (so that all the paths to your programs are unchanged).

$ sudo visudo

Then add this line:

pi      ALL=(ALL:ALL) ALL

(Sidenote: I save an image intermediate.img at this point so its easy to go back)

Startup server on boot

Open up the rc.local

$ sudo nano /etc/rc.local

And add the following line before exit 0:

su pi -c '/usr/bin/sudo /usr/bin/python3 /home/pi/raspberry-pi-turnkey/startup.py &'

Shutdown the pi

Shutdown the Raspberry Pi and do not start it up until after you write the image. Otherwise the unique ID that is generated will be the same for all the images.

$ sudo shutdown now

3. Resize Raspberry Pi SD image

If you don't want to resize the image, you can just write the entire image file to your computer and use that from here on. If you do want to resize (especially useful if you are installing on a 16GB card and want to flash onto a smaller card), follow these instructions.

Put the newly made image into Ubuntu and do

$ xhost +local:
$ sudo gparted-pkexec

Right click on the SD card image and do "Unmount". Then right click on the image and do "Resize/Move" and change the size to 2400.

Then you can copy the image to your computer using the following command

$ sudo dd if=/dev/mmcblk0 of=/some/place/turnkey.img bs=1M count=2400 status=progress

Again /dev/mmcblk0 is your SD card which you can determine using fdisk -l. The location of the image, /some/place/, should be set by you.

4. Test the turnkey image

The new image will be in /some/place/2018-turnkey.img which you can use to flash other SD cards. To test it out, get a new SD card and do:

$ sudo dd bs=4M if=/some/place/turnkey.img of=/dev/mmcblk0 conv=fsync status=progress

Roadmap

  • Add messaging system to send the LAN IP address once online (uses https://github.com/schollz/snaptext)
  • Add startup hooks (just edit startup.sh)
  • connect immediately to wifi and disable hostapd without rebooting

If you'd like to contribute, please do send a PR!

Thanks

Thanks to @ilirb for checking if passphrase is correct before rebooting!

License

MIT

raspberry-pi-turnkey's People

Contributors

ilirb avatar schollz avatar yeyeto2788 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

raspberry-pi-turnkey's Issues

Auto switch to Wifi without rebooting

In order to automatically switch to AP and Wifi without need to reboot following commands could be used. I am not creating PR as long as I am not sure if this is still active.

sudo ifconfig wlan0 down
sleep 5
sudo ifconfig wlan0 up

pi.id file creation on startup.py

Hello @schollz,

I have noticed that on first try, the startup.py script tries to find a pi.id file that if it is not on the directory it will create it with and random generated key and then expands the filesystem.

There are 2 things that caught my mind:

1 - Why expanding the filesystem if the file is not present? Is there a reason why the filesystem should be expanded if the file is not on the directory?

2 - If the idea of the of the id_generator() method is to create a unique, let's say, serial number maybe we can use the information on the board itself to get the unique id directly from hardware Something like this:

def id_generator():
  # Extract serial from cpuinfo file
  cpuserial = "0000000000000000"
  try:
    f = open('/proc/cpuinfo','r')
    for line in f:
      if line[0:6]=='Serial':
        cpuserial = line[10:26]
    f.close()
  except:
    cpuserial = "ERROR000000000"

  return cpuserial

We can even have a mix that if the try block fails we can generate it by the method you have implemented, so on the first blocks it will return the real unique serial number and in the second block it will generate it as it is generating it until now.

Best regards.

Snaptext.live is no longer active

Currently, the turnkey scripts say that the user can find the IP address of their Pi at a snaptext.live link, however this site is no longer around. As a user, it is confusing to be pointed to a dead link.

To reduce confusion, the snaptext.live messages should be removed. As the functionality currently does not work, this will not be a loss of any features. Developers integrating turnkey into their projects can use startup.sh to determine the IP address if it needs to be exposed to the user.

No need to use sudo by root.

You mention adding this to the crontab of the root-user:

   @reboot cd /home/pi/raspberry-pi-turnkey && /usr/bin/sudo /usr/bin/python3 startup.py

Since this will be run by root there is no need for the use of sudo. You could simplify to:

   @reboot cd /home/pi/raspberry-pi-turnkey &&  /usr/bin/python3 startup.py

Not able to install on Raspberry Pi OS (Rev Jan 2021)

I'm using Raspbian Buster Lite (v2021), I've been looking all over the web for a solution like this...I used this a while back and it worked like a charm, but now with the new OS, it doesn't work, or more accuratly I can't install it. hostapd throws an exception that it's masked, so I unmasked it, but when I ran it again, it just didn't do anything.

You don't need `sudo` for the pi user ..

As a result of fixing #2, you've switched to adding a command to /etc/rc.local. You've added:

su pi -c '/usr/bin/sudo /usr/bin/python3 /home/pi/raspberry-pi-turnkey/startup.py &'

The script rc.local will be launched as root, via the boot-up process:

  • If you want to run commands as root you just do that!
  • If you want to run commands as the user pi you can use su pi -c command-to-run

You seem to be trying to do both:

  • You run su pi -c '....' to run the command as the user pi
  • But then the command to run is sudo ....
    • Which will fail, since sudo will prompt for a password anyway ..

Failed to start hostapd.service: Unit hostapd.service is masked

This is obviously not your problem but raspbian Stretch's hostapd as it changed their installation steps and a little edit is needed in your installation steps here under README.
Run these:

sudo systemctl unmask hostapd
sudo systemctl enable hostapd

before running this:

sudo systemctl start hostapd && sudo systemctl start dnsmasq

Here is a little background reading.

not able to connect to wifi

Hello,
I am using your turnkey to convert my raspberry pi to hotspot and then connect it to wifi network. But when I enter the credentials in login page and press sign in, it gives network error. Though the raspberry pi is connected to my wifi but when I try to ssh into my pi using putty it gives connection timed out error (I am using the same ip address that I earlier used to ssh into my pi). Can anyone help me out here?

Simplify sudo

If you do want to use commands as root, from the pi user you can simplify.

Instead of editing /etc/sudoers with visudo as you currently do you could either:

  • Create the file /etc/sudoers.d/pi
    • ie. "echo 'pi ALL=(ALL:ALL) ALL ' > /etc/sudoers.d/pi"
  • Add the user to the sudo group
    • i.e. "adduser pi sudo"

xfinitywifi login?

Hi there
VERY excited by this BUT I use xfinitywifi which is a service in the USA where AP's are on people's modems and we login whereever we see xfinitywifi. We then enter our email address and our xfinitywifi password. This connects our laptops to the wifi. I don't really see how to do this on your config. I thought the email was the one that got a message sent to it??

not getting page

when i connected to ConnectToConnect , after that not getting page with 192.168.4.1.

Does not connect to open wifi

There is no place in the flask site to indicate the AP is open. It will accept any password but will not connect to the AP.

I am assuming this would require:

  • update the template to add a check box for open access points
  • update the wpa supplicant template to add a "wpa_psk NONE" (I think this is the command for open wifi in supplicant, I will have to double check)

Anything I missed? I can take a shot at this if that these are the only changes needed.

Errno 13 Permission denied: './expand_filesystem.sh'

I have set everything up according to the instructions but when I try to run I get an error on line 180 in startup.py -> subprocess.Popen("./expand_filesystem.sh")

Anybody have an idea about what is happening?

Note: I am using raspbian buster lite.

Connecting to Pi after

Hello, I just installed your image and it works wonderfully, however, I wanted to continue using my rasp by connecting to it through ssh and keep adding stuff to the server.

My question is, after installing your image, is the pi "locked" (by locked I mean in its use, it is now binded to its use and it cannot be changed)? Or can I continue logging to it?

Wonderful project btw!

No AP

I don't see the ConnecttoConnect AP. Is there anything I can do to test it is running

If RPi moves or SSID changes then it never goes back to hostapd

s = json.load(open('status.json'))
and
if len(matches) > 0:

On first startup it goes into hostapd mode but after it connects to a wireless the status is set to to 'connected' and if you move or change ssid the hostapd never activates:

  • Right before check connection is made the status is read from the file and if it was connected once the status will be 'connected'
  • If check connection doesn't succeed the status will be still 'connected' and written back again (line 84)
  • Then the condition 'elif s['status'] == 'connected'' is always met

I think I have fixed it but for some reason I can't explain I'm using Python 2.7 and if I make a PR I'm not sure it will work.

What are Node and Go for?

Just wondering why you bothered to include setup instructions for Node and Go when they are not used anywhere...?
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.