Tools: Complete Guide to Deploying Hermes Agent on Ubuntu 26.04

Tools: Complete Guide to Deploying Hermes Agent on Ubuntu 26.04

Install Docker

Set Up the Project Directory

Deploy with Docker Compose

Configure the LLM

Verify the Deployment

Next Steps Hermes Agent is an open-source self-hosted AI agent framework by Nous Research that runs continuously on a server with persistent memory and tool access. It integrates with Telegram, Discord, Slack, and WhatsApp, and supports any OpenAI-compatible LLM provider including Vultr Serverless Inference. This guide deploys Hermes Agent using Docker Compose with Traefik handling automatic HTTPS, and configures an LLM backend. By the end, you'll have a self-hosted AI agent running with a secured web dashboard and verified LLM connectivity. The official Docker repository gives you the most current Docker Engine builds. 1. Install dependency packages: 2. Add Docker's GPG key: 3. Register the Docker repository: 4. Refresh APT and install Docker: 5. Add your user to the Docker group: 1. Create the project directory: 2. Create the environment file: 3. Generate dashboard authentication credentials: 1. Create the Docker Compose file: 2. Open the firewall: 3. Start the services: 4. Verify the services are running: 1. Run the model configuration command: 2. Follow the prompts to select a provider and model. The configuration supports OpenAI, Anthropic, OpenRouter, and any OpenAI-compatible endpoint. To use Vultr Serverless Inference, select the OpenAI-compatible option and provide your Vultr API key and the inference endpoint URL. 1. Check the service logs: 2. Open the dashboard in a browser: Visit https://hermes.example.com and log in with the credentials from the .htpasswd file. 3. Test LLM connectivity: Send a simple query through the dashboard. A response from the model confirms the LLM connection is working. Hermes Agent is running and connected to a language model. From here you can: For the full guide with additional tips, visit the original article on Vultr Docs. Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

$ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">apt-transport-https ca-certificates -weight: 500;">curl -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">apt-transport-https ca-certificates -weight: 500;">curl -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">apt-transport-https ca-certificates -weight: 500;">curl -y $ -weight: 600;">sudo -weight: 500;">curl -fsSL https://download.-weight: 500;">docker.com/linux/ubuntu/gpg -o /etc/-weight: 500;">apt/keyrings/-weight: 500;">docker.asc $ -weight: 600;">sudo -weight: 500;">curl -fsSL https://download.-weight: 500;">docker.com/linux/ubuntu/gpg -o /etc/-weight: 500;">apt/keyrings/-weight: 500;">docker.asc $ -weight: 600;">sudo -weight: 500;">curl -fsSL https://download.-weight: 500;">docker.com/linux/ubuntu/gpg -o /etc/-weight: 500;">apt/keyrings/-weight: 500;">docker.asc $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/-weight: 500;">apt/keyrings/-weight: 500;">docker.asc] https://download.-weight: 500;">docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | -weight: 600;">sudo tee /etc/-weight: 500;">apt/sources.list.d/-weight: 500;">docker.list > /dev/null $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/-weight: 500;">apt/keyrings/-weight: 500;">docker.asc] https://download.-weight: 500;">docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | -weight: 600;">sudo tee /etc/-weight: 500;">apt/sources.list.d/-weight: 500;">docker.list > /dev/null $ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/-weight: 500;">apt/keyrings/-weight: 500;">docker.asc] https://download.-weight: 500;">docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | -weight: 600;">sudo tee /etc/-weight: 500;">apt/sources.list.d/-weight: 500;">docker.list > /dev/null $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">docker-ce -weight: 500;">docker-ce-cli containerd.io -weight: 500;">docker-buildx-plugin -weight: 500;">docker-compose-plugin -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">docker-ce -weight: 500;">docker-ce-cli containerd.io -weight: 500;">docker-buildx-plugin -weight: 500;">docker-compose-plugin -y $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">update $ -weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -weight: 500;">docker-ce -weight: 500;">docker-ce-cli containerd.io -weight: 500;">docker-buildx-plugin -weight: 500;">docker-compose-plugin -y $ -weight: 600;">sudo usermod -aG -weight: 500;">docker $USER $ newgrp -weight: 500;">docker $ -weight: 600;">sudo usermod -aG -weight: 500;">docker $USER $ newgrp -weight: 500;">docker $ -weight: 600;">sudo usermod -aG -weight: 500;">docker $USER $ newgrp -weight: 500;">docker $ mkdir -p ~/hermes/data $ cd ~/hermes $ mkdir -p ~/hermes/data $ cd ~/hermes $ mkdir -p ~/hermes/data $ cd ~/hermes $ nano .env $ nano .env $ nano .env DOMAIN=hermes.example.com [email protected] DOMAIN=hermes.example.com [email protected] DOMAIN=hermes.example.com [email protected] $ -weight: 500;">docker run --rm httpd:2.4-alpine htpasswd -nbB admin 'your_dashboard_password' > .htpasswd $ -weight: 500;">docker run --rm httpd:2.4-alpine htpasswd -nbB admin 'your_dashboard_password' > .htpasswd $ -weight: 500;">docker run --rm httpd:2.4-alpine htpasswd -nbB admin 'your_dashboard_password' > .htpasswd $ nano -weight: 500;">docker-compose.yml $ nano -weight: 500;">docker-compose.yml $ nano -weight: 500;">docker-compose.yml services: traefik: image: traefik:v3 command: - --providers.-weight: 500;">docker=true - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL} - --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json - --certificatesresolvers.letsencrypt.acme.tlschallenge=true ports: - "80:80" - "443:443" volumes: - /var/run/-weight: 500;">docker.sock:/var/run/-weight: 500;">docker.sock - ./data:/data hermes: image: nousresearch/hermes-agent:latest volumes: - ./data:/opt/data labels: - traefik.-weight: 500;">enable=true - traefik.http.routers.hermes.rule=Host(`${DOMAIN}`) - traefik.http.routers.hermes.entrypoints=websecure - traefik.http.routers.hermes.tls.certresolver=letsencrypt dashboard: image: nginx:alpine volumes: - ./.htpasswd:/etc/nginx/conf.d/.htpasswd labels: - traefik.-weight: 500;">enable=true - traefik.http.routers.dashboard.rule=Host(`${DOMAIN}`) && PathPrefix(`/dashboard`) - traefik.http.middlewares.dashboard-auth.basicauth.usersfile=/etc/nginx/conf.d/.htpasswd - traefik.http.routers.dashboard.middlewares=dashboard-auth services: traefik: image: traefik:v3 command: - --providers.-weight: 500;">docker=true - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL} - --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json - --certificatesresolvers.letsencrypt.acme.tlschallenge=true ports: - "80:80" - "443:443" volumes: - /var/run/-weight: 500;">docker.sock:/var/run/-weight: 500;">docker.sock - ./data:/data hermes: image: nousresearch/hermes-agent:latest volumes: - ./data:/opt/data labels: - traefik.-weight: 500;">enable=true - traefik.http.routers.hermes.rule=Host(`${DOMAIN}`) - traefik.http.routers.hermes.entrypoints=websecure - traefik.http.routers.hermes.tls.certresolver=letsencrypt dashboard: image: nginx:alpine volumes: - ./.htpasswd:/etc/nginx/conf.d/.htpasswd labels: - traefik.-weight: 500;">enable=true - traefik.http.routers.dashboard.rule=Host(`${DOMAIN}`) && PathPrefix(`/dashboard`) - traefik.http.middlewares.dashboard-auth.basicauth.usersfile=/etc/nginx/conf.d/.htpasswd - traefik.http.routers.dashboard.middlewares=dashboard-auth services: traefik: image: traefik:v3 command: - --providers.-weight: 500;">docker=true - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL} - --certificatesresolvers.letsencrypt.acme.storage=/data/acme.json - --certificatesresolvers.letsencrypt.acme.tlschallenge=true ports: - "80:80" - "443:443" volumes: - /var/run/-weight: 500;">docker.sock:/var/run/-weight: 500;">docker.sock - ./data:/data hermes: image: nousresearch/hermes-agent:latest volumes: - ./data:/opt/data labels: - traefik.-weight: 500;">enable=true - traefik.http.routers.hermes.rule=Host(`${DOMAIN}`) - traefik.http.routers.hermes.entrypoints=websecure - traefik.http.routers.hermes.tls.certresolver=letsencrypt dashboard: image: nginx:alpine volumes: - ./.htpasswd:/etc/nginx/conf.d/.htpasswd labels: - traefik.-weight: 500;">enable=true - traefik.http.routers.dashboard.rule=Host(`${DOMAIN}`) && PathPrefix(`/dashboard`) - traefik.http.middlewares.dashboard-auth.basicauth.usersfile=/etc/nginx/conf.d/.htpasswd - traefik.http.routers.dashboard.middlewares=dashboard-auth $ -weight: 600;">sudo ufw allow 80/tcp $ -weight: 600;">sudo ufw allow 443/tcp $ -weight: 600;">sudo ufw allow 80/tcp $ -weight: 600;">sudo ufw allow 443/tcp $ -weight: 600;">sudo ufw allow 80/tcp $ -weight: 600;">sudo ufw allow 443/tcp $ -weight: 500;">docker compose up -d $ -weight: 500;">docker compose up -d $ -weight: 500;">docker compose up -d $ -weight: 500;">docker compose ps $ -weight: 500;">docker compose ps $ -weight: 500;">docker compose ps $ -weight: 500;">docker run -it --rm \ -v ~/hermes/data:/opt/data \ nousresearch/hermes-agent:latest model $ -weight: 500;">docker run -it --rm \ -v ~/hermes/data:/opt/data \ nousresearch/hermes-agent:latest model $ -weight: 500;">docker run -it --rm \ -v ~/hermes/data:/opt/data \ nousresearch/hermes-agent:latest model $ -weight: 500;">docker compose logs hermes $ -weight: 500;">docker compose logs hermes $ -weight: 500;">docker compose logs hermes - Connect messaging integrations for Telegram, Discord, Slack, or WhatsApp through the dashboard - Enable persistent memory so the agent retains context across sessions - Switch to Vultr Serverless Inference for a cost-effective, OpenAI-compatible LLM backend