54 Commits

Author SHA1 Message Date
Bill Zimmerman
abd4c1e962 Change pi-gen repository to billz/pi-gen 2025-10-23 19:44:36 +02:00
billz
78d0b1a958 Create shim for resolvconf under debian 13 2025-10-23 04:37:38 -07:00
billz
2aafe2b61c Revert install openresolv for wg-quick 2025-10-23 03:39:52 -07:00
billz
079191b660 Update release version 2025-10-23 00:58:36 -07:00
Bill Zimmerman
ca8485d80b Merge pull request #1970 from RaspAP/maint/fr_FR-locale-translations
Maintenance: Update fr_FR locale messages
2025-10-22 16:27:00 +02:00
billz
beb40ec7b9 Update w/ final localized messages 2025-10-22 07:18:58 -07:00
billz
939c5d164c Revise navigation label to prevent wrapping 2025-10-22 05:05:56 -07:00
billz
1e6bd6f516 Update fr_FR locale messages 2025-10-22 04:56:47 -07:00
Bill Zimmerman
5cdd174e29 Merge pull request #1969 from RaspAP/fix/persistent-locales
Fix: Add cookie-based locale persistence
2025-10-22 12:00:52 +02:00
billz
b84d26447f Add cookie-based locale persistence 2025-10-22 02:25:34 -07:00
Bill Zimmerman
b2f7cad0d9 Update issue_form.yml 2025-10-22 11:05:14 +02:00
Bill Zimmerman
3f47043bbc Merge pull request #1967 from RaspAP/maint/de_DE-locale-translations
Translations: Update de_DE locale messages
2025-10-21 10:17:40 +02:00
billz
90981a9f21 Revise strings, thanks @Noschvie 2025-10-21 01:10:42 -07:00
billz
03c48a1c42 Update de_DE locale messages 2025-10-21 00:10:23 -07:00
Bill Zimmerman
6433d83967 Merge pull request #1965 from RaspAP/feat/br0-config
Feature: Bridged AP mode static IP configuration
2025-10-21 08:15:39 +02:00
billz
c6a738097a Revert "Exclude compiled .mo files"
This reverts commit 53581c813f.
2025-10-20 23:11:05 -07:00
billz
276f6585e1 Merge branch 'master' into feat/br0-config 2025-10-20 23:05:59 -07:00
billz
53581c813f Exclude compiled .mo files 2025-10-20 23:03:20 -07:00
Bill Zimmerman
b4d5e9033c Merge pull request #1966 from RaspAP/maint/translations
Maintenance: Update en_US locale messages
2025-10-21 07:59:47 +02:00
billz
9cf65a29cb Update en_US locale messages 2025-10-19 23:45:40 -07:00
billz
c74b410e8c Update en_US locale messages 2025-10-19 23:30:58 -07:00
billz
593acb93bd Auto-populate DNS field when gateway loses focus 2025-10-19 11:58:08 -07:00
billz
5fa691bca1 Fix: domain_name_server declaration for br0 2025-10-19 11:08:50 -07:00
billz
bc2679ac68 Update $arrConfig form field values 2025-10-19 11:08:10 -07:00
billz
d5ac2f6881 Fetch br0 properties with $dhcpcd->getInterfaceConfig 2025-10-19 11:07:43 -07:00
billz
3691489194 Minor: revise label + help text 2025-10-19 10:24:19 -07:00
billz
74bd81a92c Add status message when bridge is enabled, newlines to br0 config 2025-10-19 10:22:03 -07:00
billz
74194205ec Formatted for clarity 2025-10-19 09:29:56 -07:00
billz
fb4571a191 Construct bridgeConfig when enabled, pass to dhcpcd->buildConfig() 2025-10-19 09:28:43 -07:00
billz
b98c1fb912 Add bridgedEnable + br0 config handling to buildConfig() 2025-10-19 09:28:21 -07:00
billz
fdfbc62e9b Validate bridged mode static IP configuration 2025-10-19 09:23:46 -07:00
billz
cc6771ba07 Add required attribute to bridged form inputs 2025-10-19 09:21:37 -07:00
billz
b654e6bb33 Add Bootstrap has-validation class to required fields 2025-10-19 09:17:54 -07:00
Bill Zimmerman
6093b8107f Merge pull request #1964 from RaspAP/fix/dependencies-resolvconf
Fix: Install openresolv package for Debian 13
2025-10-18 14:54:19 +02:00
billz
1b708bc947 Install openresolv package for Debian 13 2025-10-18 03:45:43 -07:00
billz
6a61320ea0 Add contextual bridged interface settings 2025-10-17 10:28:16 -07:00
Bill Zimmerman
321c98de24 Update README.md 2025-10-13 13:39:43 +02:00
Bill Zimmerman
b9e78faf30 Set release: ${{ matrix.release }} in use clause 2025-10-13 09:44:43 +02:00
Bill Zimmerman
e3991a476b Set release: "trixie" 2025-10-13 09:37:03 +02:00
Bill Zimmerman
0f9583e366 Use matrix.release for image_ + asset_name 2025-10-13 09:34:48 +02:00
billz
34dd95f341 Update release version 2025-10-12 23:46:51 -07:00
billz
a33cb4ad57 Update plugins submodule to latest master 2025-10-12 23:46:25 -07:00
Bill Zimmerman
6148d39e1b Update usimd/pi-gen-action@v1.11.0 (latest) 2025-10-13 08:23:27 +02:00
Bill Zimmerman
589126a83c Merge pull request #1955 from RaspAP/feat/plugin-installer-dpkgs
Feature: Extend plugin installer with .deb package support
2025-10-11 09:57:29 +02:00
billz
a844328da3 php7.4 compatibility: str_starts_with -> strncmp 2025-10-11 00:45:21 -07:00
Bill Zimmerman
4b67191823 Merge pull request #1962 from brazier/fix/no-vpn-provider
Fix: Empty VPN providers info when selecting 'None'
2025-10-11 08:43:29 +02:00
Bill Zimmerman
ccd4db70bc Merge pull request #1960 from brazier/feat&fix/sshgit
Feature & fixes: Add ssh/pubkey option, resolve minor bugs
2025-10-11 08:41:21 +02:00
brazier
895b880d69 fix empty providers info
Fix empty providers infor when selecting "0 None" in the list
2025-10-11 00:32:52 +02:00
brazier
e0d0ec05e3 refrence source_dir instead of hardlink
Change hardlink to $source_dir
2025-10-10 20:01:54 +02:00
brazier
29be30479e Update common.sh
Add -x/--use-ssh
Add missing "f" at "rm -r $sourcedir"
Add missing "_" infront of functions
2025-10-10 18:31:40 +02:00
brazier
ae09dda000 Update raspbian.sh
Add -x/--use-ssh
Fix duplicate -n(username/uninstall) temp -z
2025-10-10 18:28:32 +02:00
billz
e3e9adb63e Extend plugin-helper to install .deb packages 2025-10-10 04:22:10 -07:00
billz
8bf4116b42 Create installDebianPackages(), select .deb dpkg for current arch 2025-10-10 04:21:39 -07:00
Bill Zimmerman
2c896bbc12 Update supported distros 2025-10-07 21:04:55 +02:00
24 changed files with 2628 additions and 657 deletions

View File

@@ -52,13 +52,15 @@ body:
attributes:
label: Operating System
options:
- Raspberry Pi OS (64-bit) Lite Bookworm
- Raspberry Pi OS (32-bit) Lite Bookworm
- Raspberry Pi OS (64-bit) Desktop Bookwom
- Raspberry Pi OS (64-bit) Lite Bullseye
- Raspberry Pi OS (32-bit) Lite Bullseye
- Armbian 23.05 (Suni)
- Debian Bookworm
- Raspberry Pi OS Lite 64-bit Debian 13 (trixie)
- Raspberry Pi OS Lite 32-bit Debian 13 (trixie)
- Raspberry Pi OS Lite 64-bit Debian 12 (bookworm)
- Raspberry Pi OS Lite 32-bit Debian 12 (bookworm)
- Raspberry Pi OS Desktop 64-bit Debian 12 (bookworm)
- Raspberry Pi OS Lite 64-bit Debian 11 (bullseye)
- Raspberry Pi OS Lite 32-bit Debian 11 (bullseye)
- Armbian 23.11 (jammy)
- Debian 12 (bookworm)
validations:
required: true
- type: dropdown

View File

@@ -15,8 +15,10 @@ jobs:
include:
- arch: "32-bit"
pi_gen_version: "master"
release: "trixie"
- arch: "64-bit"
pi_gen_version: "arm64"
release: "trixie"
fail-fast: false
steps:
- name: Checkout repository
@@ -27,19 +29,20 @@ jobs:
- name: Build RaspAP Image
id: build
uses: usimd/pi-gen-action@v1
uses: usimd/pi-gen-action@v1.11.0
with:
image-name: "raspap-bookworm-${{ matrix.arch == '32-bit' && 'armhf' || 'arm64' }}-lite-${{ github.event.inputs.tag || github.ref_name }}"
release: ${{ matrix.release }}
image-name: "raspap-${{ matrix.release }}-${{ matrix.arch == '32-bit' && 'armhf' || 'arm64' }}-lite-${{ github.event.inputs.tag || github.ref_name }}"
enable-ssh: 1
stage-list: stage0 stage1 stage2 ./stage-raspap
verbose-output: true
pi-gen-version: ${{ matrix.pi_gen_version }}
pi-gen-repository: RaspAP/pi-gen
pi-gen-repository: billz/pi-gen
- name: Upload Artifact
uses: svenstaro/upload-release-action@v2
with:
asset_name: "raspap-bookworm-${{ matrix.arch == '32-bit' && 'armhf' || 'arm64' }}-lite-${{ github.event.inputs.tag || github.ref_name }}.img.zip"
asset_name: "raspap-${{ matrix.release }}-${{ matrix.arch == '32-bit' && 'armhf' || 'arm64' }}-lite-${{ github.event.inputs.tag || github.ref_name }}.img.zip"
file: ${{ steps.build.outputs.image-path }}
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.event.inputs.tag || github.ref }}

View File

@@ -1,5 +1,5 @@
![RaspAP Hero](https://i.imgur.com/aNAG3Wa.jpeg)
[![Release 3.4.3](https://img.shields.io/badge/release-v3.4.3-green)](https://github.com/raspap/raspap-webgui/releases) [![Awesome](https://awesome.re/badge.svg)](https://github.com/thibmaek/awesome-raspberry-pi) [![Join Insiders](https://img.shields.io/static/v1?label=Insiders&message=%E2%9D%A4&logo=GitHub&color=ff69b4)](https://github.com/sponsors/RaspAP) [![Build Status](https://app.travis-ci.com/RaspAP/raspap-webgui.svg?branch=master)](https://app.travis-ci.com/RaspAP/raspap-webgui) [![Crowdin](https://badges.crowdin.net/raspap/localized.svg)](https://crowdin.com/project/raspap) [![Twitter URL](https://img.shields.io/twitter/url?label=%40RaspAP&logoColor=%23d8224c&url=https%3A%2F%2Ftwitter.com%2Frasp_ap)](https://twitter.com/rasp_ap) [![Reddit](https://img.shields.io/badge/%2Fr%2FRaspAP-e05d44?style=flat&logo=Reddit&logoColor=white&labelColor=e05d44&color=b14835)](https://reddit.com/r/RaspAP) [![Discord](https://img.shields.io/discord/642436993451819018?color=7289DA&label=Discord&logo=discord&style=flat)](https://discord.gg/KVAsaAR)
[![Release 3.4.5](https://img.shields.io/badge/release-v3.4.5-green)](https://github.com/raspap/raspap-webgui/releases) [![Awesome](https://awesome.re/badge.svg)](https://github.com/thibmaek/awesome-raspberry-pi) [![Join Insiders](https://img.shields.io/static/v1?label=Insiders&message=%E2%9D%A4&logo=GitHub&color=ff69b4)](https://github.com/sponsors/RaspAP) [![Build Status](https://app.travis-ci.com/RaspAP/raspap-webgui.svg?branch=master)](https://app.travis-ci.com/RaspAP/raspap-webgui) [![Crowdin](https://badges.crowdin.net/raspap/localized.svg)](https://crowdin.com/project/raspap) [![Twitter URL](https://img.shields.io/twitter/url?label=%40RaspAP&logoColor=%23d8224c&url=https%3A%2F%2Ftwitter.com%2Frasp_ap)](https://twitter.com/rasp_ap) [![Reddit](https://img.shields.io/badge/%2Fr%2FRaspAP-e05d44?style=flat&logo=Reddit&logoColor=white&labelColor=e05d44&color=b14835)](https://reddit.com/r/RaspAP) [![Discord](https://img.shields.io/discord/642436993451819018?color=7289DA&label=Discord&logo=discord&style=flat)](https://discord.gg/KVAsaAR)
RaspAP is feature-rich wireless router software that _just works_ on many popular [Debian-based devices](#supported-operating-systems), including the Raspberry Pi. Our [custom OS images](#pre-built-image), [Quick installer](#quick-installer) and [Docker container](#docker-support) create a known-good default configuration for all current Raspberry Pis with onboard wireless. A fully responsive, mobile-ready interface gives you control over the relevant services and networking options. Advanced DHCP settings, [WireGuard](https://docs.raspap.com/wireguard/), [Tailscale](https://docs.raspap.com/tailscale/) and [OpenVPN](https://docs.raspap.com/openvpn/) support, [SSL certificates](https://docs.raspap.com/ssl/), [ad blocking](#ad-blocking), security audits, [captive portal integration](https://docs.raspap.com/captive/), themes and [multilingual options](https://docs.raspap.com/translations/) are included.
@@ -41,10 +41,10 @@ RaspAP gives you two different ways to get up and running quickly. The simplest
### Pre-built image
Custom Raspberry Pi OS Lite images with the latest RaspAP are available for [direct download](https://github.com/RaspAP/raspap-webgui/releases/latest). This includes both 32- and 64-bit builds for ARM architectures.
| Operating system | Debian version | Kernel version | RaspAP version | Size |
| ---------------------| ---------------|-----------------|----------------|-------|
| Raspberry Pi OS (64-bit) Lite | 12 (bookworm) | 6.6 | Latest | 777 MB|
| Raspberry Pi OS (32-bit) Lite | 12 (bookworm) | 6.6 | Latest | 805 MB|
| Operating system | Debian version | Kernel version | RaspAP version | Size |
| ------------ | -------------- | -------------- | -------------- | ---- |
| Raspberry Pi OS (64-bit) Lite | 13 (trixie) | 6.12 | Latest | 826 MB |
| Raspberry Pi OS (32-bit) Lite | 13 (trixie) | 6.12 | Latest | 799 MB |
These images are automatically generated with each release of RaspAP. You may choose between an `arm64` or `armhf` (32-bit) based build. Refer to [this resource](https://www.raspberrypi.com/software/operating-systems/) to ensure compatibility with your hardware.
@@ -84,7 +84,8 @@ It's _strongly recommended_ that your first post-install action is to change the
Please [read this](https://docs.raspap.com/issues/) before reporting an issue.
## Join Insiders
[![](https://i.imgur.com/eml7k0b.png)](https://github.com/sponsors/RaspAP/)
[<img src="https://github.com/user-attachments/assets/832f1f0d-517a-4d73-8b62-068cf1a2041d" width="320">](https://github.com/sponsors/RaspAP/)
RaspAP is free software, but powered by _your_ support. If you find RaspAP useful for your personal or commercial projects, [become an Insider](https://github.com/sponsors/RaspAP/) and get early access to [exclusive features](https://docs.raspap.com/insiders/#exclusive-features) in the [Insiders Edition](https://docs.raspap.com/insiders/).
@@ -92,8 +93,6 @@ A tangible side benefit of sponsorship is that **Insiders** are able to help _st
## WireGuard support
![](https://i.imgur.com/5YDv37e.png)
WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be considerably more performant than OpenVPN, and is generally regarded as the most secure, easiest to use, and simplest VPN solution for modern Linux distributions.
WireGuard may be optionally installed by the [Quick Installer](https://docs.raspap.com/quick/). Once this is done, you can manage local (server) settings, create a peer configuration and control the `wg-quick` service with RaspAP.
@@ -102,8 +101,6 @@ Details are [provided here](https://docs.raspap.com/wireguard/).
## OpenVPN support
![](https://i.imgur.com/ta7tCon.png)
OpenVPN may be optionally installed by the Quick Installer. Once this is done, you can [manage client configurations](https://docs.raspap.com/openvpn/) and the `openvpn-client` service with RaspAP.
To configure an OpenVPN client, upload a valid .ovpn file and, optionally, specify your login credentials. RaspAP will store your client configuration and add firewall rules to forward traffic from OpenVPN's `tun0` interface to your configured wireless interface.
@@ -137,15 +134,17 @@ RaspAP provides an 802.11ac wireless mode option for supported hardware (current
## Supported operating systems
RaspAP was originally made for Raspbian, but now also installs on the following Debian-based distros.
| Distribution | Release | Architecture | Support |
|---|:---:|:---:|:---:|
| Raspberry Pi OS | (64-bit) Lite Bookworm | ARM | Official |
| Raspberry Pi OS | (32-bit) Lite Bookworm | ARM | Official |
| Raspberry Pi OS | (64-bit) Desktop Bookworm | ARM | Official |
| Raspberry Pi OS | (64-bit) Lite Bullseye | ARM | Official |
| Raspberry Pi OS | (32-bit) Lite Bullseye | ARM | Official |
| Armbian | 23.11 (Jammy) | [ARM](https://docs.armbian.com/#supported-socs) | Beta |
| Debian | Bookworm | ARM / x86_64 | Beta |
| Distribution | Release | Architecture | Support |
| ------------ | ------- | ------------ | ------- |
| Raspberry Pi OS Lite | 64-bit Debian 13 (trixie) | ARM | Official |
| Raspberry Pi OS Lite | 32-bit Debian 13 (trixie) | ARM | Official |
| Raspberry Pi OS Lite | 64-bit Debian 12 (bookworm) | ARM | Official |
| Raspberry Pi OS Lite | 32-bit Debian 12 (bookworm) | ARM | Official |
| Raspberry Pi OS Desktop | 64-bit Debian 12 (bookworm) | ARM | Official |
| Raspberry Pi OS Lite | 64-bit Debian 11 (bullseye) | ARM | Official |
| Raspberry Pi OS Lite | 32-bit Debian 11 (bullseye) | ARM | Official |
| Armbian | 23.11 (jammy) | ARM | Beta |
| Debian | 12 (bookworm) | ARM / x86_64 | Beta |
<img src="https://i.imgur.com/XiAJNKb.png" style="width:480px;" />

View File

@@ -78,6 +78,38 @@ $(document).on("submit", ".js-dhcp-settings-form", function(e) {
$(".js-add-dhcp-upstream-server").trigger("click");
});
document.addEventListener('DOMContentLoaded', function() {
const bridgeCheckbox = document.getElementById('chxbridgedenable');
const bridgeSection = document.getElementById('bridgeStaticIpSection');
const staticIpInput = document.getElementById('bridgeStaticIp');
const netmaskInput = document.getElementById('bridgeNetmask');
const gatewayInput = document.getElementById('bridgeGateway');
const dnsInput = document.getElementById('bridgeDNS');
const previewIp = document.getElementById('previewStaticIp');
const bridgeInputs = [staticIpInput, netmaskInput, gatewayInput, dnsInput];
// toggle visibility and required fields
bridgeCheckbox.addEventListener('change', function() {
if (this.checked) {
bridgeSection.style.display = 'block';
bridgeInputs.forEach(input => input.setAttribute('required', 'required'));
} else {
bridgeSection.style.display = 'none';
bridgeInputs.forEach(input => input.removeAttribute('required'));
}
});
// auto-populate DNS when gateway loses focus
gatewayInput.addEventListener('blur', function() {
const gatewayVal = this.value.trim();
if (gatewayVal !== '' && dnsInput.value.trim() === '') {
dnsInput.value = gatewayVal;
}
});
});
/**
* mark a form field, e.g. a select box, with the class `.js-field-preset`
* and give it an attribute `data-field-preset-target` with a text field's

View File

@@ -7,7 +7,7 @@ if (!defined('RASPI_CONFIG')) {
$defaults = [
'RASPI_BRAND_TEXT' => 'RaspAP',
'RASPI_BRAND_TITLE' => RASPI_BRAND_TEXT.' Admin Panel',
'RASPI_VERSION' => '3.4.3',
'RASPI_VERSION' => '3.4.5',
'RASPI_CONFIG_NETWORK' => RASPI_CONFIG.'/networking/defaults.json',
'RASPI_CONFIG_PROVIDERS' => 'config/vpn-providers.json',
'RASPI_CONFIG_API' => RASPI_CONFIG.'/api',

View File

@@ -3,6 +3,7 @@
use RaspAP\Networking\Hotspot\HostapdManager;
use RaspAP\Networking\Hotspot\HotspotService;
use RaspAP\Networking\Hotspot\WiFiManager;
use RaspAP\Networking\Hotspot\DhcpcdManager;
use RaspAP\Messages\StatusMessage;
use RaspAP\System\Sysinfo;
@@ -18,6 +19,7 @@ function DisplayHostAPDConfig()
$hostapd = new HostapdManager();
$hotspot = new HotspotService();
$status = new StatusMessage();
$dhcpcd = new DhcpcdManager();
$system = new Sysinfo();
$operatingSystem = $system->operatingSystem();
@@ -61,7 +63,15 @@ function DisplayHostAPDConfig()
$status->addMessage($line, 'info');
}
} elseif (isset($_POST['SaveHostAPDSettings'])) {
$hotspot->saveSettings($_POST, $arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $reg_domain, $status);
$result = $hotspot->saveSettings(
$_POST,
$arrSecurity,
$arrEncType,
$arr80211Standard,
$interfaces,
$reg_domain,
$status
);
} elseif (isset($_POST['StopHotspot'])) {
$status->addMessage('Attempting to stop hotspot', 'info');
exec('sudo /bin/systemctl stop hostapd.service', $return);
@@ -96,6 +106,30 @@ function DisplayHostAPDConfig()
error_log('Error: ' . $e->getMessage());
}
// bridge configuration
if (!empty($arrHostapdConf['BridgedEnable']) && (int)$arrHostapdConf['BridgedEnable'] === 1) {
$iface = 'br0';
$bridgeConfig = $dhcpcd->getInterfaceConfig($iface);
if (is_array($bridgeConfig) && !empty($bridgeConfig)) {
$arrConfig['bridgeStaticIP'] = !empty($bridgeConfig['StaticIP'])
? $bridgeConfig['StaticIP']
: '192.168.1.10';
$arrConfig['bridgeNetmask'] = !empty($bridgeConfig['SubnetMask'])
? mask2cidr($bridgeConfig['SubnetMask'])
: '24';
$arrConfig['bridgeGateway'] = !empty($bridgeConfig['StaticRouters'])
? $bridgeConfig['StaticRouters']
: '192.168.1.1';
$arrConfig['bridgeDNS'] = !empty($bridgeConfig['StaticDNS'])
? $bridgeConfig['StaticDNS']
: '192.168.1.1';
}
}
// assign disassoc_low_ack boolean if value is set
$arrConfig['disassoc_low_ack_bool'] = isset($arrConfig['disassoc_low_ack']) ? 1 : 0;
$hostapdstatus = $system->hostapdStatus();

View File

@@ -16,16 +16,24 @@
$validLocales = array_keys(getLocales());
if (!empty($_POST['locale']) && in_array($_POST['locale'], $validLocales, true)) {
$_SESSION['locale'] = $_POST['locale'];
setcookie('locale', $_POST['locale'], time() + (86400 * 30), '/', '', false, true);
}
// Set locale from browser detection, if not already set
// Set locale from cookie or browser detection, if not already set in session
if (empty($_SESSION['locale'])) {
$_SESSION['locale'] = detectBrowserLocale();
if (isset($_COOKIE['locale']) && in_array($_COOKIE['locale'], $validLocales, true)) {
$_SESSION['locale'] = $_COOKIE['locale'];
} else {
$_SESSION['locale'] = detectBrowserLocale();
setcookie('locale', $_SESSION['locale'], time() + (86400 * 30), '/', '', false, true);
}
}
// Enforce only valid locale values in session
if (!in_array($_SESSION['locale'], $validLocales, true)) {
$_SESSION['locale'] = 'en_GB.UTF-8';
// Update cookie with default locale
setcookie('locale', $_SESSION['locale'], time() + (86400 * 30), '/', '', false, true);
}
// Apply locale settings

View File

@@ -7,14 +7,14 @@
* Enables use of simple web interface rather than SSH to control WiFi and related services on the Raspberry Pi.
* Recommended distribution is Raspberry Pi OS (64-bit) Lite. Specific instructions to install the supported software are
* in the README and original post by @SirLagz. For a quick run through, the packages required for the WebGUI are:
* lighttpd (version 1.4.69 installed via apt)
* php-cgi (version 8.2.28 installed via apt)
* lighttpd (version 1.4.79 installed via apt)
* php-fpm (version 8.4.11 installed via apt)
* along with their supporting packages, php8.2 will also need to be enabled.
*
* @author Lawrence Yau <sirlagz@gmail.com>
* @author Bill Zimmerman <billzimmerman@gmail.com>
* @license GNU General Public License, version 3 (GPL-3.0)
* @version 3.4.3
* @version 3.4.5
* @link https://github.com/RaspAP/raspap-webgui/
* @link https://raspap.com/
* @see http://sirlagz.net/2013/02/08/raspap-webgui/

View File

@@ -34,7 +34,16 @@ if [ "$insiders" == 1 ]; then
repo="RaspAP/raspap-insiders"
branch=${RASPAP_INSIDERS_LATEST}
fi
git_source_url="https://github.com/$repo"
#Use ssh IF $ssh is set AND $username and $acctoken IS NOT set
if [ -n "$username" ] && [ -n "$acctoken" ]; then
git_source_url="https://${username}:${acctoken}@github.com/$repo"
ssh=0
elif [ "$ssh" == 1 ]; then
git_source_url="git@github.com:$repo"
else
git_source_url="https://github.com/$repo"
fi
webroot_dir="/var/www/html"
# NOTE: all the below functions are overloadable for system-specific installs
@@ -277,8 +286,8 @@ function _install_dependencies() {
sudo apt-get install -y lighttpd git hostapd dnsmasq iptables-persistent $php_package $dhcpcd_package $iw_package $rsync_package $network_tools $ifconfig_package vnstat qrencode jq isoquery || _install_status 1 "Unable to install dependencies"
if [[ "$php_package" == *"-fpm" ]]; then
install_log "Enabling lighttpd fastcgi-php-fpm module for $php_package"
sudo lighty-enable-mod fastcgi-php-fpm || install_status 1 "Unable to enable fastcgi-php-fpm module"
_install_log "Enabling lighttpd fastcgi-php-fpm module for $php_package"
sudo lighty-enable-mod fastcgi-php-fpm || _install_status 1 "Unable to enable fastcgi-php-fpm module"
fi
_install_status 0
@@ -498,6 +507,7 @@ function _install_provider() {
if [ "$answer" != "${answer#[0]}" ]; then
_install_status 0 "(Skipped)"
skip=true
break
elif [[ "$answer" =~ ^[0-9]+$ ]] && [[ -n ${options[$answer]+abc} ]]; then
break
@@ -506,25 +516,25 @@ function _install_provider() {
fi
done
fi
if ! [ "$skip" ]; then
selected="${options[$answer]}"
echo "Configuring support for ${selected%%|*}"
bin_path=${selected#*|}
if ! grep -q "$bin_path" "$webroot_dir/installers/raspap.sudoers"; then
echo "Adding $bin_path to raspap.sudoers"
echo "www-data ALL=(ALL) NOPASSWD:$bin_path *" | sudo tee -a "$webroot_dir/installers/raspap.sudoers" > /dev/null || _install_status 1 "Unable to modify raspap.sudoers"
fi
echo "Enabling administration option for ${selected%%|*}"
sudo sed -i "s/\('RASPI_VPN_PROVIDER_ENABLED', \)false/\1true/g" "$webroot_dir/includes/config.php" || _install_status 1 "Unable to modify config.php"
selected="${options[$answer]}"
echo "Configuring support for ${selected%%|*}"
bin_path=${selected#*|}
if ! grep -q "$bin_path" "$webroot_dir/installers/raspap.sudoers"; then
echo "Adding $bin_path to raspap.sudoers"
echo "www-data ALL=(ALL) NOPASSWD:$bin_path *" | sudo tee -a "$webroot_dir/installers/raspap.sudoers" > /dev/null || _install_status 1 "Unable to modify raspap.sudoers"
fi
echo "Enabling administration option for ${selected%%|*}"
sudo sed -i "s/\('RASPI_VPN_PROVIDER_ENABLED', \)false/\1true/g" "$webroot_dir/includes/config.php" || _install_status 1 "Unable to modify config.php"
echo "Adding VPN provider to $raspap_dir/provider.ini"
if [ ! -f "$raspap_dir/provider.ini" ]; then
sudo touch "$raspap_dir/provider.ini"
echo "providerID = $answer" | sudo tee "$raspap_dir/provider.ini" > /dev/null || _install_status 1 "Unable to create $raspap_dir/provider.ini"
elif ! grep -q "providerID = $answer" "$raspap_dir/provider.ini"; then
echo "providerID = $answer" | sudo tee "$raspap_dir/provider.ini" > /dev/null || _install_status 1 "Unable to write to $raspap_dir/provider.ini"
fi
echo "Adding VPN provider to $raspap_dir/provider.ini"
if [ ! -f "$raspap_dir/provider.ini" ]; then
sudo touch "$raspap_dir/provider.ini"
echo "providerID = $answer" | sudo tee "$raspap_dir/provider.ini" > /dev/null || _install_status 1 "Unable to create $raspap_dir/provider.ini"
elif ! grep -q "providerID = $answer" "$raspap_dir/provider.ini"; then
echo "providerID = $answer" | sudo tee "$raspap_dir/provider.ini" > /dev/null || _install_status 1 "Unable to write to $raspap_dir/provider.ini"
fi
fi
_install_status 0
}
@@ -537,6 +547,13 @@ function _install_wireguard() {
fi
echo "Installing wireguard from apt"
sudo apt-get install -y wireguard $wg_dep || _install_status 1 "Unable to install wireguard"
# create shim for resolvconf under debian 13
if { ! command -v resolvconf >/dev/null || [ "$RELEASE" == 13 ]; } then
echo "Applying resolvconf shim to prevent DNS conflicts"
sudo ln -sf /usr/bin/true /usr/local/bin/resolvconf || _install_status 1 "Failed to apply resolvconf shim"
fi
echo "Enabling wg-quick@wg0"
sudo systemctl enable wg-quick@wg0 || _install_status 1 "Failed to enable wg-quick service"
echo "Enabling WireGuard management option"
@@ -605,22 +622,16 @@ function _download_latest_files() {
source_dir="/tmp/raspap-webgui"
if [ -d "$source_dir" ]; then
echo "Temporary download destination $source_dir exists. Removing..."
rm -r "$source_dir"
rm -rf "$source_dir"
fi
if [ "$repo" == "RaspAP/raspap-insiders" ]; then
if [ -n "$username" ] && [ -n "$acctoken" ]; then
insiders_source_url="https://${username}:${acctoken}@github.com/$repo"
git clone --branch $branch --depth 1 --recurse-submodules -c advice.detachedHead=false $insiders_source_url $source_dir || clone=false
git -C $source_dir submodule update --remote plugins || clone=false
else
_install_status 3
echo "Insiders please read this: https://docs.raspap.com/insiders/#authentication"
fi
fi
if [ -z "$insiders_source_url" ]; then
git clone --branch $branch --depth 1 --recurse-submodules -c advice.detachedHead=false $git_source_url $source_dir || clone=false
git -C $source_dir submodule update --remote plugins || clone=false
if [ "$insiders" == 1 ] && [ "$ssh" != 1 ] && [[ -z "$username" || -z "$acctoken" ]]; then
_install_status 3
_install_status 0 "Insiders please read this: https://docs.raspap.com/insiders/#authentication"
fi
git clone --branch $branch --depth 1 --recurse-submodules -c advice.detachedHead=false $git_source_url $source_dir || clone=false
git -C $source_dir submodule update --remote plugins || clone=false
if [ "$clone" = false ]; then
_install_status 1 "Unable to download files from GitHub"
echo "The installer cannot continue." >&2

View File

@@ -41,6 +41,21 @@ case "$action" in
echo "OK"
;;
"deb")
[ $# -lt 1 ] && { echo "Usage: $0 deb <deb_file>"; exit 1; }
deb_file="$1"
if [ ! -f "$deb_file" ]; then
echo "Error: File not found: $deb_file"
exit 1
fi
echo "Installing .deb package: $deb_file"
dpkg -i "$deb_file"
echo "OK"
;;
"user")
[ $# -lt 2 ] && { echo "Usage: $0 user <username> <password>."; exit 1; }

View File

@@ -49,6 +49,7 @@ OPTIONS:
-b, --branch <name> Overrides the default git branch (latest release)
-t, --token <accesstoken> Specify a GitHub token to access a private repository
-n, --name <username> Specify a GitHub username to access a private repository
-x, --use-ssh Use ssh instead of https for git
-u, --upgrade Upgrades an existing installation to the latest release version
-d, --update Updates an existing installation to the latest release version
-p, --path <path> Used with -d, --update, sets the existing install path
@@ -56,7 +57,7 @@ OPTIONS:
-m, --minwrite Configures a microSD card for minimum write operation
-k, --check <flag> Sets the connectivity check flag (default is 1=perform check)
-v, --version Outputs release info and exits
-n, --uninstall Loads and executes the uninstaller
-z, --uninstall Loads and executes the uninstaller
-h, --help Outputs usage notes and exits
Examples:
@@ -106,6 +107,7 @@ function _parse_params() {
adblock_option=1
wg_option=1
insiders=0
ssh=0
minwrite=0
acctoken=""
path=""
@@ -165,6 +167,9 @@ function _parse_params() {
-m|--minwrite)
minwrite=1
;;
-x|--use-ssh)
ssh=1
;;
-t|--token)
acctoken="$2"
shift
@@ -187,7 +192,7 @@ function _parse_params() {
-v|--version)
_version
;;
-n|--uninstall)
-z|--uninstall)
uninstall=1
;;
-*|--*)

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -10,7 +10,7 @@ msgstr ""
"Project-Id-Version: 1.2.1\n"
"Report-Msgid-Bugs-To: Bill Zimmerman <billzimmerman@gmail.com>\n"
"POT-Creation-Date: 2017-10-19 08:56+0000\n"
"PO-Revision-Date: 2022-01-05 20:35+0000\n"
"PO-Revision-Date: 2025-10-20 08:35+0000\n"
"Last-Translator: Bill Zimmerman <billzimmerman@gmail.com>\n"
"Language-Team: \n"
"Language: en_US\n"
@@ -414,9 +414,6 @@ msgstr "Signal quality"
msgid "WAN IP"
msgstr "WAN IP"
msgid "Web-GUI"
msgstr "Web-GUI"
msgid "Signal strength"
msgstr "Signal strength"
@@ -581,11 +578,8 @@ msgstr "This option adds <code>dhcp-host</code> entries to the dnsmasq configura
msgid "This toggles the <code>gateway</code>/<code>nogateway</code> option for this interface in the dhcpcd.conf file."
msgstr "This toggles the <code>gateway</code>/<code>nogateway</code> option for this interface in the dhcpcd.conf file."
msgid "This toggles the <code>nohook wpa_supplicant</code> option for this interface in the DHCPCD configuration."
msgstr "This toggles the <code>nohook wpa_supplicant</code> option for this interface in the DHCPCD configuration."
msgid "Enable this only if you want your device to use this interface as its primary route to the internet."
msgstr "Enable this only if you want your device to use this interface as its primary route to the internet."
msgid "This toggles the <code>nohook wpa_supplicant</code> option for this interface in the dhcpcd.conf file."
msgstr "This toggles the <code>nohook wpa_supplicant</code> option for this interface in the dhcpcd.conf file."
msgid "Disable wpa_supplicant dhcp hook for this interface"
msgstr "Disable wpa_supplicant dhcp hook for this interface"
@@ -735,6 +729,9 @@ msgstr "Bridged AP mode"
msgid "WiFi repeater mode"
msgstr "WiFi repeater mode"
msgid "Dual band AP mode"
msgstr "Dual band AP mode"
msgid "Hide SSID in broadcast"
msgstr "Hide SSID in broadcast"
@@ -837,6 +834,75 @@ msgstr "Parameter hiddenSSID contains invalid configuration value."
msgid "Parameter hiddenSSID is not a number."
msgstr "Parameter hiddenSSID is not a number."
msgid "Bridge interface configuration"
msgstr "Bridge interface configuration"
msgid "Configure a static IP address for the <code>br0</code> interface to maintain connectivity during bridge mode activation."
msgstr "Configure a static IP address for the <code>br0</code> interface to maintain connectivity during bridge mode activation."
msgid "Static IP Address"
msgstr "Static IP Address"
msgid "Netmask / CIDR"
msgstr "Netmask / CIDR"
msgid "Example: 192.168.1.100"
msgstr "Example: 192.168.1.100"
msgid "CIDR notation (e.g., 24 for 255.255.255.0)"
msgstr "CIDR notation (e.g., 24 for 255.255.255.0)"
msgid "Gateway"
msgstr "Gateway"
msgid "Your router's IP address"
msgstr "Your router's IP address"
msgid "Usually same as gateway"
msgstr "Usually same as gateway"
msgid "Bridge static IP address must be a valid IPv4 address"
msgstr "Bridge static IP address must be a valid IPv4 address"
msgid "Bridge netmask must be a number between 1 and 32"
msgstr "Bridge netmask must be a number between 1 and 32"
msgid "Bridge netmask is required when using static IP"
msgstr "Bridge netmask is required when using static IP"
msgid "Bridge gateway must be a valid IPv4 address"
msgstr "Bridge gateway must be a valid IPv4 address"
msgid "Bridge gateway is required when using static IP"
msgstr "Bridge gateway is required when using static IP"
msgid "Bridge DNS server must be a valid IPv4 address"
msgstr "Bridge DNS server must be a valid IPv4 address"
msgid "Bridge DNS server is required when using static IP"
msgstr "Bridge DNS server is required when using static IP"
msgid "Bridge static IP and gateway must be in the same subnet"
msgstr "Bridge static IP and gateway must be in the same subnet"
msgid "Please enter a valid IPv4 address"
msgstr "Please enter a valid IPv4 address"
msgid "Please enter a valid netmask"
msgstr "Please enter a valid netmask"
msgid "DHCP configuration for br0 enabled"
msgstr "DHCP configuration for br0 enabled"
msgid "Unable to save WiFi hotspot settings due to validation errors"
msgstr "Unable to save WiFi hotspot settings due to validation errors"
msgid "Enable AP isolation"
msgstr "Enable AP isolation"
msgid "Blocks wireless clients from seeing or connecting to each other. Recommended for guest networks and public access points."
msgstr "Blocks wireless clients from seeing or connecting to each other. Recommended for guest networks and public access points."
#: includes/networking.php
msgid "Summary"
msgstr "Summary"
@@ -886,14 +952,14 @@ msgstr "Devices"
msgid "Diagnostics"
msgstr "Diagnostics"
msgid "Properties of network devices"
msgstr "Properties of network devices"
msgid "Network devices"
msgstr "Network devices"
msgid "Device"
msgstr "Device"
msgid "MAC"
msgstr "MAC"
msgid "MAC address"
msgstr "MAC address"
msgid "USB vid/pid"
msgstr "USB vid/pid"
@@ -907,11 +973,11 @@ msgstr "Fixed name"
msgid "Change"
msgstr "Change"
msgid "Settings for Mobile Data Devices"
msgstr "Settings for Mobile Data Devices"
msgid "Mobile data settings"
msgstr "Mobile data settings"
msgid "PIN of SIM card"
msgstr "PIN of SIM card"
msgid "SIM card PIN number"
msgstr "SIM card PIN number"
msgid "APN Settings (Modem device ppp0)"
msgstr "APN Settings (Modem device ppp0)"
@@ -1256,11 +1322,29 @@ msgstr "Installed"
msgid "Alert messages"
msgstr "Alert messages"
msgid "Alert close timeout (milliseconds)"
msgstr "Alert close timeout (milliseconds)"
msgid "Automatically close alerts after a specified timeout"
msgstr "Automatically close alerts after a specified timeout"
msgid "Alert close timeout (milliseconds)"
msgstr "Alert close timeout (milliseconds)"
msgid "To <a href=\"%s\" target=\"_blank\">inspect adapters</a> attached to this device, click or tap the button below."
msgstr "To <a href=\"%s\" target=\"_blank\">inspect adapters</a> attached to this device, click or tap the button below."
msgid "The adapter inspection tool returns details about external WLAN devices including drivers, supported modes and so on."
msgstr "The adapter inspection tool returns details about external WLAN devices including drivers, supported modes and so on."
msgid "Choose a network interface to inspect"
msgstr "Choose a network interface to inspect"
msgid "Select an interface..."
msgstr "Select an interface..."
msgid "Adapter health check"
msgstr "Adapter health check"
msgid "Inspect adapters"
msgstr "Inspect adapters"
#: includes/data_usage.php
msgid "Data usage"
@@ -2198,12 +2282,30 @@ msgstr "Configure exit node"
msgid "The device <code>%s</code> is connected to your tailnet with the address <code>%s</code>."
msgstr "The device <code>%s</code> is connected to your tailnet with the address <code>%s</code>."
msgid "By default, Tailscale only routes traffic between the devices on which it's been installed. By configuring <code>%s</code> as an <strong>exit node</strong>, your public internet traffic will be routed through this device"
msgstr "By default, Tailscale only routes traffic between the devices on which it's been installed. By configuring <code>%s</code> as an <strong>exit node</strong>, your public internet traffic will be routed through this device"
msgid "By default, Tailscale only routes traffic between the devices on which it's been installed. You can also route all your public internet traffic by configuring a device on your network as a <strong>exit node</strong>"
msgstr "By default, Tailscale only routes traffic between the devices on which it's been installed. You can also route all your public internet traffic by configuring a device on your network as a <strong>exit node</strong>"
msgid "When you route all traffic through an exit node, you're effectively using default routes (0.0.0.0/0, ::/0), similar to how you would if you were using a typical VPN."
msgstr "When you route all traffic through an exit node, you're effectively using default routes (0.0.0.0/0, ::/0), similar to how you would if you were using a typical VPN."
msgid "You have the option of configuring this device as an exit node, or using another exit node in your tailnet."
msgstr "You have the option of configuring this device as an exit node, or using another exit node in your tailnet."
msgid "Select an existing exit node on your tailnet"
msgstr "Select an existing exit node on your tailnet"
msgid "This is a typical configuration if you're using this device as a VPN travel router, for example."
msgstr "This is a typical configuration if you're using this device as a VPN travel router, for example."
msgid "Configure this device as a new exit node"
msgstr "Configure this device as a new exit node"
msgid "By configuring this device as an exit node, public internet traffic from devices connected in your tailnet will be routed through it."
msgstr "By configuring this device as an exit node, public internet traffic from devices connected in your tailnet will be routed through it."
msgid "For security reasons, you must opt in to enable exit node functionality. The first step is to advertise <code>%s</code> as an exit node in your tailnet. In the next step, you'll allow this device to be an exit node."
msgstr "For security reasons, you must opt in to enable exit node functionality. The first step is to advertise <code>%s</code> as an exit node in your tailnet. In the next step, you'll allow this device to be an exit node."
msgid "Advertise <code>%s</code> as an exit node"
msgstr "Advertise <code>%s</code> as an exit node"
@@ -2219,12 +2321,370 @@ msgstr "Recommended for Tailscale exit nodes with Linux 6.2 or later kernels, th
msgid "This option enables transport layer offloads for better performance."
msgstr "This option enables transport layer offloads for better performance."
msgid "Select an exit node"
msgstr "Select an exit node"
msgid "To use <code>%s</code> as a VPN gateway, configure Tailscale to use an exit node. Tailscale's suggested node is indicated with a star."
msgstr "To use <code>%s</code> as a VPN gateway, configure Tailscale to use an exit node. Tailscale's suggested node is indicated with a star."
msgid "Advertise a <strong>subnet route</strong> for the active <code>%s</code> AP interface"
msgstr "Advertise a <strong>subnet route</strong> for the active <code>%s</code> AP interface"
msgid "Subnet routes let you extend your Tailscale network (known as a tailnet) to include devices that don't or can't run the Tailscale client."
msgstr "Subnet routes let you extend your Tailscale network (known as a tailnet) to include devices that don't or can't run the Tailscale client."
msgid "A subnet route acts as a gateway between your tailnet and a physical subnet. The subnet of the active AP interface is preconfigured below; edit if necessary."
msgstr "A subnet route acts as a gateway between your tailnet and a physical subnet. The subnet of the active AP interface is preconfigured below; edit if necessary."
msgid "Route LAN traffic through the exit node."
msgstr "Route LAN traffic through the exit node."
msgid "This will direct all LAN traffic to go through your exit node only."
msgstr "This will direct all LAN traffic to go through your exit node only."
msgid "Choose <strong>Next</strong> to configure <code>%s</code> to use the selected exit node with these options."
msgstr "Choose <strong>Next</strong> to configure <code>%s</code> to use the selected exit node with these options."
msgid "No exit nodes found on your tailnet. Choose <strong>Back</strong> to continue."
msgstr "No exit nodes found on your tailnet. Choose <strong>Back</strong> to continue."
msgid "Using exit node"
msgstr "Using exit node"
msgid "The device <code>%s</code> is configured to use exit node <code>%s</code>. It has the Tailscale MagicDNS address <code>%s</code>."
msgstr "The device <code>%s</code> is configured to use exit node <code>%s</code>. It has the Tailscale MagicDNS address <code>%s</code>."
msgid "Choose <strong>Save settings</strong> to continue."
msgstr "Choose <strong>Save settings</strong> to continue."
msgid "Choose <strong>Next</strong> to continue."
msgstr "Choose <strong>Next</strong> to continue."
msgid "Tailnet status"
msgstr "Tailnet status"
msgid "Current <code>tailnet</code> status is displayed below."
msgstr "Current <code>tailnet</code> status is displayed below."
msgid "Use Tailscale DNS settings (default)."
msgstr "Use Tailscale DNS settings (default)."
msgid "Uncheck to use local DNS. This sets <code>--accept-dns=false</code>."
msgstr "Uncheck to use local DNS. This sets <code>--accept-dns=false</code>."
msgid "Do not use Tailscale subnets (default on Linux)."
msgstr "Do not use Tailscale subnets (default on Linux)."
msgid "If subnet routes exist for your tailnet, you can route your device's traffic to a subnet router. Enabling this sets <code>--accept-routes=true</code>."
msgstr "If subnet routes exist for your tailnet, you can route your device's traffic to a subnet router. Enabling this sets <code>--accept-routes=true</code>."
msgid "If keys expire for a device, connections to/from the given endpoint will stop working."
msgstr "If keys expire for a device, connections to/from the given endpoint will stop working."
msgid "This option uses <code>--force-reauth</code> to renew the keys for this device."
msgstr "This option uses <code>--force-reauth</code> to renew the keys for this device."
#: wireshark plugin
msgid "Start capture"
msgstr "Start capture"
msgid "Stop capture"
msgstr "Stop capture"
msgid "Capture files"
msgstr "Capture files"
msgid "Capture interface"
msgstr "Capture interface"
msgid "Output file"
msgstr "Output file"
msgid "Path where capture file will be saved (.pcap format)"
msgstr "Path where capture file will be saved (.pcap format)"
msgid "File will be saved with .pcap extension"
msgstr "File will be saved with .pcap extension"
msgid "Capture filter (BPF syntax)"
msgstr "Capture filter (BPF syntax)"
msgid "Berkeley Packet Filter syntax. Leave empty to capture all traffic."
msgstr "Berkeley Packet Filter syntax. Leave empty to capture all traffic."
msgid "Examples: <code>port 80</code>, <code>host 192.168.1.1</code>, <code>tcp and not port 22</code>"
msgstr "Examples: <code>port 80</code>, <code>host 192.168.1.1</code>, <code>tcp and not port 22</code>"
msgid "Capture limits"
msgstr "Capture limits"
msgid "Packet count limit"
msgstr "Packet count limit"
msgid "Stop capture after this many packets. Leave empty for unlimited."
msgstr "Stop capture after this many packets. Leave empty for unlimited."
msgid "Duration limit (seconds)"
msgstr "Duration limit (seconds)"
msgid "Stop capture after this many seconds. Leave empty for unlimited."
msgstr "Stop capture after this many seconds. Leave empty for unlimited."
msgid "Ring buffer settings"
msgstr "Ring buffer settings"
msgid "File size (KB)"
msgstr "File size (KB)"
msgid "Create new file when this size is reached. Leave empty to disable."
msgstr "Create new file when this size is reached. Leave empty to disable."
msgid "10000 = 10 MB per file"
msgstr "10000 = 10 MB per file"
msgid "Number of files"
msgstr "Number of files"
msgid "Maximum number of ring buffer files to keep. Oldest files are deleted."
msgstr "Maximum number of ring buffer files to keep. Oldest files are deleted."
msgid "Advanced options"
msgstr "Advanced options"
msgid "Snapshot length (bytes)"
msgstr "Snapshot length (bytes)"
msgid "Limit the amount of data captured per packet. Leave empty for full packets."
msgstr "Limit the amount of data captured per packet. Leave empty for full packets."
msgid "96 bytes captures headers only, reduces file size"
msgstr "96 bytes captures headers only, reduces file size"
msgid "Promiscuous mode"
msgstr "Promiscuous mode"
msgid "Capture all packets on the network segment, not just those destined for this interface"
msgstr "Capture all packets on the network segment, not just those destined for this interface"
msgid "Quick filter presets"
msgstr "Quick filter presets"
msgid "Capture files generated by <code>tshark</code> are displayed below."
msgstr "Capture files generated by <code>tshark</code> are displayed below."
msgid "No capture files found in /tmp directory"
msgstr "No capture files found in /tmp directory"
msgid "Filename"
msgstr "Filename"
msgid "Size"
msgstr "Size"
msgid "Modified"
msgstr "Modified"
msgid "Actions"
msgstr "Actions"
msgid "Download file"
msgstr "Download file"
msgid "Delete file"
msgstr "Delete file"
msgid "Confirm deletion"
msgstr "Confirm deletion"
msgid "Are you sure you want to delete this file?"
msgstr "Are you sure you want to delete this file?"
msgid "All Traffic"
msgstr "All Traffic"
msgid "HTTP/HTTPS"
msgstr "HTTP/HTTPS"
msgid "ICMP (Ping)"
msgstr "ICMP (Ping)"
msgid "SSH"
msgstr "SSH"
msgid "Exclude SSH"
msgstr "Exclude SSH"
msgid "A Wireshark (TShark) CLI packet capture for RaspAP"
msgstr "A Wireshark (TShark) CLI packet capture for RaspAP"
msgid "Information provided by tshark"
msgstr "Information provided by tshark"
msgid "Total: %d file(s), %s"
msgstr "Total: %d file(s), %s"
#: captive portal plugin
msgid "Captive portal"
msgstr "Captive portal"
msgid "Gateway interface"
msgstr "Gateway interface"
msgid "Gateway name"
msgstr "Gateway name"
msgid "Gateway address"
msgstr "Gateway address"
msgid "Gateway port"
msgstr "Gateway port"
msgid "Defaults to the active AP interface, typically <code>wlan0</code>"
msgstr "Defaults to the active AP interface, typically <code>wlan0</code>"
msgid "Auto-detected from gateway interface if not specified"
msgstr "Auto-detected from gateway interface if not specified"
msgid "Start portal"
msgstr "Start portal"
msgid "Stop portal"
msgstr "Stop portal"
msgid "Information provided by nodogsplash"
msgstr "Information provided by nodogsplash"
msgid "Stop portal service"
msgstr "Stop portal service"
msgid "Start portal service"
msgstr "Start portal service"
msgid "Changing the portal service will momentarily disrupt client traffic. Choose <strong>Proceed</strong> to continue."
msgstr "Changing the portal service will momentarily disrupt client traffic. Choose <strong>Proceed</strong> to continue."
msgid "Interface to be managed by the portal"
msgstr "Interface to be managed by the portal"
msgid "Name of your gateway (available as \\$gatewayname variable)"
msgstr "Name of your gateway (available as \\$gatewayname variable)"
msgid "IP address of the router. Leave empty for auto-detection"
msgstr "IP address of the router. Leave empty for auto-detection"
msgid "Port for Nodogsplash HTTP server"
msgstr "Port for Nodogsplash HTTP server"
msgid "Maximum clients"
msgstr "Maximum clients"
msgid "Session timeout (minutes)"
msgstr "Session timeout (minutes)"
msgid "Pre-auth idle timeout (minutes)"
msgstr "Pre-auth idle timeout (minutes)"
msgid "Does not include users on the trusted MAC list"
msgstr "Does not include users on the trusted MAC list"
msgid "Auth idle timeout (minutes)"
msgstr "Auth idle timeout (minutes)"
msgid "Check interval (seconds)"
msgstr "Check interval (seconds)"
msgid "MAC address control"
msgstr "MAC address control"
msgid "MAC mechanism"
msgstr "MAC mechanism"
msgid "Blocked MAC list"
msgstr "Blocked MAC list"
msgid "Trusted MAC list"
msgstr "Trusted MAC list"
msgid "These devices are not subject to authentication or firewall rules"
msgstr "These devices are not subject to authentication or firewall rules"
msgid "Maximum number of concurrent authenticated users"
msgstr "Maximum number of concurrent authenticated users"
msgid "Default session length in minutes. 0 = unlimited"
msgstr "Default session length in minutes. 0 = unlimited"
msgid "Time before unauthenticated idle users are removed"
msgstr "Time before unauthenticated idle users are removed"
msgid "Time before authenticated idle users are deauthenticated"
msgstr "Time before authenticated idle users are deauthenticated"
msgid "How often to check client timeouts"
msgstr "How often to check client timeouts"
msgid "Block: blocklisted MACs are blocked. Allow: only allowlisted MACs are allowed"
msgstr "Block: blocklisted MACs are blocked. Allow: only allowlisted MACs are allowed"
msgid "Example: <code>00:11:22:33:44:55,AA:BB:CC:DD:EE:FF</code>"
msgstr "Example: <code>00:11:22:33:44:55,AA:BB:CC:DD:EE:FF</code>"
msgid "Comma-separated MAC addresses that bypass authentication entirely"
msgstr "Comma-separated MAC addresses that bypass authentication entirely"
msgid "Block (blocklist mode)"
msgstr "Block (blocklist mode)"
msgid "Allow (allowlist mode)"
msgstr "Allow (allowlist mode)"
msgid "Gateway IP range"
msgstr "Gateway IP range"
msgid "Default: 0.0.0.0/0 (all addresses)"
msgstr "Default: 0.0.0.0/0 (all addresses)"
msgid "Debug level"
msgstr "Debug level"
msgid "Firewall settings"
msgstr "Firewall settings"
msgid "Allow all traffic for authenticated users"
msgstr "Allow all traffic for authenticated users"
msgid "Allow DNS for pre-authenticated users"
msgstr "Allow DNS for pre-authenticated users"
msgid "IP range to manage in CIDR notation. Leave empty for all addresses"
msgstr "IP range to manage in CIDR notation. Leave empty for all addresses"
msgid "Amount of logging detail reported by the nodogsplash.service"
msgstr "Amount of logging detail reported by the nodogsplash.service"
msgid "0 - Errors only"
msgstr "0 - Errors only"
msgid "1 - Errors, warnings, infos"
msgstr "1 - Errors, warnings, infos"
msgid "2 - Errors, warnings, infos, verbose"
msgstr "2 - Errors, warnings, infos, verbose"
msgid "3 - Errors, warnings, infos, verbose, debug"
msgstr "3 - Errors, warnings, infos, verbose, debug"
msgid "When enabled, authenticated users have unrestricted access"
msgstr "When enabled, authenticated users have unrestricted access"
msgid "Required for clients to resolve domain names before authentication"
msgstr "Required for clients to resolve domain names before authentication"
msgid "Portal status"
msgstr "Portal status"
msgid "Current <code>nodogsplash</code> status is displayed below."
msgstr "Current <code>nodogsplash</code> status is displayed below."

Binary file not shown.

File diff suppressed because it is too large Load Diff

Submodule plugins updated: b8e51de448...deb689143e

View File

@@ -79,9 +79,13 @@ class HTTPAuth
*/
public function logout(): void
{
$locale = $_SESSION['locale'] ?? 'en_GB.UTF-8'; // save locale
session_regenerate_id(true); // generate a new session id
session_unset(); // unset all session variables
session_destroy(); // destroy the session
session_start();
$_SESSION['locale'] = $locale;
setcookie('locale', $locale, time() + (86400 * 30), '/', '', false, true);
$basePath = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/');
$redirectUrl = $_SERVER['REQUEST_URI'];
if (strpos($redirectUrl, '/login') === false) {

View File

@@ -36,6 +36,7 @@ class DhcpcdManager
bool $repeaterEnable,
bool $wifiAPEnable,
bool $dualAPEnable,
?array $bridgeConfig = null,
StatusMessage $status
): bool
{
@@ -61,9 +62,14 @@ class DhcpcdManager
if ($bridgedEnable) {
$config = array_keys(getDefaultNetOpts('dhcp', 'options'));
$config[] = '';
$config[] = '# RaspAP br0 configuration';
$config[] = 'denyinterfaces eth0 wlan0';
$config[] = 'interface br0';
$config[] = 'static ip_address='.$bridgeConfig['staticIp'] . '/'. $bridgeConfig['netmask'];
$config[] = 'static routers='.$bridgeConfig['gateway'];
$config[] = 'static domain_name_server='.$bridgeConfig['dns'];
$config[] = PHP_EOL;
} elseif ($repeaterEnable) {
$config = [
'# RaspAP ' . $ap_iface . ' configuration',
@@ -110,7 +116,10 @@ class DhcpcdManager
if (preg_match('/wlan[3-9]\d*|wlan[1-9]\d+/', $ap_iface)) {
$skip_dhcp = true;
} elseif ($bridgedEnable == 1 || $wifiAPEnable == 1) {
} elseif ($bridgedEnable == 1) {
$dhcp_cfg = join(PHP_EOL, $config);
$status->addMessage('DHCP configuration for br0 enabled', 'success');
} elseif ($wifiAPEnable == 1) {
$dhcp_cfg = join(PHP_EOL, $config);
$status->addMessage(sprintf(_('DHCP configuration for %s enabled.'), $ap_iface), 'success');
} elseif (!preg_match('/^interface\s'.$ap_iface.'$/m', $dhcp_cfg)) {

View File

@@ -136,65 +136,84 @@ class HotspotService
// validate config from post data
$validated = $this->hostapd->validate($post_data, $wpa_array, $enc_types, $modes, $interfaces, $reg_domain, $status);
if ($validated !== false) {
if ($validated === false) {
$status->addMessage('Unable to save WiFi hotspot settings due to validation errors', 'danger');
error_log("HotspotService::validate() -> validated = false");
return false;
}
try {
// normalize state flags
$validated['interface'] = $apIface;
$validated['bridge'] = !empty($states['BridgedEnable']);
$validated['apsta'] = !empty($states['WifiAPEnable']);
$validated['repeater'] = !empty($states['RepeaterEnable']);
$validated['dualmode'] = !empty($states['DualAPEnable']);
$validated['txpower'] = $post_data['txpower'];
// hostapd
$config = $this->hostapd->buildConfig($validated, $status);
$this->hostapd->saveConfig($config, $dualAPEnable, $validated['interface']);
$this->maybeSetRegDomain($post_data['country_code'], $status);
$status->addMessage('WiFi hotspot settings saved.', 'success');
// dnsmasq
try {
// normalize state flags
$validated['interface'] = $apIface;
$validated['bridge'] = !empty($states['BridgedEnable']);
$validated['apsta'] = !empty($states['WifiAPEnable']);
$validated['repeater'] = !empty($states['RepeaterEnable']);
$validated['dualmode'] = !empty($states['DualAPEnable']);
$validated['txpower'] = $post_data['txpower'];
// hostapd
$config = $this->hostapd->buildConfig($validated, $status);
$this->hostapd->saveConfig($config, $dualAPEnable, $validated['interface']);
$this->maybeSetRegDomain($post_data['country_code'], $status);
$status->addMessage('WiFi hotspot settings saved.', 'success');
// dnsmasq
try {
$syscfg = $this->dnsmasq->getConfig($validated['interface'] ?? RASPI_WIFI_AP_INTERFACE);
} catch (\RuntimeException $e) {
error_log('Error: ' . $e->getMessage());
}
try {
$dnsmasqConfig = $this->dnsmasq->buildConfig(
$syscfg,
$validated['interface'],
$validated['apsta'],
$validated['bridge']
);
$this->dnsmasq->saveConfig($dnsmasqConfig, $validated['interface'], $status);
} catch (\RuntimeException $e) {
error_log('Error: ' . $e->getMessage());
}
// dhcpcd
try {
$return = $this->dhcpcd->buildConfig(
$validated['interface'],
$validated['bridge'],
$validated['repeater'],
$validated['apsta'],
$validated['dualmode'],
$status,
);
} catch (\RuntimeException $e) {
error_log('Error: ' . $e->getMessage());
}
} catch (\Throwable $e) {
error_log(sprintf(
"Error: %s in %s on line %d\nStack trace:\n%s",
$e->getMessage(),
$e->getFile(),
$e->getLine(),
$e->getTraceAsString()
));
$status->addMessage('Unable to save WiFi hotspot settings', 'danger');
$syscfg = $this->dnsmasq->getConfig($validated['interface'] ?? RASPI_WIFI_AP_INTERFACE);
} catch (\RuntimeException $e) {
error_log('Error: ' . $e->getMessage());
}
try {
$dnsmasqConfig = $this->dnsmasq->buildConfig(
$syscfg,
$validated['interface'],
$validated['apsta'],
$validated['bridge']
);
$this->dnsmasq->saveConfig($dnsmasqConfig, $validated['interface'], $status);
} catch (\RuntimeException $e) {
error_log('Error: ' . $e->getMessage());
}
// dhcpcd
// pass bridge configuration if available
try {
$bridgeConfig = null;
if ($validated['bridge'] && !empty($validated['bridgeStaticIp'])) {
$bridgeConfig = [
'staticIp' => $validated['bridgeStaticIp'],
'netmask' => $validated['bridgeNetmask'],
'gateway' => $validated['bridgeGateway'],
'dns' => $validated['bridgeDNS']
];
}
$return = $this->dhcpcd->buildConfig(
$validated['interface'],
$validated['bridge'],
$validated['repeater'],
$validated['apsta'],
$validated['dualmode'],
$bridgeConfig,
$status,
);
} catch (\RuntimeException $e) {
error_log('Error: ' . $e->getMessage());
$status->addMessage('Error configuring DHCP: ' . $e->getMessage(), 'danger');
return false;
}
} catch (\Throwable $e) {
error_log(sprintf(
"Error: %s in %s on line %d\nStack trace:\n%s",
$e->getMessage(),
$e->getFile(),
$e->getLine(),
$e->getTraceAsString()
));
$status->addMessage('Unable to save WiFi hotspot settings', 'danger');
}
return true;

View File

@@ -117,6 +117,66 @@ class HostapdValidator
$post['max_num_sta'] = $post['max_num_sta'] > 2007 ? 2007 : $post['max_num_sta'];
$post['max_num_sta'] = $post['max_num_sta'] < 1 ? null : $post['max_num_sta'];
// validate bridged mode static IP configuration
$bridgedEnable = !empty($post['bridgedEnable']);
$bridgeStaticIp = trim($post['bridgeStaticIp'] ?? '');
$bridgeNetmask = trim($post['bridgeNetmask'] ?? '');
$bridgeGateway = trim($post['bridgeGateway'] ?? '');
$bridgeDNS = trim($post['bridgeDNS'] ?? '');
if ($bridgedEnable) {
// validate static IP address
if (!filter_var($bridgeStaticIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$status->addMessage('Bridge static IP address must be a valid IPv4 address', 'danger');
$goodInput = false;
}
// validate netmask (CIDR notation)
if (!empty($bridgeNetmask)) {
if (!ctype_digit($bridgeNetmask) || (int)$bridgeNetmask < 1 || (int)$bridgeNetmask > 32) {
$status->addMessage('Bridge netmask must be a number between 1 and 32', 'danger');
$goodInput = false;
}
} else {
$status->addMessage('Bridge netmask is required when using static IP', 'danger');
$goodInput = false;
}
// validate gateway
if (!empty($bridgeGateway)) {
if (!filter_var($bridgeGateway, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$status->addMessage('Bridge gateway must be a valid IPv4 address', 'danger');
$goodInput = false;
}
} else {
$status->addMessage('Bridge gateway is required when using static IP', 'danger');
$goodInput = false;
}
// validate DNS server
if (!empty($bridgeDNS)) {
if (!filter_var($bridgeDNS, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$status->addMessage('Bridge DNS server must be a valid IPv4 address', 'danger');
$goodInput = false;
}
} else {
$status->addMessage('Bridge DNS server is required when using static IP', 'danger');
$goodInput = false;
}
// validate that static IP and gateway are in the same subnet
if ($goodInput && !empty($bridgeStaticIp) && !empty($bridgeGateway) && !empty($bridgeNetmask)) {
$ipLong = ip2long($bridgeStaticIp);
$gatewayLong = ip2long($bridgeGateway);
$mask = -1 << (32 - (int)$bridgeNetmask);
if (($ipLong & $mask) !== ($gatewayLong & $mask)) {
$status->addMessage('Bridge static IP and gateway must be in the same subnet', 'danger');
$goodInput = false;
}
}
}
if (!$goodInput) {
return false;
}
@@ -136,7 +196,11 @@ class HostapdValidator
'max_num_sta' => $post['max_num_sta'],
'beacon_interval' => $post['beacon_interval'] ?? null,
'disassoc_low_ack' => $post['disassoc_low_ackEnable'] ?? null,
'bridge' => ($post['bridgedEnable'] ?? false) ? 'br0' : null
'bridge' => ($post['bridgedEnable'] ?? false) ? 'br0' : null,
'bridgeStaticIp' => ($post['bridgeStaticIp']),
'bridgeNetmask' => ($post['bridgeNetmask']),
'bridgeGateway' => ($post['bridgeGateway']),
'bridgeDNS' => ($post['bridgeDNS'])
];
}

View File

@@ -197,6 +197,10 @@ class PluginInstaller
$this->installDependencies($manifest['dependencies']);
$rollbackStack[] = 'uninstallDependencies';
}
if (!empty($manifest['dpkgs'])) {
$this->installDebianPackages($manifest['dpkgs'], $pluginDir);
$rollbackStack[] = 'uninstallDebianPackages';
}
if (!empty($manifest['user_nonprivileged'])) {
$this->createUser($manifest['user_nonprivileged']);
$rollbackStack[] = 'deleteUser';
@@ -285,6 +289,54 @@ class PluginInstaller
}
}
/**
* Installs a Debian package (.deb) for the current architecture
*
* @param array $dpkgs
* @param string $pluginDir
* @return void
* @throws \Exception
*/
private function installDebianPackages(array $dpkgs, string $pluginDir): void
{
$arch = trim(shell_exec('dpkg --print-architecture'));
if (empty($arch)) {
throw new \Exception('Unable to detect system architecture');
}
// match .deb file for current arch
$debFile = null;
foreach ($dpkgs as $pkg) {
if (strpos($pkg, $arch) !== false) {
$debFile = $pkg;
break;
}
}
if (!$debFile) {
throw new \Exception("No matching .deb package found for architecture: $arch");
}
$debPath = realpath(rtrim($pluginDir, '/') . '/dpkgs/' . $debFile);
if ($debPath === false || !is_file($debPath)) {
throw new \Exception("Debian package not found: $debFile");
}
// invoke the plugin-helper
$cmd = sprintf(
'sudo %s deb %s 2>&1',
escapeshellcmd($this->helperScriptPath), escapeshellarg($debPath)
);
$return = shell_exec($cmd);
// check for success
if (stripos($return, 'ok') === false) {
throw new \Exception("Plugin helper failed to install .deb package: $debFile\nOutput: $return");
}
error_log("Installed Debian package: $debFile for arch $arch");
}
/**
* Creates a non-priviledged Linux user
*
@@ -317,7 +369,7 @@ class PluginInstaller
$source = escapeshellarg($pluginDir . DIRECTORY_SEPARATOR . $config['source']);
$destination = $config['destination'];
if (!str_starts_with($destination, '/')) {
if (strncmp($destination, '/', 1) !== 0) {
$destination = $this->rootPath . '/' . ltrim($destination, '/');
}
$destination = escapeshellarg($destination);

View File

@@ -10,6 +10,76 @@
</div>
</div>
</div>
<!-- static IP settings -->
<div class="row" id="bridgeStaticIpSection" style="display: <?php echo $arrHostapdConf['BridgedEnable'] == 1 ? 'block' : 'none' ?>;">
<div class="col-md-12 mb-3">
<div class="card">
<div class="card-body">
<h6 class="card-title"><?php echo _("Bridge interface configuration"); ?></h6>
<p class="text-muted small mb-3">
<?php echo _("Configure a static IP address for the <code>br0</code> interface to maintain connectivity during bridge mode activation."); ?>
</p>
<div class="row g-3">
<div class="col-md-6">
<label for="bridgeStaticIp" class="form-label"><?php echo _("Static IP Address"); ?></label>
<div class="input-group has-validation">
<input type="text" class="form-control ip_address" id="bridgeStaticIp" name="bridgeStaticIp"
value="<?php echo htmlspecialchars($arrConfig['bridgeStaticIP'] ?? '', ENT_QUOTES); ?>"
placeholder="192.168.1.100" />
<div class="invalid-feedback">
<?php echo _("Please enter a valid IPv4 address"); ?>
</div>
</div>
<div class="form-text"><?php echo _("Example: 192.168.1.100"); ?></div>
</div>
<div class="col-md-6">
<label for="bridgeNetmask" class="form-label"><?php echo _("Netmask / CIDR"); ?></label>
<div class="input-group has-validation">
<input type="text" class="form-control" id="bridgeNetmask" name="bridgeNetmask"
value="<?php echo htmlspecialchars($arrConfig['bridgeNetmask'] ?? '24', ENT_QUOTES); ?>"
placeholder="24" />
<div class="invalid-feedback">
<?php echo _("Please enter a valid netmask"); ?>
</div>
</div>
<div class="form-text"><?php echo _("CIDR notation (e.g., 24 for 255.255.255.0)"); ?></div>
</div>
<div class="col-md-6">
<label for="bridgeGateway" class="form-label"><?php echo _("Gateway"); ?></label>
<div class="input-group has-validation">
<input type="text" class="form-control ip_address" id="bridgeGateway" name="bridgeGateway"
value="<?php echo htmlspecialchars($arrConfig['bridgeGateway'] ?? '', ENT_QUOTES); ?>"
placeholder="192.168.1.1" />
<div class="invalid-feedback">
<?php echo _("Please enter a valid IPv4 address"); ?>
</div>
</div>
<div class="form-text"><?php echo _("Your router's IP address"); ?></div>
</div>
<div class="col-md-6">
<label for="bridgeDNS" class="form-label"><?php echo _("DNS Server"); ?></label>
<div class="input-group has-validation">
<input type="text" class="form-control ip_address" id="bridgeDNS" name="bridgeDNS"
value="<?php echo htmlspecialchars($arrConfig['bridgeDNS'] ?? '', ENT_QUOTES); ?>"
placeholder="192.168.1.1" />
<div class="invalid-feedback">
<?php echo _("Please enter a valid IPv4 address"); ?>
</div>
</div>
<div class="form-text"><?php echo _("Usually same as gateway"); ?></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-2">
<div class="form-check form-switch">