Factories

MultiAgent works with two levels. A factory is the deployment unit — the place where agents are assembled. A server is the physical machine a factory lives on: a Linux box reached over SSH, or a local WSL distribution. One server can host several factories, and all of them share its one connection. This page is about factories; the machines themselves and their connections live on the Servers page.

What a Factory Is

A factory gathers everything that belongs to one deployment under one name — the deployment slug (default agents). From the slug are built the docker network ({slug}), the name prefix of every container on it ({slug}-…, agents and apps as well as the core services nginx, Postgres, Forgejo, the backup daemon and the central login) and the folder roots on the machine (/root/{slug}/…). Inside that namespace the factory owns its shared Postgres database, its Forgejo Git server, its nginx with the routes and certificates, its home page, its brand and the licence handed to every new agent.

Because the namespace is per factory, several factories on one machine never get in each other’s way: two slugs mean two networks, two sets of container names and two folder trees. The same slug on different servers is not a conflict — only two factories of one server cannot share it.

Adding a Factory

The “Add Factory” dialog asks for three things: the server, the factory name and the deployment slug. The server is picked from the list of the machines you already connected (the “New server…” choice opens the server dialog right there and selects the created row); the connection itself — address, SSH port, username, password or key, a local WSL mode — belongs to the server now, so one set of credentials serves every factory on that machine. The slug field comes prefilled with the first free value for the chosen server: agents when it is free, else agents1, agents2 and so on. A slug you edited by hand is never overwritten when the server changes. The dialog also offers the fleet — it defaults to the fleet selected in the header, and you can pick another one or leave it out.

The brand and the licence are not part of the minimal create — they are set later on the “General” tab. Everything downstream derives from the slug: docker network, container names, folder roots. Changing the slug later affects only new deployments — running containers keep their names and nothing moves on the machine.

The Factory Card

At the top of the page sits the factory card with its name, the machine address and the connection badge. To the left of the badge are the live load figures — CPU load, memory used and the disk space occupied by this factory’s containers. The numbers refresh by themselves every five seconds; hovering over the occupied space shows how much data the containers have read and written. The first measurement round is thrown away (Docker’s first sample is misleading), so a spinner stands in until the second one lands; a failed poll keeps the last known numbers — they do not disappear. Next to the figures a “Hardware stats” icon opens the physical server’s page in Hardware.

The same card holds a row of actions. “Check and fix” opens the readiness checklist (below). “Manage” is shown when the factory hosts a MultiAgent of its own — it opens that instance in a new tab, already signed in. “Copy login”, “Copy password” and “Login link” appear while the central login is installed: they hand out the same credentials a person types on the factory’s login page. The “Files” button opens access to the factory’s folders, and deleting the factory sits at the far right of the row. A factory that still has agents cannot be deleted — the agents must go first; deleting a factory removes only the record and touches nothing on the machine.

“Login link” puts a one-time link on the clipboard that takes a person to the factory panel without a password. Every click issues a new link, while earlier ones keep working until they expire. If the home page is not installed yet, the button says honestly that it must be installed on the “Home page” tab first; if the central login is missing or protection is off, it reminds you that the link needs the central login behind a working HTTPS gate.

The General Tab

The General tab collects the factory’s own fields. The name is what the tree and the lists show. The icon is changed by a click on the avatar or the icon field: the shared searchable icon gallery — the same one agents and chat labels use — opens, and the “Default icon” row resets to the MultiAgent factory mark. The slug renames the deployment namespace (new deployments only). The server selector moves the whole connection: point the factory at another machine and its next operation opens there.

The brand picks which image catalog new agents on this factory are offered and which language the home page speaks. The public address is the base browsers use when the factory is published under a different address than the machine itself. The agent URL template tells MultiAgent how to reach the factory’s agents (and doubles as the public base in the reverse-proxy shape). The licence chosen here is copied to every agent and product created on the factory — no per-agent issuing needed. The fleet selector assigns the factory to a fleet: every agent already on it joins the fleet, and every new one is added automatically.

The Row Menu

A right-click on the factory row in the navigation tree (or the three-dot button) opens the actions menu. “Open” shows the factory’s home page, “Add agent” opens the wizard preset to this factory. “Deploy” raises all the factory’s rows that have no container yet in one go — the item is visible only while such rows exist, and it runs the work through the task queue: its log opens in the “Tasks” section, where the work can also be stopped (a row that has already begun deploying runs to completion). Next are “Recreate smoothly” and “Recreate forcefully” for all deployed rows; a forced recreation removes the unneeded Docker images itself at the end — in the same log, no separate cleanup click needed.

Further down the menu carries the agent-level bulk actions: “Copy agents” and “Paste agents” move a set of agents between factories as portable definitions, “Move agents” migrates every agent of the factory to another one together with its folders and databases, and “Erase agents” removes them for good — containers dropped, data and databases deleted, after a confirmation that names the whole factory.

The root “Factories” row of the tree offers “Add Factory” and repeats the two recreate actions — both scoped to the selected fleet: with every factory visible the recreates touch all of them, with a fleet in the header only the factories hosting its members.

Onboarding Checks

The “Check and fix” action opens a checklist: every check is its own row with a green check mark (done), a yellow warning, a red cross (error) or a gray “skipped” mark, and at the bottom a summary — “All checks passed” or “{n} of {m} checks need attention”. Checklist rows are named after the service’s role, not the product name:

  • SSH connection — whether the machine is reachable;
  • Docker — installed and running, and whether daemon.json is correct;
  • Host folders — the folders for agents, data, home files, projects, tools and temporary files;
  • Agent user (agent, 999:999) — whether the account exists with the right uid/gid;
  • Nginx — the web server for routing;
  • SSL certificate — issued and not expiring (when TLS is terminated by an upstream proxy, the row passes once the public address is set);
  • Home page — the card board at the factory’s root (checked right after Nginx and skipped when there is no Nginx);
  • Central login (Authelia) — the mandatory single sign-on service;
  • Database (Postgres) — the shared Postgres instance: installed, running, and the stored credentials work;
  • Git service (Forgejo) — the built-in Git server;
  • Backup service (rsyncd) — the backup container serving all seven modules.

When a check shows a “Click here to install it” link (or “create” / “request”) — that is a one-click fix: it starts the same one-step install as the matching tab (Docker, folders, agent user, Nginx, a certificate, Postgres, Forgejo, backups, home page, central login). After a successful fix the checks re-run automatically and the row turns green. A check whose prerequisites are missing (for example, no Docker or Nginx) is marked “skipped” — it does not count and offers no fix link.

Some rows wait for your input or a simple action. The “SSL certificate” row with no certificates offers one combined link: set the factory’s public address of the form https://your-domain/{slug} when a secure connection is terminated by an upstream proxy — or request a Let’s Encrypt certificate right from the dialog. The domain for Let’s Encrypt is taken from the machine address when it looks like a domain, otherwise from the factory name; when neither can be issued for, the advice is a self-signed certificate on the Nginx tab. A Postgres instance that is installed but stopped is fixed with a start button, not a reinstall: the data is not touched.

Installing Docker

If Docker is missing on the machine, MultiAgent installs it itself — one button, with the commands streaming into the task log. Errors are shown in full: a machine without curl gets the wget fallback, and a failed run ends with the installer’s real exit code and its own diagnostics, not a bare “docker: command not found”. A default /etc/docker/daemon.json is seeded at install, and the same file can be read and edited later (registry mirrors or logging, for example) — MultiAgent applies the file and restarts the daemon.

For images from a private registry, the factory has a Registry Auth setting: the registry user and token MultiAgent uses when pulling agent and tool images.

Factory Folders

MultiAgent keeps agent files in several folders on the machine — all configurable, with these defaults built from the slug:

  • Agents folder — /root/agents/docker: one subfolder per agent with its compose.yml;
  • Data folder — /root/agents/data: agent data, one subfolder each, mounted into the container at /data;
  • Home folder — /root/agents/home: the agent’s home directory inside the container, /home/agent;
  • Projects folder — /root/agents/projects: the agents’ git repositories, mounted at /project;
  • Tools folder — /root/agents/tools: files of services deployed from the tools library;
  • Temp folder — /root/agents/tmp: the agent’s scratch folder inside the container (/tmp/agent) — temporary model files and anything recreatable land here; it is deliberately excluded from backups.

The single folder structure simplifies backups: all data of all agents of the factory lives in one directory tree. Factories you created earlier keep their stored paths — MultiAgent moves nothing on the machine.

Ports Are Closed by Default

A new agent, app or tool comes up with a private port: it binds to the machine’s loopback, does not answer from the outside and is reachable only through that factory’s nginx — via its subfolder — and from the machine itself. That is how deployments on one computer stay invisible to each other: even when several factories share one machine, one’s ports are open neither to the others nor to the internet.

To open a port to the world, flip its “Public port” switch — the Ports tab of an agent or an app, the port row of a tool. Two ports are always public and have no switch: nginx’s own HTTP/HTTPS — the front door to all the factory’s apps — and the backup service port, through which other machines pull backups from the factory. The shared Postgres, on the contrary, is always closed.

A link to an app with a private port points at its address through nginx, not at the direct http://{host}:{port}: the browser could not reach the direct one anyway. MultiAgent itself manages such apps over its own secure channel to the machine, so closed ports never get in the way of chats or checks.

Shared Factory Environment

When the same environment variable must be set for every deployment on a factory (a time zone or log verbosity, for example), you set it once on the factory’s “Environment” tab — it lands in the configuration of every agent and app on that factory. A value set on a specific agent always wins over the shared one: that is how you make an exception for a single deployment. Details on the Agents page.

Shared Postgres

Instead of a separate SQLite database per agent, the factory runs one shared Postgres: MultiAgent deploys the container (port 5432 by default), generates and stores the admin password, and checks the connection live — not just the container’s presence. For agents with Postgres enabled, the AGENT_DATABASE connection string is injected into their environment automatically. When the port is busy at install time, MultiAgent takes the next free one by itself and repeats the deployment — the moved port is saved and shown in the interface, so nothing dies with “port is already allocated”. A stopped instance is a start button, not a reinstall.

The Forgejo Git Server

MultiAgent deploys Forgejo on the factory — your own Git server (internal port 3200). It is reachable at the /forgejo/ subfolder on the factory’s public address, and MultiAgent derives and stores that address by itself — no need to type it in. For every agent you can link an existing repository or create a new one; MultiAgent issues and stores the SSH keys for access. If you set an organization in the “Company” field, all new agent repositories are created inside it (created automatically when missing), and repository lists show its contents. Details in the Agents section.

Forgejo joins the central login by itself: as soon as the login is installed, protection is working and Forgejo is running, its login page gets a sign-in-through-central-login button, and the first such sign-in creates the account from the central-login identity. There is no switch to flip. While the wiring is active, the login and password fields on the Forgejo tab are read-only — they follow the central login — and the “Sync authorization” button re-applies the current credentials. The Forgejo interface speaks the factory brand’s language. When the conditions go away, the wiring disappears by itself.

Backups

Onboarding installs an rsyncd container on the factory with seven read-only modules covering everything: docker, home, data, projects, tools, plus two dump modules — postgres and forgejo. The tools module takes what no other module serves: nginx certificates, central-login state and tool compose files; its own dump subfolders are excluded from the upload — those dumps are served by their own modules, so a full download does not copy them twice. The temp folder has no module at all: scratch content that can be regenerated never reaches a backup. Postgres and Forgejo dumps are produced on the factory itself (sidecar containers drop them into the backup folders daily). Backups are pulled from the factory by your client machines over rsync — for example, a nightly job on the machine with the backup storage:

rsync -avz rsync://backup@factory-host:873/data/ /backups/factory-host/data/

Ready-to-run download commands for all seven modules are collected in the “Backup” tab of the factory page — they run unchanged. There are three clients: a script for Linux, an archive for Windows (rsync itself is bundled inside — nothing to install) and a file for a Docker host: drop it into an empty folder and run docker compose up -d — from then on the copies are taken by themselves, at the start and then every day on a built-in schedule, with the log written next to the copies. In all three, the address, port, user and password are already filled in, and the downloads are named after the factory — backup-<factory>.zip, backup-<factory>.sh and backup-<factory>.yml — so copies of several factories sharing one machine do not get mixed up.

When there are several factories, there is no need to walk them one by one: the “Backup” page in the Assets section hands out the same client for the whole fleet scope chosen in the header at once. One run walks every factory in the scope and puts each into its own folder (~/backups/<name>, c:\backup\agents\<name> or ./backups/<name>), and a factory without a server address is honestly named as skipped.

The “Test connection” button checks four things at once and reports every finding in one list: the container is running, all seven modules are served, the published port matches the stored one, and the port accepts a connection from the outside. The factory can only pass the backup check when all four hold; if something is off, the check points at “Reinstall rsync” — the same streamed install that re-renders the configuration in place.

Nginx Routing and Certificates

MultiAgent itself never routes requests: every factory runs its own Nginx container (named {slug}-nginx, agents-nginx by default), installed and updated from the Nginx tab of the factory page. It is the Debian build of nginx, not Alpine: it runs on old kernels where the Alpine build fails to start. The routing configuration is a projection of the database: it is rebuilt and applied automatically on every change (create an agent, product or tool — it immediately gets its own subfolder). Applying happens without dropping connections: the configuration is validated and reloaded inside the already running web server, so open pages and live chats do not break.

  • Five kinds of routes — agents and products (read-only), tools with a web interface (read-only), extra links of agents and products (read-only: a subfolder with a port from the “Links” tab), custom routes to any http(s) address (the only manually managed kind: edit, disable, delete) and, when the central login is installed, its derived auth route (read-only, with no protection toggle);
  • One namespace — a first-level slug of [a-z0-9-]+ per factory for all kinds; MultiAgent’s system paths and the auth slug are reserved;
  • Internal container network — apps are addressed by container names on the shared docker network; a crashed service returns 502 only on its own subfolder, the other routes keep working.

Certificates — three kinds from the same tab: self-signed (becomes the fallback certificate), your own PEM pair, and Let’s Encrypt (ACME through Nginx itself, staging and production CAs, one request at a time; the domain is taken from the machine address, else from the factory name). Certificates and keys are stored only on the machine — the database keeps just metadata. Expiry is tracked on every configuration update (renewal 30 days before expiration). The HTTPS port is optional: while it is empty, certificates are saved but not served and only HTTP is published. A Let’s Encrypt request with an empty port enables it by itself (443), so the issued certificate is served immediately; a port you have chosen, or an explicitly disabled HTTPS, is never overridden. Immediately to the right of the Nginx tab sits the Authorization tab — the central login install (see below).

The Factory Home Page

At the factory’s root you can publish a home page — a card board from which every app on the factory opens. It is a static, self-contained page: MultiAgent builds the file itself and uploads it to the machine, and nginx serves it at the root. No separate container is needed — the installed Nginx is enough; the page has no login of its own, and when the central login is on, it closes together with the other apps. The page carries the factory’s own mark — the same one the interface shows — and names itself “Agent Factory”.

MultiAgent maintains the cards from its database: one card per agent, product and tool with its address — with the projects’ real logos, and agent and app cards show badges of their extra links in the corner (the “Links” tab). Common actions are not cards but a row of icon buttons in the top-right corner: “Git” (while Forgejo runs on the factory), “QR login” (when the central login is on) and always “Logout” on the far right; “Logout” ends the central-login session, signs out of all agents and products and of the page itself. The board refreshes itself on every change — deploy an agent or a tool and its card appears; the tab offers a manual apply too. The page’s language follows the factory’s brand — there is no separate language selector. Details on the Factory Home Page page.

Central Login (the “Authorization” Tab)

So that a visitor signs in once and gets access to any protected app on the factory, you can install the central login on the factory — it is the “Authorization” tab (Authelia), sitting right of the Nginx tab. The login is a service container {slug}-auth (agents-auth by default) with the fixed slug auth and portal address /auth/; it publishes no port of its own, so Nginx is installed first. The login is agents, the password is generated automatically and visible in the tab; the install never touches the certificate or the HTTPS port. A central-login session lasts 90 days — people sign in rarely.

When the central login is active, agents and products are locked “behind the central login” by default, and tools with a web interface and custom routes — at your choice (a toggle). One login on the login page opens every protected app on the factory — no repeated sign-ins. A new agent or app inherits the factory’s central-login account as its own login.

The protection works only over a secure connection (HTTPS): either a local certificate and HTTPS port from the Nginx tab, or the factory’s public address (or an address template of the form https://{base}/{slug}) when TLS is terminated by the upstream reverse proxy (then no certificate of your own is needed). Otherwise the installed login stays inactive. Reaching an app directly at host:port (when the port is open), bypassing nginx, is not locked — the app keeps its own login. Service machine paths /{slug}/api/… and /{slug}/svelteChatHub also stay open (they have their own JWT or API-key authorization). Apps receive identity headers and the X-SSO-Token secret (checked against SSO_PROXY_TOKEN in the agent’s environment), so they cannot be forged from outside.

The “Apply configuration” button on that tab does more than apply the settings — it also ends every open session: each browser has to sign in again with the current password. A protected app’s manifest file (manifest.json) stays available without a login — the browser requests it separately from the page, and without that the page would show an error.

The auth slug is reserved on every factory — you cannot create an agent, tool or route with that name. Forgejo connects to the central login by itself (see above): no switch, the wiring follows the login’s own login and password. Deleting the central login reopens the protected routes, and its data and secrets are kept — a reinstall reuses them. More about routes and protection in the Nginx Routing section.

The Agents URL Template

Where the public links to a factory’s apps point is decided in order. First — the “Public address” field on the General tab: when it is filled, all links are built from it, and the machine’s real address stays internal — it is what MultiAgent uses for SSH and tunnels. This is the case when the public domain and the machine itself are different things: say, the factory sits in a closed network and an external reverse proxy opens it to the world.

When the public address is empty, the public base becomes the base of the agents’ address template of the form {base}/{slug} — as before. When the template is not set either, links are built from the machine’s address: http(s)://{host}[:{nginx port}]/{slug}/. Why keep a separate field, then? The template with the {slug}, {host} and {port} placeholders primarily tells MultiAgent how it itself reaches the APIs of that factory’s agents. If you put the public domain into the template, management traffic takes the same path — out through the external proxy and back; the separate field keeps the two jobs apart. Direct access at http(s)://{host}[:{port}] remains the fallback path. Changing the public address, the template or the factory name rebuilds the nginx routes at once and syncs the central-login configuration with the new address.

https://apps.example.com/{slug}

Files

Every factory has built-in access to files (the “Files” item in the sidebar): browse the directory tree, read and edit files, upload and download, rename in place, and count size and tokens of text files. It lets you fix a config or look at logs on the factory without leaving MultiAgent.

The separate “Files” page shows two panels — each with its own factory and its own folder. Tick files and folders in the left panel and press “Copy” — they move to the right panel’s folder. The panels can look at one factory or at two different ones: MultiAgent itself transfers the files between machines over its own saved accesses — nothing to configure between them. The transfer runs in the background, the progress percentage is visible right in the button, and the process can be canceled; files with the same name are replaced, folders with matching names merge. While the copy runs, the right panel refreshes itself, so arriving files appear in place.

Next to it is the “Terminal” button: it opens a command line in the folder you are currently in. Commands run on the machine, output streams to the screen line by line, and command history and interrupt work as usual. Handy for a quick look at a service’s state or sorting out file permissions.

Handing a Factory to a Client

When a factory belongs to a client, you can hand management over: the client’s own MultiAgent is deployed, and the records move to it — agents, apps, tools, routes, access keys and the server record with its credentials. The handover is a one-time operation: it starts from the “Handover” tab on the factory page, and a preview shows in advance what moves and what stays with you. Running apps are not touched: nothing stops or reinstalls.

After the handover, routing is managed by the client’s instance, while the machine stays with you: SSH access, checks, folders and Docker cleanup — and the factory row itself, with the client’s MultiAgent as an app you can still recreate or update. You can peek into the client’s instance with the “Manage” button in the page header — the sign-in happens by itself, no password needed. Details on the Factory Handover page.

← Back to documentation