Self-Hosted Package Installation Guide

Deploy ManageLM on bare-metal or VM with the self-extracting installer.

Overview

The ManageLM installer is a single self-extracting .sh.gz file that includes the portal, agent source, and a bundled Node.js runtime. No prerequisites need to be installed on the target server — just download, extract, and run.

What's includedDescription
ManageLM PortalWeb UI, API, MCP server, task engine
Agent sourceServed to managed hosts for agent installation and auto-updates
Node.js runtimeBundled runtime — no system Node.js needed

The installer handles both first install and upgrades. On upgrade, your configuration (.env) is preserved automatically.

Prefer Docker? See the Self-Hosted Docker Installation Guide. Don't want to self-host? Use the managed SaaS at app.managelm.com.

Requirements

Node.js is bundled in the installer — no system packages required beyond the database and cache.

Download

Download the latest release for your architecture from GitHub Releases.

Then extract and run:

gunzip managelm-<version>-linux-<arch>.sh.gz

Install

Run the installer as root:

sudo bash managelm-<version>-linux-<arch>.sh

The installer will prompt for:

PromptDefaultDescription
Service usermanagelmSystem user the portal runs as
Portal port3000HTTP listen port (behind reverse proxy)
Register systemd service?YCreates and enables managelm-server.service

For unattended installation, use --yes to accept all defaults:

sudo bash managelm-<version>-linux-<arch>.sh --yes

Other flags:

  --install-dir DIR   Override install directory (default: /opt/managelm-server)
  --user USER         Service user (default: managelm)
  --port PORT         Portal port (default: 3000)
  --no-systemd        Skip systemd service registration

Configure

After installation, edit the .env file:

sudo vi /opt/managelm-server/portal/.env

At minimum, set these values:

# How browsers and agents reach the portal
SERVER_URL=https://managelm.example.com

# PostgreSQL connection
DATABASE_URL=postgresql://managelm:your-password@localhost:5432/managelm

# Redis connection
REDIS_URL=redis://localhost:6379

# Sender email
SMTP_FROM=ManageLM <noreply@example.com>

Then start the service:

systemctl start managelm-server

Check it's running:

systemctl status managelm-server
curl -s http://localhost:3000/health

First Steps After Install

Once the portal is running:

  1. Set up a reverse proxy with TLS (nginx or Apache) for production.
  2. Register your account at your SERVER_URL. The first user becomes the account owner.
  3. Configure the LLM — Local (Ollama), Cloud, or Proxied access mode.
  4. Import skills from the built-in catalog.
  5. Install an agent on your first server.
  6. Connect Claude via MCP.
SERVER_URL must match how clients reach the portal. Agents derive their WebSocket URL from this value, so it must be the exact address reachable from agent machines.
For detailed instructions on all portal features, see the Portal Documentation.

Reverse Proxy

Place a reverse proxy in front of the portal for TLS. WebSocket support is required for agent connections.

nginx

server {
    listen 443 ssl http2;
    server_name managelm.example.com;

    ssl_certificate     /etc/ssl/certs/managelm.pem;
    ssl_certificate_key /etc/ssl/private/managelm.key;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";
        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 X-Forwarded-Proto $scheme;
        proxy_read_timeout 86400s;
        proxy_send_timeout 86400s;
    }
}

Apache

<VirtualHost *:443>
    ServerName managelm.example.com

    SSLEngine on
    SSLCertificateFile    /etc/ssl/certs/managelm.pem
    SSLCertificateKeyFile /etc/ssl/private/managelm.key

    ProxyPreserveHost On
    ProxyPass        / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/

    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]

    ProxyTimeout 86400
</VirtualHost>
Agents stuck connecting? Check that your proxy forwards the Upgrade and Connection headers for WebSocket.

SMTP / Email

The portal sends emails for account verification, password resets, and team invitations. When SMTP_HOST is not set, email sending is disabled entirely — no connection attempts are made.

To enable emails, configure an SMTP relay:

SMTP_HOST=smtp.brevo.com
SMTP_PORT=587
SMTP_SECURE=starttls
SMTP_USER=your-username
SMTP_PASS=your-password

PostgreSQL Setup

ManageLM requires PostgreSQL 15+ (16 recommended). The portal runs migrations automatically on startup and needs full control over its schema.

  1. Create the database and user
    # Connect as a PostgreSQL superuser
    sudo -u postgres psql
    
    -- Create the ManageLM user
    CREATE USER managelm WITH PASSWORD 'your-strong-password';
    
    -- Create the database owned by that user
    CREATE DATABASE managelm OWNER managelm;
    
    -- Connect to the new database
    \c managelm
    
    -- Grant full schema permissions (required for migrations)
    GRANT ALL ON SCHEMA public TO managelm;
    
    -- PostgreSQL 15+ changed defaults — grant CREATE explicitly
    ALTER DEFAULT PRIVILEGES IN SCHEMA public
      GRANT ALL ON TABLES TO managelm;
    ALTER DEFAULT PRIVILEGES IN SCHEMA public
      GRANT ALL ON SEQUENCES TO managelm;
    
    \q
  2. Allow remote connections (if PostgreSQL is on a different host)
    # In postgresql.conf
    listen_addresses = '*'
    
    # In pg_hba.conf — allow the portal host
    host  managelm  managelm  10.0.0.0/8  scram-sha-256

    Restart PostgreSQL: systemctl restart postgresql

  3. Set DATABASE_URL in .env
    DATABASE_URL=postgresql://managelm:your-strong-password@localhost:5432/managelm
  4. Test the connection
    psql "postgresql://managelm:your-strong-password@localhost:5432/managelm" -c "SELECT 1;"
SSL/TLS: For encrypted connections, set DB_SSL=require in .env. To verify the server certificate, use DB_SSL=verify-ca with DB_SSL_CA=/path/to/ca.pem.

Redis Setup

ManageLM requires Redis 7+ (or Valkey). It is used for real-time agent communication, session state, and pub/sub — it must be available at all times.

  1. Enable persistence (recommended)
    # In redis.conf
    appendonly yes
    appendfsync everysec
  2. Set REDIS_URL in .env
    # Without authentication
    REDIS_URL=redis://localhost:6379
    
    # With authentication (Redis 6+ ACL)
    REDIS_URL=redis://username:password@redis-host:6379
  3. Test the connection
    redis-cli ping
    # Expected: PONG
Redis TLS: Set REDIS_TLS=on in .env for encrypted connections. Use a rediss:// URL scheme.

Environment Variables

All settings are in /opt/managelm-server/portal/.env. The full reference is the same as the Docker guide.

Required

VariableDescription
SERVER_URLPublic URL that browsers and agents use to reach the portal (e.g. https://managelm.example.com)
DATABASE_URLPostgreSQL connection string
REDIS_URLRedis connection string
SMTP_FROMSender email address

Common optional

VariableDefaultDescription
SERVER_PORT3000Portal listen port
CLUSTER_WORKERS2Node.js cluster workers (set to 1 to disable)
ENCRYPTION_KEYAES-256 key for secrets at rest. Generate: openssl rand -hex 32
SMTP_HOSTSMTP server (empty = email disabled)
LOG_LEVELinfotrace, debug, info, warn, error
DB_SSLnonePostgreSQL SSL mode
REDIS_TLSautoRedis TLS mode

See the Self-Hosted Docker guide for the complete list including SMTP, DKIM, token TTLs, retention, and more.

File Layout

/opt/managelm-server/
├── nodejs/          # Bundled Node.js runtime
│   └── bin/node
├── portal/          # ManageLM portal application
│   ├── dist/        # Compiled backend (bytecode)
│   ├── web/dist/    # Frontend build
│   ├── node_modules/
│   ├── cluster.cjs  # Multi-worker entry point
│   ├── loader.cjs   # Bytecode loader
│   ├── .env         # Configuration (root:managelm 640)
│   └── ...
└── agent/           # Agent source (served to managed hosts)
    ├── managelm-agent.py
    ├── lib/
    └── bin/

All files are owned by root:root except .env which is root:<service-user> 640. The service user can read the configuration but cannot modify any binaries.

Upgrading

Download the new release and run it on the same server. The installer detects the existing installation and upgrades in place:

gunzip managelm-<version>-linux-<arch>.sh.gz
sudo bash managelm-<version>-linux-<arch>.sh

The upgrade will:

Database migrations run automatically on startup.

Backup & Restore

Backup

# PostgreSQL
pg_dump -U managelm managelm > managelm-backup-$(date +%F).sql

# Redis (if using persistence)
redis-cli BGSAVE
cp /var/lib/redis/dump.rdb ./redis-backup-$(date +%F).rdb

# Configuration
cp /opt/managelm-server/portal/.env ./env-backup-$(date +%F)

Restore

# Stop the portal
systemctl stop managelm-server

# Restore PostgreSQL
psql -U managelm managelm < managelm-backup-YYYY-MM-DD.sql

# Restore Redis
systemctl stop redis
cp redis-backup-YYYY-MM-DD.rdb /var/lib/redis/dump.rdb
systemctl start redis

# Restore configuration (if needed)
cp env-backup-YYYY-MM-DD /opt/managelm-server/portal/.env

# Start the portal
systemctl start managelm-server

Monitoring

# Service status
systemctl status managelm-server

# Health check
curl -s http://localhost:3000/health

# Live logs
journalctl -u managelm-server -f

# Last 100 lines
journalctl -u managelm-server -n 100

Uninstall

# Stop and disable the service
systemctl stop managelm-server
systemctl disable managelm-server
rm /etc/systemd/system/managelm-server.service
systemctl daemon-reload

# Remove the install directory
rm -rf /opt/managelm-server

# (Optional) Remove the service user
userdel managelm

This does not remove PostgreSQL or Redis data. Drop the database manually if no longer needed:

sudo -u postgres dropdb managelm
sudo -u postgres dropuser managelm

Troubleshooting

Portal won't start

  • Check logs: journalctl -u managelm-server -n 50
  • Verify DATABASE_URL and REDIS_URL in .env are correct.
  • Test PostgreSQL: psql "$DATABASE_URL" -c "SELECT 1;"
  • Test Redis: redis-cli ping
  • Check for port conflicts: ss -tlnp | grep 3000

Agents can't connect

  • Verify SERVER_URL in .env is reachable from the agent server.
  • Check reverse proxy forwards WebSocket headers. See Reverse Proxy.
  • Test: curl -I https://your-hostname/health

Database permission errors

  • "permission denied for schema public" — Run: GRANT ALL ON SCHEMA public TO managelm;
  • "FATAL: password authentication failed" — Verify DATABASE_URL credentials.
  • "could not connect to server" — Check listen_addresses in postgresql.conf and pg_hba.conf.

Email not sending

  • Without SMTP_HOST, email is disabled. Set it to your SMTP server.
  • Check logs: journalctl -u managelm-server | grep -i mail

.env permission denied

  • The .env file is root:managelm 640. Edit with sudo.
  • After editing, verify permissions: ls -la /opt/managelm-server/portal/.env