24 min read

Self-Host Sentio for AI Agents with Localtonet

Install and verify the Sentio email inbox API, then securely expose its local REST API over HTTP with Localtonet for remote agent access.

Sentio runs locally in Docker while a remote AI agent reaches its REST API through a secure Localtonet tunnel.
Sentio remains on the local host while Localtonet provides the remote HTTP path used by an AI agent.
Self-Hosting ยท Sentio ยท AI Agents ยท Localtonet ยท 2026

Give AI agents real email inboxes while keeping the management API under your control

Sentio is a self-hosted email inbox API designed for applications and AI agents that need to receive messages, process structured email events, and send replies through a REST API. In this guide, we install the complete Sentio stack with Docker Compose, verify its local API on port 8080, address its bootstrap credentials, and cover essential operating and troubleshooting tasks. Once the service works locally, we connect it to an HTTP tunnel with Localtonet so an authorized remote agent can reach the REST API without inbound router port forwarding, firewall changes, a VPN, or a public IP address.

๐Ÿ”’ Rotate bootstrap credentials before remote access ๐ŸŒ REST API available locally on port 8080 โšก Docker Compose provides the complete dependency stack

What Sentio provides for AI agents

Many agent workflows need more than a notification address. An agent may need to receive a customer conversation, inspect the authenticated and parsed message, take an action, and reply in the same thread. Building that flow from separate components usually means combining an SMTP server, message parser, spam and malware checks, storage, queues, an IMAP polling process or webhook layer, and an outbound delivery mechanism.

Sentio packages that path into a self-hosted, multi-tenant mail service. A deployment can create domains and mailboxes for agents, route inbound messages to application webhooks, and accept outbound messages through a bearer-authenticated REST API. Tenancy applies to domains, mailboxes, API keys, rate limits, suppression lists, and spam profiles, which is useful when one application serves multiple customers or separates multiple agent environments.

This guide concentrates on installing and remotely reaching the REST API. It does not attempt to turn an ordinary tunnel into a complete public mail-delivery architecture. Sentio exposes SMTP listeners as well, but production email requires additional DNS, certificate, reputation, and network planning that is separate from making an HTTP API available to an authorized agent.

๐Ÿ“จ Mailbox per agent Sentio can assign a mailbox on one of your domains to an agent and associate application metadata with that mailbox.
๐Ÿ”” Structured webhooks Inbound mail can be parsed and delivered to an application as a webhook instead of requiring an agent to poll an IMAP mailbox.
โ†ฉ๏ธ REST-based replies Applications can submit outbound messages through the API and include the original message identifiers needed for normal email threading.
๐Ÿ›ก๏ธ Mail authentication and filtering Sentio supports inbound and outbound mail infrastructure including DKIM, SPF, DMARC, ARC, MTA-STS, DANE, virus scanning, and multiple anti-spam stages.
๐Ÿข Multi-tenant organization Domains, mailboxes, keys, limits, suppression data, and spam profiles belong to tenants rather than being shared as one undifferentiated configuration.
๐Ÿ“˜ Machine-readable API The running server provides interactive API documentation at /docs and an OpenAPI 3.1 description at /openapi.json.

The services behind the API

Sentio is not a single stateless HTTP binary when operated as a complete mail platform. Its documented Docker Compose stack starts Sentio together with PostgreSQL, Redis, NATS with JetStream, MinIO, ClamAV, and rspamd. These services cover persistent state, key-value operations, queues, object storage, malware scanning, and content analysis.

Component Role in the stack Operational implication
PostgreSQL 18+ Stores persistent application state Version 18 is a hard requirement because the schema uses the built-in uuidv7() function.
Redis or Valkey Supports rate limits, bans, greylisting, and reputation data Sentio expects the key-value layer to remain reachable during operation.
NATS with JetStream Runs delivery, retry, webhook, and event pipelines JetStream must be enabled. A plain NATS deployment without it is insufficient.
S3-compatible storage Stores raw email and attachment blobs The Compose stack uses MinIO, while manual deployments can use another compatible endpoint.
ClamAV Scans content for malware Its startup and readiness can affect how quickly the complete stack becomes usable.
rspamd Provides content-oriented spam analysis It is included in the full Compose environment rather than needing a separate initial installation.

Prerequisites and deployment choices

The most reproducible installation path is the official Docker Compose stack. It includes the supporting services and applies Sentio's migrations during startup, so this is the path used for the complete procedure below.

Prepare a host with Docker Engine 24 or newer, the Docker Compose plugin, approximately 4 GB of available memory, and approximately 8 GB of disk space. The published container image supports Linux on AMD64 and ARM64. Ensure that Git and curl are available as well, because we use them to retrieve the repository and verify the local API.

Review host port usage before starting

The Compose configuration publishes mail and API ports. Check whether another mail server, reverse proxy, development service, or management console already occupies ports 25, 465, 587, 8080, or 9001. A conflict prevents the affected container from binding successfully. Port 465 is skipped by Sentio when no certificates are present, but the remaining published ports still need careful review.

Docker Compose versus a manual installation

Installation path Best suited to Requirements and tradeoffs
Prebuilt Compose stack Most evaluations and self-hosted deployments Pulls a prebuilt Sentio image and starts the documented PostgreSQL, Redis, NATS, MinIO, ClamAV, and rspamd dependencies.
Compose build from source Developers changing Sentio itself Builds the Rust workspace from the checkout and takes longer than using the prebuilt image.
Manual installation Operators integrating with existing infrastructure Requires a stable Rust toolchain, C toolchain, CMake, libclang-dev, PostgreSQL 18+, Redis or Valkey, JetStream-enabled NATS, and S3-compatible storage.

A manual deployment gives an operator more control over service placement, but it also transfers responsibility for configuring every dependency, applying migrations, supplying a correct Sentio configuration, and defining a service manager unit. The supplied evidence confirms those requirements but does not provide enough complete configuration content here to reproduce every manual file safely. We therefore do not invent systemd units, environment variables, migration flags, or storage credentials. Use the Docker workflow below unless you have reviewed the exact manual configuration for the Sentio version you intend to deploy.

If you do select a manual deployment, confirm the database version before applying migrations:

psql -tAc 'SHOW server_version'

PostgreSQL 18 is a strict floor. On an older server, the migration fails because uuidv7() does not exist. Upgrading or selecting the correct PostgreSQL server is the proper resolution rather than trying to remove the function from Sentio's schema.

Install Sentio with Docker Compose

Docker Compose configuration and terminal status showing the Sentio service running.
Docker Compose starts Sentio with its configuration and persistent data attached.

The following workflow uses the full official stack. Run it on the machine that will host Sentio and, later, the Localtonet client.

1

Clone the Sentio repository

Retrieve the repository and enter its directory. The Compose files and supporting configuration are maintained with the source tree.

git clone https://github.com/truespar/sentio.git
cd sentio
2

Choose whether to follow the current checkout or pin a release

For a reproducible deployment, check out a release that you have reviewed. The evidenced release is v0.1.6. Pinning avoids silently changing application code when the repository advances.

git checkout v0.1.6
3

Start the complete stack

Docker Compose pulls the prebuilt Sentio image and starts its required supporting services. The image is published for Linux AMD64 and ARM64, so this path does not compile the Rust workspace locally.

docker compose up -d
4

Watch the migration process

Sentio applies migrations before the server starts. Follow the migration service logs and look for a successful schema and bootstrap process rather than assuming that a running container means initialization finished.

docker compose logs -f sentio-migrate
5

Inspect the Sentio server logs

After migrations complete, follow the application logs. Exit log-following with your terminal's normal interrupt shortcut when the server is ready.

docker compose logs -f sentio

Building Sentio from the checkout

If you intentionally want to compile the complete workspace instead of pulling the published image, use the documented Compose build overlay:

docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build

This is a release build of the workspace and can take substantially longer than pulling the prebuilt image. It is useful when auditing or modifying code, but it is not required for the normal self-hosting path.

Understand the published ports

Port Protocol or service Purpose
25 SMTP Inbound email from other mail servers through MX delivery.
465 SMTPS Implicit TLS. Sentio only binds this listener when certificates are present.
587 SMTP submission Authenticated message submission using STARTTLS.
8080 HTTP REST API Application API, health endpoint, interactive documentation, and OpenAPI description.
9001 MinIO console Optional object-storage administration console that should not be exposed unnecessarily.

The rest of this guide targets only port 8080. We do not send SMTP ports through the HTTP tunnel because SMTP is a different protocol and public mail delivery has additional requirements.

Verify Sentio locally before exposing it

A local HTTP request returns a successful response from the Sentio REST API.
Confirm the local Sentio API responds correctly before creating a public tunnel.

A remote tunnel should be the final connectivity layer, not a substitute for local diagnosis. Confirm that Sentio and its dependencies work on the host first. This separates application failures from tunnel configuration errors.

Check container state

docker compose ps

Review every service, not only the main Sentio container. The API can start late or report an unhealthy dependency when PostgreSQL, Redis, NATS, storage, or a scanning service is still initializing. If a service is restarting, inspect its logs before proceeding.

Call the readiness endpoint

Sentio documents /health/ready as the readiness check on the local REST listener:

curl localhost:8080/health/ready

A healthy documented response is:

{"status":"ok","database":"ok","kv":"ok"}

This result proves that the HTTP server answers and that the readiness check sees the database and key-value layer as available. It does not prove that public DNS, SMTP delivery, webhooks, or outbound mail reputation are configured.

Inspect the API description

Download or inspect the OpenAPI 3.1 document from the local service:

curl http://localhost:8080/openapi.json

You can also open http://localhost:8080/docs in a browser on a machine that can reach the host. The interactive documentation includes a request client for the running server. Treat that interface as an administrative surface because it helps users discover and call API operations.

Readiness is the first acceptance test

Do not create the Localtonet tunnel until the local readiness request succeeds consistently. If localhost:8080 fails on the Sentio host, changing relay servers, public URLs, or tunnel settings cannot repair the underlying Sentio deployment.

Secure Sentio before remote agent access

Sentio's migrations create a bootstrap administrator tenant and a bootstrap API key. That initial key has wildcard scope and is intended to get the installation started. It is not an appropriate credential to leave in place when the API becomes reachable from an untrusted network.

We deliberately do not reproduce the bootstrap secret in this article. Retrieve the initial value from the version-specific Sentio deployment material on the host, use it only over a trusted local connection, create a replacement through the tenant API-key endpoint, update the authorized application, verify the replacement, and then delete the bootstrap key. Never place a real key in a shell history recording, source repository, frontend application, issue report, screenshot, or Localtonet tunnel configuration.

Rotate the bootstrap administrator key first

The seeded key has wildcard scope. Exposing port 8080 before replacing and deleting that credential can place the complete administrative API at risk. Create narrowly scoped keys for agent workloads and keep administrative credentials separate from runtime credentials.

Apply least privilege to agents

An agent that only sends messages should not automatically receive tenant administration privileges. Likewise, a process that reads mailbox events may not need domain, key, suppression, or IP-pool administration. Use Sentio's scoped API-key model to give each integration only the operations it requires.

Separate credentials by environment and workload. Development, staging, production, administrative automation, and individual customer integrations should not all share one wildcard key. This limits the impact of an accidental log entry or compromised agent runtime and makes revocation more targeted.

Review all listeners

Creating an HTTP tunnel for port 8080 does not hide other host ports already published by Docker. Review the host's firewall, cloud security rules, router configuration, and Compose port mappings independently. In particular, do not expose the MinIO console merely because Sentio uses MinIO internally.

Sentio ships without TLS certificates, so it starts its own listeners in plaintext where applicable and skips port 465. For the REST workflow in this article, Localtonet provides a public HTTPS address for the HTTP tunnel, while the client connects from the device to the local target. Do not infer from that arrangement that unrelated SMTP listeners or direct host access have been secured.

Optional Sentio TLS mount

Sentio's documented Compose configuration can mount a certificate and key from a local directory. It expects files named cert.pem and key.pem:

services:
  sentio:
    volumes:
      - ./tls:/etc/sentio/tls:ro

Certificate issuance, renewal, hostname selection, and private-key permissions depend on your deployment and are not established by the supplied evidence. Do not insert placeholder certificates or reuse unrelated private keys.

Expose the Sentio REST API with Localtonet

Remote agent traffic passes through a Localtonet HTTP tunnel to the local Sentio REST API.
Localtonet routes remote HTTP requests to Sentio without moving the service off the private host.

Once localhost:8080/health/ready succeeds and the bootstrap key has been replaced, the Sentio REST listener is ready for the remote-access layer. An HTTP tunnel is the appropriate Localtonet tunnel type because the target is an HTTP API.

Our client runs on the Sentio host, or on another device that can reach the Sentio host, and establishes an outbound connection to a Localtonet relay server. You do not need inbound router port forwarding, firewall changes, VPN setup, or a public IP address for this HTTP access path. The resulting tunnel provides a public HTTPS URL while it is started and its selected client remains connected.

A public URL still needs application authorization

The tunnel makes the target reachable. It does not remove the need for Sentio bearer authentication, scoped keys, secret handling, webhook validation, or least-privilege design. Assume that an internet-reachable URL may be discovered and protect every sensitive API operation accordingly.

1

Install and run the Localtonet client

Install our client on the Sentio host or on a device that can reach its HTTP listener. Keep the client running for as long as remote agents need the tunnel.

2

Authenticate and select the client device

Use the device-specific authentication token associated with the client that will run the tunnel. Treat the token as a secret and never copy it into documentation, source code, screenshots, or agent prompts.

3

Select an available relay server

Choose a server or region currently available in the Localtonet dashboard. Availability can vary, so obtain the value from the current product rather than copying a hardcoded server code from an article.

4

Create the HTTP tunnel configuration

Select an HTTP tunnel and set its local target to the Sentio REST listener. When the Localtonet client runs on the same host, use local IP address 127.0.0.1 and port 8080. Choose the available process type appropriate to your deployment: Random Sub Domain, Custom Sub Domain, or Custom Domain. Exact custom-domain DNS requirements must be checked in the current dashboard documentation before changing DNS.

5

Start the tunnel

Creating the configuration does not start it. Press the Start button and wait for the tunnel to run. Localtonet then assigns the applicable public HTTPS address.

6

Verify the public route and manage its lifecycle

Request the Sentio readiness path through the assigned public URL, then test an authenticated operation with a narrowly scoped non-bootstrap key. Stop the tunnel when remote access is no longer required, or delete it if the configuration should not be retained.

The public readiness check follows this shape, with the assigned URL substituted at review time:

curl https://your-assigned-host/health/ready

Do not copy a private production hostname or bearer token into shared troubleshooting output. For an authenticated API test, use a secret-management method suitable for your agent platform and verify that the selected key can perform only the required operation.

Selecting the local target correctly

Use 127.0.0.1:8080 only when the Localtonet client and the published Sentio API port are on the same machine. If our client runs on a different device, the local target must be an address that device can actually reach. Confirm that route privately before creating the tunnel.

If you run the Localtonet client inside a container, 127.0.0.1 refers to that container rather than automatically referring to the Sentio container or Docker host. Container networking varies by deployment, and the supplied evidence does not establish a universal container hostname. Test connectivity from the exact environment where our client runs instead of guessing.

What remote agents should use

Give the remote agent the public API base URL and a scoped Sentio bearer credential through the agent platform's secret store. The agent can use the OpenAPI description to understand supported operations, but unrestricted exposure of /docs or /openapi.json may disclose unnecessary API structure. Whether to permit those paths depends on your surrounding access controls and threat model.

Keep inbound webhooks conceptually separate from the REST API. The tunnel described here lets a remote process call Sentio. If Sentio must call a webhook running on another private machine, that webhook endpoint needs its own reachable HTTPS route and its own request-verification policy. Do not reuse a Sentio API key as a webhook signing secret.

Routine operation and maintenance

Inspect status and logs

Use Compose to see the current service state and inspect the two most relevant startup logs:

docker compose ps
docker compose logs sentio-migrate
docker compose logs -f sentio

A tunnel can remain connected while Sentio is unhealthy, so monitor the application and tunnel as separate layers. Sentio readiness confirms the local application state. Localtonet tunnel status confirms that the selected client is connected and the tunnel is running.

Stop Sentio without deleting its data

docker compose down

This stops the stack while retaining its Docker volumes. After Sentio stops, a Localtonet HTTP tunnel targeting port 8080 has no healthy application to forward to. Stop the tunnel as well if maintenance should not leave a public endpoint returning connection errors.

Delete the stack and its volumes

docker compose down -v
The -v option deletes volumes

Use this only when you intentionally want to remove the Compose-managed data. It is not an ordinary restart command. Verify your backup and recovery plan before deleting any production volume.

Plan upgrades rather than following moving code

Review release notes, container tags, migration behavior, and compatibility before upgrading. Test the target release against a copy of the deployment and confirm the readiness endpoint, authenticated API operations, queue processing, storage access, and agent integration.

The exact backup tools and upgrade sequence depend on whether you use Compose-managed PostgreSQL and MinIO or external services. The supplied evidence does not define one universal production backup command, so we do not invent one. At minimum, a recovery plan must account for persistent database state and stored message or attachment objects, not just the Git checkout.

Troubleshooting Sentio and Localtonet

Symptom Likely area What to check
localhost:8080 refuses connections Sentio startup or port publication Run docker compose ps, inspect Sentio logs, and confirm that another process is not using port 8080.
Migration reports that uuidv7() does not exist PostgreSQL version Confirm that the actual connected database is PostgreSQL 18 or newer.
Readiness reports a database problem PostgreSQL availability or configuration Inspect database and migration logs, then verify that initialization completed successfully.
Readiness reports a key-value problem Redis or Valkey Check the key-value service state and logs rather than changing the HTTP tunnel.
Port 25 cannot bind Existing mail server or privileged port restrictions Check for Postfix, Exim, or another listener. On a manual non-root Linux binary, binding port 25 requires the appropriate capability.
Port 465 is not listening Missing Sentio TLS certificates This is expected when no certificate and key are mounted. Sentio skips the implicit-TLS listener without them.
Local readiness works but the public URL fails Localtonet lifecycle or target Confirm that the selected client is connected, the tunnel was started, and the target is the reachable Sentio address and port.
Public readiness works but API calls return unauthorized Sentio authentication Check bearer-token handling, key scope, revocation status, and tenant association. Do not weaken authentication to fix it.
The URL works only while a terminal is open Client lifecycle Ensure the Localtonet client remains running on the selected device. A tunnel is available only while its client is connected and the tunnel is running.

Resolve a port 25 conflict during evaluation

If another service already uses port 25, Sentio documents a Compose override that replaces its published port list:

services:
  sentio:
    ports: !override
      - "2525:25"
      - "4465:465"
      - "5587:587"
      - "8080:8080"

Save that content as docker-compose.override.yml. The file is loaded automatically and is ignored by the repository. This can resolve local conflicts for evaluation, but remapping inbound SMTP from public port 25 to 2525 does not make normal internet MX delivery use port 2525. Other mail servers ordinarily connect to the standard SMTP port.

Separate application errors from tunnel errors

Use a layered test sequence:

  1. Check the Compose service state.
  2. Call localhost:8080/health/ready on the Sentio host.
  3. If the Localtonet client is on another device, call the private Sentio address from that device.
  4. Confirm that the selected Localtonet client is connected.
  5. Confirm that the HTTP tunnel is started.
  6. Call the public readiness URL.
  7. Finally, test a permitted authenticated operation with a scoped key.

This sequence identifies the first broken layer. For example, a successful public readiness response combined with a failed authenticated request usually points to Sentio authorization or request formatting, not to Localtonet connectivity.

Why production SMTP is a separate project

The HTTP tunnel solves remote access to Sentio's REST API. It does not by itself make the installation a deliverable, reputable public mail server.

Receiving internet email requires control over a domain and correct MX records that lead other mail systems to an SMTP listener. Sending reliably also involves forward and reverse DNS alignment, PTR records controlled by the address owner, SPF, DKIM, DMARC, TLS, reputation, suppression handling, bounce processing, complaint feedback, and provider-specific policies. Port 25 may be blocked by a hosting provider or ISP, and a nonstandard replacement port is not a transparent substitute for server-to-server SMTP.

Sentio includes substantial protocol and authentication functionality, but those capabilities still require deployment-specific DNS and infrastructure. Localtonet supports raw TCP tunnels, yet that fact alone does not establish that a relay endpoint is appropriate for production SMTP, that it provides the required reverse DNS, or that receiving providers will accept mail from it. No such deliverability claim is made here.

Use the HTTP tunnel for the agent control plane

A practical first deployment is to install Sentio, verify the API, rotate credentials, and let authorized agents reach port 8080 through Localtonet. Treat public SMTP delivery, DNS publication, certificates, and mail reputation as a separate production workstream.

Frequently asked questions

What hardware does the Docker installation require?

The documented quick-start baseline is Docker Engine 24 or newer with the Compose plugin, approximately 4 GB of RAM, and approximately 8 GB of disk. The published Sentio image supports Linux AMD64 and ARM64. Production capacity depends on message volume, attachment storage, retention, scanning load, and queue activity, so the quick-start baseline should not be treated as a universal sizing guarantee.

Which Sentio endpoint should I expose through Localtonet?

For remote agent API access, expose the HTTP REST listener on port 8080. When the Localtonet client runs on the same host, the target is 127.0.0.1:8080. Verify /health/ready locally before creating the tunnel.

Does creating a Localtonet tunnel automatically start it?

No. Creating a tunnel and running it are separate lifecycle actions. After configuring the HTTP target, press Start. The tunnel remains available only while the selected client is connected and the tunnel is running.

Does the public HTTPS URL replace Sentio authentication?

No. The URL provides network reachability to the local HTTP service. Sentio's bearer authentication, scoped API keys, tenant boundaries, secret storage, and authorization policies remain necessary. Rotate and delete the bootstrap key before enabling remote access.

Can I run Sentio without Docker?

Yes, but a manual deployment requires a stable Rust toolchain, CMake, libclang-dev, a C toolchain, PostgreSQL 18 or newer, Redis or Valkey, NATS with JetStream, and S3-compatible storage. You must also supply correct configuration, apply migrations, and manage the service. Docker Compose is the safer documented quick-start path because it brings up the complete dependency stack.

Why does Sentio require PostgreSQL 18?

Sentio's schema uses the built-in uuidv7() function introduced in PostgreSQL 18. Running migrations against an older PostgreSQL server causes a missing-function failure. Confirm the actual server version before installation rather than assuming that a client package version identifies the database server.

Can I expose Sentio's SMTP ports with the same HTTP tunnel?

No. An HTTP tunnel is appropriate for the REST API, not raw SMTP. Localtonet supports raw TCP tunnels, but production mail delivery also depends on MX records, port 25 reachability, PTR and other DNS records, TLS, authentication alignment, reputation, and recipient policies. Those requirements must be designed and validated separately.

What happens if I stop Sentio but leave the tunnel running?

The tunnel can remain active, but its local target will not provide a healthy response because nothing is serving the Sentio API on port 8080. During planned maintenance, stop the tunnel if you do not want the public endpoint to remain reachable while the application is unavailable.

Connect your self-hosted Sentio API with Localtonet

Install Sentio, confirm its local readiness endpoint, replace the bootstrap administrator key, and then create an HTTP tunnel to port 8080 for your authorized remote agent workflow.

Get Started Free โ†’

Localtonet is a secure multi-protocol tunneling and proxy platform designed to expose localhost, devices, private services, and AI agents to the public internet supporting HTTP/HTTPS tunnels, TCP/UDP forwarding, mobile proxy infrastructure, file server publishing, latency-optimized game connectivity, and developer-ready AI agent endpoint exposure from a single unified control plane.

support