Ask HN: How to setup own server hosting a service with API (and no front end)?
Hello HN, I'd like to use my own server to host a new service, accessible through an API, for an application (Win/Android/iOS) that I wrote and that already has users. No web frontend is necessary. Just the service that my app calls through an API.
So far I have relied on Google Cloud (App Engine, Cloud functions, etc..) to run these kinds of things but for the new service I find that Google Cloud is too limited. It also requires Mac computers with M1, running Monterey.
My question is: how do I get started setting up my own server(s)? I found numerous tutorials for setting up web servers but I don't need a website / frontend. Just the service with an API. I would also like to have some amount of scalability and protection against DDoS and similar attacks. Is this possible?
(
17 comments
| 12 points
| on HN
)
> It also requires Mac computers with M1, running Monterey.
Does the operation requiring macOS needs to be synchronous & instant or can it be asynchronous and respond within a few seconds/minutes?
I'd highly suggest decoupling the Mac-related part of the API into an asynchronous task, that way the actual API servers can be inexpensive Linux servers.
There would be an instant response as some kind of receipt confirmation, but the actual result would be delivered later (within some minutes).
On the macOS side, you would need an application (in whatever language you prefer), that pulls events on Pub/Sub topic, processes the image/video, and then uploads the result to the cloud (either on API, or maybe directly to Cloud Storage or the database.)
This will ensure that your M1 machines are never directly exposed to the users, and allow you to scale out to multiple machines if needed.
On the macOS side, you would need an application (in whatever language you prefer), that pulls events on Pub/Sub topic,
I assume there's an easy way for my server to talk to Google Cloud's pub/sub?
The core of a worker is while (true) { download_job_request(); do_job(); send_result(); }. [4] Having the worker connect outwards to get the job, and submit the result, has benefits: (1) not having your worker "listen for incoming traffic" dramatically improves your security situation (2) you don't need to build a separate system to track which workers are accepting jobs right now.
I don't know your use case, or what physical and network security is truly needed. A Mac Mini or two in your house, ideally on a separate network [5], may be enough. Or you could rent from some cloud providers (Note: you do not want your Mac accepting connections from the Internet! You want a hardened remote-access method your cloud provider manages). Renting a cubic foot in a data center, and putting Mac Minis in it, is an in-between for cost/security, but will require the most expertise.
Workers running on cloud compute, or serverless, typically connect to the job queue using security permissions provisioned in that cloud. Just like your webapp talks to its database. If your workers are on-prem or in a different cloud, you'll need to provision access tokens/keys in your main cloud, and somehow make them available to your Mac software, which will use them to initialize the GCP/AWS/Azure SDK. Doing this "properly" is a big job! If you're going to YOLO and copy-paste them into a config file, I suggest (0) don't keep them in version control! (1) unique token per worker host (2) strictly limit tokens' permissions to what is needed (3) expire tokens after 120 days, meaning any worries about tokens issued in January, become moot by June.
You'd need a Mac-native solution to deploy and run software. If you have 3 "worker nodes", you can probably manage by hand. Past that, I've read Hashicorp's Nomad can manage deploying and running software on Macs like Kubernetes can on Linux.
You will eventually encounter situations like: (1) Workers lock up (2) Particular jobs take much longer than others (3) I just fixed an issue but there are 7 hours of jobs backed up in the queue... Until these cause unacceptable customer pain, I suggest you have one reliable and documented process to (1) Stop all workers (2) Empty the queue (3) Restart all workers. Practice this, to eliminate one source of stress during an outage. Also, make sure your UI behaves sensibly if the result for a particular job never appears.
If you get to the point of 24/7 monitoring, the things to page on are: (1) upper/lower thresholds for rate at which items enter the queue (2) same for items exiting the queue (3) upper threshold for queue size (4) upper threshold for per-job end-to-end time. All but the last should be trivial to monitor in a cloud queue product.
Definitely do some back-of-the-envelope math on the data size of the request and response. These can affect latency and cloud network egress cost. If that makes hybrid GCP/off-GCP impractical, I'd still recommend a worker-based solution that avoids exposing the Macs to user HTTP requests.
[1] https://docs.microsoft.com/en-us/azure/architecture/guide/ar... [2] https://aws.amazon.com/blogs/compute/running-cost-effective-... [3] https://shopify.engineering/high-availability-background-job... [4] Note the Neural Engine is doing no work while waiting for downloads/uploads. You can get a lot more efficient by downloading the next job in the background, and sending results asynchronously. If macOS can handle a few different processes contending for the Neural Engine, you can likely get the same result by running multiple copies of a single-threaded worker per Mac. [5] https://www.actiontec.com/blog/how-to-create-a-separate-wifi...
The Mac machines can poll the DB for new items, process them, then submit the finished item of work back to the DB.
The client can poll (using the previously-obtained reference) for the status, or the completion of a job can notify the client (push notifications, websocket, etc) to avoid polling.
With this you won't have to expose port to public internet, and fiddle with your firewall and router.
Then you can use Cloudflare DDoS protection and other offerings.
[0] https://developers.cloudflare.com/cloudflare-one/connections...
How does Docker(and compatibles) handle M1? I’d recommend getting your app containerized as early as possible, that should improve the portability, operability and reliability stories.
But also, if OP sees a business opportunity today, and they've already solved it on top of macOS, I think they should strike while the iron is hot, with the code that exists. Most businesses die because they can't get enough users and keep them. IMO it makes sense to take on tech debt.