mirror of
https://github.com/cjfranko/NTP-Timeturner.git
synced 2025-11-08 18:32:02 +00:00
Compare commits
9 commits
ea55d087b5
...
04165f2686
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04165f2686 | ||
|
|
459e44250e | ||
|
|
604d118d25 | ||
|
|
320174fe53 | ||
|
|
8903d6d006 | ||
|
|
32e785bd88 | ||
|
|
fb4ecc5f2a | ||
|
|
0c51fd77fa | ||
|
|
474e62d487 |
3 changed files with 173 additions and 32 deletions
19
README.md
19
README.md
|
|
@ -86,6 +86,25 @@ The installation script automates the following steps:
|
||||||
|
|
||||||
After installation is complete, the script will provide instructions to start the service manually or to run the application in its interactive terminal mode.
|
After installation is complete, the script will provide instructions to start the service manually or to run the application in its interactive terminal mode.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Updating
|
||||||
|
|
||||||
|
If you installed TimeTurner by cloning the repository with `git`, you can use the `update.sh` script to easily update to the latest version.
|
||||||
|
|
||||||
|
**Note**: This script will not work if you used the `curl` one-line command for installation, as that method does not create a Git repository.
|
||||||
|
|
||||||
|
To run the update script, navigate to the `NTP-Timeturner-main` directory and run:
|
||||||
|
```bash
|
||||||
|
chmod +x update.sh && ./update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The update script automates the following:
|
||||||
|
1. Pulls the latest code from the `main` branch on GitHub.
|
||||||
|
2. Rebuilds the application binary.
|
||||||
|
3. Copies the new binary to `/opt/timeturner/`.
|
||||||
|
4. Restarts the `timeturner` service to apply the changes.
|
||||||
|
|
||||||
---
|
---
|
||||||
## 🕰️ Chrony NTP
|
## 🕰️ Chrony NTP
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
158
setup.sh
158
setup.sh
|
|
@ -3,6 +3,43 @@ set -e
|
||||||
|
|
||||||
echo "--- TimeTurner Setup ---"
|
echo "--- TimeTurner Setup ---"
|
||||||
|
|
||||||
|
# Check if TimeTurner is already installed.
|
||||||
|
INSTALL_DIR="/opt/timeturner"
|
||||||
|
if [ -f "${INSTALL_DIR}/timeturner" ]; then
|
||||||
|
echo "✅ TimeTurner is already installed."
|
||||||
|
# Ask the user what to do
|
||||||
|
read -p "Do you want to (U)pdate, (R)einstall, or (A)bort? [U/r/a] " choice
|
||||||
|
case "$choice" in
|
||||||
|
r|R )
|
||||||
|
echo "Proceeding with full re-installation..."
|
||||||
|
# Stop the service to allow overwriting the binary, ignore errors if not running
|
||||||
|
echo "Stopping existing TimeTurner service..."
|
||||||
|
sudo systemctl stop timeturner.service || true
|
||||||
|
# The script will continue to the installation steps below.
|
||||||
|
;;
|
||||||
|
a|A )
|
||||||
|
echo "Aborting setup."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
* ) # Default to Update
|
||||||
|
echo "Attempting to run the update script..."
|
||||||
|
# Ensure we are in a git repository and the update script exists
|
||||||
|
if [ -d ".git" ] && [ -f "update.sh" ]; then
|
||||||
|
chmod +x update.sh
|
||||||
|
./update.sh
|
||||||
|
# Exit cleanly after the update
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "⚠️ Could not find 'update.sh' or not in a git repository."
|
||||||
|
echo "Please re-clone the repository to get the update script, or remove the existing installation to run setup again:"
|
||||||
|
echo " sudo rm -rf ${INSTALL_DIR}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Determine package manager
|
# Determine package manager
|
||||||
PKG_MANAGER=""
|
PKG_MANAGER=""
|
||||||
if command -v apt &> /dev/null; then
|
if command -v apt &> /dev/null; then
|
||||||
|
|
@ -227,8 +264,9 @@ if [ "$PKG_MANAGER" == "apt" ]; then
|
||||||
echo "✅ nodogsplash installed successfully."
|
echo "✅ nodogsplash installed successfully."
|
||||||
|
|
||||||
# Disable the standalone hostapd service to let NetworkManager manage it.
|
# Disable the standalone hostapd service to let NetworkManager manage it.
|
||||||
sudo systemctl disable hostapd
|
# We are now using the classic hostapd service, so unmask it.
|
||||||
sudo systemctl mask hostapd
|
sudo systemctl unmask hostapd
|
||||||
|
sudo systemctl enable hostapd
|
||||||
sudo systemctl enable nodogsplash
|
sudo systemctl enable nodogsplash
|
||||||
else
|
else
|
||||||
echo "This script is designed for Debian-based systems like Raspberry Pi OS."
|
echo "This script is designed for Debian-based systems like Raspberry Pi OS."
|
||||||
|
|
@ -240,40 +278,71 @@ fi
|
||||||
sudo systemctl stop hostapd || true
|
sudo systemctl stop hostapd || true
|
||||||
sudo systemctl stop dnsmasq || true
|
sudo systemctl stop dnsmasq || true
|
||||||
|
|
||||||
# Ensure NetworkManager is managing wlan0 by removing any conflicting configurations.
|
# --- Configure networking for AP mode ---
|
||||||
# This is the critical fix for the "No suitable device" error.
|
|
||||||
echo "Ensuring NetworkManager is managing wlan0..."
|
# Set the WiFi country code to prevent radio issues. This is a critical step.
|
||||||
sudo rm -f /etc/NetworkManager/conf.d/99-unmanaged-wlan0.conf
|
echo "Setting WiFi Country Code to US..."
|
||||||
|
sudo raspi-config nonint do_wifi_country US
|
||||||
|
|
||||||
|
# Tell NetworkManager to ignore wlan0 completely to prevent conflicts.
|
||||||
|
echo "Configuring NetworkManager to ignore wlan0..."
|
||||||
|
sudo tee /etc/NetworkManager/conf.d/99-unmanaged-wlan0.conf > /dev/null <<EOF
|
||||||
|
[keyfile]
|
||||||
|
unmanaged-devices=interface-name:wlan0
|
||||||
|
EOF
|
||||||
|
# Also remove the DNS disabling config as it's no longer relevant for this method
|
||||||
|
sudo rm -f /etc/NetworkManager/conf.d/99-disable-dns.conf
|
||||||
sudo systemctl reload NetworkManager
|
sudo systemctl reload NetworkManager
|
||||||
|
|
||||||
# Configure static IP for wlan0 using NetworkManager (nmcli)
|
# Configure a static IP for wlan0 using dhcpcd.
|
||||||
echo "Configuring static IP for wlan0 using NetworkManager..."
|
echo "Configuring static IP for wlan0 via dhcpcd..."
|
||||||
|
# Ensure dhcpcd is installed
|
||||||
|
sudo apt install -y dhcpcd5
|
||||||
|
|
||||||
# Define the connection name
|
# First, remove any existing configurations for wlan0 to prevent conflicts.
|
||||||
CON_NAME="TimeTurner-AP"
|
# This is a more robust way to ensure our settings are applied.
|
||||||
|
sudo sed -i '/^interface wlan0/,/^\s*$/d' /etc/dhcpcd.conf
|
||||||
|
|
||||||
# If a connection with this name already exists, delete it to ensure a clean slate.
|
# Now, add our static IP config to the end of the file.
|
||||||
if nmcli c show --active | grep -q "$CON_NAME"; then
|
sudo tee -a /etc/dhcpcd.conf > /dev/null <<EOF
|
||||||
sudo nmcli c down "$CON_NAME" || true
|
|
||||||
fi
|
|
||||||
if nmcli c show | grep -q "$CON_NAME"; then
|
|
||||||
echo "Deleting existing '$CON_NAME' connection profile..."
|
|
||||||
sudo nmcli c delete "$CON_NAME" || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create a new connection profile for the Access Point with a static IP.
|
# Static IP configuration for Hachi Time AP
|
||||||
echo "Creating new '$CON_NAME' connection profile..."
|
interface wlan0
|
||||||
sudo nmcli c add type wifi ifname wlan0 con-name "$CON_NAME" autoconnect yes ssid "TimeTurner"
|
static ip_address=10.0.252.1/24
|
||||||
sudo nmcli c modify "$CON_NAME" 802-11-wireless.mode ap 802-11-wireless.band bg
|
nohook wpa_supplicant
|
||||||
sudo nmcli c modify "$CON_NAME" 802-11-wireless-security.key-mgmt wpa-psk
|
EOF
|
||||||
sudo nmcli c modify "$CON_NAME" 802-11-wireless-security.psk "harry-ron-hermione"
|
|
||||||
sudo nmcli c modify "$CON_NAME" ipv4.method manual ipv4.addresses 10.0.252.1/24
|
# Configure hostapd for the Access Point
|
||||||
|
echo "Configuring hostapd..."
|
||||||
|
sudo tee /etc/hostapd/hostapd.conf > /dev/null <<EOF
|
||||||
|
interface=wlan0
|
||||||
|
driver=nl80211
|
||||||
|
ssid=Fetch-Hachi
|
||||||
|
hw_mode=g
|
||||||
|
channel=7
|
||||||
|
ieee80211n=1
|
||||||
|
wmm_enabled=1
|
||||||
|
macaddr_acl=0
|
||||||
|
auth_algs=1
|
||||||
|
ignore_broadcast_ssid=0
|
||||||
|
EOF
|
||||||
|
# Point the hostapd service to the new config file.
|
||||||
|
sudo sed -i 's|#DAEMON_CONF=""|DAEMON_CONF="/etc/hostapd/hostapd.conf"|' /etc/default/hostapd
|
||||||
|
|
||||||
# Configure dnsmasq for DHCP
|
# Configure dnsmasq for DHCP
|
||||||
echo "Configuring dnsmasq..."
|
echo "Configuring dnsmasq..."
|
||||||
sudo tee /etc/dnsmasq.conf > /dev/null <<EOF
|
sudo tee /etc/dnsmasq.conf > /dev/null <<EOF
|
||||||
|
# Listen only on this interface
|
||||||
interface=wlan0
|
interface=wlan0
|
||||||
|
# Don't bind to all interfaces, only the one specified above
|
||||||
|
bind-interfaces
|
||||||
|
# Set the IP range for DHCP clients
|
||||||
dhcp-range=10.0.252.10,10.0.252.50,255.255.255.0,24h
|
dhcp-range=10.0.252.10,10.0.252.50,255.255.255.0,24h
|
||||||
|
# Provide a gateway address
|
||||||
|
dhcp-option=option:router,10.0.252.1
|
||||||
|
# Provide a DNS server address
|
||||||
|
dhcp-option=option:dns-server,10.0.252.1
|
||||||
|
# For captive portal, resolve all DNS queries to the AP itself
|
||||||
address=/#/10.0.252.1
|
address=/#/10.0.252.1
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
|
@ -285,17 +354,30 @@ GatewayAddress 10.0.252.1
|
||||||
MaxClients 250
|
MaxClients 250
|
||||||
AuthIdleTimeout 480
|
AuthIdleTimeout 480
|
||||||
FirewallRuleSet preauthenticated-users {
|
FirewallRuleSet preauthenticated-users {
|
||||||
FirewallRule allow tcp port 80
|
# Allow DHCP for clients to get an IP address
|
||||||
|
FirewallRule allow udp port 67
|
||||||
|
FirewallRule allow udp port 68
|
||||||
|
# Allow DNS for captive portal detection
|
||||||
FirewallRule allow tcp port 53
|
FirewallRule allow tcp port 53
|
||||||
FirewallRule allow udp port 53
|
FirewallRule allow udp port 53
|
||||||
|
# Allow HTTP for the captive portal redirect
|
||||||
|
FirewallRule allow tcp port 80
|
||||||
}
|
}
|
||||||
RedirectURL http://10.0.252.1/static/index.html
|
RedirectURL http://10.0.252.1/static/index.html
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Restart services in the correct order and add delays to prevent race conditions
|
# Restart services in the correct order and add delays to prevent race conditions
|
||||||
echo "Restarting services..."
|
echo "Restarting services..."
|
||||||
# Bring up the new AP connection using nmcli
|
|
||||||
sudo nmcli c up "$CON_NAME"
|
# Stop and disable systemd-resolved to prevent any DNS/DHCP conflicts
|
||||||
|
echo "Disabling systemd-resolved to ensure dnsmasq has full control..."
|
||||||
|
sudo systemctl stop systemd-resolved || true
|
||||||
|
sudo systemctl disable systemd-resolved || true
|
||||||
|
|
||||||
|
# Restart dhcpcd to apply the static IP
|
||||||
|
sudo systemctl restart dhcpcd
|
||||||
|
# Restart hostapd to create the access point
|
||||||
|
sudo systemctl restart hostapd
|
||||||
|
|
||||||
# Wait for the interface to come up and get the IP address
|
# Wait for the interface to come up and get the IP address
|
||||||
echo "Waiting for wlan0 to be configured..."
|
echo "Waiting for wlan0 to be configured..."
|
||||||
|
|
@ -314,7 +396,19 @@ done
|
||||||
# Check for the IP address before starting nodogsplash
|
# Check for the IP address before starting nodogsplash
|
||||||
if [ "$IP_CHECK" == "10.0.252.1" ]; then
|
if [ "$IP_CHECK" == "10.0.252.1" ]; then
|
||||||
echo "✅ wlan0 configured with IP $IP_CHECK."
|
echo "✅ wlan0 configured with IP $IP_CHECK."
|
||||||
sudo systemctl restart dnsmasq
|
|
||||||
|
# Add a small delay to ensure the interface is fully ready for dnsmasq
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
echo "Attempting to start dnsmasq service..."
|
||||||
|
if ! sudo systemctl restart dnsmasq; then
|
||||||
|
echo "❌ dnsmasq service failed to start. Displaying logs..."
|
||||||
|
sleep 2
|
||||||
|
sudo journalctl -u dnsmasq.service --no-pager -n 50
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "✅ dnsmasq service started successfully."
|
||||||
|
|
||||||
if command -v nodogsplash &> /dev/null; then
|
if command -v nodogsplash &> /dev/null; then
|
||||||
echo "Attempting to start nodogsplash service..."
|
echo "Attempting to start nodogsplash service..."
|
||||||
if ! sudo systemctl restart nodogsplash; then
|
if ! sudo systemctl restart nodogsplash; then
|
||||||
|
|
@ -332,11 +426,11 @@ if [ "$IP_CHECK" == "10.0.252.1" ]; then
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "❌ Error: wlan0 failed to get the static IP 10.0.252.1. Found: '$IP_CHECK'."
|
echo "❌ Error: wlan0 failed to get the static IP 10.0.252.1. Found: '$IP_CHECK'."
|
||||||
echo "Please check 'sudo nmcli c show \"$CON_NAME\"' and 'ip addr show wlan0'."
|
echo "Please check 'sudo systemctl status hostapd' and 'sudo systemctl status dhcpcd'."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "✅ WiFi hotspot and captive portal configured. SSID: TimeTurner, IP: 10.0.252.1"
|
echo "✅ WiFi hotspot and captive portal configured. SSID: Fetch-Hachi, IP: 10.0.252.1"
|
||||||
echo "Clients will be redirected to http://10.0.252.1/static/index.html"
|
echo "Clients will be redirected to http://10.0.252.1/static/index.html"
|
||||||
|
|
||||||
# 1. Build the release binary
|
# 1. Build the release binary
|
||||||
|
|
@ -389,7 +483,7 @@ if [[ "$(uname)" == "Linux" ]]; then
|
||||||
echo " sudo systemctl start timeturner.service"
|
echo " sudo systemctl start timeturner.service"
|
||||||
echo ""
|
echo ""
|
||||||
echo "To view live logs, run:"
|
echo "To view live logs, run:"
|
||||||
echo " journalctl -u tim_turner.service -f"
|
echo " journalctl -u timeturner.service -f"
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
echo "To run the interactive TUI instead, simply run from the project directory:"
|
echo "To run the interactive TUI instead, simply run from the project directory:"
|
||||||
|
|
|
||||||
28
update.sh
Normal file
28
update.sh
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "--- TimeTurner Update Script ---"
|
||||||
|
|
||||||
|
# 1. Fetch the latest changes from the git repository
|
||||||
|
echo "🔄 Pulling latest changes from GitHub..."
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# 2. Rebuild the release binary
|
||||||
|
echo "📦 Building release binary with Cargo..."
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
# 3. Stop the currently running service to release the file lock
|
||||||
|
echo "🛑 Stopping TimeTurner service..."
|
||||||
|
sudo systemctl stop timeturner.service
|
||||||
|
|
||||||
|
# 4. Copy the new binary to the installation directory
|
||||||
|
echo "🚀 Deploying new binary..."
|
||||||
|
sudo cp target/release/timeturner /opt/timeturner/timeturner
|
||||||
|
|
||||||
|
# 5. Restart the service with the new binary
|
||||||
|
echo "✅ Restarting TimeTurner service..."
|
||||||
|
sudo systemctl restart timeturner.service
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Update complete. To check the status of the service, run:"
|
||||||
|
echo " systemctl status timeturner.service"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue