Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.tar1090
file: Dockerfile
platforms: linux/arm64
push: false
load: true
Expand Down
44 changes: 13 additions & 31 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
FROM debian:bullseye-slim
FROM ghcr.io/sdr-enthusiasts/docker-tar1090:latest

RUN apt-get update && apt-get install -y \
nginx \
lighttpd \
git \
curl \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js for our adsb.lol proxy
RUN apt-get update && apt-get install -y nodejs npm && rm -rf /var/lib/apt/lists/*

RUN mkdir -p /usr/local/share/tar1090/html
# Copy our proxy server (reads from file, avoids circular dependency)
COPY proxy/server.js /opt/proxy/server.js

COPY html/ /usr/local/share/tar1090/html/
COPY *.conf /usr/local/share/tar1090/
COPY *.sh /usr/local/share/tar1090/
RUN chmod +x /usr/local/share/tar1090/*.sh
# Runtime nginx config injection - runs AFTER 07-nginx-configure regenerates config
# Must be numbered > 07 to run after nginx config is generated
# (Build-time sed doesn't persist because tar1090 regenerates nginx config at startup)
COPY docker/08-inject-proxy-config /etc/s6-overlay/startup.d/08-inject-proxy-config
RUN chmod +x /etc/s6-overlay/startup.d/08-inject-proxy-config

COPY docker/lighttpd-tar1090.conf /etc/lighttpd/conf-available/89-tar1090.conf
RUN lighttpd-enable-mod tar1090

RUN sed -i 's/server.port\s*=.*/server.port = 8504/' /etc/lighttpd/lighttpd.conf && \
sed -i 's|server.document-root\s*=.*|server.document-root = "/usr/local/share/tar1090/html/"|' /etc/lighttpd/lighttpd.conf

COPY <<'EOF' /usr/local/bin/start.sh
#!/bin/bash
set -e

echo "Starting tar1090 web interface on port 8504..."
lighttpd -D -f /etc/lighttpd/lighttpd.conf
EOF

RUN chmod +x /usr/local/bin/start.sh

EXPOSE 8504

CMD ["/usr/local/bin/start.sh"]
# Start proxy as a background service using s6-overlay cont-init
COPY docker/01-start-proxy /etc/cont-init.d/01-start-proxy
RUN chmod +x /etc/cont-init.d/01-start-proxy
18 changes: 0 additions & 18 deletions Dockerfile.tar1090

This file was deleted.

49 changes: 16 additions & 33 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,52 +1,35 @@
services:
readsb:
image: ghcr.io/sdr-enthusiasts/docker-readsb-protobuf:latest
container_name: readsb
hostname: readsb
tar1090:
build:
context: .
dockerfile: Dockerfile
container_name: tar1090
hostname: tar1090
restart: unless-stopped
network_mode: host
# network_mode: host # Use on Linux; doesn't work on macOS Docker
Comment thread
Sol455 marked this conversation as resolved.
Outdated
ports:
- "8078:80" # tar1090 web UI
environment:
- TZ=UTC
# readsb config (built into docker-tar1090)
- READSB_DEVICE_TYPE=none
- READSB_NET_ENABLE=true
- READSB_NET_CONNECTOR=${READSB_NET_CONNECTOR:-}
- READSB_LAT=${RECEIVER_LAT:-0}
- READSB_LON=${RECEIVER_LON:-0}
- READSB_ALT=${RECEIVER_ALT:-0}
- READSB_RX_LOCATION_ACCURACY=2
- READSB_STATS_RANGE=true
- READSB_NET_ENABLE=true
- DISABLE_WEBAPP=true
- READSB_NET_CONNECTOR=192.168.8.183,30005,beast_in
volumes:
- readsb-autogain:/run/autogain
- readsb-collectd:/run/collectd
tmpfs:
- /var/log:size=32M

tar1090:
build:
context: .
dockerfile: Dockerfile.tar1090
container_name: tar1090
hostname: tar1090
restart: unless-stopped
network_mode: host
depends_on:
- readsb
environment:
- TZ=UTC
- BEASTHOST=127.0.0.1
- BEASTPORT=30005
# tar1090 map config
- LAT=${RECEIVER_LAT:-0}
- LONG=${RECEIVER_LON:-0}
- TAR1090_DEFAULTCENTERLAT=${RECEIVER_LAT:-0}
- TAR1090_DEFAULTCENTERLON=${RECEIVER_LON:-0}
- READSB_URL=http://127.0.0.1:80/data/aircraft.json
# adsb.lol proxy config
- ADSBLOL_ENABLED=${ADSBLOL_ENABLED:-false}
- RECEIVER_LAT=${RECEIVER_LAT:-0}
- RECEIVER_LON=${RECEIVER_LON:-0}
- ADSBLOL_RADIUS=${ADSBLOL_RADIUS:-40}
- PROXY_PORT=3005

volumes:
readsb-autogain:
readsb-collectd:
tmpfs:
- /var/log:size=32M
4 changes: 4 additions & 0 deletions docker/01-start-proxy
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/command/with-contenv bash
# Start the adsb.lol fallback proxy
echo "[01-start-proxy] Starting aircraft data proxy on port ${PROXY_PORT:-3005}..."
node /opt/proxy/server.js &
22 changes: 22 additions & 0 deletions docker/08-inject-proxy-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/command/with-contenv bash
# Inject proxy location block AFTER tar1090's 07-nginx-configure runs
# This must run at startup (not build time) because 07-nginx-configure regenerates the config

echo "[08-inject-proxy-config] Injecting adsb.lol proxy config into nginx..."

# Add proxy location for aircraft.json
sed -i '/include \/etc\/nginx\/nginx-tar1090-webroot.conf;/i\ location = /data/aircraft.json { proxy_pass http://127.0.0.1:3005/data/aircraft.json; }' \
/etc/nginx/sites-enabled/tar1090

# Disable binCraft in receiver.json so frontend uses JSON format (required for adsb.lol)
# Uses nginx sub_filter to modify the response on-the-fly
sed -i '/include \/etc\/nginx\/nginx-tar1090-webroot.conf;/i\ location = /data/receiver.json { alias /run/readsb/receiver.json; sub_filter_types application/json; sub_filter '\''\"binCraft\": true'\'' '\''\"binCraft\": false'\''; sub_filter '\''\"zstd\": true'\'' '\''\"zstd\": false'\''; sub_filter_once off; }' \
/etc/nginx/sites-enabled/tar1090

# Verify the injection worked
if grep -q "proxy_pass" /etc/nginx/sites-enabled/tar1090; then
echo "[08-inject-proxy-config] Proxy config injected successfully"
else
echo "[08-inject-proxy-config] ERROR: Failed to inject proxy config"
exit 1
fi
20 changes: 0 additions & 20 deletions docker/entrypoint.sh

This file was deleted.

7 changes: 0 additions & 7 deletions docker/lighttpd-proxy.conf

This file was deleted.

20 changes: 0 additions & 20 deletions docker/lighttpd-tar1090.conf

This file was deleted.

68 changes: 48 additions & 20 deletions proxy/server.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
const http = require('http');
const https = require('https');
const fs = require('fs').promises;

const READSB_URL = process.env.READSB_URL || 'http://127.0.0.1:80/data/aircraft.json';
const LOCAL_DATA_PATH = process.env.LOCAL_DATA_PATH || '/run/readsb/aircraft.json';
const ADSBLOL_ENABLED = process.env.ADSBLOL_ENABLED === 'true';
const RECEIVER_LAT = parseFloat(process.env.RECEIVER_LAT || '0');
const RECEIVER_LON = parseFloat(process.env.RECEIVER_LON || '0');
const ADSBLOL_RADIUS = parseInt(process.env.ADSBLOL_RADIUS || '40');
const PORT = parseInt(process.env.PROXY_PORT || '3000');
const PORT = parseInt(process.env.PROXY_PORT || '3005');

const ADSBLOL_API = `https://api.adsb.lol/v2/lat/${RECEIVER_LAT}/lon/${RECEIVER_LON}/dist/${ADSBLOL_RADIUS}`;

Expand Down Expand Up @@ -80,31 +81,58 @@ function convertAdsbLolToReadsb(adsbLolData) {
};
}

async function getAircraftData() {
async function fetchAdsbLol() {
console.log('Fetching from adsb.lol...');
const adsbLolData = await fetchUrl(ADSBLOL_API);
const convertedData = convertAdsbLolToReadsb(adsbLolData);
console.log(`adsb.lol: ${convertedData.aircraft?.length || 0} aircraft`);

// Write to local file so tar1090's backend process can read it
try {
console.log('Attempting to fetch from local readsb...');
const localData = await fetchUrl(READSB_URL);
console.log(`✓ Local readsb: ${localData.aircraft?.length || 0} aircraft`);
return { data: localData, source: 'local' };
await fs.writeFile(LOCAL_DATA_PATH, JSON.stringify(convertedData));
} catch (err) {
console.log(`Warning: Could not write to ${LOCAL_DATA_PATH}: ${err.message}`);
}

return { data: convertedData, source: 'adsb.lol' };
}

async function readLocalFile() {
try {
const data = await fs.readFile(LOCAL_DATA_PATH, 'utf8');
return JSON.parse(data);
} catch (error) {
console.log(`✗ Local readsb failed: ${error.message}`);
return null;
}
}

if (!ADSBLOL_ENABLED) {
console.log('✗ adsb.lol fallback disabled');
throw new Error('Local feed unavailable and fallback disabled');
}
async function getAircraftData() {
// Try local file first (readsb writes to /run/readsb/aircraft.json)
const localData = await readLocalFile();

if (localData && localData.aircraft?.length > 0) {
console.log(`Local file: ${localData.aircraft.length} aircraft`);
return { data: localData, source: 'local' };
}

// Try adsb.lol fallback if enabled
if (ADSBLOL_ENABLED) {
const reason = localData ? '0 aircraft from local' : 'local file not found';
console.log(`Falling back to adsb.lol (${reason})...`);
try {
console.log('Attempting fallback to adsb.lol...');
const adsbLolData = await fetchUrl(ADSBLOL_API);
const convertedData = convertAdsbLolToReadsb(adsbLolData);
console.log(`✓ adsb.lol fallback: ${convertedData.aircraft?.length || 0} aircraft`);
return { data: convertedData, source: 'adsb.lol' };
return await fetchAdsbLol();
} catch (fallbackError) {
console.log(`✗ adsb.lol fallback failed: ${fallbackError.message}`);
throw new Error('Both local and fallback feeds unavailable');
console.log(`adsb.lol fallback failed: ${fallbackError.message}`);
}
}

// Return local data even if empty (if we got a response)
if (localData) {
return { data: localData, source: 'local' };
}

// No data sources available
throw new Error('No data sources available');
Comment thread
Sol455 marked this conversation as resolved.
}

const server = http.createServer(async (req, res) => {
Expand Down Expand Up @@ -136,7 +164,7 @@ const server = http.createServer(async (req, res) => {

server.listen(PORT, () => {
console.log(`Aircraft data proxy listening on port ${PORT}`);
console.log(`Local feed: ${READSB_URL}`);
console.log(`Local data file: ${LOCAL_DATA_PATH}`);
console.log(`adsb.lol fallback: ${ADSBLOL_ENABLED ? 'enabled' : 'disabled'}`);
if (ADSBLOL_ENABLED) {
console.log(`adsb.lol API: ${ADSBLOL_API}`);
Expand Down