feat: native macos installer distribution (#1633)
* Add uninstall option and output pkg Improve installer mode detection Fix macOS installer packaging Fix default selection for uninstall choice Remove obsolete tar handling and clean script copies * Improve macOS build script * fix: update macos firewall and package scripts for better compatibility and cleanup * Add DeveloperID certificate and improve macOS signing script Use keychain option for codesign and restore login keychain to list after signing * Update build_macos.sh * feat: add script to quit GUI application during uninstall on macos * fix: handle macos post-install when app is unpacked into localized folder * fix: improve post_install script to handle missing service plist and provide error logging
This commit is contained in:
parent
b341934863
commit
4d17e913b5
14 changed files with 311 additions and 156 deletions
5
deploy/data/macos/check_install.sh
Executable file
5
deploy/data/macos/check_install.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
if [ -d "/Applications/AmneziaVPN.app" ] || pgrep -x "AmneziaVPN-service" >/dev/null; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
5
deploy/data/macos/check_uninstall.sh
Executable file
5
deploy/data/macos/check_uninstall.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
if [ -d "/Applications/AmneziaVPN.app" ] || pgrep -x "AmneziaVPN-service" >/dev/null; then
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
17
deploy/data/macos/distribution.xml
Normal file
17
deploy/data/macos/distribution.xml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<installer-gui-script minSpecVersion="1">
|
||||
<title>AmneziaVPN Installer</title>
|
||||
<license file="LICENSE"/>
|
||||
<choices-outline>
|
||||
<line choice="install"/>
|
||||
<line choice="uninstall"/>
|
||||
</choices-outline>
|
||||
<choice id="install" title="Install AmneziaVPN" start_selected="true">
|
||||
<pkg-ref id="org.amneziavpn.package"/>
|
||||
</choice>
|
||||
<choice id="uninstall" title="Uninstall AmneziaVPN" start_selected="false">
|
||||
<pkg-ref id="org.amneziavpn.uninstall"/>
|
||||
</choice>
|
||||
<pkg-ref id="org.amneziavpn.package" auth="Root" install-check="scripts/check_install.sh">AmneziaVPN_install.pkg</pkg-ref>
|
||||
<pkg-ref id="org.amneziavpn.uninstall" auth="Root" install-check="scripts/check_uninstall.sh">AmneziaVPN_uninstall_component.pkg</pkg-ref>
|
||||
</installer-gui-script>
|
13
deploy/data/macos/distribution_uninstall.xml
Normal file
13
deploy/data/macos/distribution_uninstall.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<installer-gui-script minSpecVersion="1">
|
||||
<title>Uninstall AmneziaVPN</title>
|
||||
<options customize-install-button="always"/>
|
||||
<welcome file="uninstall_welcome.html"/>
|
||||
<conclusion file="uninstall_conclusion.html"/>
|
||||
<choices-outline>
|
||||
<line choice="uninstall"/>
|
||||
</choices-outline>
|
||||
<choice id="uninstall" title="Uninstall AmneziaVPN" start_selected="true">
|
||||
<pkg-ref id="org.amneziavpn.uninstall"/>
|
||||
</choice>
|
||||
<pkg-ref id="org.amneziavpn.uninstall" auth="Root">AmneziaVPN_uninstall_component.pkg</pkg-ref>
|
||||
</installer-gui-script>
|
|
@ -7,29 +7,42 @@ LOG_FOLDER=/var/log/$APP_NAME
|
|||
LOG_FILE="$LOG_FOLDER/post-install.log"
|
||||
APP_PATH=/Applications/$APP_NAME.app
|
||||
|
||||
if launchctl list "$APP_NAME-service" &> /dev/null; then
|
||||
launchctl unload $LAUNCH_DAEMONS_PLIST_NAME
|
||||
rm -f $LAUNCH_DAEMONS_PLIST_NAME
|
||||
# Handle new installations unpacked into localized folder
|
||||
if [ -d "/Applications/${APP_NAME}.localized" ]; then
|
||||
echo "`date` Detected ${APP_NAME}.localized, migrating to standard path" >> $LOG_FILE
|
||||
sudo rm -rf "$APP_PATH"
|
||||
sudo mv "/Applications/${APP_NAME}.localized/${APP_NAME}.app" "$APP_PATH"
|
||||
sudo rm -rf "/Applications/${APP_NAME}.localized"
|
||||
fi
|
||||
|
||||
tar xzf $APP_PATH/$APP_NAME.tar.gz -C $APP_PATH
|
||||
rm -f $APP_PATH/$APP_NAME.tar.gz
|
||||
sudo chmod -R a-w $APP_PATH/
|
||||
sudo chown -R root $APP_PATH/
|
||||
sudo chgrp -R wheel $APP_PATH/
|
||||
if launchctl list "$APP_NAME-service" &> /dev/null; then
|
||||
launchctl unload "$LAUNCH_DAEMONS_PLIST_NAME"
|
||||
rm -f "$LAUNCH_DAEMONS_PLIST_NAME"
|
||||
fi
|
||||
|
||||
sudo chmod -R a-w "$APP_PATH/"
|
||||
sudo chown -R root "$APP_PATH/"
|
||||
sudo chgrp -R wheel "$APP_PATH/"
|
||||
|
||||
rm -rf $LOG_FOLDER
|
||||
mkdir -p $LOG_FOLDER
|
||||
|
||||
echo "`date` Script started" > $LOG_FILE
|
||||
|
||||
killall -9 $APP_NAME-service 2>> $LOG_FILE
|
||||
echo "Requesting ${APP_NAME} to quit gracefully" >> "$LOG_FILE"
|
||||
osascript -e 'tell application "AmneziaVPN" to quit'
|
||||
|
||||
mv -f $APP_PATH/$PLIST_NAME $LAUNCH_DAEMONS_PLIST_NAME 2>> $LOG_FILE
|
||||
chown root:wheel $LAUNCH_DAEMONS_PLIST_NAME
|
||||
launchctl load $LAUNCH_DAEMONS_PLIST_NAME
|
||||
PLIST_SOURCE="$APP_PATH/Contents/Resources/$PLIST_NAME"
|
||||
if [ -f "$PLIST_SOURCE" ]; then
|
||||
mv -f "$PLIST_SOURCE" "$LAUNCH_DAEMONS_PLIST_NAME" 2>> $LOG_FILE
|
||||
else
|
||||
echo "`date` ERROR: service plist not found at $PLIST_SOURCE" >> $LOG_FILE
|
||||
fi
|
||||
|
||||
chown root:wheel "$LAUNCH_DAEMONS_PLIST_NAME"
|
||||
launchctl load "$LAUNCH_DAEMONS_PLIST_NAME"
|
||||
echo "`date` Launching ${APP_NAME} application" >> $LOG_FILE
|
||||
open -a "$APP_PATH" 2>> $LOG_FILE || true
|
||||
|
||||
echo "`date` Service status: $?" >> $LOG_FILE
|
||||
echo "`date` Script finished" >> $LOG_FILE
|
||||
|
||||
#rm -- "$0"
|
||||
|
|
|
@ -9,6 +9,19 @@ SYSTEM_APP_SUPPORT="/Library/Application Support/$APP_NAME"
|
|||
LOG_FOLDER="/var/log/$APP_NAME"
|
||||
CACHES_FOLDER="$HOME/Library/Caches/$APP_NAME"
|
||||
|
||||
# Attempt to quit the GUI application if it's currently running
|
||||
if pgrep -x "$APP_NAME" > /dev/null; then
|
||||
echo "Quitting $APP_NAME..."
|
||||
osascript -e 'tell application "'"$APP_NAME"'" to quit' || true
|
||||
# Wait up to 10 seconds for the app to terminate gracefully
|
||||
for i in {1..10}; do
|
||||
if ! pgrep -x "$APP_NAME" > /dev/null; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
|
||||
# Stop the running service if it exists
|
||||
if pgrep -x "${APP_NAME}-service" > /dev/null; then
|
||||
sudo killall -9 "${APP_NAME}-service"
|
||||
|
@ -32,3 +45,40 @@ sudo rm -rf "$LOG_FOLDER"
|
|||
|
||||
# Remove any caches left behind
|
||||
rm -rf "$CACHES_FOLDER"
|
||||
|
||||
# Remove PF data directory created by firewall helper, if present
|
||||
sudo rm -rf "/Library/Application Support/${APP_NAME}/pf"
|
||||
|
||||
# ---------------- PF firewall cleanup ----------------------
|
||||
# Rules are loaded under the anchor "amn" (see macosfirewall.cpp)
|
||||
# Flush only that anchor to avoid destroying user/system rules.
|
||||
|
||||
PF_ANCHOR="amn"
|
||||
|
||||
### Flush all PF rules, NATs, and tables under our anchor and sub-anchors ###
|
||||
anchors=$(sudo pfctl -s Anchors 2>/dev/null | awk '/^'"${PF_ANCHOR}"'/ {sub(/\*$/, "", $1); print $1}')
|
||||
for anc in $anchors; do
|
||||
echo "Flushing PF anchor $anc"
|
||||
sudo pfctl -a "$anc" -F all 2>/dev/null || true
|
||||
# flush tables under this anchor
|
||||
tables=$(sudo pfctl -s Tables 2>/dev/null | awk '/^'"$anc"'/ {print}')
|
||||
for tbl in $tables; do
|
||||
echo "Killing PF table $tbl"
|
||||
sudo pfctl -t "$tbl" -T kill 2>/dev/null || true
|
||||
done
|
||||
done
|
||||
|
||||
### Reload default PF config to restore system rules ###
|
||||
if [ -f /etc/pf.conf ]; then
|
||||
echo "Restoring system PF config"
|
||||
sudo pfctl -f /etc/pf.conf 2>/dev/null || true
|
||||
fi
|
||||
|
||||
### Disable PF if no rules remain ###
|
||||
if sudo pfctl -s info 2>/dev/null | grep -q '^Status: Enabled' && \
|
||||
! sudo pfctl -sr 2>/dev/null | grep -q .; then
|
||||
echo "Disabling PF"
|
||||
sudo pfctl -d 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
|
7
deploy/data/macos/uninstall_conclusion.html
Normal file
7
deploy/data/macos/uninstall_conclusion.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head><title>Uninstall Complete</title></head>
|
||||
<body>
|
||||
<h1>AmneziaVPN has been uninstalled</h1>
|
||||
<p>Thank you for using AmneziaVPN. The application and its components have been removed.</p>
|
||||
</body>
|
||||
</html>
|
7
deploy/data/macos/uninstall_welcome.html
Normal file
7
deploy/data/macos/uninstall_welcome.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
<html>
|
||||
<head><title>Uninstall AmneziaVPN</title></head>
|
||||
<body>
|
||||
<h1>Uninstall AmneziaVPN</h1>
|
||||
<p>This process will remove AmneziaVPN from your system. Click Continue to proceed.</p>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue