add cloudflare tunneling to broadcaster

This commit is contained in:
Boaz Sender 2025-06-29 12:49:02 -04:00
parent 733135d8d1
commit 1b5892fd5f
6 changed files with 337 additions and 60 deletions

View file

@ -5,7 +5,7 @@
User: grace
Hostname: portal.local
Password: emergence
Running icecast (port 80) and darkice with Namecheap Dynamic DNS for external access. See icecast-darkice.md for setup instructions.
Running icecast (port 8000) with nginx proxy (port 80) and Cloudflare Tunnel for external access. No port forwarding or static IP required.
## Bill of Materials
@ -99,35 +99,122 @@ WantedBy=multi-user.target
3. sudo systemctl enable icecast2
4. sudo systemctl enable darkice
### Dynamic DNS Configuration (Automated)
### Cloudflare Tunnel Configuration (Automated)
The install script automatically configures Namecheap Dynamic DNS to make the stream accessible at blackportaldetroit.com without requiring a static IP address.
The install script automatically configures Cloudflare Tunnel to make the stream accessible at blackportaldetroit.com. This bypasses CG-NAT, port forwarding, and firewall issues completely.
#### What gets installed:
- **ddclient** - Updates your domain's IP address automatically
- **Configuration file** - Pre-configured for Namecheap at `/etc/ddclient.conf`
- **Systemd service** - Runs ddclient as a background service
- **Icecast on port 80** - Eliminates need for router port forwarding
- **cloudflared** - Creates secure tunnel to Cloudflare edge servers
- **Configuration file** - Pre-configured tunnel settings at `/etc/cloudflared/config.yml`
- **Systemd service** - Runs cloudflared as a background service
- **Nginx reverse proxy** - Proxies port 80 to icecast port 8000 (no root privileges needed)
#### Manual steps required after installation:
1. **In Namecheap account**: Enable Dynamic DNS for blackportaldetroit.com
2. **Add DNS record**: Create an "A + Dynamic DNS" record for "@" (root domain)
3. **Get password**: Note the Dynamic DNS password from Namecheap
4. **Update config**: Edit `/etc/ddclient.conf` and replace `REPLACE_WITH_NAMECHEAP_DDNS_PASSWORD`
5. **Start service**: Run `sudo systemctl start ddclient`
6. **No router setup needed** - icecast runs directly on port 80
1. **Transfer domain**: Move blackportaldetroit.com nameservers to Cloudflare (if not already done)
2. **Authenticate**: Run `cloudflared tunnel login` when prompted
3. **Create tunnel**: Run `cloudflared tunnel create blackportal`
4. **Add DNS record**: Create CNAME record in Cloudflare dashboard pointing to tunnel
5. **Start service**: Tunnel starts automatically via systemd
#### Verify Dynamic DNS is working:
#### Verify Cloudflare Tunnel is working:
```bash
# Check ddclient status
sudo systemctl status ddclient
# Check tunnel status
sudo systemctl status cloudflared
# View ddclient logs
sudo journalctl -u ddclient -f
# View tunnel logs
sudo journalctl -u cloudflared -f
# Test DNS resolution
nslookup blackportaldetroit.com
# Test external access
curl -I https://blackportaldetroit.com/portal
```
#### Verify nginx proxy is working:
```bash
# Check nginx status
sudo systemctl status nginx
# Check icecast status
sudo systemctl status icecast2
# Check listening ports
sudo netstat -tlnp | grep -E ':(80|8000)'
# Test local access
curl -I http://localhost:80
curl -I http://localhost:8000
```
## Troubleshooting Cloudflare Tunnel
### Common Issues and Solutions
#### 1. Domain Not on Cloudflare
**Problem**: Domain still using Namecheap nameservers
**Solution**: Transfer nameservers to Cloudflare
1. Login to Cloudflare, add blackportaldetroit.com
2. Copy Cloudflare nameservers (e.g. `alice.ns.cloudflare.com`)
3. Update nameservers in Namecheap domain settings
4. Wait for DNS propagation (up to 24 hours)
#### 2. Authentication Issues
**Problem**: `cloudflared tunnel login` fails
**Solution**: Manual authentication
```bash
# Run authentication manually
cloudflared tunnel login
# If browser doesn't open automatically, copy the URL and open manually
# Complete authentication in browser
```
#### 3. Tunnel Not Connecting
**Problem**: Tunnel shows as disconnected
**Solution**: Check service and logs
```bash
# Check tunnel service status
sudo systemctl status cloudflared
# View detailed logs
sudo journalctl -u cloudflared -f
# Restart tunnel service
sudo systemctl restart cloudflared
```
#### 4. DNS Record Issues
**Problem**: Domain doesn't resolve to tunnel
**Solution**: Check CNAME record in Cloudflare
1. Login to Cloudflare dashboard
2. Go to DNS → Records
3. Ensure CNAME record exists: `@``tunnel-id.cfargotunnel.com`
4. Ensure Proxy status is enabled (orange cloud)
### Architecture Diagram with Cloudflare Tunnel
```
Internet → Cloudflare Edge → Cloudflare Tunnel → Raspberry Pi 4B
nginx (port 80) → icecast (port 8000)
```
**Key Benefits**:
- Bypasses CG-NAT completely
- No router configuration needed
- Built-in SSL and DDoS protection
- Works with any internet connection

View file

@ -1,14 +1,15 @@
# Hardware setup instructions
This readme contains insructions for plugging in the system and turning it on. Full software setup documentation is in the broadcaster-software.md and listener-software.md files.
This readme contains instructions for plugging in the system and turning it on. Full software setup documentation is in the broadcaster-software.md and listener-software.md files.
Make sure to do the following steps in the order they are listed:
## Requirements
- Modem and internet plan (no static IP required - uses Dynamic DNS).
- Provisioned [broadcaster](broadcaster.md) with Dynamic DNS configured
- Modem and internet plan (no static IP required - uses Cloudflare Tunnel)
- Provisioned [broadcaster](broadcaster.md) with Cloudflare Tunnel configured
- Provisioned [listener](listener.md)
- Domain transferred to Cloudflare (blackportaldetroit.com)
## Steps
@ -19,14 +20,9 @@ Make sure to do the following steps in the order they are listed:
3. Plug the ethernet cable into the broadcaster and the router
4. Plug the power into the broadcaster (this is how you turn it on)
### Networking (Simplified with Dynamic DNS)
### Networking
6. Log into the router.
7. Find the ip address of the broadcaster (hostname portal) - usually in the advanced > network > dhcp.
8. No port forwarding needed - icecast runs directly on port 80.
9. The broadcaster will automatically update blackportaldetroit.com with the current public IP address via Dynamic DNS.
1. Either configure cloudlfare tunnel, ddns or setup a static ip and forward from your router
### Turn on listener
@ -37,7 +33,36 @@ Make sure to do the following steps in the order they are listed:
### Important notes
* The microphone must always be plugged into the broadcaster before the broadcaster is on
* The broadcaster must always be on when the listener is turned on. if it is not, then the listener needs to be restarted once the broadcaster is on.
* Dynamic DNS automatically keeps blackportaldetroit.com pointed to your current IP address
* No router port forwarding required - icecast runs directly on port 80
- The microphone must always be plugged into the broadcaster before the broadcaster is on
- The broadcaster must always be on when the listener is turned on. if it is not, then the listener needs to be restarted once the broadcaster is on.
- SSL certificates are handled automatically by Cloudflare
- Stream will be accessible at https://blackportaldetroit.com/portal
- No router configuration or port forwarding needed
## Troubleshooting Cloudflare Tunnel
### Setup Steps:
1. Transfer blackportaldetroit.com to Cloudflare (change nameservers)
2. Run `./cloudflare-tunnel-setup.sh` on the Pi
3. Follow the authentication prompts
4. Create CNAME record in Cloudflare dashboard
### Common Issues:
- **Domain not on Cloudflare**: Transfer nameservers first
- **Authentication failed**: Run `cloudflared tunnel login` manually
- **Tunnel not connecting**: Check `sudo systemctl status cloudflared`
### Test Commands:
```bash
# Check tunnel status
sudo systemctl status cloudflared
# View tunnel logs
sudo journalctl -u cloudflared -f
# Test local connectivity
curl -I http://localhost:80
```

View file

@ -21,14 +21,15 @@ This repository contains custom software for turning a m3u radio stream into a l
Prior research that didn't work in `research-` md files.
## Dynamic DNS Setup
## Cloudflare Tunnel Setup
The broadcaster configures Namecheap Dynamic DNS to make the stream available at blackportaldetroit.com without requiring a static IP address. The setup includes:
The broadcaster uses Cloudflare Tunnel to make the stream available at blackportaldetroit.com without requiring static IP, port forwarding, or dealing with CG-NAT. The setup includes:
- Automatic IP address detection and updates
- Namecheap integration for seamless domain management
- Icecast running directly on port 80 (no router port forwarding needed)
- Secure tunnel bypassing router/firewall restrictions
- Automatic SSL certificate management
- Built-in DDoS protection and global CDN
- Works with any internet connection type (LTE, cable, DSL, fiber)
## Live access
5. If everything is turned on and configured properly, you may visit http://blackportaldetroit.com to hear the broadcaster.
5. If everything is turned on and configured properly, you may visit https://blackportaldetroit.com/portal to hear the broadcaster.

View file

@ -0,0 +1,156 @@
#!/bin/bash
# Cloudflare Tunnel Setup for Black Portal Detroit
# This bypasses CG-NAT by creating a secure tunnel to Cloudflare
set -e
echo "🔗 Setting up Cloudflare Tunnel for Black Portal Detroit..."
# Check if running as root
if [[ $EUID -eq 0 ]]; then
echo "This script should NOT be run as root"
echo "Run as: ./cloudflare-tunnel-setup.sh"
exit 1
fi
# Install cloudflared
echo "📦 Installing cloudflared..."
sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bullseye main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt-get update && sudo apt-get install cloudflared
# Create tunnel configuration directory
sudo mkdir -p /etc/cloudflared
sudo chown $USER:$USER /etc/cloudflared
echo ""
echo "MANUAL STEPS REQUIRED:"
echo ""
echo "1. Authenticate with Cloudflare (if not already done):"
echo " cloudflared tunnel login"
echo ""
echo " FOR HEADLESS PI:"
echo " - Copy the URL that appears"
echo " - Open it in a browser on another device"
echo " - Complete authentication"
echo " - If you see 'existing certificate' error, skip to step 2"
echo ""
echo "2. Create a tunnel:"
echo " cloudflared tunnel create blackportal"
echo ""
echo "3. Copy the tunnel ID that gets displayed, then run:"
echo " echo 'TUNNEL_ID=your-tunnel-id-here' | sudo tee /etc/cloudflared/.env"
echo ""
echo "4. Copy credentials to system location:"
echo " sudo cp ~/.cloudflared/your-tunnel-id.json /etc/cloudflared/"
echo " sudo chmod 600 /etc/cloudflared/your-tunnel-id.json"
echo ""
echo "5. Create DNS record in Cloudflare dashboard:"
echo " - Type: CNAME"
echo " - Name: @ (or blackportaldetroit.com)"
echo " - Target: your-tunnel-id.cfargotunnel.com"
echo " - Proxy status: Proxied (orange cloud)"
echo ""
echo "6. Run this script again to complete setup"
echo ""
# Check if tunnel already exists
if [ -f "/etc/cloudflared/.env" ]; then
source /etc/cloudflared/.env
if [ -z "$TUNNEL_ID" ]; then
echo "TUNNEL_ID not found in /etc/cloudflared/.env"
echo "Please complete manual steps above first"
exit 1
fi
echo "✅ Found tunnel ID: $TUNNEL_ID"
# Check if credentials file exists (might be in user's home or system location)
if [ ! -f "/etc/cloudflared/$TUNNEL_ID.json" ]; then
if [ -f "$HOME/.cloudflared/$TUNNEL_ID.json" ]; then
echo "📋 Copying credentials from user directory..."
sudo cp "$HOME/.cloudflared/$TUNNEL_ID.json" /etc/cloudflared/
sudo chown root:root "/etc/cloudflared/$TUNNEL_ID.json"
sudo chmod 600 "/etc/cloudflared/$TUNNEL_ID.json"
else
echo "Credentials file not found at /etc/cloudflared/$TUNNEL_ID.json"
echo "Please run: cloudflared tunnel create blackportal"
exit 1
fi
fi
# Create tunnel configuration
echo "📝 Creating tunnel configuration..."
cat > /etc/cloudflared/config.yml << EOF
tunnel: $TUNNEL_ID
credentials-file: /etc/cloudflared/$TUNNEL_ID.json
ingress:
- hostname: blackportaldetroit.com
service: http://localhost:80
- hostname: www.blackportaldetroit.com
service: http://localhost:80
- service: http_status:404
EOF
# Set proper permissions
sudo chown root:root /etc/cloudflared/config.yml
sudo chmod 644 /etc/cloudflared/config.yml
# Create systemd service
echo "🔧 Creating systemd service..."
sudo tee /etc/systemd/system/cloudflared.service > /dev/null << EOF
[Unit]
Description=Cloudflare Tunnel
After=network.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable cloudflared
sudo systemctl start cloudflared
echo ""
echo "Cloudflare Tunnel setup complete!"
echo ""
echo "Check status:"
echo "sudo systemctl status cloudflared"
echo ""
echo "View logs:"
echo "sudo journalctl -u cloudflared -f"
echo ""
echo "IMPORTANT: Did you create the DNS record?"
echo "Go to Cloudflare Dashboard → DNS → Records"
echo "Add CNAME: @ → $TUNNEL_ID.cfargotunnel.com"
echo ""
echo "Your stream should now be accessible at:"
echo "https://blackportaldetroit.com/portal"
echo ""
echo "Benefits:"
echo " - Bypasses CG-NAT completely"
echo " - Free SSL certificate"
echo " - DDoS protection"
echo " - Works from anywhere"
echo ""
echo "Troubleshooting:"
echo " - If tunnel fails: Check logs with 'sudo journalctl -u cloudflared -f'"
echo " - If DNS doesn't work: Ensure CNAME record is added in Cloudflare"
echo " - If stream not accessible: Check 'sudo systemctl status nginx' and 'sudo systemctl status icecast2'"
echo ""
else
echo "⏳ Complete the manual steps above, then run this script again"
fi

View file

@ -19,10 +19,10 @@ ver="1.0"
marker="0.0.0"
apt update
apt -y install git vim zsh darkice icecast2 ddclient
apt -y install git vim zsh darkice icecast2 nginx
# Configure icecast to run on port 80
sed -i 's/<port>8000<\/port>/<port>80<\/port>/g' /etc/icecast2/icecast.xml
# Keep icecast on port 8000 (can't bind to port 80 without root)
# Nginx will proxy port 80 to icecast port 8000
cp ./darkice.cfg /etc/
cp ./darkice.service /lib/systemd/system/
@ -31,30 +31,29 @@ systemctl daemon-reload
systemctl enable darkice
systemctl start darkice
# Configure ddclient for Namecheap Dynamic DNS
cat > /etc/ddclient.conf << EOF
# Namecheap Dynamic DNS configuration
daemon=300 # Check every 5 minutes
syslog=yes # Log to syslog
pid=/var/run/ddclient.pid # PID file location
ssl=yes # Use SSL
# Configure nginx to proxy port 80 to icecast port 8000
cat > /etc/nginx/sites-available/blackportaldetroit.com << EOF
server {
listen 80;
server_name blackportaldetroit.com;
# How to get IP address
use=web, web=dynamicdns.park-your-domain.com/getip
# Namecheap settings
protocol=namecheap
server=dynamicdns.park-your-domain.com
login=blackportaldetroit.com
password=REPLACE_WITH_NAMECHEAP_DDNS_PASSWORD
@ # Update root domain
location / {
proxy_pass http://127.0.0.1:8000;
proxy_buffering off;
}
}
EOF
# Set proper permissions for ddclient config
chmod 600 /etc/ddclient.conf
# Enable the nginx site and disable default
ln -sf /etc/nginx/sites-available/blackportaldetroit.com /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
systemctl restart nginx
# Enable and start ddclient (but don't start until password is configured)
systemctl enable ddclient
echo ""
echo "🔗 Setting up Cloudflare Tunnel..."
chmod +x ./cloudflare-tunnel-setup.sh
su grace
./cloudflare-tunnel-setup.sh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

View file

@ -0,0 +1,9 @@
server {
listen 80;
server_name blackportaldetroit.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_buffering off;
}
}