Installation
Requirements
- A server running Ubuntu 24.04 (tested: Ubuntu 22.04, 24.04 and 26.04, Debian 12; other apt-based systems usually work) with systemd, on x86_64 or arm64. 2 vCPU, 4 GB RAM and 40 GB disk recommended (the tools for videos and scraping take ~1.5 GB). Under 4 GB of RAM without swap the installer adds a 2 GB swap file; under 3 GB local voice transcription stays off unless you ask for it.
- Root access (
sudo -i). - A Claude subscription (Pro/Max) or an Anthropic API key.
- For HTTPS access: a domain name whose DNS A/AAAA record points to the server, and ports 80/443 open. Alternatively Tailscale, or an SSH tunnel.
We recommend a server dedicated to Harness Maxxing: by default Claude runs with full permissions (see Security). A server that already runs other things works too - see Installing on a server already in use.
Install
As root on the server (sudo -i first if you are logged in as another user):
curl -fsSL https://get.harness-maxxing.com | bash
It asks three questions (access mode, domain, restore a backup), then clones the public git repository
(github.com/makushingu/harness-maxxing, branch stable = the published versions) - no key, no account. Updates then come from that branch
(maxxing update). Unattended install:
curl -fsSL https://get.harness-maxxing.com | ACCESS=domain DOMAIN=ui.example.com ASSUME_YES=1 bash.
Harness Maxxing is free under a fair source license: see License.
No license key is asked. A company that needs an Enterprise key gives it after the install, in Settings → License (or the onboarding step About you); see License.
After the questions the installer runs unattended with a live progress display. Voice messages are enabled with the local engine (on servers with at least 3 GB of RAM) and the time zone is chosen in the web onboarding:
- checks the server (root, apt, systemd, architecture) and whether it is already in use (see below);
- installs every system package it needs in one pass (git, curl, python3, gnupg, openssh-client, cron, ffmpeg,
jq, ripgrep, ImageMagick, the browser libraries, unattended-upgrades, fail2ban...), turning Ubuntu's
universecomponent on if the image shipped without it; on a small server without swap it adds a 2 GB swap file; - clones the code into
/opt/claude-maxxing; your customizations sit on top of it, see Customizing; - installs uv (Python toolchain) in
/usr/local/bin, the Python of the server in/var/lib/claude-maxxing/tools/python, and the Claude Code CLI: each one a pinned version whose checksum is in the release's list of components,deps.toml- nothing downloaded is run before it is checked (see Security, "Downloads"); - creates the Python environment and the
maxxingcommand, then runsmaxxing init: configuration, workspace, skills, default jobs; - optionally restores your memory from a backup;
- sets up access (Caddy for a domain, Tailscale, or local only);
- secures the server: automatic security updates, SSH logins by key only (only when it is proven safe, see Security), fail2ban for SSH, and a firewall (ufw) that lets in only SSH, 80/443 (domain) or Tailscale - see Security (on a server already in use, the firewall is handled carefully: see below);
- installs and starts the
claude-maxxingservice and checks it answers; - prints a one-time setup link (valid one hour);
- meanwhile, in the background, installs the tools Claude uses every day: Node.js 22, Remotion (motion
design videos), Scrapling (web scraping) and one Chromium they share with PDF printing, plus the speech
model - see Videos, PDFs and images.
maxxing deps listshows where they are.
About a minute until the setup link on a small server, a minute or two more for the tools. A re-run only redoes what
changed (about 10 seconds). Re-run one part alone on an existing server: bash /opt/claude-maxxing/install.sh --tools
(= maxxing deps update) or --secure. Technical names keep the original spelling: the service is
claude-maxxing, the code /opt/claude-maxxing, the state /var/lib/claude-maxxing.
Install from a local copy
No download at all: unpack a Harness Maxxing archive (with its built web/dist) on the server and run its
installer, bash /path/to/harness-maxxing/install.sh (or SOURCE_DIR=/path/to/harness-maxxing bash install.sh).
The code is copied to /opt/claude-maxxing; such an install has no update source, so "Check for updates" is off
and maxxing update says "updates unavailable". To update it, unpack the newer copy and run its installer again.
External components
Everything the installer adds besides the system packages is listed, with its version and checksum, in
server/maxxing/deps.toml and managed with maxxing deps:
maxxing deps list # installed and expected versions
maxxing deps verify # checksums, and files another user could replace
maxxing deps update # move to the versions of this release (each update does it on its own)
maxxing deps clean # old versions, leftovers, oversized logs (also every Sunday); --caches: root's uv/npm/pip caches too
maxxing deps check # known vulnerabilities (osv.dev; also every Monday, with a notification)
On an installation made before 2.0.0-alpha.70, the two weekly jobs are created turned off (Crons page: turn them
on if you want them), and maxxing update keeps a working server Python and a uv it did not install where they are
(maxxing deps update python / uv moves them). Node.js is never linked into /usr/local/bin when the server
already has its own node: Harness Maxxing uses its copy, your programs keep theirs.
Each maxxing update moves them to the versions of the new release (installed next to the old ones, switched once
they work). Claude Code keeps updating itself (Settings -> Claude). System packages (Caddy, ffmpeg, git...) get their
security updates from unattended-upgrades.
Open the link: the onboarding does the rest.
Installing on a server already in use
Before changing anything, the installer looks at the server and prints a Server check: other services reachable from outside, a web server on ports 80/443, an active firewall, Docker, other scheduled jobs, an older Node.js, an existing Claude Code setup, other Telegram bridges. To only see that report (nothing is changed):
curl -fsSL https://get.harness-maxxing.com | bash -s -- --check
When the server is already in use, the installer asks for confirmation and then:
| What it finds | What it does |
|---|---|
| other services reachable from outside, or Docker | does not turn the firewall on (it could cut them off). Force it with FIREWALL=1 bash /opt/claude-maxxing/install.sh --secure |
| an active ufw firewall | keeps your rules and only adds SSH (+ 80/443 for a domain, + Tailscale) |
| nginx, Apache or another web server on 80/443 | does not install Caddy; with a domain, saves the reverse-proxy block to add to your web server in /var/lib/claude-maxxing/reverse-proxy.conf |
| a Caddy you already use | adds its own site with one import line, your sites stay as they are |
| other scheduled jobs | never changes the server clock: your jobs keep their times, Harness Maxxing jobs run at the times you pick in your own zone |
| a Node.js of its own | keeps it; Harness Maxxing gets its Node.js 22 in /var/lib/claude-maxxing/tools/nodejs, used only by its sessions and tools |
| port 8787 taken | uses the next free port |
Claude Code already signed in, with skills or a ~/.claude/CLAUDE.md |
keeps everything, and asks: give Harness Maxxing its own Claude Code folder (~/.claude-harness, the default - your ~/.claude is not touched, you sign in again in the web setup and bring skills over when you need them) or share ~/.claude (its global instructions and skills then also apply to Harness Maxxing sessions; a skill with the same name as a product skill is moved to the trash first). Without a terminal: own folder. Re-running the installer keeps the choice made the first time |
| another Telegram bridge or agent | warns you: give Harness Maxxing a new bot (one bot token can only be read by one program) |
| SSH password logins on | turned off only when the session running the installer is proven to use a key (asked first when you answer questions); otherwise left on, with a warning |
| your crontab, fail2ban SSH jail, automatic-update settings | kept (Harness Maxxing only edits its own crontab block) |
maxxing uninstall lists what the installer changed on the server (firewall turned on, SSH by key only, time zone)
and how to undo it.
Access modes
| Mode | URL | How |
|---|---|---|
domain (recommended) |
https://ui.example.com |
Caddy is installed from its official repository, gets a Let's Encrypt certificate on the first visit and forwards to 127.0.0.1:8787. Site file: /etc/caddy/claude-maxxing.caddy. |
tailscale |
http://100.x.y.z:8787 |
The server listens on the Tailscale IP only: reachable from your Tailscale devices. |
local |
http://127.0.0.1:8787 |
Listens on localhost only. From your computer: ssh -N -L 8787:127.0.0.1:8787 root@<server> then open the URL. |
The server never listens on 0.0.0.0 or a public address.
Unattended install
Answer every question with variables and add ASSUME_YES=1:
curl -fsSL https://get.harness-maxxing.com | ACCESS=domain DOMAIN=ui.example.com ASSUME_YES=1 bash
| Variable | Default | Meaning |
|---|---|---|
REPO, BRANCH |
makushingu/harness-maxxing, stable |
the git repository and branch the code and the updates come from (stable = published versions, main = work in progress) |
GH_TOKEN |
– | a read token, only for a private fork or mirror (REPO=owner/name) |
LICENSE |
– | optional: an Enterprise key, recorded at the end (same as Settings → License, see License) |
LICENSE_API |
https://api.harness-maxxing.com |
license server (checks an Enterprise key) |
INSTALL_DIR |
/opt/claude-maxxing |
code + Python environment |
WORKSPACE |
/root/maxxing |
your workspace |
STATE_DIR |
/var/lib/claude-maxxing |
configuration and state |
PORT |
8787 |
HTTP port |
ACCESS |
asked (local when unattended) |
domain, tailscale or local |
DOMAIN |
– | required for domain |
TIMEZONE |
system zone | IANA name, e.g. Europe/Paris. Usually chosen in the web onboarding instead. On a fresh server the system zone is switched (timedatectl set-timezone) so scheduled jobs fire at the times shown in the UI |
SYSTEM_CLOCK |
auto |
follow = the system zone follows yours (default on a fresh server), keep = never touch it (default on a server already in use; jobs still run at your times) |
CLAUDE_DIR |
~/.claude (~/.claude-harness when Claude Code is already used and you keep the default answer) |
Claude Code folder used by Harness Maxxing; set it to skip the question. Another folder (e.g. /root/.claude-harness) keeps it apart from a Claude Code you already use on this server: its own skills, global CLAUDE.md, conversations and sign-in; your ~/.claude is not touched. Bring skills over one by one when you need them |
RESTORE_FROM, RESTORE_TOKEN |
– | restore an existing memory backup (see below) |
CLAUDE_TOKEN / ANTHROPIC_API_KEY |
– | optional: Claude credentials stored right away |
FIREWALL |
auto |
auto = ufw only on a server with nothing else exposed (an active ufw is kept, rules added), 1 = always, 0 = never (security updates and fail2ban are still set up) |
SSH_HARDEN |
auto |
auto = turn SSH password logins off only when this session is proven to use a key, 1 = also when a key is installed but the session cannot be checked (console, web terminal), 0 = never touch SSH |
VOICE |
local (off under 3 GB of RAM) |
voice messages: local (Whisper on the server, model downloaded in the background), groq, openai or off - see Voice messages. VOICE=local on a smaller server is asked, refused unattended |
TOOLS |
background |
background = Node.js, Chromium, Remotion, Scrapling and the speech model are installed once the service runs, foreground = wait for them, 0 = skip (maxxing deps update later) |
SWAP |
auto |
auto = a 2 GB /swapfile under 4 GB of RAM when there is no swap, on a fresh server only (not in containers, not on a server already in use or a re-run), 1 = the same on any server, 0 = never |
SOURCE_DIR |
– | install this local copy of the code (see "Install from a local copy") |
ASSUME_YES |
0 |
1 = never ask, use defaults |
Restore on a new server
Moving to a new server? Install with your backup repository (with an Enterprise key, first free it on the old server: Settings → License → Remove the key, see License):
curl -fsSL https://get.harness-maxxing.com | RESTORE_FROM=owner/memory-backup RESTORE_TOKEN=<token> bash
The installer runs maxxing backup restore --from owner/memory-backup after creating the
workspace. See Backup.
Re-running, updating, uninstalling
- Re-run the installer at any time: every step keeps what exists (useful to change the access mode or repair an install).
- Update:
maxxing update(or... | bash -s -- --update). It pulls the new version, replays your customizations on top, syncs dependencies, refreshes skills and templates (never your files), restarts the service, checks it answers (otherwise it rolls back) and prints what changed. Also available in Settings -> System and in the topicsystem/harness(system/updateon older servers). - Uninstall:
maxxing uninstall(or... | bash -s -- --uninstall) removes the service, Caddy site, crontab block, product skills and themaxxingcommand. Add--purgeto also delete the code, the state directory and every external component the installer added (deps.toml: uv, Node.js, the tools, Claude Code and Caddy when the installer installed them, the swap file it created),--purge-workspaceto delete the workspace too (irreversible).
Check the installation
maxxing doctor
Every line is ✔ (fine), ! (warning) or ✘ (problem), with a fix hint. See
Troubleshooting.