Skip to main content
Using Linux Mint to request a photo from my iPhone

Using Linux Mint to request a photo from my iPhone

Hi!

I can transfer photos from my iPhone easily to my MacBook, but not to my Linux Mint PC! By combining the apps Shortcuts, Scriptables and ntfy, I built my own quirky version of AirDrop that runs inside my own network:

Illustration of the automation
#

Full automation illustration
Figure 1: Full automation illustration

1. Step: On Linux Mint
#

Using the context menu in the Linux Mint file manager Nemo, I can press “Foto hier einfügen”, which means “Insert Photo here”. This starts a Python script that sends a notification to my iPhone and then starts a small barebones webserver in my local network to accept the photo and store it in the corresponding file location:

Video 1: Requesting a photo from Linux Mint context menu

2. Step: On iOS
#

On my iPhone, I can click on the notification, which then opens the iOS Shortcut automation. The automation requests a photo and passes it to the Scriptables app, which uploads the photo to my local webserver!

Video 2: Take a photo on my iPhone that automatically gets sent to the Linux Mint PC

How this automation was developed
#

I was annoyed by existing solutions like the LocalSend app, since they all require a lot of clicks! So I already tested the ShortCuts and the Scriptables app on the iPhone and was wondering about further capabilities – so I discussed with AI and this came together. All the code is AI-generated. For this automation, I only need four manual clicks on iPhone and Linux Mint combined!

That’s it! Thanks for reading.

I am interested in your thoughts! - Reply with a simple Email

Have a nice day,

Carl

Attachments
#

In the following, I attached all the resources, so you can build the automation yourself! However, please avoid using the automation in public networks. The automation relies on transferring files using raw, unauthenticated HTTP! Since this project is a prototype, use it at your own risk.

1. iOS Scriptable
#

Download the app “Scriptable” from the App Store and create a new script, called SendPhotoFromArgs. Adjust the hostname to your Linux Mint machine!

let image = args.images[0]

if (image) {
  let data = Data.fromJPEG(image,0.9)
  let base64Text = data.toBase64String()
  let url = "http://<my_local_hostname>:8080/"

  let req = new Request(url)
  req.method = "POST"
  req.body = base64Text
  req.timeoutInterval = 10
  
  await req.load()
}

Script.complete()

2. iOS Shortcuts
#

You may need to download this app too. Then rebuild the shortcut called Send2Mint and link your new Scriptables script from step 1 in the second block of the Shortcut.

iOS ShortCut
Figure 2: iOS ShortCut

3. NTFY Setup
#

ntfy.sh is a service that provides push-notifications on an HTTP publication / subscription-basis. The Python script executed with the context menu on Linux Mint publishes a notification to a so-called topic. For the iPhone to receive the notifications:

  1. Install the ntfy app from the iOS App Store
  2. Click on + to subscribe to a topic <SECRET_TOPIC_NAME> (change the name!)

4. Linux Mint Nemo Setup
#

Add a custom Nemo context menu action:

Create a new file ~/.local/share/nemo/actions/paste_photo.nemo_action with the following content (adjust it to your computer):

[Nemo Action]
Active=true
Name=Add Photo from iPhone
Comment=Wait 60 seconds to receive a photo
Exec=bash -c 'python3 /home/<your username>/.local/share/nemo/actions/paste_iphone_photo.py "%F"'
Terminal=true
Icon-Name=camera-photo
Selection=none
Extensions=dir;any;

Save it and observe a new context menu entry! (It doesn’t work yet).

Open port 8080:

Since you want to receive images from your local network over HTTP, you need to have the port 8080 open for TCP in your firewall. Then your iPhone can access the webserver on your Linux Mint machine!

Add the Python script to the context menu action:

Create another new Python file: ~/.local/share/nemo/actions/paste_iphone_photo.py. Don’t forget to adjust the NTFY topic.

#!/usr/bin/env python3
import sys
import os
import socketserver
import http.server
import base64
import time
import urllib.request  # New for the push ping
from datetime import datetime

PORT = 8080
TARGET_DIR = sys.argv[1].replace('\\ ', ' ') if len(sys.argv) > 1 else os.path.expanduser('~')
NTFY_TOPIC = "SECRET_TOPIC_NAME"  # REPLACE with the topic name you subscribed to on the iPhone

try:
    req_url = f"https://ntfy.sh/{NTFY_TOPIC}"
    headers = {
        "Title": "Linux Mint Photo Request",
        "Click": "shortcuts://run-shortcut?name=Send2Mint", 
        "Priority": "high"
    }
    push_req = urllib.request.Request(req_url, data="Tap to take photo".encode('utf-8'), headers=headers)
    urllib.request.urlopen(push_req, timeout=5)
    print("Push notification sent to iPhone.")
except Exception as e:
    print(f"Push error (Server is starting anyway): {e}")
# -------------------------------------------------------

class SingleImageHandler(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        content_length = int(self.headers['Content-Length'])
        if content_length == 0:
            print("ERROR: No data received.")
            self.send_response(400)
            self.end_headers()
            sys.exit(1)

        print(f"Receiving {content_length} bytes of text data from iPhone...")
        base64_data = self.rfile.read(content_length)
        
        print("Decoding image data...")
        image_data = base64.b64decode(base64_data)
        
        filename = f"iPhone_Photo_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
        filepath = os.path.join(TARGET_DIR, filename)
        
        with open(filepath, 'wb') as f:
            f.write(image_data)
            
        print(f"SUCCESS! File saved: {filepath}")

        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"OK")
        
        time.sleep(0.2)
        sys.exit(0)

class HTTPServerTimeout(http.server.HTTPServer):
    def handle_timeout(self):
        print("TIMEOUT - No connection received.")
        sys.exit(0)

print(f"Server started for folder: {TARGET_DIR}")
server = HTTPServerTimeout(("0.0.0.0", PORT), SingleImageHandler)
server.timeout = 60
server.handle_request()