{"id":18930326,"url":"https://github.com/tomhumphries/raspberrypihotspot","last_synced_at":"2025-04-15T15:31:21.075Z","repository":{"id":139772928,"uuid":"219177840","full_name":"TomHumphries/RaspberryPiHotspot","owner":"TomHumphries","description":"Offline WiFi hotspot with a Node.js captive portal","archived":false,"fork":false,"pushed_at":"2019-11-04T22:55:49.000Z","size":15,"stargazers_count":48,"open_issues_count":5,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-28T22:51:13.887Z","etag":null,"topics":["accesspoint","captiveportal","nodejs","raspberrypi"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomHumphries.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-02T16:03:39.000Z","updated_at":"2024-10-24T00:34:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"45b0a4fd-0162-4f9b-9575-3045562533bf","html_url":"https://github.com/TomHumphries/RaspberryPiHotspot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomHumphries%2FRaspberryPiHotspot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomHumphries%2FRaspberryPiHotspot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomHumphries%2FRaspberryPiHotspot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomHumphries%2FRaspberryPiHotspot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomHumphries","download_url":"https://codeload.github.com/TomHumphries/RaspberryPiHotspot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249097934,"owners_count":21212381,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["accesspoint","captiveportal","nodejs","raspberrypi"],"created_at":"2024-11-08T11:37:15.929Z","updated_at":"2025-04-15T15:31:21.069Z","avatar_url":"https://github.com/TomHumphries.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Raspberry Pi Wifi Hotspot with Captive Portal\nThis turns a Raspberry Pi into a WiFi hotspot that is not connected to the internet, hosting a single website.\n\nWhen connecting to the Raspberry Pi it should redirect you to the website hosted on it.\n\nThis is done by mimicking a signin step, which opens a browser window on Windows, Android, and Apple devices when connecting to the WiFi.\n\n\n**This guide is an extension of the guide \"[Setting up a Raspberry Pi as a Wireless Access Point](https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md)\" from the RaspberryPi.org website.**\n\n\n# Setting up a Raspberry Pi as an open Wireless Access Point with a Captive Portal\n\nBefore proceeding, please ensure your Raspberry Pi is [up to date](../../raspbian/updating.md) and rebooted.\n\n## Setting up a Raspberry Pi as an open access point in a standalone network (NAT)\n\n\nThe Raspberry Pi can be used as a wireless access point, running a standalone network. This can be done using the inbuilt wireless features of the Raspberry Pi 3 or Raspberry Pi Zero W, or by using a suitable USB wireless dongle that supports access points.\n\nNote that this documentation was tested on a Raspberry Pi Zero W, and it is possible that some USB dongles may need slight changes to their settings. If you are having trouble with a USB wireless dongle, please check the forums.\n\nIn order to work as an access point, the Raspberry Pi will need to have access point software installed, along with DHCP server software to provide connecting devices with a network address.\n\nTo create an access point, we'll need DNSMasq and HostAPD. Install all the required software in one go with this command:\n\n```\nsudo apt install dnsmasq hostapd\n```\n\nSince the configuration files are not ready yet, turn the new software off as follows:\n\n```\nsudo systemctl stop dnsmasq\nsudo systemctl stop hostapd\n```\n\n### Configuring a static IP\n\nWe are configuring a standalone network to act as a server, so the Raspberry Pi needs to have a static IP address assigned to the wireless port. This documentation assumes that we are using the standard 192.168.x.x IP addresses for our wireless network, so we will assign the server the IP address 192.168.4.1. It is also assumed that the wireless device being used is `wlan0`.\n\n\nTo configure the static IP address, edit the dhcpcd configuration file with:\n\n```\nsudo nano /etc/dhcpcd.conf\n```\n\nGo to the end of the file and edit it so that it looks like the following:\n\n```\ninterface wlan0\n    static ip_address=192.168.4.1/24\n    nohook wpa_supplicant\n```\n\nNow restart the dhcpcd daemon and set up the new `wlan0` configuration:\n\n```\nsudo service dhcpcd restart\n```\n\n### Configuring the DHCP server (dnsmasq)\n\nThe DHCP service is provided by dnsmasq. By default, the configuration file contains a lot of information that is not needed, and it is easier to start from scratch. Rename this configuration file, and edit a new one:\n\n```\nsudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig\nsudo nano /etc/dnsmasq.conf\n```\n\nType or copy the following information into the dnsmasq configuration file and save it:\n\n```\ninterface=wlan0      # Use the require wireless interface - usually wlan0\ndhcp-range=192.168.4.2,192.168.4.255,255.255.255.0,15m\naddress=/#/192.168.4.1 # Redirect all domains (the #) to the address 192.168.4.1 (the server on the (Pi)\n```\n\nSo for `wlan0`, we are going to provide IP addresses between 192.168.4.2 and 192.168.4.20, with a lease time of 15 minutes. If you are providing DHCP services for other network devices (e.g. eth0), you could add more sections with the appropriate interface header, with the range of addresses you intend to provide to that interface. We are also redirecting all domains to the ip address 192.168.4.1. Later on we're going to redirect all traffic destined for 192.168.4.1 to the IP and port where we're hosting the server - 192.168.4.1:3000.\n\nThere are many more options for dnsmasq; see the [dnsmasq documentation](http://www.thekelleys.org.uk/dnsmasq/doc.html) for more details.\n\nReload `dnsmasq` to use the updated configuration:\n```\nsudo systemctl reload dnsmasq\n```\n\n\u003ca name=\"hostapd-config\"\u003e\u003c/a\u003e\n### Configuring the access point host software (hostapd)\n\nYou need to edit the hostapd configuration file, located at /etc/hostapd/hostapd.conf, to add the various parameters for your wireless network. After initial install, this will be a new/empty file.\n\n```\nsudo nano /etc/hostapd/hostapd.conf\n```\n\nAdd the information below to the configuration file. This configuration assumes we are using channel 7, with a network name of Pi WiFi, and no password. This means anyone can connect to the network. The original Raspberry Pi guide has configuration options for a passworded WiFi.\n\nTo use the 5 GHz band, you can change the operations mode from hw_mode=g to hw_mode=a. Possible values for hw_mode are:\n - a = IEEE 802.11a (5 GHz)\n - b = IEEE 802.11b (2.4 GHz)\n - g = IEEE 802.11g (2.4 GHz)\n - ad = IEEE 802.11ad (60 GHz) (Not available on the Raspberry Pi)\n\n```\ninterface=wlan0\ndriver=nl80211\nssid=Pi WiFi\nchannel=7\nhw_mode=g\n```\n\nWe now need to tell the system where to find this configuration file.\n\n```\nsudo nano /etc/default/hostapd\n```\n\nFind the line with #DAEMON_CONF, and replace it with this:\n\n```\nDAEMON_CONF=\"/etc/hostapd/hostapd.conf\"\n```\n\n### Start it up\n\nNow enable and start `hostapd`:\n\n```\nsudo systemctl unmask hostapd\nsudo systemctl enable hostapd\nsudo systemctl start hostapd\n```\n\nDo a quick check of their status to ensure they are active and running:\n\n```\nsudo systemctl status hostapd\nsudo systemctl status dnsmasq\n```\n\n### Add routing and masquerade\n\nEdit /etc/sysctl.conf and uncomment this line:\n\n```\nnet.ipv4.ip_forward=1\n```\n\nAdd a masquerade for outbound traffic on eth0:\n\n```\nsudo iptables -t nat -A  POSTROUTING -o eth0 -j MASQUERADE\n```\n\n(more information about masquerade in iptables https://askubuntu.com/a/466451)\n\nAdd redirect for all inbound http traffic for 192.168.4.1 (which we defined earlier in dnsmasq.conf) to our Node.js server on port 3000 (192.168.4.1:3000).\n\n```\nsudo iptables -t nat -I PREROUTING -d 192.168.4.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.4.1:3000\n```\n\nSave the iptables rules.\n\n```\nsudo sh -c \"iptables-save \u003e /etc/iptables.ipv4.nat\"\n```\n\nEdit /etc/rc.local \n\n```\nsudo nano /etc/rc.local\n```\n\nand add this just above \"exit 0\" to install the iptables rules on boot.\n\n```\niptables-restore \u003c /etc/iptables.ipv4.nat\n```\n\nReboot and ensure it still functions.\n\nUsing a wireless device, search for networks. The network SSID you specified in the hostapd configuration should now be present, and it should be accessible with the specified password.\n\nIf SSH is enabled on the Raspberry Pi access point, it should be possible to connect to it from another Linux box (or a system with SSH connectivity present) as follows, assuming the `pi` account is present:\n\n```\nssh pi@192.168.4.1\n```\n\nBy this point, the Raspberry Pi is acting as an access point, and other devices can associate with it. Associated devices can access the Raspberry Pi access point via its IP address for operations such as `rsync`, `scp`, or `ssh`.\n\n# Configuring the Node.js server to start on boot\nCreate service that starts the Node.js server automatically whenever the Pi boots up. \n\nCreate a directory for the Node.js files:\n\n```\nsudo mkdir -p /Node/PiWiFi\n```\n\nChange to the directory:\n\n```\ncd Node/PiWiFi\n```\n\nCreate a package.json file for our Node.js server and accept all the default options:\n\n```\nnpm init\n```\n\nInstall express as a dependency:\n\n```\nnpm install express\n```\n\nCreate the Node.js file:\n\n```\nsudo nano app.js\n```\n\nAnd write / paste the code:\n\n```\nconst express = require('express');\nconst app = express();\nconst port = 3000;\n\nvar hostName = 'pi.wifi';\n\napp.use((req, res, next) =\u003e {\n    if (req.get('host') != hostName) {\n        return res.redirect(`http://${hostName}`);\n    }\n    next();\n})\n\napp.get('/', (req, res, next) =\u003e {\n    res.send('Pi WiFi - Captive Portal');\n})\n\napp.listen(port, () =\u003e {\n    console.log(`Server listening on port ${port}`)\n})\n```\n\nThe key part here is the redirection of any requests that were not from the hostname \"pi.wifi\".\n\nThe redirection command returns a 302 status code. It's this 302 code that triggers the \"Sign in to network\" functionality, the kind you see when connecting to an open WiFi network at an airport etc.\n\nCreate the service file:\n\n```\nsudo nano piwifi.service\n```\n\nAnd write / paste the code:\n\n```\n[Unit]\nDescription=Pi WiFi Hotspot Service\nAfter=network.target\n\n[Service]\nWorkingDirectory=/home/pi/Node/PiWiFi\nExecStart=/usr/bin/nodejs /home/pi/Node/PiWiFi/app.js\nRestart=on-failure\nUser=root\nEnvironment=PORT=3000\n\n[Install]\nWantedBy=multi-user.target\n```\n\nCopy the file across:\n```\nsudo cp piwifi.service /etc/systemd/system\n```\n\nand set it up with:\n\n```\nsudo systemctl enable piwifi.service\n```\n\nIt will start automatically on boot, but you can start it now with:\n\n```\nsudo systemctl start piwifi\n```\n\nWhen you connect to the WiFi you should be prompted to signin to the network (tested on Windows, Android, and iPhone). Otherwise, any time you try to connect to a http site, you should be redirected to the web server at the domain **pi.wifi**, a domain that doesn't exist on the \"real\" internet.\n\nIf you are redirected to the site successfully, you should see the text \"Pi WiFi - Captive Portal\".\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomhumphries%2Fraspberrypihotspot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomhumphries%2Fraspberrypihotspot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomhumphries%2Fraspberrypihotspot/lists"}