Documentation
argon
The complete guide to argon 1.0: installing it, adding projects, writing workflows, deploying, collecting logs, tracking errors and connecting apps.
Introduction
argon is a CLI tool that runs on each of your Linux servers. It deploys projects from
workflows kept in their repositories, collects their logs, groups their errors and samples the
server's health. It is one CLI tool with no dependencies; a background service does the work and
the argon command talks to it.
argon is built around a few ideas:
- The terminal is enough. Every action is a command. Apps such as IWS Console can connect and become argon's UI, but argon never needs them.
- The repo describes the pipeline. Workflows live in
.argon/workflow/, in GitHub Actions syntax, and argon reads them from the commit it deploys. - The server holds the truth. Runs, logs and errors are stored on the server. Apps ask argon; argon never depends on them.
- Root decides, code runs unprivileged. argon's service runs as root, but workflow steps run as the project folder's owner, never as root, unless root allows it for root-owned folders (
sudo argon policy allow-root on, off by default).
Requirements
- Linux on amd64 or arm64, with systemd
gitandbashon the server;curlandsha256sumto install- Root access (
sudo) to install argon and to change what it does - Optional: pm2, Docker or journald, for argon to read your apps' logs
Installation
Run one line on the server:
curl -fsSL https://console-server.iwsconsole.com/argon/install.sh | sudo bash The script:
- downloads argon for the server's processor and refuses it unless its SHA-256 matches the release;
- installs
/usr/local/bin/argon,/etc/argon/and theargon.servicesystemd unit; - creates the
argongroup; - enables and starts the service.
Installing takes no token and connects argon to nothing. Check it:
argon -v
sudo argon doctor
sudo argon status Using argon without sudo
Commands that only read (argon projects, argon runs, argon logs,
the live view) work for members of the argon group. Commands that change something
always need root.
sudo usermod -aG argon $USER # then log out and back in Updating and removing
sudo argon update installs the newest release of the same major version (1.0.4 to 1.2.0, never to 2.0), checks its SHA-256 and that it runs, and restarts the service; if it does not stay up, the previous build goes back. Name a version to pick one: 1.1 is the newest 1.1.x, 2 the newest 2.x, and v1.0.3 an older one. A major version or an older one is installed only this way, on the server. argon version list shows what is released, newest first. An app with the update scope can start an update too, only to a newer version of the same major. argon does not update while a run is going (--force does). Running the install line again also updates. Your projects, runs and logs stay. To remove argon completely:
sudo systemctl disable --now argon
sudo rm -rf /usr/local/bin/argon /etc/argon /var/lib/argon /etc/systemd/system/argon.service
sudo systemctl daemon-reload Quick start
This takes an app that already runs on the server (here under pm2) and gives it deployments, logs and error tracking.
1. Add a workflow to the repo
Commit .argon/workflow/deploy.yml:
name: Deploy
on:
workflow_dispatch:
push: {branches: [main]}
environment: production
jobs:
deploy:
steps:
- run: npm ci
- run: npm run build
- argon/restart: pm2:my-app
- argon/health: https://my-app.example.com/health Check it before you commit: argon validate .argon/workflow/deploy.yml. argon never writes into a repo, so the workflow must be committed and pushed.
2. Add the project
In the repo root on the server:
cd /srv/my-app
sudo argon add project Added my-app (/srv/my-app); its steps run as deploy.
Logs: pm2 my-app, storage/logs/*.log
Deployments: 1 workflow (deploy.yml)
Errors: sudo argon dsn my-app 3. Allow the restart
Root decides which services a workflow may restart:
sudo argon policy restart add pm2:my-app 4. Deploy
sudo argon deploy my-app deploy.yml -f From now on, a push to main deploys by itself once argon sees it, unless the environment is production, which only deploys by hand until root allows push (see Triggers).
5. Watch
argon # the live view
argon logs -f # in the repo folder: this project's logs Projects
A project is a Git checkout on the server that argon knows about. A project may have workflows (then it can be deployed) or none (then argon still collects its logs and errors).
Adding a project
cd /srv/my-app
sudo argon add project [--name my-app] argon checks that the folder:
- is a repo root (has
.git); - is inside the allowed folders (default
/srv,/var/www,/home,/opt); - has a real path, without symlinks;
- is owned by a user other than root, or has a
run_asuser in the policy.
The name defaults to the folder's name in lowercase, with dots and spaces turned into dashes. It then finds the project's logs (see Logs) and starts following them.
Only root on the server adds projects; connected apps show them but cannot add or remove them. List them with argon projects; set where projects may live with sudo argon policy roots /srv,/var/www.
Removing a project
sudo argon remove project # in the repo root
sudo argon remove project my-app # or by name, from anywhere argon stops running and watching it, and removes the webhook it added, if any. Its files, run history and stored logs stay.
Git access
argon fetches code as the project's owner, never as root. Over SSH it uses that user's keys and
~/.ssh/config, exactly as when the user runs git pull, so a deploy key works
as you would set it up by hand:
# ~/.ssh/config of the project's owner
Host gitlab.com
IdentityFile ~/.ssh/gitlab_id_rsa
IdentitiesOnly yes The key never goes in a workflow. Use HTTPS remotes for public repositories.
Workflows
Workflows are YAML files in .argon/workflow/, written in a subset of GitHub Actions' syntax.
Anything argon does not understand is refused with a reason, never silently skipped.
name: Production
on:
workflow_dispatch:
inputs:
migrate: {type: boolean, default: "true"}
push: {branches: [main]}
environment: production # development | staging | production
env:
NODE_ENV: production
jobs:
build:
steps:
- run: pnpm install --frozen-lockfile
- run: pnpm build
timeout-minutes: 15
release:
needs: build
steps:
- run: pnpm migrate
if: inputs.migrate == 'true'
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
- argon/restart: pm2:shop-api
- argon/health: https://api.example.com/health
- argon/notify: "Shipped ${{ github.sha }}" Supported syntax
| Key | Meaning |
|---|---|
name | Shown in runs and apps |
on | push, pull_request, workflow_dispatch (with inputs), schedule |
environment | development, staging or production; or {name, approval: required} |
approval: required | Every run of this workflow waits for approval |
concurrency | A group name (or {group}): a newer run of the group replaces one still waiting. A running run is never stopped; cancel-in-progress is accepted and ignored |
env | At workflow, job and step level |
jobs.<id> | needs, if, runs-on, env, timeout-minutes, steps |
| steps | run, name, if, working-directory (inside the project), env, timeout-minutes, continue-on-error, shell: bash |
uses | Refused (argon never downloads actions), except actions/checkout, which does nothing |
argon's own steps
| Step | What it does |
|---|---|
argon/restart: pm2:<process>argon/restart: systemd:<unit> | Restarts it, only if root allowed it with argon policy restart add |
argon/health: <url> | Passes when the address answers 2xx within 5 tries |
argon/notify: <message> | Writes the message into the run's log |
How steps run
- Each
run:goes throughbash --noprofile --norc -e -o pipefail: the first failing command fails the step. - Steps run as the project folder's owner (or the policy's
run_as), never root; a root-owned folder runs as root only aftersudo argon policy allow-root on. - The environment is clean:
PATH, the user'sHOME,CI=true, and argon's variables below. Add a tool's folder withenv: PATH: …. - A step may take 30 minutes unless
timeout-minutessays otherwise. Cancelling kills its whole process group.
| Variable | Value |
|---|---|
ARGON | true |
ARGON_PROJECT | The project's name |
ARGON_WORKFLOW | The workflow's file |
ARGON_JOB | The job's ID |
ARGON_COMMIT | The commit being deployed |
ARGON_BRANCH | The checkout's branch |
ARGON_ENVIRONMENT | The workflow's environment |
ARGON_RUN | The run's ID |
ARGON_RELEASE | The release for error tracking (the commit) |
Expressions
${{ }} in values and if: conditions understand:
- Contexts:
inputs.*,secrets.*,env.*,github.ref,github.ref_name,github.sha,github.event_name,github.actor - Status:
success(),failure(),always(),cancelled() - Operators:
==,!=,&&,||,!
As in any CI system, whatever a workflow puts in a run: runs on the server. Treat the ability to push to a deployed branch as the ability to run code there.
Secrets
Secrets stay on the server, in /etc/argon/secrets/<project>.env (owned by root, mode 0600):
DATABASE_URL=postgres://app:…@127.0.0.1/app
STRIPE_KEY=sk_live_… Use them as ${{ secrets.DATABASE_URL }}, only in run: and env:. Their values, the project's .env* values and known key shapes are hidden in every log. argon doctor warns when a secrets file is readable by others.
Adding a workflow to a project
The project does not need to be added again: argon reads .argon/workflow/ from the checkout
every time. It lists workflows, and knows their triggers, from the files in the folder on the server, so
a new workflow counts once the server's checkout has it.
- Check it:
argon validate .argon/workflow/new.yml, then commit and push it. -
Bring it into the server's checkout, as the project's owner (
argon projectsshows who), or deploy one of the project's existing workflows, which fast-forwards the checkout:cd /srv/my-app && sudo -u <owner> git pull --ff-only - See it:
argon workflows my-app. Connected apps show it within a few seconds. - Run it by hand with
sudo argon deploy my-app new.yml(it needsworkflow_dispatch), or let its push, tag or schedule triggers run it from now on.
If it restarts something new, allow that once: sudo argon policy restart add pm2:<name>.
A changed .argon/ deploys like any other commit, unless root asks for approval of it
(sudo argon policy set production workflow-change=required). Changing or removing
a workflow works the same way: push it, and argon follows the checkout.
A checkout lists only the workflows that can run on its branch: one whose on.push.branches leaves out
the checkout's branch is not shown to apps; argon workflows <project> names it under "For other branches".
Workflows kept on the server
A project's workflows can also live on the server, in /etc/argon/workflows/<project>/, so the
repo stays untouched and someone who can push cannot change how it deploys. argon reads both places for every
project; when a file name is in both, the server's wins. argon workflows <project> shows where
each one comes from.
sudo install -d -m 755 /etc/argon/workflows/my-app
sudo install -m 644 deploy.yml /etc/argon/workflows/my-app/deploy.yml
argon workflows my-app # from: /etc/argon/workflows/my-app/ (server)
The folder and the files must be owned by root and writable by root only; otherwise the workflow is listed as
invalid and never runs. A server workflow is read as it is when the run starts (not from the commit), and a
change under .argon/ in the repo does not ask for approval of it.
Deploying
sudo argon deploy # choose the project, then the workflow
sudo argon deploy my-app # choose the workflow
sudo argon deploy my-app production.yml # deploy it now
sudo argon deploy my-app production.yml --input migrate=false --note "hotfix" -f
Without a project or a workflow, deploy asks in the terminal (↑ ↓ or a number,
Enter; q cancels). It offers only projects with a workflow that has
workflow_dispatch, and then follows the run's log.
What a deploy does
- Fetches the checkout's branch from its remote.
- Reads the workflow from the commit it will ship, not from the working tree.
- Fast-forwards the checkout. A branch that has diverged fails the run; nothing on the server is thrown away.
- Runs the jobs in order of
needs, step by step.
A deploy is always the branch's latest commit. To roll back, push a revert.
The queue
argon runs one run per project and, by default, one at a time on the server
(sudo argon policy runs <n> lets more projects run at once). Projects take turns: the one whose
last run started longest ago goes next, so a busy project never holds the others back; within a project,
first come first served. The same deploy asked twice while it waits is queued once. A deploy by hand and a
webhook always run the whole workflow, even on a commit that is already deployed. argon's own Git check
(every 5 minutes by default) only runs when the branch has a commit the checkout is not at yet, so a push
already deployed by hand is not run again. A run cut short by a restart of argon is marked failed.
argon runs # recent runs and queue positions
argon run <id> -f # follow one
sudo argon cancel <id> Approval
A run waits for approval when any of these asks for it; the strictest wins:
- root's policy for the environment (
sudo argon policy set production approval=required); - the workflow itself (
approval: required); - a connected app's own rule;
- a change under
.argon/since the running commit, when root's policy asks for it (sudo argon policy set production workflow-change=required; off by default).
environment:
name: production
approval: required A waiting run leaves the queue; once approved it joins the back. An approval holds for that commit. Root can always approve with sudo argon approve <id>; a production run asked for by an app is approved from that app, and one no app asked for (a push, a schedule, the CLI) from any app with the approve scope.
Turning approval off
Approval is off unless something turns it on. If runs still wait, turn off every source; one left on is enough to hold a run:
- Root's policy:
sudo argon policy set production approval=none workflow-change=none, then check withargon policy. - The workflow: remove
approval: requiredfrom it and push the change. - Each connected app's own rule: switch it off in that app's deployment settings.
A run already waiting keeps waiting after this. Approve it once (sudo argon approve <id>) or cancel it and deploy again.
Approval is not what lets a push deploy production: that is push=allow (see Triggers). Without it a push to the production branch never deploys, approval or not. With approval off and push=allow, every push to that branch goes to production unchecked.
Triggers and CI/CD
argon checks Git itself with git ls-remote: no webhook is needed. It asks only for the
checkout's branch (plus tags or pull request refs when a workflow uses them), once per remote even when
several projects use it, every 5 minutes by default, and every 30 minutes while webhooks
arrive.
sudo argon policy poll 15m # any interval from 1m
sudo argon policy poll off # no polling: pushes deploy only through a webhook on:
push:
branches: [main, dev]
tags: ["v*"]
pull_request:
branches: [main]
schedule:
- cron: "0 3 * * *" # 03:00 server time
workflow_dispatch:
inputs:
tag: {type: string}
target: {type: choice, options: [blue, green]} | Trigger | When it runs |
|---|---|
push | A new commit on the checkout's branch (a merge is a push). [skip ci] or [argon skip] in the message skips it. |
push.tags | A new tag that is the tip of the checkout's branch |
pull_request | A new or updated pull or merge request; runs in a scratch clone, without secrets, never restarting anything |
schedule | Five-field cron in the server's time |
workflow_dispatch | By hand: argon deploy or a connected app |
sudo argon policy set production push=allow.
Pull request runs are off by default and only run on a server labelled builder:
sudo argon policy label add builder
sudo argon policy pull-requests on Keep them off on servers that run production: a pull request's code runs as the project's owner.
Webhooks (optional)
Without a webhook, argon finds a push at its next check (every 5 minutes by default). With one, GitHub or GitLab tells argon right after the push and argon checks at once. The webhook only says "check now": argon still reads the remote itself, so a forged call cannot name a commit or start a deploy.
1. Let GitHub or GitLab reach argon
argon serves webhooks itself, with nothing in front of it. Make its listener public and open the port (7745) in the server's firewall:
sudo argon listen public 2a. Add the webhook by hand
Get the project's address and secret:
sudo argon hook my-app
# Address: http://203.0.113.10:7745/argon/hook/my-app
# Secret: … - GitHub: the repo → Settings → Webhooks → Add webhook. Payload URL: the address; content type:
application/json; secret: the secret; events: pushes and pull requests. - GitLab: the project → Settings → Webhooks → Add new webhook. URL: the address; secret token: the secret; triggers: push events, tag push events and merge request events.
2b. Or let argon add them
argon can add the webhooks for you. For that it needs an access token, which you create once in
GitHub or GitLab (argon cannot create one itself) and give to argon git connect. argon
then adds a webhook to every added project whose workflows run on a push or pull request, now and whenever
you add a project later.
Create the token on GitHub (github.com):
- Your avatar → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token.
- Repository access: the repos argon deploys (or all repositories).
- Permissions → Repository permissions → Webhooks: Read and write. Nothing else is needed.
- Choose an expiry, generate it, and copy the token; GitHub shows it only once.
A classic token with the admin:repo_hook scope works too.
Create the token on GitLab (gitlab.com or your own server):
- Your avatar → Edit profile → Access tokens → Add new token. To limit it to one group or project, use that group's or project's Settings → Access tokens instead, with the Maintainer role.
- Scope:
api. - Choose an expiry, create it, and copy the token; GitLab shows it only once.
Give it to argon, on the server:
sudo argon git connect github --token <token> # github.com
sudo argon git connect gitlab --token <token> # gitlab.com
When the token expires, the webhooks argon already added keep working; argon only cannot add or remove
them any more. Create a new token and run git connect again. If you would rather not give argon
a token, add the webhooks by hand (2a).
Your own GitLab server. If your company runs GitLab itself (self-hosted, for example
gitlab.example.com) rather than using gitlab.com, argon cannot guess its address. Give its API
with --api. The repo's remote tells you which one you use: git remote -v showing
git@gitlab.com:… means gitlab.com; any other host means your own server. The same goes for GitHub
Enterprise.
sudo argon git connect gitlab --token <token> --api https://gitlab.example.com/api/v4
# GitHub Enterprise:
sudo argon git connect github --token <token> --api https://github.example.com/api/v3 argon keeps the token in /etc/argon/git.json (root only) and fills in its own public address. Behind NAT, where the server does not know its public address, give it: --hook-url http://<public address>:7745/argon/hook.
sudo argon git sync # add webhooks that are missing (adding a project does this too)
sudo argon git disconnect # remove every webhook argon added, and forget the token GitHub webhooks are checked with their HMAC signature, GitLab's with their secret token. The listener speaks HTTP, so a webhook's body is not encrypted on the way; at worst a forged call makes argon check early. After a disconnect, or with no webhook at all, argon still finds every push by polling.
Logs
When you add a project, argon looks at what runs the app (not at its language or framework) and follows its output from there:
| Source | How argon finds it | What it reads |
|---|---|---|
pm2:<name> | pm2 processes whose working folder is in the repo | pm2's out and error log files |
systemd:<unit> | services whose processes run in the repo | journalctl -u |
docker:<container> | containers Docker Compose started from the repo | docker logs: stdout as info, stderr as error |
file:<glob> | logs/, log/, storage/logs/, var/log/ *.log | new lines, following rotation |
An app that only prints to a terminal or nohup has nowhere to read from: run it under pm2 or systemd, or have it write a file.
Managing sources
In the project's folder:
sudo argon logs find # look again, e.g. after starting a new pm2 process
sudo argon logs add storage/logs/app.log # a file or glob, relative to the repo
sudo argon logs off # stop collecting; sources are kept
sudo argon logs on From anywhere, by name:
sudo argon sources my-app
sudo argon sources my-app add pm2:my-worker
sudo argon sources my-app remove file:/srv/my-app/logs/*.log Files are read only inside the project, its owner's home or /var/log.
Reading logs
argon logs -f # in the project's folder
argon logs my-app --level warn --since 2h
argon logs my-app --grep payment -n 500
argon logs my-app --since 2026-10-31T08:00:00Z JSON log lines (pino, winston, zap and the like) keep their level and fields; plain lines get a level from words such as error or warn. Secrets and fields named like secrets are hidden before anything is stored. Logs stay on the server, one file per project and day.
Sending lines directly
An app can also write JSON lines to /run/argon/ingest.sock. argon only accepts lines for a project from that project's own Unix user.
{"project":"my-app","level":"warn","msg":"slow query","time":"2026-10-31T09:12:04Z","fields":{"ms":1240}} Error tracking
argon accepts errors in Sentry's format, so any official Sentry SDK works by changing its address. Get the project's DSN:
sudo argon dsn my-app
# SENTRY_DSN=http://<key>@127.0.0.1:7745/1
# From other machines or browsers: http://<key>@203.0.113.10:7745/1 (when the listener is public) Apps on the same server use the first address. Apps on other machines, and browser SDKs, use the second once the listener is public (see The listener); argon answers CORS for them.
Give it to the app, for example in Node.js:
import * as Sentry from "@sentry/node";
Sentry.init({
dsn: process.env.SENTRY_DSN, // from: sudo argon dsn my-app
release: process.env.ARGON_RELEASE, // set by argon in every step
}); argon then:
- groups events into issues by exception type and top in-app frames, or by the SDK's fingerprint;
- links each issue to the release and the run that shipped it, and marks regressions;
- keeps the project's last log lines with every event;
- leaves out cookies, auth headers and request bodies;
- sends new issues and regressions at once to connected apps that may see errors.
argon errors my-app
argon error <id>
sudo argon error <id> resolve # or ignore, unresolve Live view
Type argon in a terminal. Like top, it redraws every two seconds:
- whether argon is running; CPU, memory, load and disks (a disk over 90 % turns red);
- each project: branch, workflows, last run, unresolved errors, log sources;
- the queue: the running run and its current step, runs waiting for approval, then the rest;
- for the chosen project: its logs, runs or errors.
| Key | Action |
|---|---|
| ↑ ↓ or k j | Choose a project |
| l | Its logs |
| r | Its runs |
| e | Its errors |
| q, Esc, Ctrl+C | Quit |
It needs root or the argon group. Piped or outside a terminal, argon prints its help.
Health and retention
Every 30 seconds argon records CPU, memory, load, disks and each allowed pm2 or systemd process. A disk over 90 % full raises an alert, at most once an hour. A day of samples is kept.
| Data | Kept |
|---|---|
| Runs | 90 days |
| A project's logs | 7 days or 1 GB; finished days are compressed |
| Errors | 30 days |
| Health samples | 1 day |
Policy
Root's rules for the server, kept in /etc/argon/argon.json:
argon policy # show it
sudo argon policy roots /srv,/var/www # where projects may be added
sudo argon policy run-as <user|owner> # who steps run as (default: the folder's owner)
sudo argon policy allow-root on|off # root-owned folders run as root (default off)
sudo argon policy restart add pm2:my-app # any project may restart it; remove …
sudo argon policy restart my-app add pm2:my-app # only my-app may restart it
sudo argon policy limits my-app cpu=100% memory=1G tasks=512 time=20m # off clears them
sudo argon policy runs 2 # runs at once, each of a different project
sudo argon policy label add builder # for runs-on
sudo argon policy pull-requests on|off
sudo argon policy poll 5m|15m|off # how often argon checks Git (default 5m)
sudo argon policy set production approval=required push=deny # approval=none push=allow to undo
sudo argon policy set production workflow-change=required # approval when .argon/ changed (default none) A workflow can add approval but never remove it, and run_as can never be root.
With limits, each step of the project's runs goes in its own systemd scope (argon.slice) with that
CPU, memory and task limit, and a run longer than time fails. A project's restart list is its own;
the server's list holds for every project.
The listener
argon receives webhooks and errors on one HTTP listener, port 7745. By default it listens on
127.0.0.1, for apps on the same server only. Made public, it takes them from anywhere:
GitHub and GitLab webhooks, and errors from apps on other machines or from browsers.
sudo argon listen public [--port 7745] # every address; open the port in the firewall
sudo argon listen local [--port 7745] # 127.0.0.1 only (the default)
argon listen # which, and the webhook and error addresses It answers only these, each checked with its project's secret or DSN key; anything else is 404:
| Path | What |
|---|---|
POST /argon/hook/<project> | A webhook from GitHub or GitLab |
POST /api/<n>/envelope/POST /api/<n>/store/ | Errors from Sentry SDKs; at most 300 a minute per project (over that 429, which the SDKs respect) |
Connecting UI
argon works on its own from the terminal. For a full web UI of your server (projects, deployments with live logs, app logs, errors and server health) connect it to IWS Console:
- In IWS Console, open the Argon menu and choose Add server.
- Copy the command it shows.
- Run it on your server, where argon is installed.
The server appears in the Argon menu with every project you added on it, and you get the full UI.
Servers from IWS Console come with argon preinstalled and already connected: their projects, deployments, logs and errors are in each project's page, with nothing to install or connect.
Scopes
Root chooses what each app may do; the app can never widen it.
| Scope | Allows |
|---|---|
view | Projects, runs and their logs, policy, health, alerts (always included) |
deploy | Deploy (not production), cancel |
deploy-production | Deploy a production workflow |
approve | Approve runs; set the app's own approval rule |
logs | Query and follow logs |
errors | Issues and their events |
update | Update argon to a newer version of the same major |
The default is view, deploy, logs, errors.
sudo argon apps
sudo argon apps scope "IWS Console" view,deploy,deploy-production,approve,logs,errors,update
sudo argon apps revoke "IWS Console" Security model
- Workflows are trusted like any CI. Whoever can push to a deployed branch decides what runs, exactly as with GitHub Actions or GitLab Runner. Protect your branches.
- Never root. Steps run as the project's owner; a root-owned folder or
run_as rootis refused. Restarts are limited to root's allow-list. - No open port by default. argon dials out to apps. Its listener binds to
127.0.0.1until root makes it public, and then answers only webhooks and errors, each checked with its project's secret or key. - Signed commands. Apps' commands are Ed25519-signed, short-lived and never replayed. Registration is HTTPS only, with verified certificates. An app ID already held by another app is refused.
- Secrets stay on the server and are hidden in run logs and app logs; private keys and secrets files are 0600.
- Production is guarded. No push deploys it unless root allows; root can also require approval whenever
.argon/changed. - Pull requests are off by default and run without secrets on builder servers only.
CLI reference
Projects
sudo argon add project [--name n] [--path p] | Add the repo you are in (or at p): logs at once, deployments if it has workflows |
argon projects | Added projects |
argon workflows <project> | A project's workflows, triggers and jobs |
argon validate <file> | Check a workflow file without running it |
sudo argon remove project [<name>] | Stop running and watching it (in its folder, or by name); files, runs and logs stay |
Runs
sudo argon deploy [<project> [<workflow>]] | Deploy; asks for what is missing, then follows the run |
--input k=v · --note … · -f | Workflow inputs, a note shown with the run, follow its log |
argon runs [--all] | Recent runs and the queue |
argon run <id> [-f] | A run and its log; -f follows it |
sudo argon cancel <id> | Cancel a waiting or running run |
sudo argon approve <id> | Approve a run that waits for approval |
Logs and errors
sudo argon logs find | Look for the project's logs again (in its folder) |
sudo argon logs add <file> | Follow a file or glob, relative to the repo |
sudo argon logs off | on | Stop or restart collecting |
argon logs [<project>] [-f] [--level warn] [--since 1h] [--grep text] [-n 500] | Query and follow logs |
sudo argon sources <project> [add|remove <source>] | Log sources by name |
sudo argon dsn <project> | The Sentry DSN for the project's app |
argon errors [<project>] | Issues, newest first |
argon error <id> · sudo argon error <id> resolve|ignore|unresolve | One issue; change its state |
CI/CD
sudo argon hook <project> | The webhook address and secret |
sudo argon git connect github|gitlab --token … [--hook-url …] | Let argon add webhooks itself |
sudo argon git sync | disconnect | Add missing webhooks; remove them all |
Apps
sudo argon connect <app> --token … --name … [--scope …] | Connect an app that becomes argon's UI |
sudo argon apps | Connected apps and their scopes |
sudo argon apps scope <app> <scopes> | Change what an app may do |
sudo argon apps revoke <app> | Disconnect an app |
The server
argon | The live view (in a terminal) |
argon status | Version, apps, projects, the queue |
argon policy · sudo argon policy … | Show or change the policy |
sudo argon policy poll <interval>|off | How often argon checks Git (default 5m) |
argon listen · sudo argon listen public|local [--port 7745] | Take webhooks and errors from anywhere, or from this server only |
argon doctor | Check tools, folders, the service and projects |
sudo argon logs [-f] | argon's own log (outside a project's folder) |
argon version · -v · --version | The version |
argon version list | Released versions, newest first |
sudo argon update [x | x.y | x.y.z] | Update argon (without a version: the newest of this major) |
Files and paths
| Path | What |
|---|---|
/usr/local/bin/argon | The argon CLI tool |
/etc/systemd/system/argon.service | The service (runs as root) |
/etc/argon/argon.json | Policy |
/etc/argon/enlisted.json | Added projects and their log sources |
/etc/argon/secrets/<project>.env | Secrets for a project's workflows (0600) |
/etc/argon/workflows/<project>/ | A project's workflows kept on the server (root only) |
/etc/argon/apps.json | Connected apps and their keys (0600) |
/var/lib/argon/runs/<id>/ | A run and its log |
/var/lib/argon/logs/<project>/ | A project's logs, one file per day |
/var/lib/argon/errors/ | Issues and their events |
/var/lib/argon/health.jsonl | Health samples |
/run/argon/ingest.sock | Local socket for apps to send log lines |
port 7745 | The listener: webhooks and errors; 127.0.0.1 unless made public |
State files under /etc/argon and /var/lib/argon are readable by the argon group, except keys and secrets, which only root reads.
Troubleshooting
- The live view says argon's state is not readable
- Use
sudo argon, or join the group:sudo usermod -aG argon $USER, then log in again. - argon is not running
sudo systemctl start argon, thensudo argon logs(outside a project folder) shows why it stopped.add projectfound no logs- Start the app under pm2 or systemd, or with Docker Compose from the repo, then run
sudo argon logs find. Or name a file:sudo argon logs add path/to/app.log. - A deploy fails at the fetch
- argon fetches as the project's owner. Run
sudo -u <owner> git fetchin the repo to see the error; usually the owner's SSH key or~/.ssh/configis missing. - A deploy fails with "diverged"
- Someone committed on the server. argon never throws work away: commit and push it, or reset the checkout yourself.
- A workflow is refused
argon validate .argon/workflow/<file>prints the reason, for example auses:step or an unknown key.- A restart step is refused
- Allow it first:
sudo argon policy restart <project> add pm2:<name>(orrestart addfor every project). - A run waits forever
- It may wait for approval (
argon runsshows it):sudo argon approve <id>. Turning approval off later does not release it (see Turning approval off). Otherwise a run of the same project is going, or the server is at itspolicy runslimit.
Still stuck? argon doctor checks tools, folders, the service and each project. Write to support@iwsconsole.com.