# Huginn: an event graph on your own server, with a development profile as the default

> Huginn's agents create and consume events along a directed graph, which makes the configuration the real logic of your automation. The catch is in the defaults: a placeholder secret token, a MySQL root user with no password, email intercepted by letter_opener, SSL not forced, and a deployment story spread across Heroku, OpenShift, Docker, Cloud Foundry, and a git merge.

**huginn/huginn** — GitHub describes it as Create agents that monitor and act on your behalf. Your agents are standing by!. The repository metadata lists Ruby as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/huginn/huginn
- Stars: 50,018 · Forks: 4,302
- Language: Ruby
- License: MIT
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/huginn-huginn

## The logic lives in the links between agents

Huginn's agents create and consume events, propagating them along a directed graph, which the README compares to a hackable version of IFTTT or Zapier on your own server. That single design choice explains most of how the system behaves. An agent does not push to another agent; it emits events, and other agents that have been pointed at it receive them. Consequence: the graph you draw is the program, and a link that is missing or aimed at the wrong agent produces no error, just data nobody reads and notifications nobody receives. Nothing in the README describes a check for an agent whose events go nowhere, so the graph has to be reviewed by hand, which is why the examples in the seeded database are the fastest way to learn the pattern.

## Email is swallowed locally unless you switch it back on

In the development Rails environment you just set up, outbound email is intercepted rather than sent, and the captured messages are readable at http://localhost:3000/letter_opener. If you want real mail while playing with it locally, you set SEND_EMAIL_IN_DEVELOPMENT to true in your .env file. That is a sensible default and it hides a class of mistake: an email agent that looks broken locally is often working exactly as configured, and the first person to find out is whoever receives the message once it is deployed. The mirror image sits further down the same file, where FORCE_SSL is false by default, so a production instance that keeps the development profile will serve its interface, and the credentials stored in its agents, over plain HTTP.

## APP_SECRET_TOKEN ships as a placeholder string

The configuration template is honest about being a template: APP_SECRET_TOKEN is set to REPLACE_ME_NOW! with a comment telling you to paste in the output of rake secret, and DOMAIN is localhost:3000, which the same file says has to change for a real deployment. The database block defaults to DATABASE_ADAPTER=mysql2, DATABASE_USERNAME=root, and an empty DATABASE_PASSWORD, with host, port, and socket commented out. Consequence: the shipped profile is a single machine development setup and nothing warns you that you kept it, so the three values to change before anyone else can reach the instance are the secret, the domain, and SSL. Two more decisions are cheaper now than later: NATIVE_JSON_COLUMNS converts serialized fields to native JSON, and its comment warns that on MySQL 8 sorting rows with JSON columns can fail with Out of sort memory unless sort_buffer_size is raised from its 256K default to 4M or more, which you can only do before the migrations run.

## A Ruby application with a Node build step for one polyfill

The root package.json is marked private and holds four dependencies: @fortawesome/fontawesome-free at 7.3.1, esbuild at ^0.28.0, vanilla-jsoneditor at ^3.12.0, and whatwg-url-without-unicode at ^8.0.0-3. The single script bundles a URL polyfill:

```
esbuild --bundle --minify --format=iife --target=es2020 --outfile=tmp/build/url-polyfill.js build/url-polyfill-entry.js
```

Consequence: bundle and assets are not only a Ruby concern here, and the artifact is written into tmp/build, which is also a top level directory in the tree and therefore in reach of anything that clears temporary files. The dependency name also states an intent worth reading before you trust URL handling with non ASCII input: it is a build of the WHATWG URL implementation with unicode deliberately left out, which is a reasonable trade for predictable parsing in an app that fetches arbitrary user supplied URLs, but it is a trade someone made for you.

## PostgreSQL support costs an env prefix on every command

Either MySQL or PostgreSQL will work, and the installation steps say that if you choose PostgreSQL you need to prepend all subsequent commands with DATABASE_ADAPTER=postgresql. The configuration template defaults to the mysql2 adapter, so a Postgres install is the documented exception rather than the default path. The same asymmetry shows up in the JSON columns feature, which carries a MySQL specific warning about sort buffer memory. Consequence: a Postgres user follows the page and ends up with a shell full of prefixed commands, and anyone who later compares notes with a MySQL user is comparing setups that differ in adapter, encoding, and JSON column behaviour. Pick the database before you seed, because rake db:seed writes example agents that you will otherwise be migrating twice.

## Every agent ships with specs, and acceptance tests drive a browser

The develop section states that all agents have specs, and that there are acceptance tests simulating Huginn running in a headless browser. To run the feature specs locally you install Google Chrome and ChromeDriver, or you use the Docker based test environment described in docker/test/README.md.

```
bundle exec rspec
```

```
bundle exec rspec path/to/specific/test_spec.rb
```

Consequence for a contributor: adding an agent means writing its spec as part of the change, which is a good forcing function and also a real cost for a one off integration. Consequence for an operator: the test environment needs a browser, so any image you build to run the suite has to carry Chrome and a matching driver, and a Chrome upgrade without a driver bump breaks the acceptance layer rather than the application.

## Agents split between the core and gems listed at boot

Agents can be written as external gems and added to an installation through the ADDITIONAL_GEMS environment variable, with a section of the configuration template devoted to it, and a separate huginn_agent project is the recommended starting point for writing your own. The stated intention is a division of labour: complex and specific agents are encouraged to live in gems, while new general purpose agents keep landing in the core repository. Consequence: your installation is assembled from two sources, and the external half is resolved at boot from whatever the environment variable names, with no version constraint discussed in the README. A gem that fails to load is a boot problem rather than a degraded feature, and you own the version pinning for the part that is not in the core.

## Five deployment scaffolds and two documented routes

The tree carries scaffolding for several platforms at once: a Procfile and Procfile.CF, app.json and .buildpacks for Heroku, a .s2i/ directory and openshift/ templates for OpenShift, a Capfile and deployment/ directory for Capistrano, manifest.yml.sample, a Dockerfile under docker/, mise.toml, and separate VERSION, CHANGES.md, and UPGRADING.md files. The written guidance is thinner than the scaffolding. Docker is called the quickest way to look at Huginn, Heroku has a deploy button, and OpenShift has template URLs such as the mysql one. The README also notes that Huginn launches only on a paid Heroku plan and recommends the 1GB paid plan or the container. Consequence: the free hosting route named first in most discussions is not available, and the update procedure the page gives is periodic, a git fetch upstream followed by a merge into master, with no stated rollback if that merge goes badly.

## Conclusion

Huginn fits a person who wants the automation to live on their own machine and is willing to own the maintenance, especially where a hosted service would hold credentials they would rather not hand over. It does not fit a team that needs a UI to hand to non technical staff, and the event graph means misconfiguration fails quietly rather than loudly. Before you deploy, replace APP_SECRET_TOKEN with the output of rake secret, change DOMAIN off localhost, set FORCE_SSL, decide on utf8mb4 before the first migration rather than after, and read UPGRADING.md, because the documented update path is a merge into master with no stated rollback.

## FAQ

### how to use huginn

Fork the repository, copy .env.example to .env and at least set APP_SECRET_TOKEN, install MySQL or PostgreSQL, then run bundle, bundle exec rake db:create, bundle exec rake db:migrate, and bundle exec rake db:seed. Start it with bundle exec foreman start, open http://localhost:3000/, and log in as admin with the password that db:seed printed.

### what is huginn

It is a system for building agents that perform automated tasks online, reading the web, watching for events, and taking actions for you. The agents create and consume events and propagate them along a directed graph, which the project describes as a hackable version of IFTTT or Zapier on your own server.

### is huginn free

The software is MIT licensed and self hosted, so the code costs nothing. Hosting is a separate matter: the README says Huginn launches only on a paid Heroku plan, and for anything beyond experimenting it recommends Heroku's 1GB paid plan or the Docker container instead.

### Who is Huginn in Norse mythology?

This repository says nothing about the mythology; it only borrows the name for a Ruby automation system. Everything documented here concerns the software: agents, events, the graph that connects them, the configuration template, and the supported deployment targets.

## Sources

- [Official README](https://github.com/huginn/huginn#readme)
- [Project repository](https://github.com/huginn/huginn)
- [Release notes](https://github.com/huginn/huginn/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/huginn-huginn
