I am making this post as I want to do a remote control car using the Raspberry Pi and controlling the car with my handphone. I want to use the car away from my home network and therefore need it to function as an access point (AP).
I will be making use of the wlan0 on the Pi and running it headless. The os that I have decided to use is Dietpi (Bookworm) since it is small and I will install just what I need.
I spent quite some time making it work and with the help of ChatGPT, finally got it going. I would like to document the process and hope it will be helpful to others.
The first step is to download Dietpi from dietpi.com and flash the sd card for the Pi.
I highly recommend editing the dietpi.txt and set you keyboard, locale, timezone and country there. Thereafter edit the dietpi-wifi.txt to enter the ssid and password of the wifi network the Pi should connect to. I also replaced DropBear with OpenSSH which I can transfer file easily.
I enabled the eth0 and wlan0 in the dietpi.txt file.
I do not recommend using dietpi-config as it might overwrite your config files.
I am assuming the user is dietpi and will be using the /home/dietpi directory to some of my log files.
After doing the initial setup for the dietpi os, you would need to install hostapd, dnsmasq:-
sudo apt install hostapd
sudo apt install dnsmasq
Somehow I also need to install dbus using sudo apt install dbus as without it wpa_supplicant may fail (as in my case).
Then create the hostapd.conf file: sudo nano /etc/hostapd/hostapd.conf
Enter this into the hostapd.conf file:
interface=wlan0
driver=nl80211
ssid=Your_desired_ap_ssid
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
wpa=2
wpa_passphrase=yourpassword
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP
Then tell hostapd where to look for the config file:
sudo nano /etc/default/hostapd
Make this entry:
DAEMON_CONF="/etc/hostapd/hostapd.conf"
Next edit dnsmasq..conf: sudo nano /etc/dnsmasq.conf
Make the following entries in the file:
interface=wlan0
dhcp-range=192.168.4.10,192.168.4.20,255.255.255.0,24h
You can decide what IP range but I suggest using 192.168.4.0/24 network.
BTW, if the conf files are not created when the softwares are installed, you can create them as above. If they are created, I suggest making a copy of them before editing the original.
Next edit the network interfaces file: sudo nano /etc/network/internaces
Make the following entries:
# Ethernet
allow-hotplug eth0
iface eth0 inet dhcp
# WiFi
allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-ssid "wifi-ssid"
wpa-psk "wifi-password"
pre-up iw dev wlan0 set power_save off
post-down iw dev wlan0 set power_save on
Next, open wpa_supplicant.conf: sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
Make the following entries:
# WiFi country code, set here in case the access point does send one
country=SG
# Grant all members of group "netdev" permissions to configure WiFi, e.g. via wpa_cli or wpa_gui
ctrl_interface=DIR=/run/wpa_supplicant GROUP=netdev
# Allow wpa_cli/wpa_gui to overwrite this config file
update_config=1
network={
ssid="wifi-ssid"
scan_ssid=1
key_mgmt=WPA-PSK
psk=38djlq1380f71bde2bc2jd83idy2a365be04f0ffc7b147221b51f9dje9274e8
}
Ensure that the ssid is the same as that in the /etc/network/interfaces file. I don't think you should touch the psk as it is encrypted.
Next I created a wifi_check.sh script to check if there is wifi connection. It check is there is wifi connection to the wifi netwrok. If there is none, hostapd and dnsmasq will start and the AP will broadcastthe SSID.
sudo nano /usr/local/bin/wifi_check.sh
The content of the script:
#!/bin/bash
# Log file path
LOG_FILE="/home/dietpi/ap_log.log"
# Function to log messages with timestamps
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}
log "----- Script started -----"
# Get the wireless interface (e.g., wlan0)
WIFI_IFACE=$(ip link | awk -F: '/wl/ {print $2; exit}' | xargs)
if [ -z "$WIFI_IFACE" ]; then
log "[!] No wireless interface found. Exiting."
exit 1
fi
log "[i] Detected wireless interface: $WIFI_IFACE"
# Log current state of hostapd and dnsmasq
for svc in hostapd dnsmasq; do
if systemctl is-active --quiet "$svc"; then
log "[i] $svc is currently ACTIVE"
else
log "[i] $svc is currently INACTIVE"
fi
if systemctl is-enabled --quiet "$svc"; then
log "[i] $svc is ENABLED at boot"
else
log "[i] $svc is DISABLED at boot"
fi
done
# Stop AP services
systemctl stop hostapd >> "$LOG_FILE" 2>&1 && log "[i] Stopped hostapd"
systemctl disable hostapd >> "$LOG_FILE" 2>&1 && log "[i] Disabled hostapd"
systemctl stop dnsmasq >> "$LOG_FILE" 2>&1 && log "[i] Stopped dnsmasq"
systemctl disable dnsmasq >> "$LOG_FILE" 2>&1 && log "[i] Disabled dnsmasq"
# Check internet connectivity
if ping -I wlan0 -c 4 -W 2 google.com > /dev/null 2>&1; then
log "[✓] Connected to WiFi. Disabling AP mode."
# Unmask and enable wpa_supplicant
systemctl unmask wpa_supplicant >> "$LOG_FILE" 2>&1 && log "[i] Unmasked wpa_supplicant"
systemctl enable wpa_supplicant >> "$LOG_FILE" 2>&1 && log "[i] Enabled wpa_supplicant"
systemctl restart wpa_supplicant >> "$LOG_FILE" 2>&1 && log "[i] Restarted wpa_supplicant"
# Bring up interface just in case
ip link set "$WIFI_IFACE" up >> "$LOG_FILE" 2>&1
else
log "[✗] No WiFi. Enabling AP mode."
# Stop and mask wpa_supplicant
systemctl stop wpa_supplicant >> "$LOG_FILE" 2>&1 && log "[i] Stopped wpa_supplicant"
systemctl disable wpa_supplicant >> "$LOG_FILE" 2>&1 && log "[i] Disabled wpa_supplicant"
systemctl mask wpa_supplicant >> "$LOG_FILE" 2>&1 && log "[i] Masked wpa_supplicant"
# Bring interface down and flush
ip link set "$WIFI_IFACE" down >> "$LOG_FILE" 2>&1
ip addr flush dev "$WIFI_IFACE" >> "$LOG_FILE" 2>&1
sleep 1
# Assign static IP and bring up interface
ip addr add 192.168.4.1/24 dev "$WIFI_IFACE" >> "$LOG_FILE" 2>&1
ip link set "$WIFI_IFACE" up >> "$LOG_FILE" 2>&1
# Start AP services
systemctl enable hostapd >> "$LOG_FILE" 2>&1
systemctl start hostapd >> "$LOG_FILE" 2>&1
systemctl enable dnsmasq >> "$LOG_FILE" 2>&1
systemctl start dnsmasq >> "$LOG_FILE" 2>&1
sleep 1
# Confirm services
if systemctl is-active --quiet dnsmasq; then
log "[✓] dnsmasq is running"
else
log "[!] dnsmasq failed to start"
fi
if systemctl is-active --quiet hostapd; then
log "[✓] hostapd is running"
else
log "[!] hostapd failed to start"
fi
fi
log "----- Script completed -----"
Ensure the script is executable: sudo chmod u+x wifi_check.sh
Next I created a root cronjob to start the script on boot: sudo crontab -e
Make the following entry:-
@reboot /usr/local/bin/wifi_check.sh
You can check the entries in /home/dietpi/ap_log.log to see the starting of the AP and enabling of hostapd and dnsmasq.
When you test the AP away from you wifi network you may not have a monitor and a keyboard connected to your Pi; as in my case. Also Dietpi keeps its journal log in the RAM and so the journal log is lost when you reboot the Pi when in range of you wifi connection. To overcome this, I save the journal log into a file so that I can go through the log to see if there are errors.
To do this create a systemd service: sudo nano /etc/systemd/system/export-journal.service
Type the following into the file:
[Unit]
Description=Export journal log after boot
After=multi-user.target
[Service]
Type=oneshot
User=root
ExecStart=/bin/bash -c "/bin/journalctl -b --no-pager --no-full > /home/dietpi/journal_$(date +%%Y-%%m-%%d_%%H%%M%%S).txt"
Next create a timer (I started the copying 5 min after booting up): sudo nano /etc/systemd/system/export-journal.timer
Enter the following into the file:
[Unit]
Description=Run journal export 5 minutes after boot
[Timer]
OnBootSec=5min
AccuracySec=1s
Unit=export-journal.service
[Install]
WantedBy=timers.target
Restart systemd: sudo systemctl daemon-reexec
Enable the timer to start on boot: sudo systemctl daemon-reload
Test the export of the log: sudo systemctl enable --now export-journal.timer
You should see the journal log at /home/dietpi with a timestamp. The log may be truncated to the right but still provide useful information.
That should be it.
Reboot the Pi and hopefully you will see the AP in the wifi list of your phone or PC. Remember there is no Internet connection.
During setup, I have the LAN cable, keyboard and monitor connected to the Pi. This is great to debug any issues - browse through the journal entries, check entries in the ap_log.log file created by the script above.
Good luck!