Distributing Mac apps outside the App Store, a quick start guide (2021)
rambo.codes
rambo.codes
On the surface, "just bundle an update framework and be done, right?"
Sparkle is great, but very complex--xml AppCasts, delta updates, fancy mukti-party signing etc... Not a workflow you can quickly set up.
Squirrel (which Electron uses) is dead simple, but is absolutely ancient and basically unusable outside of Electron at this point. I seem to remember that the Electron project had some custom patches to keep it alive, but these weren't usable elsewhere.
And with either of these, because it ships as part of your app you have to be very careful to never push a broken build. If you do, your users get terminally updated to a broken app that you can't update again.
And never shipping a crashing build is easier said than done :) Are you really testing on every point release of the OS? Are you confident that you've tested all of the "magic" security behavior of macOS (the OS loves to insta-crash your app for these things)
The inevitably of shipping a broken build is why big companies build update agents that run in the background and independently update (or roll back) the app, e.g. Dropbox. But to my knowledge none of these updaters are open source.
Is the situation any better on Windows?
"to my knowledge none of these updaters are open source."
It's a bit better on other platforms. Omaha does this on Windows and is open source, but it's also abandoned. Google are rewriting it as Chromium Updater. Also Omaha's complexity makes Sparkle look like hello world.
Conveyor makes MSIX packages for Windows and DEBs for Linux. MSIX is a bit like Omaha, there's a local agent that wakes up from time to time and updates apps on their behalf. There are bugs in it for older versions of Windows but Conveyor works around them. I wouldn't recommend trying to use it directly because it'll seem to work on your nice and up to date Windows but fail for people who aren't accepting online updates. However, when you get it stable, it's actually a really nice feature set.
Sparkle has the ability to update apps independently, without being invoked by the app itself, via a command line tool. Currently Conveyor does invoke Sparkle from within the packaged app at startup as per usual, but moving to a dedicated background service would be a good improvement.
They've done the work of finding which APIs actually work and handling all the edge cases. <rant> macOS's APIs in this area are a woeful mess of "deprecated, but the new APIs don't actually work". Sometimes the only way of reliably doing something is using Applescript... https://mjtsai.com/blog/2020/04/20/privileged-operations-on-... </rant>
Just distribute on the App Store, if possible, and maybe with less functionality
How do I bypass the notarization requirement? Can I use a shell script that would remove the quarantine attribute? As in, I'd put the script into my disk image and instruct the user to click it to install the app.
I don't know if this still works, but it used to be that when you right-click an app bundle in Finder and select "open" (as opposed to double clicking the bundle) you get an "open anyway" option in the OMG APPLE CORP JUST WANTS YOUR BEST warning dialog.
The easiest solition is, as kybernetyk says, to right-click the app. If you do that, you can bypass most the warnings.
Another possibility would be to install the app in a way that doesn't set the quarantine attribute, eg. with curl, rsync or brew cask.
But Apple has been tightening seccurity year after year, so it's questionable how long all the workarounds will continue working.
My recommendation would be to just notarize the app - Mac users expect notarized software, and if you tell users they need to bypass the security checks, then a lot of people will think you are sketchy.
The problem is that this involves having a developer ID, which costs $100/year — which is the one thing I'd like to avoid. Hence my question. The apps I'm contemplating about would be free and open-source so I won't be making any money on them.
Real question: why is $100/yr such an egregious amount of money?
If it’s a matter of principle, perhaps targeting macOS also lies outside those principles.
$100/year is a lot of money to people in a wide variety of life situations. Being unable to afford this does not make them any less of a programmer.
Each of them were between 150 and 200 euros on today's money.
High school student allowance in early 1990's Portugal after decades of dictatorship wasn't that great either.
Anyone that can afford Apple hardware as an high school student surely can afford the dev subscription.
It is up for the customers to validate their business decisions.
Second, Web also exists.
Third, this whole thread is about macOS.
> Yes, a company has the right to do whatever they want with their products. > It is up for the customers to validate their business decisions.
So, to verify: you do agree that your argument at least does not apply to the iPhone?
Still the point stands.
Do you want to defend Apple's absolute control over the iPhone in front of God, Saurik and everyone, or admit that the world's richest company operates out of greed sometimes?
Are Apple’s fees worth 15%[1] of the vendors revenue? Possibly not, though as a provider, they are entitled to make a profit.
[1] Yes, yes; 30% if the vendor make > $1,000,000. Let get real, the significant majority of the app that you are arguing about are likely to be grossing less than that. And of course 15% of $0 is $0, so the argument is completely moot for freely distributed apps.
The big thing people seem to disagree with is Apple forcing themselves to be a provider (and thereby forcing their entitlement to a profit). Apple is certainly entitled to compensation when people use their service, but no computer should force it's services on the user. Regulators seem to really hate that bit, and it will be interesting to see how Apple responds to the Digital Markets act.
UWP died because the large pool of Windows developers didn't want to buy into it.
If you try to take your business elsewhere, you have no market, because no one else is able to create a store which targets the same market. This is entirely unlike a grocery store, because if Safeway is unreasonable you can launch an entire store just for your own products and people can shop at both.
However, with these curated store platforms, a user can only use the App Store. They can get a different phone--at ridiculous expense, as there are numerous anticompetitive lock-in mechanisms with respect to licenses that prevent this: I would, for example, lose access to all of the music and books and apps I've ever bought--but then they aren't able to use the App Store anymore.
The problem is that virtually all sane people only carry around a single phone. This is not true of grocery stores or frankly any other form of store unless you map the analogy to geographic regions, where people have to move to a new house in a different community--at great difficulty and expense--to get to another grocery store. Even if you only have a monopoly over one "small" region, that's still a monopoly.
Plus I have known many offshore colleagues from African and Asian countries that managed to be successful in selling software, despite the conditions they were raised in.
So painting the Apple story as gate keeping is playing it short, there are many ways to skin a rabbit.
I'm not going to sit around all day and play pity-party with you about impoverished developers. I've known my fair share too, and I might even be one depending on your definition of poor living conditions. The point is simple: Apple stops people from doing arbitrary stuff for no reason. Perhaps you don't care; I'm not arguing that. Maybe it doesn't stop people from getting rich; obviously, money is still made. Regardless, everyone knows their deal stinks like shit - the cat's out of the bag. Apple bought themselves a couple months with the 15% punch-line, but the laughing stops next year.
This isn't controversial or high-concept stuff. You should be able to freely install stuff on your iPhone even if you don't personally intend to. It seems like by-and-large, the democratic world agrees.
Looking around in the average small city in the US today, McDonalds is paying $15-$20 an hour.
Bit of a difference there, perhaps something worth being upset about.
But even if I buy your argument, are you saying that selling software also has no value since once you write it, the marginal cost of delivering software is basically $0
The problem was never that Apple wanted to offer cloud resources or scan for known exploits. Go wild, Microsoft does that too and it works great for them. People are only mad when Apple conflates completely arbitrary capabilities with their $99 dev service fee. I should not need a recurring subscription to install an App from Github. We're not in 2005 anymore, we're done selling feature phones.
Every platform that respects the freedom and authority of it's users seems to agree that all software is free. As Apple is an American company, it would make me very happy to see them agree with those values.
I’ve been paying the $100/yr to sell my iPhone apps since I was 15. It’s really not very much money, even to a high school kid.
I think this is the first time I’ve seen someone dig in so passionately that the fee is unreasonable. Most people just pay it and keep building.
I'll happily answer any further questions, but I'm afraid my opinion isn't as interesting as you think it is.
You also don't need any subscription to install any macOS app, but without it being signed by a developer, you have to -- le gasp -- control-click or right-click, and accept the warning that the developer is unverified. Hardly a massive tax on end users.
Wanting to work on software for macOS doesn't automatically mean you own a $3000 MacBook Pro...
That aside, if GP did run an Apple Silicon machine, there's also the market to buy used, and buy lower-spec models like the base-spec Mac Mini or MacBook Air.
Once again, these aren't $3000 machines, and you don't know whether the machine they use was gifted, loaned, used, a work machine, etc. -- although the decided choice by their own admission, and their profile, suggests cost wasn't a factor for them.
Do you have a point, or are you just looking to argue? The response was in your incredulous "Yet you can afford to buy a Mac?" accusation to GP -- which is loaded with baseless assumptions. I reasonably pointed out any ways someone could own a Mac without significant or any cost to themselves. Nobody said anything about it being the most modern or powerful machine, all GP said was that they want to create FOSS apps for Mac, and didn't agree with paying the $99/yr Developer program fee for signing apps as an "authorised developer."
GP says they're "Ex VKontakte, Telegram" in their profile though, which would imply they've made some money at least... and their comments read as more of an unwillingness to pay the $99, not an inability to do so ¯\_(ツ)_/¯
The hardware itself has some value though
Does your app have value? It’s not hardware.
Why stop at Apple then? Why not paying the antivirus companies as well?
And I'm not sure it's relevant either since SSL does give additional technical security, Apple stamping doesn't.
I'm targeting macOS because that's the OS I use. I use it because the two alternatives suck a lot more. Modern Mac hardware is also really nice and a joy to use. The integration of software and hardware is unmatched by any competition.
It basically requires you to be incorporated and hire a notary so you‘re probably spending $ 1000 or more for the first year. Renewal is cheaper but you will still be paying at least $ 100 a year.
Also if you know a good affordable way for a code signing certificate on Windows answer to this comment. I gave up the last time I tried.
https://www.ksoftware.net/code-signing-certificates/
Last time I looked they had the best pricing I could find at about $70/year. However, you still have to jump through the antiquated hoops for them to validate your business. One of the hoops was something like "have a business address and phone number listed in a commercial directory" which was particularly tricky to do for us since we don't have a company office anywhere and don't have a company phone number. In 2022, it should be reasonable for a software company to exist without a published phone number. I think we got around that by setting up a Twilio or Google Voice number and then adding a business listing in Google to one of our owner's residential addresses. Totally useless but apparently good enough to pass validation.
I'm using it for my app, and I never had any issues. You don't need to incorporate a company to get this certificate ( https://support.sectigo.com/PS_KnowledgeDetailPageFaq?Id=kA0... scroll down to the Individual Validation Requirements).
If your ID has your address printed on it, then you are lucky and can just take a photo of the ID and yourself holding the ID. If you don't, then you need to go to a notary and sign a special form provided by Sectigo.
Sectigo doesn't even need to call you anymore, as it was about 5-10 years ago.
The downside of the OV certificate is that Windows Defender will show a blue pop-up saying that your app might put the user's PC at risk. Good thing is that it will eventually go away after some time. For my app it took about a year.
That's the problem ID's don't have addresses printed on them in most European countries. So you have to get a notary and this is really expensive. There is a system to proof your place of residence here without a notary but these companies don't accept them.
There's no reason to do windows code signing unless you're writing a hardware driver(?).
If you love the hardware and the integration, and have the money, what exactly is your issue? -- if you were about FLOSS more than anything you wouldn't be pushing the proprietary platform stuff to begin with, and if you don't like the "walled garden" approach you shouldn't be using Apple ¯\_(ツ)_/¯
The same things apply to the Microsoft Store for apps, and similar (but to a much lesser degree) for the likes of the Ubuntu Software Center. It's about trust, ease of use, and having apps and updates all handleable from one location.
If you're distributing the app yourself, outwith the App Store, you don't have any of those "dependencies" -- and if your complaint is paying to have your code signed properly as a dev, that's the same across macOS and Windows, in a similar vein to SSL certs for websites. Sure, you can work without it, but you're going to alienate and scare some users by doing so.
But I use none of Apple's online services. Not even the app store. App store for me is the place to update Apple apps, and that's really it.
> and if your complaint is paying to have your code signed properly as a dev, that's the same across macOS and Windows,
Windows? I know you can sign Windows executables, but why would anyone want to? I have Windows 11 on a VM. It runs unsigned executables just fine and, unlike macOS, doesn't treat them like they're radioactive. You just get a differently-colored confirmation window if you run them as administrator.
> in a similar vein to SSL certs for websites
And before Let's Encrypt and other similar free automatic CAs came along, SSL/TLS was very niche.
See, it's about choice. If you want to throw your money away for some reason, sure you can still pay for an SSL certificate. Or you can use Let's Encrypt for free, set it up once and forget. Your users would see a lock icon either way. No such luck with macOS app signing — Apple is your only option.
I like Android's security model better. You sign your apk with a self-signed certificate. No signing identity is enforced upon initial installation, but if you release an update, the new apk has to be signed with the same certificate. You can install an apk with the same package id but a different signature only after you uninstall the previous one (and delete all its private data). This helps with security and data integrity. I see no reason why Apple couldn't adopt a similar scheme on their platforms, except that they want all control they could get away with.
It ought to! I'd love to see this in Linux and the BSD's too. Signing applications and binaries should be the norm.
> And before Let's Encrypt and other similar free automatic CAs came along, SSL/TLS was very niche.
Let's Encrypt came about to help with security. Happy to hear arguments pro a similar service for application signing, but it will have to follow similar, or tighter restrictions and you'd still be at the whim of third party.
> I like Android's security model better. You sign your apk with a self-signed certificate.
That is most definitely not a security policy. Self-signing is no different to not signing at all. There is no provenance, no chain-of-trust.
We should've probably started with the fact that I despise security policies based on provenance, chains of trust, public key infrastructure, and third parties. This kind of "security" feels extremely fragile and unnecessarily centralized. We somehow live with how SSH identifies servers by their keys, with no third-party verification, and consider that an okay level of security. Why can't we use the same approach for TLS and for executable signatures? What's so fundamentally different that third parties are required in these cases?
Self signing is open to too much abuse. The whole point of signing is that the provenance can be verified (yes, checksums are a thing) and that the signing can be revoked should something bad happen. Notarising code is the process of a third party verifying your identity. So rather than saying, “hey, you can trust me”, you are asking a third party to vet and prove that you are trustworthy. If you can’t see the value in that for all parties - including the most important party, your customers - then that’s up to you. No sane SOC will allow unsigned or self-signed binaries. Consumers with the slightest bit of savvy will not run unsigned or self-signed binaries, and OS vendors need to take care of the rest. Thinking of the Confidentiality, Integrity and Availability triad, your solution is unworkable.
> Consumers with the slightest bit of savvy will not run unsigned or self-signed binaries
I'm a "consumer with the slightest bit of savvy" and I despise code signing schemes that care about the signing identity, so you're already wrong. I absolutely will run unsigned and self-signed binaries. I trust myself and my own judgement more than I do anyone else in the entire universe.
Do we think it costs Apple $100 a year to grant this?
The burden should be on Apple to justify this.
If you need an argument in defense of paying $100/yr for a signing certificate: it’s definitely a barrier to entry. It makes high volume scams based on obtaining signing keys too expensive. If it were free for all, it would be a free-for-all for scammers … until the world asked Apple to “do something about it” and that something would be charging for access to those certs.
If you want to distribute Mac apps you don't need a Developer ID. You can literally control-click (or right-click) the app and click Open, and you'll be given a warning asking if you're sure, as it's from an unidentified developer -- simple.
It's not a "problem" -- it's a choice.
If you want to distribute Mac apps without having to have an FAQ about Gatekeeper, suck it up and pay the $99.
A $100 developer account from Apple allows you to sign software so that there will be no scary dialog boxes when a user downloads your software off the internet and opens it.
An ~$100 code signing certificate for use on Windows will allow you to digitally sign your Windows application, but users will still see a scary dialog box from Windows SmartScreen when they download your software unless you spend a good bit more to step up to an Extended Validation certificate.
If you don't want to pay, you'll just have to accept that users are going to see a scary dialog box, and take care to warn them that it will happen on your website.
But I'm not sure if that would remove notarization requirement.
There is a significant difference between “just click on this”, and “open the DOS prompt and write these magical runes”
May be it could work with software? Like you've executed some scary command to enable this software to work, now you attached to it.
IKEA furniture assembly involves very simple tasks and tools, and a guide that's purely pictorial -- and even then, there are an array of services where people will do that assembly for you, even offerings from IKEA themselves.
Software neither has the same physical presence, nor the same relative lack of risk. The average person can appreciate something "made with their own hands," but lacks the specialist knowledge to appreciate a script or code deployment.
Given how scared and how easily-scammed people can be by having someone open Event Viewer in Windows and claim this means their computer has viruses, opening some script and demanding verbatim typing of commands is more likely to lead to anxiety or unsureness than anything, and certainly not attachment.
You're thinking as if the average person is the average HN reader -- they're not. At all.
The average user shouldn't need to delve into the command line -- whether it's macOS, Windows, Ubuntu (for example), whatever -- that's the whole point of a GUI.
System Software (later Mac OS, for Mac OS 7.6 through Mac OS 9) didn't have a command line interface available. That did Apple pretty well from 1984 to 2001.
Mac OS X (and later OS X, then macOS) obviously have the Terminal app, but it is neither a requirement nor in common usage for the average desktop user.
Maybe don't be so classist and reductive? Not everyone hangs out on HN and uses terminal emulators regularly...
You keep doing what you're doing -- I'm pleased to have encountered the world's most popular blogging anesthesiologist!
I've made my very first MacOS app and users didn't complain installing it. It's https://github.com/ris58h/Touch-Tab BTW.
Why? As a software user I want you to notarise your software.
"One day," Apple could do anything. One day, they could totally prevent installing things that are not notarized. One day, they could entirely prevent non-AppStore, non-sandboxed applications from running on macOS. They haven't, but they could and indeed all signs point to these being on the very long-term roadmap. Does this mean you stop writing Mac apps today?
This has in fact happened: https://blog.charliemonroe.net/a-day-without-business/
Otherwise… that is kind of the point of Gatekeeper. If it was any easier, notarization would be pointless and ineffective.
---
PS. Thanks for posting this. I got stuck and, frankly, demotivated after spending a few days porting my app (https://enso.sonnet.io) just to realise that I couldn't properly sign it for App Store distribution (took another 3 days of painful work with the AppStore Connect API). I know it sounds silly but learning that even someone like Guilherme would consider publishing paid apps without the App Store made me think that I might've lost track of the actual problem: putting the app in front of the users.
But for my aging parents, my kid when he was young etc I was glad the App Store was the default and that apple normally warns you the first time you run something downloaded. It helps stop drive by downloads.
I still would posit post people do. It comes pre-installed on your Mac, and even gets an appearance in the app launcher and Spotlight.
Give it a chance, I guess? This is one of those "XKCD's lucky 10,000" moments: https://xkcd.com/1053/
Homebrew's search is better, and there are more applications available. Many applications aren't on the App Store at all, so one needs to Google and download possibly unnotarized .dmg archives. Surely this is no easier than Homebrew.
Homebrew's search isn't better if the average user isn't familiar with or used to the command line.
The "possible unnotarized .dmg archives" is a straw man and distracts from the main point -- GP just doesn't want to spend the $99/year.
You've now got multiple people stating that your understanding of view of the average user seems substantially skewed, maybe it's worth taking a look at that.
>...they don't know enough to know better.
is rather snarky and condescending IMHO
Making people follow a step-by-step guide is already a challenge on its own. Manuals are discarded because people consider themselves too good to need to read them, even if they have no idea what they're doing.
If you distribute your code in a way that's harder than clicking on a file and maybe dragging it into a folder, you're going to leave users stranded.
These days almost everyone may have a computer or tablet, but the average computer literacy hasn't gone up since the 90s. Especially on platforms like Apple's, which tries its hardest to hide away difficult concepts like "files" and "directories", you're going to need to babyproof your software for the average audience.
Now, if your target audience has a higher than average technical skill (programmers etc.) then you can get away with curl|bash no problem. Even still, I've had to help full-time developers on Windows open a command prompt several times because it's just not what they'll use in their normal day job, so even curl|bash may be too much to ask for some people in a strictly technical target audience!
A few misc thoughts:
1. Sparkle is a great update engine, Zorg is a very skilled and hard working developer. Conveyor integrates it into your app without needing any code changes so you can use it even if you aren't an Objective-C/Swift dev.
2. Skipping notarization. Conveyor can generate self signed apps along with a download.html page that tells users what to do, if you don't give it signing keys. The page repeats Apple's instructions for bypassing Gatekeeper via the UI (right click+open), and it also supplies a `curl|bash` script that does the same thing. It's free for open source apps and we have some users who use it to distribute self-signed apps via GitHub Releases with updates. You can also distribute CLI apps this way (without homebrew) but that feature isn't quite finished/documented yet, it's sort of pending launch until we understand how much demand there actually is.
I personally think notarization is a reasonable balance that works better than the approaches taken by Windows and Linux, but there are cases where it's just getting in the way. One obvious case is internal tools that you're distributing to colleagues - in this situation personal developer ID might not be appropriate but the company may guard its actual signing keys with complex process. In those cases you already know the source of the app and don't need Apple's help staying safe. Self-signing (rather than being entirely unsigned) makes Apple Silicon Macs happy, and allows the OS to remember what permissions the app has across upgrades.
3. You don't need code signing certs for sign web apps (just TLS certs) because of the sandbox. I'm exploring the possibility of a new feature - signing using our keys for people/projects that can live inside an app sandbox. You'd upload the output of your build system and we'd then build, sign and host the resulting packages. If you control the packaging you control the entry point which means you can then drop arbitrary privileges before executing the real code, and it means you can force updates to occur if sandbox holes are found. The problem is that you're competing against the price of just buying keys, so it's a bit unclear how much demand there is from the non-open source users who would ultimately be paying for it.
4. Desktop distribution can be a somewhat mysterious/difficult topic for people new to it, especially all the signing stuff. Conveyor isn't open source for better or worse, but the flip side is that it comes with commercial support. In the past we've been able to help customers even with bugs in third party libraries that only showed up when an app was packaged, and only on macOS.
[1] https://hydraulic.software/ (disclosure notice: I wrote it and run the company)
While possible, I highly recommend going the extra mile of shipping a .dmg from the start if your app requires any extra permissions (file access, network, etc.)
macOS turns out to be very, very hesitant to provide file access to apps that were downloaded as zips and will do so SILENTLY.
I spent more than three weeks banging my head against this. Here's the full run-down with all the details: https://forum.obsidian.md/t/streamline-a-stream-of-conscious... if you're interested.
Based on your comment and mike_hearn's, Gatekeeper Path Randomization squatted in squarely my blind spot :)
In every test, I copied the app to /Applications before starting it.
For reproducibility, here are the exact steps I took, with .zip[^1] and .dmg[^2] respectively on a test machine:
1. Download the archive from github
2. Extract/mount the archive
3. Drag the app to /Applications
4. Open the app
5. Configure a specific file-path for indexing
And here's the difference I observed:
- Zip: Silent failing, no indexing of files, no exceptions, no errors, "app doesn't work"
- Dmg: Files are indexed as intended, "app works"
Is this what you would have expected as well?
[1]: Streamline.zip from https://github.com/akaalias/getstreamline/releases/tag/v3.5....
[2]: Streamline.dmg from https://github.com/akaalias/getstreamline/releases/tag/v3.5....
Try downloading both and then using otool to see:
otool -fahl Streamline.app/Contents/MacOS/Streamline >/tmp/sl1
otool -fahl Streamline\ 2.app/Contents/MacOS/Streamline >/tmp/sl2
diff -u /tmp/sl{1,2}|lessFrom 3.5.2 to 3.5.3 I did remove image assets from a view[^1], so the app contents are not the same.
I have an idea:
How about I bump the version to 3.5.4 without changing anything else, and create a release with both, .zip and .dmg to compare them.
Ideally, I'd use a completely new Mac (to avoid re-using an existing permission) to...
- first install and run the app from .zip, expecting the app to be shadow-banned
- secondly install and run the app from .dmg, expecting the app to work
What do you think?
[^1]: https://github.com/akaalias/Streamline/commit/d113095604ce4c...
If you want, I've created the release with .zip and .dmg here: https://github.com/akaalias/getstreamline/releases/tag/v3.5.... – Here's the commit: https://github.com/akaalias/Streamline/commit/28b063c91f720e...
I've added screenshots of what it should look like for reference.
Will do a test as soon as I can get another test-naïve test machine :D