Skip to content

New Script: AirTrail - #2030

Closed
Majiiin wants to merge 7 commits into
community-scripts:mainfrom
Majiiin:airtrail-dev
Closed

New Script: AirTrail#2030
Majiiin wants to merge 7 commits into
community-scripts:mainfrom
Majiiin:airtrail-dev

Conversation

@Majiiin

@Majiiin Majiiin commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

✍️ Description

Adds a fully functional and tested native AirTrail LXC script.

AirTrail is a self-hosted application for tracking flights, viewing flight history on an interactive map, importing flight data, and displaying travel statistics.

Implementation details:

  • Native installation in an unprivileged Debian 13 LXC
  • Node.js 22
  • Bun
  • PostgreSQL 16
  • Dedicated airtrail system user
  • Native systemd service
  • GitHub release-based installation and updates
  • PostgreSQL backup before application updates
  • Database migrations during installation and updates
  • Airport overlay installed from the exact OCI data artifact pinned by the upstream AirTrail Dockerfile
  • Skopeo is used only to extract the upstream data artifact; no Docker daemon or Docker Compose deployment is installed or used

Tested on Proxmox VE 9.2.4:

  • Fresh installation completed successfully
  • AirTrail and PostgreSQL services active
  • Main application returns HTTP 200
  • Airport overlay returns HTTP 200
  • Airport overlay file installed correctly
  • Container reboot tested
  • User account and flight data persisted after reboot
  • Complete update workflow tested by forcing the local version marker to 0.0.0
  • User account and flight data persisted after update
  • Database backup created successfully
  • Backup confirmed non-empty with root:root ownership and 0600 permissions

🔗 Related PR / Issue

This PR addresses the existing AirTrail script request:

The request was opened in September 2025 and received follow-up interest from two additional community members.

✅ Prerequisites

  • Self-review completed – Code follows project standards.
  • Tested thoroughly – Changes work as expected.
  • No breaking changes – Existing functionality remains intact.
  • No security risks – No hardcoded secrets, unnecessary privilege escalations, or permission issues.

🏗️ arm64 Support

  • arm64 supported - Tested and supported on arm64.
  • arm64 not tested - Assumed to work on arm64, but testing has not been done.
  • arm64 not supported - Confirmed upstream dependencies or binaries do not support arm64.

ARM64 is currently disabled in the script metadata until it can be properly tested.


🛠️ Type of Change

  • 🐞 Bug fix – Resolves an issue without breaking functionality.
  • New feature – Adds new, non-breaking functionality.
  • 💥 Breaking change – Alters existing functionality in a way that may require updates.
  • 🆕 New script – A fully functional and tested script or script set.
  • 🌍 Website update – Changes to website-related JSON files or metadata.
  • 🔧 Refactoring / Code Cleanup – Improves readability or maintainability without changing functionality.
  • 📝 Documentation update – Changes to README, AppName.md, CONTRIBUTING.md, or other docs.

🔍 Code & Security Review

  • Follows CODE-AUDIT.md & CONTRIBUTING.md guidelines
  • Uses correct script structure (AppName.sh, AppName-install.sh, AppName.json)
  • No hardcoded credentials
  • No Docker / Docker Compose – The application is installed bare-metal; Docker is not used.
  • No git pull – Updates use fetch_and_deploy_gh_release.

🤖 AI Assistance

  • No AI used – Scripts were written without AI assistance.
  • AI was used – I confirm the scripts were built using AGENTS.md and .github/agents/pve-script-creator.agent.md as guidance, and the output has been reviewed and corrected to match those guidelines.

📋 Additional Information

The upstream AirTrail source release does not include airport-overlay.pmtiles.

AirTrail's official Dockerfile obtains this required static data file from a separately published and digest-pinned OCI image. The LXC installer reproduces only that asset extraction using Skopeo while running the application itself directly with Node.js and systemd.


📦 Application Requirements (for new scripts)

  • The application is at least 6 months old
  • The application is actively maintained
  • The application has 600+ GitHub stars
  • Official release tarballs are published
  • I understand that not all scripts will be accepted due to various reasons and criteria by the community-scripts ORG

🌐 Source

@Majiiin
Majiiin requested a review from a team as a code owner July 16, 2026 13:43
Comment thread install/airtrail-install.sh Outdated
Comment on lines +18 to +20
curl \
skopeo \
unzip

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl and unzip are base deps

Comment thread install/airtrail-install.sh Outdated
Comment on lines +37 to +42
msg_info "Configuring AirTrail"
useradd \
--system \
--home-dir /opt/airtrail \
--shell /usr/sbin/nologin \
airtrail

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for what?

Comment thread install/airtrail-install.sh Outdated
Comment on lines +72 to +121
msg_info "Installing Airport Overlay"
overlay_tmp=$(mktemp -d)

overlay_image=$(
awk '
$1 == "FROM" &&
$2 ~ /^johly\/airtrail-airport-overlay(:|@)/ {
print $2
exit
}
' /opt/airtrail/docker/Dockerfile
)

if [[ -z "$overlay_image" ]]; then
msg_error "Airport overlay image not found"
exit 1
fi

if [[ "$overlay_image" == *@sha256:* ]]; then
image_without_digest="${overlay_image%@*}"
image_digest="${overlay_image#*@}"
image_repository="${image_without_digest%:*}"
skopeo_image="${image_repository}@${image_digest}"
else
skopeo_image="$overlay_image"
fi

mkdir -p \
"$overlay_tmp/archive" \
"$overlay_tmp/rootfs"

$STD skopeo copy \
"docker://docker.io/${skopeo_image}" \
"docker-archive:${overlay_tmp}/overlay.tar:airtrail-overlay:latest"

tar -xf "$overlay_tmp/overlay.tar" \
-C "$overlay_tmp/archive"

overlay_layer=$(
jq -r '.[0].Layers[-1]' \
"$overlay_tmp/archive/manifest.json"
)

tar -xf "$overlay_tmp/archive/$overlay_layer" \
-C "$overlay_tmp/rootfs"

if [[ ! -s "$overlay_tmp/rootfs/airport-overlay.pmtiles" ]]; then
msg_error "Airport overlay file not found"
exit 1
fi

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for what? if this the state of the art of AirTrail? Then sorry, nope

Comment thread install/airtrail-install.sh Outdated
msg_ok "Applied Database Migrations"

msg_info "Creating Service"
cat <<'EOF_SERVICE' >/etc/systemd/system/airtrail.service

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong

Comment thread install/airtrail-install.sh Outdated

[Install]
WantedBy=multi-user.target
EOF_SERVICE

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong

Comment thread ct/airtrail.sh Outdated
Comment on lines +83 to +145
msg_info "Installing Airport Overlay"
if ! command -v skopeo >/dev/null 2>&1; then
$STD apt install -y skopeo
fi

overlay_tmp=$(mktemp -d)

overlay_image=$(
awk '
$1 == "FROM" &&
$2 ~ /^johly\/airtrail-airport-overlay(:|@)/ {
print $2
exit
}
' /opt/airtrail/docker/Dockerfile
)

if [[ -z "$overlay_image" ]]; then
msg_error "Airport overlay image not found"
exit 1
fi

if [[ "$overlay_image" == *@sha256:* ]]; then
image_without_digest="${overlay_image%@*}"
image_digest="${overlay_image#*@}"
image_repository="${image_without_digest%:*}"
skopeo_image="${image_repository}@${image_digest}"
else
skopeo_image="$overlay_image"
fi

mkdir -p \
"$overlay_tmp/archive" \
"$overlay_tmp/rootfs"

$STD skopeo copy \
"docker://docker.io/${skopeo_image}" \
"docker-archive:${overlay_tmp}/overlay.tar:airtrail-overlay:latest"

tar -xf "$overlay_tmp/overlay.tar" \
-C "$overlay_tmp/archive"

overlay_layer=$(
jq -r '.[0].Layers[-1]' \
"$overlay_tmp/archive/manifest.json"
)

tar -xf "$overlay_tmp/archive/$overlay_layer" \
-C "$overlay_tmp/rootfs"

if [[ ! -s "$overlay_tmp/rootfs/airport-overlay.pmtiles" ]]; then
msg_error "Airport overlay file not found"
exit 1
fi

install \
-o root \
-g root \
-m 0644 \
"$overlay_tmp/rootfs/airport-overlay.pmtiles" \
/opt/airtrail/build/client/airport-overlay.pmtiles

rm -rf "$overlay_tmp"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for what?

Comment thread ct/airtrail.sh Outdated
Comment on lines +70 to +73
CLEAN_INSTALL=1 fetch_and_deploy_gh_release \
"airtrail" \
"johanohly/AirTrail" \
"tarball"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oneliner

Comment thread ct/airtrail.sh Outdated
Comment on lines +44 to +68
msg_info "Backing Up Database"
install -d \
-o root \
-g root \
-m 0700 \
/var/lib/airtrail/backups

backup_file="/var/lib/airtrail/backups/airtrail-$(date +%Y%m%d-%H%M%S).sql"

sudo -u postgres pg_dump airtrail |
install \
-o root \
-g root \
-m 0600 \
/dev/stdin \
"$backup_file"

find /var/lib/airtrail/backups \
-type f \
-name 'airtrail-*.sql' \
-mtime +14 \
-delete
msg_ok "Backed Up Database"

systemctl stop airtrail

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not how we handle updates, backups and msgs for service shutdown

@github-actions

This comment was marked as resolved.

@github-actions github-actions Bot closed this Jul 16, 2026
Comment thread json/airtrail.json
"interface_port": 3000,
"documentation": "https://airtrail.johan.ohly.dk/docs/overview/introduction",
"website": "https://airtrail.johan.ohly.dk",
"logo": "https://cdn.jsdelivr.net/gh/johanohly/AirTrail@main/static/favicon.png",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread ct/airtrail.sh
msg_ok "Updated AirTrail"

msg_info "Updating Service"
cat <<EOF >/etc/systemd/system/airtrail.service

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a need to update the service in the update func?

Comment thread json/airtrail.json
Comment on lines +39 to +43
},
{
"text": "The AirTrail configuration is stored in /opt/airtrail/.env.",
"type": "info"
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
},
{
"text": "The AirTrail configuration is stored in /opt/airtrail/.env.",
"type": "info"
}
}

it shows the config location on the website

@MickLesk MickLesk closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants