← Blog
May 31, 2026

Running MentisDB on an AWS EC2 Ubuntu Server with Bearer Token MCP Auth

MentisDB works well as a local daemon, but the more interesting deployment is a remote memory server: one EC2 instance, many coding agents, shared durable chains, and MCP clients connecting from laptops or other hosts.

A remote deployment changes the security model. If the MCP port is reachable from the internet, every request must authenticate before it can read or mutate memory. This guide walks through a simple Ubuntu EC2 setup, the AWS security group rules, the systemd service, and global or chain-scoped bearer tokens.

Short version: expose only TLS ports, restrict security-group sources to your own IPs, set MENTISDB_BEARER_TOKEN_ACCESS=true, create scoped tokens for users and agents, and keep global tokens for administrators.

Target Architecture

SurfaceDefault PortExpose Publicly?Use
SSH22Admin IP onlyServer maintenance
HTTPS MCP9473Client IPs onlyRemote MCP clients such as Codex, Claude Code, or mcp-remote
HTTPS REST9474Optional, trusted IPs onlyDirect REST integrations
HTTPS Dashboard9475Admin IP onlyChains, agents, skills, bearer tokens, settings
HTTP MCP9471NoLocal-only or private-network use
HTTP REST9472NoLocal-only or private-network use

You can run HTTP and HTTPS at the same time, but on a public cloud host the security group should normally expose only the TLS ports you actually need.

1. Launch an Ubuntu EC2 Instance

  1. Create an Ubuntu LTS EC2 instance.
  2. Attach an SSH key pair you control.
  3. Choose a small instance first; MentisDB's storage footprint is modest for normal agent memory workloads.
  4. Allocate an Elastic IP or stable DNS name if MCP clients will keep this server in config.

SSH into the instance:

ssh -i ~/.ssh/your-key.pem ubuntu@YOUR_EC2_PUBLIC_IP

2. Open the AWS Security Group

In the EC2 console, open the instance security group and add inbound rules like this. Replace the source CIDRs with your real office, home, VPN, or client IPs.

TypeProtocolPortSourceWhy
SSHTCP22YOUR_ADMIN_IP/32Admin access
Custom TCPTCP9473YOUR_CLIENT_IP/32HTTPS MCP
Custom TCPTCP9475YOUR_ADMIN_IP/32HTTPS dashboard
Custom TCPTCP9474TRUSTED_API_IP/32Optional HTTPS REST

Do not open 9471 or 9472 to 0.0.0.0/0. If you need wide access while traveling, put a VPN or SSH tunnel in front of the instance instead of publishing unauthenticated local-development ports.

3. Install MentisDB

Install Rust and MentisDB from crates.io:

sudo apt-get update
sudo apt-get install -y build-essential pkg-config libssl-dev curl
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
cargo install mentisdb --features local-embeddings

Install the binary somewhere systemd can find it:

sudo install -m 0755 "$HOME/.cargo/bin/mentisdb" /usr/local/bin/mentisdb
mentisdb --version

4. Create a Service User and Data Directory

sudo useradd -r -s /usr/sbin/nologin -m -d /var/lib/mentisdb mentisdb || true
sudo mkdir -p /var/lib/mentisdb /etc/mentisdb
sudo chown -R mentisdb:mentisdb /var/lib/mentisdb

5. Configure the Daemon

Create /etc/mentisdb/mentisdb.env. The important remote-server settings are MENTISDB_BIND_HOST=0.0.0.0, the TLS MCP/dashboard ports, and MENTISDB_BEARER_TOKEN_ACCESS=true.

sudo tee /etc/mentisdb/mentisdb.env > /dev/null <<'EOF'
MENTISDB_DIR=/var/lib/mentisdb
MENTISDB_DEFAULT_CHAIN_KEY=mentisdb
MENTISDB_BIND_HOST=0.0.0.0

# Keep HTTP available only if the security group blocks it from the internet.
MENTISDB_MCP_PORT=9471
MENTISDB_REST_PORT=9472

# Expose these through the security group.
MENTISDB_HTTPS_MCP_PORT=9473
MENTISDB_HTTPS_REST_PORT=9474
MENTISDB_DASHBOARD_PORT=9475
MENTISDB_DASHBOARD_PIN=change-this-admin-pin

# Required for remote or multi-user MCP servers.
MENTISDB_BEARER_TOKEN_ACCESS=true

MENTISDB_VERBOSE=true
MENTISDB_AUTO_FLUSH=true
RUST_LOG=info
EOF

sudo chown root:mentisdb /etc/mentisdb/mentisdb.env
sudo chmod 640 /etc/mentisdb/mentisdb.env

If you do not need REST from remote clients, set MENTISDB_HTTPS_REST_PORT=0 and omit port 9474 from the security group.

6. Run MentisDB with systemd

sudo tee /etc/systemd/system/mentisdb.service > /dev/null <<'EOF'
[Unit]
Description=MentisDB Daemon - Durable Semantic Memory Engine
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=mentisdb
Group=mentisdb
EnvironmentFile=/etc/mentisdb/mentisdb.env
ExecStart=/usr/local/bin/mentisdb
Restart=always
RestartSec=10
WorkingDirectory=/var/lib/mentisdb
StandardOutput=journal
StandardError=journal
SyslogIdentifier=mentisdb

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/mentisdb /etc/mentisdb

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable mentisdb
sudo systemctl start mentisdb
sudo systemctl status mentisdb --no-pager

MentisDB generates a self-signed TLS certificate if one does not already exist. For production browser ergonomics you can later replace it with your own certificate and set MENTISDB_TLS_CERT and MENTISDB_TLS_KEY.

7. Verify the Server

sudo journalctl -u mentisdb -n 80 --no-pager
ss -tlnp | grep -E '9471|9472|9473|9474|9475'
curl -k https://127.0.0.1:9473/health

From your laptop, test the remote TLS MCP health endpoint:

curl -k https://YOUR_EC2_PUBLIC_DNS:9473/health

8. Create Bearer Tokens

With MENTISDB_BEARER_TOKEN_ACCESS=true, MCP requests must include an active token. Tokens are shown only once at creation time, so paste them into your password manager or MCP client config immediately.

Global Admin Token

A global token can access every chain and server-wide MCP tools such as chain listing. Use it for administrators and trusted automation.

sudo -u mentisdb env MENTISDB_DIR=/var/lib/mentisdb \
  mentisdb bearertoken create --global admin-laptop

Single-Chain User Token

A chain-scoped token can only interact with the chains it was granted. Use this when each user or agent should work inside a dedicated memory chain.

sudo -u mentisdb env MENTISDB_DIR=/var/lib/mentisdb \
  mentisdb bearertoken create --chain alice alice-agent

Multi-Chain Team Token

A single token can also allow more than one chain. Pass --chain more than once.

sudo -u mentisdb env MENTISDB_DIR=/var/lib/mentisdb \
  mentisdb bearertoken create team-agent --chain alice --chain shared

List and Revoke Tokens

sudo -u mentisdb env MENTISDB_DIR=/var/lib/mentisdb mentisdb bearertoken list
sudo -u mentisdb env MENTISDB_DIR=/var/lib/mentisdb mentisdb bearertoken list --chain alice
sudo -u mentisdb env MENTISDB_DIR=/var/lib/mentisdb mentisdb bearertoken remove alice-agent

Removing a token revokes it. Existing MCP clients using that token should fail on their next request.

9. Manage Tokens in the Dashboard

Open the dashboard at https://YOUR_EC2_PUBLIC_DNS:9475. The header includes:

Chains | Agents | Skills | Bearer Tokens | Settings

On the Bearer Tokens page you can:

The Settings page also shows MENTISDB_BEARER_TOKEN_ACCESS alongside the other daemon environment variables, plus a restart button for settings that require a process restart.

10. Connect Codex to the Remote MCP Server

In your local Codex config.toml, point the MCP server at the HTTPS MCP endpoint and include the bearer token in the request headers.

[mcp_servers.mentisdb]
url = "https://YOUR_EC2_PUBLIC_DNS:9473"
headers = { Authorization = "Bearer mentisdb_replace_me" }

Use a global token for an administrator Codex profile. Use a chain-scoped or multi-chain token for agents that should only see particular memory chains.

11. Connect Other MCP Clients

Any remote MCP client must be able to send this HTTP header:

Authorization: Bearer mentisdb_replace_me

Prefer native streamable-HTTP MCP clients that support request headers directly. Here are the common harness shapes.

Claude Code

claude mcp add-json mentisdb \
  '{"type":"http","url":"https://YOUR_EC2_PUBLIC_DNS:9473","headers":{"Authorization":"Bearer mentisdb_replace_me"}}' \
  --scope user

Qwen Code

qwen mcp add --scope user --transport http mentisdb https://YOUR_EC2_PUBLIC_DNS:9473 \
  --header "Authorization: Bearer mentisdb_replace_me"

Or edit ~/.qwen/settings.json:

{
  "mcpServers": {
    "mentisdb": {
      "httpUrl": "https://YOUR_EC2_PUBLIC_DNS:9473",
      "headers": {
        "Authorization": "Bearer mentisdb_replace_me"
      }
    }
  }
}

GitHub Copilot CLI

Edit ~/.copilot/mcp-config.json:

{
  "mcpServers": {
    "mentisdb": {
      "type": "http",
      "url": "https://YOUR_EC2_PUBLIC_DNS:9473",
      "headers": {
        "Authorization": "Bearer mentisdb_replace_me"
      },
      "tools": ["*"]
    }
  }
}

VS Code + Copilot

Edit .vscode/mcp.json or your user-level mcp.json:

{
  "servers": {
    "mentisdb": {
      "type": "http",
      "url": "https://YOUR_EC2_PUBLIC_DNS:9473",
      "headers": {
        "Authorization": "Bearer mentisdb_replace_me"
      }
    }
  }
}

OpenCode

Edit ~/.config/opencode/opencode.json:

{
  "mcp": {
    "mentisdb": {
      "type": "remote",
      "url": "https://YOUR_EC2_PUBLIC_DNS:9473",
      "enabled": true,
      "oauth": false,
      "headers": {
        "Authorization": "Bearer mentisdb_replace_me"
      }
    }
  }
}

Hermes Agent

Edit ~/.hermes/config.yaml:

mcp_servers:
  mentisdb:
    url: "https://YOUR_EC2_PUBLIC_DNS:9473"
    headers:
      Authorization: "Bearer mentisdb_replace_me"

If your client uses a stdio bridge such as mcp-remote, confirm the bridge version and client configuration support custom headers before giving that client access to a bearer-token-protected remote server. With MentisDB's self-signed certificate, Node-based bridges may also need the MentisDB certificate trusted by the operating system or certificate verification disabled for that bridge process only.

Operational Checklist

That is the whole shape: an Ubuntu service, tight firewall rules, TLS for remote transport, and bearer tokens as the MCP authorization boundary. From there you can add DNS, a trusted certificate, backups, monitoring, and eventually per-token usage stats as the deployment grows.