惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
TaoSecurity Blog
TaoSecurity Blog
H
Heimdal Security Blog
Help Net Security
Help Net Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
N
News | PayPal Newsroom
V2EX - 技术
V2EX - 技术
博客园 - 【当耐特】
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Secure Thoughts
C
CERT Recently Published Vulnerability Notes
罗磊的独立博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
有赞技术团队
有赞技术团队
S
Schneier on Security
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
H
Hacker News: Front Page
The Last Watchdog
The Last Watchdog
Schneier on Security
Schneier on Security
PCI Perspectives
PCI Perspectives
IT之家
IT之家
Project Zero
Project Zero
博客园 - 司徒正美
P
Privacy International News Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Jina AI
Jina AI
Security Latest
Security Latest
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
C
CXSECURITY Database RSS Feed - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
V
Vulnerabilities – Threatpost
W
WeLiveSecurity
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity

RTFM: Linux, DevOps, and system administration

LiteLLM: AI Gateway on Kubernetes and Metrics in VictoriaMetrics Claude Code: Monitoring with OpenTelemetry and VictoriaMetrics LiteLLM: AI Gateway for LLMs – Features Overview MikroTik: User Management, access permissions, and SSH VictoriaTraces: Recording Rules, Metrics, and Alerts from Trace Spans Arch Linux: a DNS Mystery – VPN, systemd-resolved, and Unbound VictoriaTraces: Tracing, Observability, and OpenTelemetry OpenTelemetry: OTel Collectors in Kubernetes and VictoriaMetrics Stack integration Arch Linux: WireGuard Peer for Connecting to MikroTik FreeBSD: Jails Networking and Container Management with Bastille Claude Code: creating Kubernetes debugging AI Agent for VictoriaMetrics Okta: Integration with Google Workspaces, Part 1 – Provisioning
Hermes Agent: Running an AI Agent in a FreeBSD Jail with Bastille
setevoy · 2026-05-03 · via RTFM: Linux, DevOps, and system administration

I’ll write about Hermes Agent itself and what it can do separately – today it’s about how to run it on FreeBSD.

Yesterday I played around with it on my Arch Linux – now I want a more production setup.

I’ll be running it on my NAS with FreeBSD, and obviously only inside a FreeBSD Jail, since the NAS holds access to important data and backups (the whole series of posts on FreeBSD and NAS starts here – FreeBSD: Home NAS, part 1 – setting up ZFS mirror, there are 15 parts as of now).

The agent’s configuration on Linux is exactly the same – just a simpler setup, so I won’t describe it separately.

But Hermes Agent’s capabilities and a more detailed config – that I’ll do as a separate post, there’s plenty to play with there.

For working with Jails I use Bastille – I’ll write about it separately too, I have a draft.

So, here’s what we’ll do:

  • create a FreeBSD Jail
  • set up networking
  • install Hermes Agent itself
  • configure the connection to Telegram
  • and install Hermes Agent Web UI

Let’s go.

But first, a bit of off-topic 🙂

Contents

Holywar: FreeBSD Jail or “container”?

Quick note here – whether it’s correct to call a FreeBSD Jail a “container”, because I might get flamed for it 🙂

As someone who usually works with Linux, for me a “container” is both a FreeBSD Jail and a Linux Docker container, so in this post I’ll be calling Jails “containers”.

What’s more – even the official documentation for Bastille says:

While reading the documentation and using Bastille, you will find that sometimes “container” is used, and sometimes “jail” is used. These are completely interchangeable, but there is some debate as to which one is more correct. Be that as it may, anytime you read “container” or “jail”, it means a FreeBSD jail.

Besides, my blog readers are mostly Linux users too – so let’s stick with “containers”. And in the separate Bastille post we’ll talk in more detail about Jails in FreeBSD vs Linux containers.

Alright – now let’s get to the install.

Check the FreeBSD version, prepare the container:

root@setevoy-nas:~ # freebsd-version 
14.4-RELEASE-p1

root@setevoy-nas:~ # bastille bootstrap 14.4-RELEASE
...

Create the container itself – a regular FreeBSD one (Bastille also supports Linux, I have a Jail with Opeb WebUI, I’ll write about it eventually, also a draft).

Networking – Bastille VNET, so the container will be reachable from my main network at IP 192.168.0.210:

root@setevoy-nas:~ # bastille create --vnet hermesagent1 14.4-RELEASE 192.168.0.210/24 em0

Attempting to create jail: hermesagent1

Valid IP: 192.168.0.210/24

Creating a thinjail...

...

Check the Jail status:

root@setevoy-nas:~ # bastille list hermesagent1
 JID  Name          Boot  Prio  State  Type   IP Address     Published Ports  Release               Tags
 3    hermesagent1  on    99    Up     thin   192.168.0.210  -                14.4-RELEASE          -

Get inside:

root@setevoy-nas:~ # bastille console hermesagent1

[hermesagent1]:
root@hermesagent1:~ #

Install updates:

root@hermesagent1:~ # pkg update

Install packages needed for Hermes Agent:

root@hermesagent1:~ # pkg install curl bash uv sudo

Check where bash lives – on FreeBSD it’s in /usr/local/bin/, not /usr/bin:

root@hermesagent1:~ # which bash
/usr/local/bin/bash

Create a user for Hermes Agent, set the password:

root@hermesagent1:~ # pw useradd hermes -m -s /usr/local/bin/bash -c "Hermes Agent"
root@hermesagent1:~ # passwd hermes

Enable SSH:

root@hermesagent1:~ # sysrc sshd_enable="YES"
sshd_enable: NO -> YES

root@hermesagent1:~ # service sshd start

Verify the connection from my work laptop:

[setevoy@setevoy-work ~]  $ ssh [email protected]
([email protected]) Password for hermes@hermesagent1:
...
[hermes@hermesagent1 ~]$

Run visudo, add the user there – with password prompt:

hermes ALL=(ALL:ALL) ALL

To run Hermes CLI as root – add this to /root/.profile:

...
# Hermes Agent — ensure ~/.local/bin is on PATH
export PATH="$HOME/.local/bin:$PATH"

That’s it – we can install the agent itself.

Installing Hermes Agent

Install the required libraries – because the automatic Hermes Agent installer doesn’t play very nicely with FreeBSD, so let’s do it by hand:

root@hermesagent1:~ # pkg install -y python3 py311-pip py311-sqlite3 sqlite3 git curl rust pkgconf openssl libffi node22 npm-node22 ripgrep ffmpeg

Run the install – took about 5 minutes:

[hermes@hermesagent1 ~]$ curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash

Once it’s done the installer offers to configure the agent.

Hermes Agent Setup

On Arch Linux I did the quick install, here I went with the full one – to see what’s in there.

All options can be changed later, so it’s not critical.

Documentation – Configuration.

Run the agent setup:

It burns through tokens like crazy, so Claude is a no-go – went with OpenAI and GPT 5.5, works great:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

It asks for authentication – opens a link, open it on the laptop with a browser, enter the code:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Set the model to 5.5 – can be changed later via /model (see Slash Commands):

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

And from there everything can be left at defaults until we get to Messaging.

Telegram setup

Documentation – Telegram Setup.

Plenty of options here, obviously – I’ll stick with Telegram for now:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Head over to @BotFather, create a new bot:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Configure it:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Important – see Step 3: Privacy Mode (Critical for Groups).

Go into its Settings:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Disable Group Privacy:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Grab the bot’s API token:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

So we can message the bot – find your User ID via @userinfobot.

If the bot will live in a group or channel – you can find their IDs from the same @userinfobot.

I’m making this bot just for testing, so I’ll leave my user:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

And in the “home channel” too:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Done:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Then there are browser and Tools settings – leave everything at defaults, and we’re done:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Telegram and Hermes Agent Gateway on FreeBSD

On Linux Hermes Gateway is enabled simply via systemd – on FreeBSD it’s a bit “by hand” (in quotes – because I had the agent itself do it 🙂 ).

Check the current status:

[hermes@hermesagent1 ~]$ hermes gateway status
✗ Gateway is not running

To start:
  hermes gateway run      # Run in foreground
  hermes gateway install  # Install as user service
  sudo hermes gateway install --system  # Install as boot-time system service

The hermes gateway install command on FreeBSD predictably returned “not supported on this platform“:

[root@hermesagent1 /usr/home/hermes]# /home/hermes/.hermes/hermes-agent/venv/bin/hermes gateway install --system
Service installation not supported on this platform.
Run manually: hermes gateway run

Check where exactly Hermes lives:

[hermes@hermesagent1 ~]$ head -1 "$(command -v hermes)"
#!/home/hermes/.hermes/hermes-agent/venv/bin/python3

Install the python-telegram-bot Python module:

[hermes@hermesagent1 ~]$ /home/hermes/.hermes/hermes-agent/venv/bin/python3 -m pip install python-telegram-bot
Collecting python-telegram-bot
  Downloading python_telegram_bot-22.7-py3-none-any.whl.metadata (17 kB)
...

Try running it manually:

hermes@hermesagent1 ~]$ hermes gateway run
┌─────────────────────────────────────────────────────────┐
│           ⚕ Hermes Gateway Starting...                 │
├─────────────────────────────────────────────────────────┤
│  Messaging platforms + cron scheduler                    │
│  Press Ctrl+C to stop                                   │
└─────────────────────────────────────────────────────────┘

...

And message the bot in Telegram:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Hermes Agent Gateway autostart on FreeBSD

Alright, let’s see if the agent can handle the task of “I’m a lazy engineer, do something nice for me” – let it tell us itself how to add its gateway to autostart on FreeBSD:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Okay.

But I’m so lazy I don’t even want to do copy-paste – let it do everything itself.

We’re in a Jail – so it’s safe:

To create the rc.d script it needs root – asks for the password, since our sudo here requires one:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

The script is ready:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

The script it wrote – /usr/local/etc/rc.d/hermes_gateway:

#!/bin/sh

# PROVIDE: hermes_gateway
# REQUIRE: LOGIN NETWORKING
# KEYWORD: shutdown

. /etc/rc.subr

name="hermes_gateway"
rcvar="hermes_gateway_enable"

load_rc_config "$name"

: ${hermes_gateway_enable:="NO"}
: ${hermes_gateway_user:="hermes"}
: ${hermes_gateway_home:="/home/hermes"}
: ${hermes_gateway_command:="/home/hermes/.local/bin/hermes"}
: ${hermes_gateway_log:="/var/log/hermes_gateway.log"}

pidfile="/var/run/${name}.pid"
command="/usr/sbin/daemon"
command_args="-f -p ${pidfile} -u ${hermes_gateway_user} -o ${hermes_gateway_log} /usr/bin/env HOME=${hermes_gateway_home} ${hermes_gateway_command} gateway run"

start_cmd="${name}_start"
stop_cmd="${name}_stop"
status_cmd="${name}_status"

hermes_gateway_start()
{
    if [ ! -x "${hermes_gateway_command}" ]; then
        echo "Hermes executable not found or not executable: ${hermes_gateway_command}"
        return 1
    fi

    touch "${hermes_gateway_log}"
    chown "${hermes_gateway_user}" "${hermes_gateway_log}" 2>/dev/null || true

    echo "Starting Hermes gateway."
    ${command} ${command_args}
}

hermes_gateway_stop()
{
    echo "Stopping Hermes gateway."
    if [ -f "${pidfile}" ]; then
        kill "$(cat ${pidfile})" 2>/dev/null || true
        rm -f "${pidfile}"
    else
        pkill -u "${hermes_gateway_user}" -f "${hermes_gateway_command} gateway run" 2>/dev/null || true
    fi
}

hermes_gateway_status()
{
    if [ -f "${pidfile}" ] && kill -0 "$(cat ${pidfile})" 2>/dev/null; then
        echo "Hermes gateway is running as pid $(cat ${pidfile})."
        return 0
    fi

    if pgrep -u "${hermes_gateway_user}" -f "${hermes_gateway_command} gateway run" >/dev/null 2>&1; then
        echo "Hermes gateway is running, but pidfile is missing/stale."
        return 0
    fi

    echo "Hermes gateway is not running."
    return 1
}

run_rc_command "$1"

Verify everything was added to /etc/rc.conf:

root@hermesagent1:~ # cat /etc/rc.conf | grep hermes
hermes_gateway_enable="YES"
hermes_gateway_user="hermes"
hermes_gateway_home="/home/hermes"
hermes_gateway_command="/home/hermes/.local/bin/hermes"
hermes_gateway_log="/var/log/hermes_gateway.log"

Stop the “hermes gateway run” we started by hand earlier, and try starting it via the service:

[hermes@hermesagent1 ~]$ sudo service hermes_gateway start
Starting Hermes gateway.
[hermes@hermesagent1 ~]$ sudo service hermes_gateway status
Hermes gateway is running as pid 60901.

Hermes Agent and Web UI

Googled a few options, for now I went with nesquena/hermes-webui, but you can also take a look at EKKOLearnAI/hermes-web-ui.

Clone the repo:

[hermes@hermesagent1 ~]$ git clone https://github.com/nesquena/hermes-webui.git hermes-webui
[hermes@hermesagent1 ~]$ cd hermes-webui/

To make the WebUI reachable from the network – set $HERMES_WEBUI_HOST:

[hermes@hermesagent1 ~/hermes-webui]$ export HERMES_WEBUI_HOST=0.0.0.0

Start the service:

[hermes@hermesagent1 ~/hermes-webui]$ python3 bootstrap.py 
[bootstrap] Starting Hermes Web UI on http://0.0.0.0:8787
[bootstrap] Web UI is ready: http://0.0.0.0:8787
[bootstrap] Log file: /home/hermes/.hermes/webui/bootstrap-8787.log

Try it in the browser:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

In Telegram, ask it to create some kind of reminder:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

And we see it in Tasks:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

That’s pretty much it.

But here’s one more example of what you can do with the agent.

Hermes Agent Use Case example: creating documentation in DokuWiki

Asked it to walk through all my networks and find the hosts – it ran nmap, scanned everything, put it all into a table:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Then I created a separate user for the agent in my local DokuWiki, enabled XML-RPC in /usr/local/www/dokuwiki/conf/local.php:

$conf['remote'] = 1;
$conf['remoteuser'] = 'hermes-agent';

Asked the agent – and Hermes created a documentation page for me with all my hosts:

Hermes Agent: running an AI Agent in a FreeBSD Jail with Bastille

Tested it with VictoriaMetrics – it adds metrics great even without VictoriaMetrics Skills (see Claude Code: creating Kubernetes debugging AI Agent for VictoriaMetrics), so it’ll be possible to build automation like “Alertmanager webhook > Hermes > investigate > send result to Telegram”.

In short – the system is interesting, cool – you can build some really fun stuff with it.

Loading