How to Set Up and Use the ipswd Daemon for Remote REST API Operations
The ipswd daemon transforms the ipsw command-line tool into a lightweight RESTful HTTP service, enabling remote machines and CI pipelines to execute firmware analysis operations over HTTP or Unix domain sockets.
The ipswd daemon is part of the blacktop/ipsw open-source project, providing a server mode that exposes core ipsw functionality through a structured REST API. By running the daemon, you can offload IPSW scanning, symbolication, and AEA lookup tasks to a dedicated service, allowing distributed systems to interact with Apple firmware data without local command-line installation.
Architecture of the ipswd Daemon
Understanding the daemon's internal structure helps troubleshoot configuration issues and extend functionality.
Command Entry Point
The binary entry point resides in cmd/ipswd/main.go, which simply invokes cmd.Execute() to register the CLI command tree.
// cmd/ipswd/main.go
cmd.Execute()
This lightweight main function delegates all operational logic to subcommands, following standard Go CLI patterns.
Start Command Implementation
The start subcommand creates the daemon instance and initiates the server. In cmd/ipswd/cmd/start.go, the RunE function instantiates the daemon and calls its Start() method:
// cmd/ipswd/cmd/start.go
daemon := daemon.NewDaemon()
daemon.Start()
This sequence triggers the full initialization chain: configuration loading, database setup, and HTTP server creation.
Daemon Core Orchestration
The internal/daemon/daemon.go file contains the primary orchestration logic, wiring together three critical components:
- Configuration – Loaded from
~/.config/ipsw/config.yml(or a custom path via--config) - Database layer – Initialized through
setupDB(), supporting SQLite, PostgreSQL, or in-memory storage - HTTP server – Constructed by
api/server/server.go
The Start() method coordinates these dependencies, ensuring the database connection is established before the server begins accepting requests.
Server Configuration
The HTTP server configuration is defined in api/server/server.go through a struct that specifies:
- Host and port (default
127.0.0.1:3993) - Unix socket path (optional alternative to TCP)
- Debug mode flag
- Log file destination
- PEM database path for AEA operations
- Kernel symbol signatures directory
API Routing Structure
Routes are registered under the /v1 prefix, with specific handlers located in api/server/routes/. Key endpoints include:
/v1/syms/scan– Kernel symbol scanning/v1/aea/*– AEA lookup operations/v1/version– Server version information
Configuration and Setup
Proper configuration ensures the daemon listens on the correct interface and maintains persistent data where required.
Configuration File Location
The daemon searches for config.yml in ~/.config/ipsw/ by default. You can override this with the --config flag. The repository provides a reference template in config.example.yml:
daemon:
host: 127.0.0.1
port: 3993
debug: false
log_file: /var/log/ipswd.log
Copy this template to the config directory and modify values to match your deployment environment.
Database Options
The setupDB() function in daemon.go supports three storage backends:
- SQLite – File-based storage suitable for single-node deployments
- PostgreSQL – Network database for high-availability setups
- In-memory – Volatile storage for testing or ephemeral workloads
Configure the driver in config.yml under the database section. If omitted, the daemon may initialize an SQLite file automatically in the config directory.
Starting and Managing the Daemon
Once configured, launch the service using the CLI.
Starting the Service
Execute the start command to initialize the daemon:
ipswd start
This command reads the configuration, establishes database connections, and binds the HTTP server to the configured address.
Checking Daemon Status
Verify the service is operational by querying the version endpoint:
curl http://localhost:3993/v1/version
Alternatively, use the built-in status command:
ipswd status
Using the REST API
With the daemon running, clients can execute ipsw operations via HTTP requests.
Scanning IPSW Files
To scan an IPSW file for kernel symbols remotely, send a POST request to the scan endpoint:
http POST http://localhost:3993/v1/syms/scan path=./iPhone15_2.ipsw
The daemon processes the file using the same logic as the local ipsw syms scan command, returning JSON data containing discovered kernels, build numbers, and firmware keys.
Unix Socket Communication
For local inter-process communication without TCP overhead, configure a Unix socket in config.yml:
daemon:
socket: /tmp/ipsw.sock
debug: true
After restarting the daemon, communicate through the socket using tools like socat or custom clients. The server detects the non-empty socket field and switches from TCP to Unix domain socket mode automatically.
Programmatic API Example
Fetch version information programmatically using curl and jq:
curl -s http://localhost:3993/v1/version | jq .
Expected response:
{
"api_version": "v1.0",
"os_type": "linux",
"builder_version": "0.5.2"
}
Summary
- The ipswd daemon exposes
ipswCLI functionality through HTTP endpoints defined inapi/server/routes/ - Configuration resides in
~/.config/ipsw/config.ymland supports both TCP and Unix socket listeners - The daemon supports SQLite, PostgreSQL, and in-memory databases via
setupDB()ininternal/daemon/daemon.go - Default service address is
127.0.0.1:3993, with all routes prefixed by/v1 - Remote operations mirror local commands, enabling CI pipelines to execute firmware analysis without local tool installation
Frequently Asked Questions
What is the default listening address for ipswd?
By default, the daemon binds to 127.0.0.1:3993 as defined in the server configuration struct within api/server/server.go. You can override this by specifying host and port values in your config.yml or by setting the socket parameter to use Unix domain sockets instead.
How do I run ipswd with a Unix socket instead of TCP?
Set the socket field in your configuration file to a valid filesystem path, such as /tmp/ipsw.sock. When daemon.Start() detects a non-empty socket value, it creates a Unix domain socket listener rather than a TCP socket, eliminating network overhead for local clients.
Which database backends does ipswd support?
The daemon supports three storage options through the setupDB() function: SQLite for file-based persistence, PostgreSQL for enterprise deployments requiring concurrent access, and in-memory storage for testing environments. Configure your preferred driver in the database section of config.yml.
How do I verify the daemon is running correctly?
Query the health check endpoint using curl http://localhost:3993/v1/version or execute ipswd status from the command line. A successful response returns JSON containing the API version and builder version, confirming that the daemon initialized correctly in internal/daemon/daemon.go and is actively serving requests.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →