jellyfin-server-macos/deployment
2022-08-04 11:04:39 -06:00
..
create-dmg.sh final fixes and create-dmg script 2022-08-04 11:04:39 -06:00
Jellyfin_Server.entitlements Add full Azure Pipeline CI (#32) 2020-06-02 04:12:35 -04:00
README.md Update Documentation and Fix Authors file (#49) 2022-03-03 22:30:09 -05:00

Preparing for Distribution

Developer ID Notarization

In order to distribute a notarized app that complies with GateKeeper, you must follow these steps. Using Developer ID requires a paid Apple Developer Program membership.

Set Capabilities

To notarize an app, it must be using the Hardened Runtime features of Xcode. These should already be set in the project, but for reference, you must enable these capabilities:

  • Hardened Runtime
    • Allow Execution of JIT-compiled Code
    • Allow Unsigned Executable Memory
    • Allow DYLD Environment Variables
    • Disable Library Validation

These are also listed in the Jellyfin_Server.entitlements file in this directory.

Codesign Resources

To prepare for distribution, first create an archive for distribution. All items in Contents/Frameworks and Contents/MacOS must be signed. Then you can sign the app as a whole.

An example signing command looks like this:

codesign --force --options runtime --sign "Developer ID Application: COMPANYNAME" ./Jellyfin.app

If you are an individual developer, you can place your name in the same spot as COMPANYNAME:

codesign --force --options runtime --sign "Developer ID Application: Anthony Lavado" ./Jellyfin.app

Here is an example shell script, using the signing identity like above:

# Setup variables. Ensure that the .app name is correct, and that both the .app
# and entitlements files are at the correct path.
APP_NAME="Jellyfin.app"
ENTITLEMENTS="Jellyfin_Server.entitlements"
SIGNING_IDENTITY="\"Developer ID Application: Anthony Lavado\""

# Iterate through contents that should be signed, and sign them
find "$APP_NAME/Contents/MacOS" -type f | while read fname; do
    echo "[INFO] Signing $fname"
    codesign --force --timestamp --options=runtime --entitlements "$ENTITLEMENTS" --sign $SIGNING_IDENTITY "$fname"
done

find "$APP_NAME/Contents/Frameworks" -type f | while read fname; do
    echo "[INFO] Signing $fname"
    codesign --force --timestamp --options=runtime --entitlements "$ENTITLEMENTS" --sign $SIGNING_IDENTITY "$fname"
done

echo "[INFO] Signing app file..."

codesign --force --timestamp --options=runtime --entitlements "$ENTITLEMENTS" --sign $SIGNING_IDENTITY "$APP_NAME"

After you sign the app, it is important to get it notarized by Apple so that it runs without issues on an end user's machine. If you decide to create a DMG, you must wait until you first get the app notarized, then package it in the DMG. Once you have your final DMG, you must submit it to Apple for notarization. Without this step, users will get warning messages when trying to mount the DMG.

If you want Gatekeeper validation to pass on an offline Mac, you must staple the ticket to the DMG.

DMG Considerations

If you opt to create a DMG for the app, you can use the wonderful https://github.com/sindresorhus/create-dmg.git.

Upload to Apple, and Staple Ticket

For actual steps on notarizing, I recommend two articles.

Practical Example

The current package and signing script can be viewed as a GitHub Gist.