← Return to homepage
Nous Research · MIT Open Source · 2026
How to deploy Hermes Agent on Oracle VM for free
OCI Free Tier ARM in practice · 2 vCPU / 12GB RAM Free forever (since 2026-06-15) · systemd running 24/7
Zero-cost cloud AI Agent, all pitfalls have been eliminated for you
⚡ This guide is based on actual measurement on 2026-08-01. All resources must be maintained within the "Always Free" quota, and fees will be charged if they are exceeded.
Directory
0. Architecture
0How to deploy (architecture overview)
Hermes Agent is an open source AI Agent framework (MIT protocol) developed by Nous Research - it reads files, writes code, executes commands, and controls browsers on the terminal. It is not bound to any model manufacturer and has a built-in Telegram Gateway. Put it on Oracle's permanently free VM and it becomes a 24/7 uninterrupted cloud AI Agent.
Telegram messages→
Hermes Gateway→
DeepSeek API→
AI Reply→
Telegram chat
systemd service management: auto-start at boot, auto-restart after crash, and disconnect SSH all run as usual.
💰
Free forever
ARM 2 vCPU + 12GB RAM + 200GB disk (since 2026-06-15), no long-term credit card charges
🔄
Model freedom
You can choose from DeepSeek / OpenAI / Anthropic / Google, just change the supplier and change the config.
💬
Telegram native
Built-in Gateway, a systemd service that automatically replies 24/7
🖥️
Zero operational anxiety
Automatic restart after crash + journald log + remote backup, you can’t even sleep.
1. Register
1Register for an Oracle Cloud Free Tier account
Go to registration page
https://signup.cloud.oracle.com/
Fill in your name, email, and country/region.
Pick Home Regionkey
Be sure to pickSupports Ampere ARM instancesRegion (Cannot be changed after Home Region):
Osaka / Tokyo / Paris / Frankfurt / Ashburn / Phoenix are all supported.
If you choose the wrong Home Region, there will be no ARM instances - this will determine whether you will have 2 vCPU free machines later.
Credit card verification
A valid credit or debit card is required. Oracle will temporarily deduct the contract$1 USDVerify and return after a few days.Virtual or prepaid cards are not accepted.
Waiting for activation
Usually a few minutes to a few hours. Log in after receiving the activation emailcloud.oracle.com.
⚠️ Free does not mean unlimited:Resources exceeding the "Always Free" limit will incur fees. It is recommended to upgrade to Pay-As-You-Go (still $0, but it can be solved when the capacity is insufficient, and it is also an antidote to the lack of capacity with free ARM).
2. Create VM
2Create an OCI computing instance (VM)
Open the creation page
OCI Console →Compute → Instances → Create Instance. The area should display the "Always Free-eligible" label.
Pick image file
Change image → pickUbuntu 22.04 LTS or 24.04 LTS.
Pick instance specificationsARM Ampere Recommended
| Plan | Specifications | Suggestions |
| ARM Ampere A1 | VM.Standard.A1.Flex— 2 OCPU + 12GB RAM (was 4/24 before 2026-06-15) | ✅ Main force (largest within free allowance) |
| x86Micro | VM.Standard.E2.1.Micro— 1/8 OCPU + 1GB | ❌ Too thin, only suitable for testing |
Network + SSH key
Use the default VCN/subnet and check "Assign a public IPv4 address". SSH select "Paste public keys" and paste your public key (generate it if it is not available locally):
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
Increase the boot disk size to 200GBFree cap
Show advanced options → Boot volume → Custom size → Enter200(GB). The default is 50GB. It is not so convenient to expand it first before downloading.
Create and remember the Public IP
Wait for the status to change to "Running" and record the lower Public IP (for example130.123.45.67).
3. SSH
3Connect VM and system initialization
SSH connection
ssh -i ~/.ssh/id_rsa ubuntu@<your Public IP>
Ubuntu default user systemubuntu;Oracle Linux firstopc.
Update system
sudo apt update && sudo apt upgrade -y
Install basic tools + set time zone
sudo apt install -y curl git wget nano vim ufw build-essential
sudo timedatectl set-timezone Asia/Hong_Kong
Turn on UFW firewall (first layer)
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
⚠️ Remember:Oracle has two layers of firewall— In addition to UFW/iptables inside the VM, there is also the Security List of OCI VCN (discussed in Section 10). Both floors must be opened first.
4. Installation
4Install Hermes Agent
One click installation
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
Automatic completion: install uv → build Python 3.11 venv → install 100+ dependencies → install Node.js → install cua-driver.
Reload + verify
source ~/.bashrc
hermes --version
out to the version number (e.g.hermes 0.14.0) means success. The installation path is~/.local/bin/hermes, set in~/.hermes/.
⚠️ ARM actual test pit: HTTP/2 download failed.The installation script may report when downloading Node.js
curl: (92) HTTP/2 stream error. Solution:
Ctrl+CTermination → Manually download Node.js for ARM using HTTP/1.1:
curl --http1.1 -L "https://nodejs.org/dist/v22.11.0/node-v22.11.0-linux-arm64.tar.gz" -o /tmp/node.tar.gz
mkdir -p ~/.hermes/node
tar -xzf /tmp/node.tar.gz -C ~/.hermes/node --strip-components=1
rm /tmp/node.tar.gz
If you re-execute the installation script, the downloaded Node.js will be skipped.
5. setup
5Initial settings (setup wizard)
Start wizard
hermes setup
Options at a glance
- Setting mode: Quick setup (quick) or Custom setup (detailed)
- Terminal backend:local backend
- Messaging platform: Select “Skip — set up later” and set up Telegram separately (section 7-8)
Complete
Setting writing~/.hermes/config.yaml, the key is written~/.hermes/.env.
6. API Key
6Set model provider and API Key
Hermes supports any supplier. The following uses DeepSeek as an example (high cost performance, no overseas payment required).
枞DeepSeek API Key
platform.deepseek.com→ Registration/Login → API Keys → Create Key (sk-beginning). New users have free quota.
Confirm config.yaml
nano ~/.hermes/config.yaml
provider: deepseek
model: deepseek-v4-pro
base_url: https://api.deepseek.com/v1
Write to .env
DEEPSEEK_API_KEY=sk - your deepseek key
Verify connection
hermes chat
Enter "Hello" and receive the reply successfully.Ctrl+CExit.
⚠️ Pitfall: There are two types of DeepSeek Key!People who have used Claude Code + DeepSeek may be mistaken - one is used by Claude Code
ANTHROPIC_AUTH_TOKEN, one is the DeepSeek platform native Key,
Both have the same format but different values. Use the original Key of the platform; reporting 401 means Key error. Quick test:
curl https://api.deepseek.com/v1/chat/completions \
-H "Authorization: Bearer sk-your key" \
-H "Content-Type: application/json" \
-d '{"model":"deepseek-v4-pro","messages":[{"role":"user","content":"hi"}]}'
200 = valid, 401 = invalid.
7. Gateway systemd
7Install Hermes Gateway (systemd service)
On a Linux server, Gateway must run systemd to: auto-start at boot, auto-restart on crash, stay connected 24/7, and continue running after disconnecting SSH.
Install Gateway
hermes gateway install
Manually create systemd service filecore steps
⚠️The biggest pitfall: systemd cannot read .env files!Environment variables must be written directly to the service file, otherwise the Bot session will be "No messaging platforms enabled".
sudo nano /etc/systemd/system/hermes-gateway.service
[Unit]
Description=Hermes Gateway Service
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu
ExecStart=/home/ubuntu/.local/bin/hermes gateway
Restart=always
RestartSec=10
Environment=PATH=/home/ubuntu/.local/bin:/usr/local/bin:/usr/bin:/bin
# Key: systemd does not read .env, environment variables must be written directly there!
Environment=DEEPSEEK_API_KEY=sk-your deepseek key
Environment=TELEGRAM_BOT_TOKEN=Your Bot Token
Environment=TELEGRAM_ALLOWED_USERS=Your Telegram digital ID
Environment=TELEGRAM_HOME_CHANNEL=Your Telegram digital ID
Environment=GATEWAY_ALLOW_ALL_USERS=true
[Install]
WantedBy=multi-user.target
Key points of modification:User/WorkingDirectory/ExecStartChange according to actual path; fiveEnvironment=All must be filled in with true values.
Start + Start at boot
sudo systemctl daemon-reload
sudo systemctl enable hermes-gateway
sudo systemctl start hermes-gateway
Verify + read logs
sudo systemctl status hermes-gateway
sudo journalctl -u hermes-gateway -f
status displayactive (running), the log sees✓ telegram connectedThat is success.
Set up log rotation (to prevent disk explosion)
sudo nano /etc/systemd/journald.conf
SystemMaxUse=200M
SystemKeepFree=500M
RuntimeMaxUse=100M
sudo systemctl restart systemd-journald
Lessons from actual testing (our machine):To modify the service file, you can write it locally and upload it first -sudo cpenter/etc/systemd/system/Againdaemon-reloadJust have to. In additionBefore using systemd on Bot, you must pkill the old polling process., otherwise Telegram will report 409 Conflict (two getUpdates compete for the same Bot at the same time). finallyhermes git pull --rebaseRemember to restart the service after updating.
8. Telegram
8Access Telegram Bot
Build a Bot with @BotFather
Telegram search@BotFather→/newbot→ Set name/username →Bot Token(Format123456:ABC-DEF1234ghiJKL). Store it properly and avoid leakage.
Get your Telegram digital ID
Search@userinfobot→/start→ Numeric ID (e.g.123456789).
Update systemd service files
sudo nano /etc/systemd/system/hermes-gateway.service
Environment=TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghiJKL
Environment=TELEGRAM_ALLOWED_USERS=123456789
Environment=TELEGRAM_HOME_CHANNEL=123456789
Environment=GATEWAY_ALLOW_ALL_USERS=true
sudo systemctl daemon-reload
sudo systemctl restart hermes-gateway
Verify
log see✓ telegram connected, and then talk to your Bot on Telegram and get a reply.
Troubleshooting tips:Bot has no response → ①sudo systemctl status hermes-gatewaySystem running → ② logjournalctl -u hermes-gateway -f→ ③ seeNo messaging platforms enabled= Token has not been read → ④ Check the service file Environment → ⑤daemon-reload+restart→ ⑥ Verify again.
9.SOUL.md
9Set Chinese reply (SOUL.md)
Edit SOUL.md
cp ~/.hermes/SOUL.md ~/.hermes/SOUL.md.backup
nano ~/.hermes/SOUL.md
Add language rules at the top:
CRITICAL LANGUAGE RULE: You MUST reply in Chinese (繁体中文) at all times.
The user speaks Chinese. Never use English unless the user explicitly asks.
(Optional) Inject project knowledge
SOUL.md can write identity, skills, project structure, coding specifications, and commonly used commands - it becomes Hermes' "long-term memory" and is referenced in every conversation.
Restart takes effect
sudo systemctl restart hermes-gateway
After changing SOUL.md, you must restart Gateway for it to take effect.
10. Firewall
10Firewall and security rules (both layers must be turned on)
Oracle VM hasTwo-layer firewall: Security List of OCI VCN (cloud layer) + UFW (system layer) within the instance. Both floors will not be allowed to pass until they are cleared first.
▎10.1 OCI Security List (cloud layer)
Open inbound rules
OCI Console → Networking → Virtual Cloud Networks → Select VCN → Subnets → Security Lists → Default Security List → Add Ingress Rules:
| Source type | Source CIDR | port | Purpose |
| CIDR | 0.0.0.0/0 | 22 | SSH |
| CIDR | 0.0.0.0/0 | 80 | HTTP |
| CIDR | 0.0.0.0/0 | 443 | HTTPS |
If you install WebUI, you need to open the corresponding port (such as 8787).
▎10.2 Instance firewall (system layer)
sudo ufw status verbose
should see22 / 80 / 443 ALLOW IN. Oracle Linux users may need to change iptables directly if UFW does not respond.
⚠️ Lessons from actual testing: OCI’s “NSG ≠ iptables”.If you have opened the security list in the Console but still cannot connect, it is best to check iptables in the VM - first confirm whether the OCI layer (Security List / NSG) is allowed. The two floors are independent.Any layer that blocks it will fail.. Zhong You: Many times 443 has been occupied by other services (such as sing-box proxy). Before opening the port,ss -tlnpTake a look at the location below.
11. Command quick check
11Common command cheat sheet
| instructions | function |
hermes chat | Start terminal conversation mode |
hermes --tui | Start TUI interface |
hermes setup | Run the setup wizard again |
hermes update | Update Hermes Agent (for source version)git pull --rebase) |
hermes gateway install / status / restart | Gateway Installation/Status/Restart |
hermes cron list / status | List/view scheduled tasks |
sudo systemctl status hermes-gateway | Check service status |
sudo systemctl enable hermes-gateway | Start automatically at boot |
sudo journalctl -u hermes-gateway -f | View service logs in real time |
tail -f ~/.hermes/logs/gateway.log | View Hermes logs instantly |
df -h / free -h | Disk/memory usage |
12. Step on the trap
12A collection of pitfalls (all personally tested)
Q: Bot reports 409 Conflict after running systemd?
Reason:The old polling process is still competing with the Gateway for a Bot Token.
Solution:Before starting servicepkill -f "hermes"or directlypkill -f polling, againsystemctl start hermes-gateway.
Q: Gateway is started but Bot is completely unresponsive?
Reason:9 Systemd does not read environment variables. Log appearsNo messaging platforms enabledThat is, the Token is not loaded.
Solution:Confirm the service fileEnvironment=All five variables are filled in →daemon-reload+restart→ Read the log again.
Q: DeepSeek API reports 401 Authentication Fails?
Reason:The wrong Key (the Claude Code one) is used or the Key expires.
Solution:Use curl to test the Key (see §6) → Rebuild the platform → Update the service fileDEEPSEEK_API_KEY→daemon-reload+restart.
Q: SSH connection failed/timed out?
Check order:① Is OCI Security List open? 22 → ② Public IP Yes → ③ Key permissionschmod 400 ~/.ssh/id_rsa→ ④ Username (for Ubuntuubuntu).
Q: Out of memory (OOM)?
Basically you will not encounter this with ARM 2 vCPU / 12GB instances. x86 micro needs to add Swap first:
sudo fallocate -l 4G /swapfile && sudo chmod 600 /swapfile && sudo mkswap /swapfile && sudo swapon /swapfile
Join again/etc/fstabEffective permanently.
Q: Will Oracle recycle my machine?
Oracle will recycle free instances with long periods of low activity. Gateway 24/7 operation itself is a continuous activity; if you want to be more stable, you can add keepalive:
crontab -e→ Join*/30 * * * * echo "keepalive $(date)" >> ~/keepalive.log
Q: Do I need to restart after updating?
apt upgradeAfter updating the kernel, you need tosudo rebootEffective first;hermes git pull --rebaseAfter updating the source code, you need tosudo systemctl restart hermes-gateway.
13.WebUI
13Advanced: Hermes WebUI (optional)
Want to interact with the Agent using the browser interface without using SSH? Just install WebUI.
Clone + set password
cd ~
git clone https://github.com/nesquena/hermes-webui.git hermes-webui
cd hermes-webui
echo "HERMES_WEBUI_PASSWORD=Set a strong password" > .env
Build systemd service
sudo nano /etc/systemd/system/hermes-webui.service
[Unit]
Description=Hermes WebUI
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/hermes-webui
ExecStart=/home/ubuntu/hermes-webui/start.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Launch + Access
sudo systemctl daemon-reload
sudo systemctl enable hermes-webui
sudo systemctl start hermes-webui
Open browserhttp://<Public IP>:8787, log in with the .env password. Remember OCI Security List to pass 8787.
(Optional) Nginx reverse generation + HTTPS
sudo apt install nginx certbot python3-certbot-nginx -y
sudo nano /etc/nginx/sites-available/hermes-webui
server {
listen 80;
server_name ai.yourdomain.com;
client_max_body_size 500M;
location/{
proxy_pass http://127.0.0.1:8787;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
sudo ln -s /etc/nginx/sites-available/hermes-webui /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl restart nginx
sudo certbot --nginx -d ai.yourdomain.com
14. Backup
14Backup and maintenance recommendations
▎14.1 Regular backup (the most important files)
tar -czvf hermes-backup-$(date +%Y%m%d).tar.gz \
~/.hermes/config.yaml ~/.hermes/.env ~/.hermes/SOUL.md \
~/.hermes/logs/ /etc/systemd/system/hermes-gateway.service
# Pull back to local
scp ubuntu@<Public IP>:~/hermes-backup-*.tar.gz ./
config.yaml(setting),.env(key),SOUL.md(long-term memory), systemd service files - these four additions are the "soul" of the machine, without them they are the same as starting from scratch.
▎14.2 Maintenance rhythm
| Frequency | What to do |
| weekly | sudo apt update && sudo apt upgrade -y+sudo apt autoremove -y |
| monthly | sudo journalctl --vacuum-time=30d;df -h/free -hCheck |
| every 3-6 months | rotation API Key, check Drive/remote backup integrity |
▎14.3 Safety recommendations
- Regularly update the system package; after kernel update
sudo reboot
- It’s not easy to use root to run Hermes (use ubuntu user)
- Limit
TELEGRAM_ALLOWED_USERS, to prevent unauthorized use
- Install fail2ban to prevent brute force cracking:
sudo apt install fail2ban -y
- Regularly check API usage to avoid unexpected overspending
Appendix
15 ⚠️ 2026-06-15: Oracle silently halved the free tier
On 2026-06-15 Oracle silently updated its Always Free docs with no announcement or email: the ARM allowance was halved from 4 OCPU / 24GB → 2 OCPU / 12GB (monthly cap 3,000 OCPU-hrs + 18,000 GB-hrs → 1,500 + 9,000). Network egress stays at 10TB/month (unchanged).
| Config (always-on for a month) | Usage | New cap 1,500 + 9,000 |
| 4 OCPU / 24GB (old) | 2,920 OCPU-hrs + 17,520 GB-hrs | ❌ 2x over |
| 2 OCPU / 12GB (new) | 1,460 OCPU-hrs + 8,760 GB-hrs | ✅ Fits exactly |
▎Pure free vs PAYG — different fates
- Pure free accounts: over the cap → risk of forced instance termination (shrink to 2/12 to be safe)
- PAYG: ✅ Official written confirmation (2026-08-03) — not affected; keep your existing 4 OCPU/24GB, no resize, no billing, no deadline
⚠️ Only caveat (acknowledged by Oracle): a stopped instance can be started again normally; but if it is terminated, recreating the same configuration depends on ARM capacity in Osaka at that time. Insurance in place: OCI boot volume backup + Drive off-site backup.
▎Official policy text (key excerpts)
Source: docs.oracle.com — Always Free Resources
"All tenancies get the first 1,500 OCPU hours and 9,000 GB hours per month for free for VM instances using the VM."
"you can create one or two OCI Ampere A1 Compute instances, 2 OCPUs total."
▎Official support reply, verbatim (2026-08-03, PAYG inquiry)
"Thank you for providing the details. Since your tenancy is a Pay As You Go (PAYG) account, you do not need to worry about the recent Always Free Ampere A1 resource limit update. Your existing 4 OCPU / 24 GB A1 instance does not need to be resized as a result of this policy change. You will not be billed for your existing 4 OCPU / 24 GB A1 instance solely because of the Always Free limit update. The reduction to 2 OCPUs / 12 GB RAM applies only to Always Free tenancies, not to PAYG accounts. There is no deadline requiring PAYG customers to resize existing A1 instances because of this change. If your instance is stopped, you can start it again normally. However, if it is terminated, the ability to recreate an instance with the same configuration depends on current capacity availability in your selected region. The reduction in the Always Free Ampere A1 allocation applies only to Always Free tenancies. PAYG and other paid tenancy types are not affected by this specific policy change. Based on the information available, your existing 4 OCPU / 24 GB A1 instance on your PAYG tenancy will continue to operate under the terms applicable to your paid account and will not incur charges solely because of this Always Free policy update."
▎Community consensus (2026-07)
- Reddit r/selfhosted PSA (1.5K upvotes): "Resize by June 15 to avoid charges"
- Enforcement is inconsistent: many accounts still run 4/24 untouched; Oracle's price list still shows 3K/18K free
- ⚠️ Biggest risk: ARM capacity shortage (many "insufficient capacity" reports) — if your instance terminates, you may not even be able to recreate 2/12
▎Insurance (tested)
- OCI Boot Volume Backup: Console → Compute → Instance → Boot volume → Create backup (cloud-level full restore, ~10 min to Available)
- Drive off-site backup: config tar.gz (~/.hermes, nginx, systemd, crontab) auto-uploaded daily → Google Drive (see §14)
- Don't stop the instance casually: once terminated during the grandfather period, you may never get it back
▎Alternatives (if Oracle falls apart)
| Need | Option | Cost |
| Japan IP + cheapest | Keep Oracle 2/12 | $0 |
| Japan IP (paid) | Contabo Osaka 4vCPU/8GB | Vultr Tokyo 1-2GB | ~€7/mo | $5-6/mo |
| No Japan IP needed | RackNerd 1GB | GCP e2-micro | ~$1/mo | $0 |
| GFW purposes | VLESS/REALITY (works on any VPS) + CF Worker backup | from $0 |
💡 GFW note: Oracle/Contabo datacenter IPs tend to get blocked over time; REALITY resists active probing; a CF Worker (edgetunnel) is a free backup channel.
attachedAppendix: File path + resource limit + completion list
▎Overview of file paths
| path | Description |
~/.local/bin/hermes | Hermes main program |
~/.hermes/config.yaml | main profile |
~/.hermes/.env | environment variables/keys |
~/.hermes/SOUL.md | System prompt words (long-term memory) |
~/.hermes/logs/gateway.log | Gateway log |
/etc/systemd/system/hermes-gateway.service | Gateway systemd service file |
▎OCI Always Free resource limit
| Resources | Limit |
| ARM Ampere A1 Example | 2 OCPU + 12GB RAM (halved since 2026-06-15; older accounts can keep running 4/24 until instance termination) |
| x86 AMD instance | Up to 2 E2.1.Micro (1/8 OCPU + 1GB each) |
| Total boot disk capacity | 200GB (shared by all instances) |
| Public IPv4 | up to 6 |
| Network bandwidth | 1 Gbps per vCPU |
▎Deployment completion checklist
| ✅ | Check items |
| □ | VM created (ARM 2 OCPU / 12GB) and SSH connected to |
| □ | hermes --versionThere is output |
| □ | DeepSeek API Key is valid (curl 200) |
| □ | systemd service active + enabled, see the log✓ telegram connected |
| □ | Telegram actual test has a reply |
| □ | SOUL.md has set up Traditional Chinese reply |
| □ | OCI Security List + UFW two-layer firewall is enabled |
| □ | Backup strategy has been established (tar.gz + pull back to local) |
Related links