Skip to content
Sirio is in private beta: sources and installer are sent to testers by email. Ask to join.

Installation

You need a Linux machine with systemd, on amd64 or arm64. Docker can come later: if it’s missing, the first-run wizard offers to install it.

Terminal window
curl -fsSLO https://github.com/marsaldev/siriosysadmin/releases/latest/download/install.sh
sudo bash install.sh

That’s all. The script carries the systemd units and helpers of its release; it downloads the binary for the machine’s architecture and verifies it against the release’s checksums.txt — nothing to build, no Go or Node. It needs curl or wget.

Without downloading anything on the machine — offline, or behind a proxy — bring the release’s install.sh and binary yourself (checksums.txt too, if you want the checksum verified) and pass the binary as argument:

Terminal window
sudo bash install.sh ./sirio-sysadmin-vX.Y.Z-linux-amd64

The script then never touches the network. It verifies the binary against a checksums.txt in the same folder when there is one, and refuses a binary built for the other architecture or coming from a different release than the script — the units it carries belong to its own release.

For a specific version instead of the latest one, take the script from that release:

Terminal window
curl -fsSLO https://github.com/marsaldev/siriosysadmin/releases/download/v0.5.0/install.sh

It uses the systemd units and helpers it carries and the binary it downloads or that you pass it, and:

  1. creates the sirio system user and adds it to the docker group;
  2. installs the binary at /usr/local/bin/sirio-sysadmin;
  3. prepares /var/lib/sirio with 0700 permissions;
  4. installs sirio-sysadmin.service and (re)starts it;
  5. if one of apt-get, dnf, yum or apk is present on the machine, also installs the packages helper (/usr/local/lib/sirio/sirio-pkg) with the sirio-pkg.service and sirio-pkg.path units, and enables the latter. Without it, the panel’s Packages section stays read-only — the reason why is in packages.md;
  6. under the same condition, installs the Docker installation helper (/usr/local/lib/sirio/sirio-docker-install) with its units, so the first-run wizard can install Docker if it’s missing;
  7. installs the container logs helper (/usr/local/lib/sirio/sirio-logs) with the sirio-logs.service and sirio-logs.path units, which let Clear on a container’s log delete its log files for real. Without it, logs can only be read;
  8. with apt-get, dnf or yum, installs the fail2ban helper (/usr/local/lib/sirio/sirio-fail2ban) with the sirio-fail2ban.service and sirio-fail2ban.path units, which let the Ports page install fail2ban and turn its SSH jail on. Without it, fail2ban is only checked;
  9. installs the fail2ban control helper (/usr/local/lib/sirio/sirio-fail2ban-ctl) with the sirio-fail2ban-ctl.service and sirio-fail2ban-ctl.path units, which let the fail2ban page show the running jails and the addresses they ban. Without it, those aren’t shown;
  10. installs the power helper (/usr/local/lib/sirio/sirio-power) with the sirio-power.service and sirio-power.path units, which let administrators restart or shut down the server from the user menu. Without it, the menu offers neither.

Check:

Terminal window
systemctl status sirio-sysadmin
journalctl -u sirio-sysadmin -f
curl -s localhost:22722/api/status

The panel listens on 0.0.0.0:22722: you can reach it right away at http://MACHINE-IP:22722, no domain needed. If the machine has a firewall, allow the port:

Terminal window
sudo ufw allow 22722/tcp # ufw (Debian/Ubuntu)
sudo firewall-cmd --permanent --add-port=22722/tcp && sudo firewall-cmd --reload # firewalld (RHEL family)

On many cloud VMs the network interface only has a private address (10.x, 172.16–31.x, 192.168.x) and the provider maps the public one to it through a 1:1 NAT, so it never shows up on the machine. When the installer finds only a private address it says so and, on a terminal, asks for the public one to print the right URL (Enter skips it; unattended installs don’t stop). In that setup the provider often has its own firewall too (a security group): open 22722/tcp there as well.

On http://IP:22722 the connection is plaintext: the session cookie and the first-login password travel readable over the network. That’s fine for the initial setup on a network you trust; as soon as you have a domain, put HTTPS in front and bring the listener back to loopback.

Change settings with sudo systemctl edit sirio-sysadmin, under a [Service] header: they go in a drop-in that updates never touch. (If you edit the unit file itself, an update leaves it alone and writes the new version next to it as sirio-sysadmin.service.new, to merge by hand.)

Environment=SIRIO_LISTEN=127.0.0.1:22722
Environment=SIRIO_SECURE_COOKIES=true
sirio.example.com {
reverse_proxy 127.0.0.1:22722
encode gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
}
}

Caddy obtains and renews the certificate on its own, and passes WebSockets through without further configuration.

server {
listen 443 ssl http2;
server_name sirio.example.com;
ssl_certificate /etc/letsencrypt/live/sirio.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sirio.example.com/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://127.0.0.1:22722;
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_buffering off;
proxy_read_timeout 3600s;
}
}
server {
listen 80;
server_name sirio.example.com;
return 301 https://$host$request_uri;
}

Two details aren’t optional:

  • the Upgrade and Connection headers are needed for the log/stats WebSockets;
  • proxy_buffering off keeps logs from arriving in chunks with seconds of delay (and the long proxy_read_timeout keeps a followed log from being cut off).

Alternatively Sirio can manage its own Caddy, as a container, and publish both the panel and the sites it hosts on the machine. To have it serve the panel too, at https://DOMAIN:22722 with an automatic certificate:

Environment=SIRIO_PROXY_ENABLED=true
Environment=SIRIO_PANEL_DOMAIN=sirio.example.com
Environment=SIRIO_LISTEN=127.0.0.1:22723

Here SIRIO_LISTEN goes to another port, not to 127.0.0.1:22722 as in the snippet above: the proxy publishes the panel on 22722 and reaches Sirio through a Unix socket, and Sirio refuses to start if both want the same port. Secure cookies turn on by themselves. Install the proxy from Proxy → Install before or after: either way Sirio publishes the panel’s port as soon as the container exists.

Any proxy already on the host has to be stopped first: it occupies ports 80 and 443. Full procedure, the choice of port (SIRIO_PANEL_PORT) and migration in domains.md.

Environment=SIRIO_TLS_CERT=/etc/sirio/fullchain.pem
Environment=SIRIO_TLS_KEY=/etc/sirio/privkey.pem
Environment=SIRIO_LISTEN=0.0.0.0:443

With direct TLS, secure cookies turn on by themselves. Renewing the certificate is still up to you (systemctl reload isn’t enough: the service needs a restart).

After putting HTTPS in place, also set:

Environment=SIRIO_SECURE_COOKIES=true

and restart with sudo systemctl restart sirio-sysadmin.

Open the panel: on first start the wizard that creates the administrator account appears. The password must be at least 10 characters; login attempts are limited to 10 every 15 minutes per IP address.

Behind a reverse proxy, every request arrives from the proxy’s IP: the limit then applies to the whole set of clients. That’s intentional — trusting X-Forwarded-For headers would let the limit be bypassed by spoofing them.

There’s no email-based recovery. Any account can get a new password in one of two ways:

  • from the panel: an administrator sets it from Users → Reset password;
  • from the command line, on the machine — the way back in when no administrator can log in:
Terminal window
sudo -u sirio /usr/local/bin/sirio-sysadmin -data-dir /var/lib/sirio -reset-password admin@example.com

It shows the account (email, role, creation date) and asks for the new password twice, without echoing it; the same rules as the panel apply (at least 10 characters). If the email doesn’t match any account, it lists the existing ones. From a script, the password can arrive on standard input instead, one line, asked once:

Terminal window
printf '%s\n' "$NEW_PASSWORD" | sudo -u sirio /usr/local/bin/sirio-sysadmin -data-dir /var/lib/sirio -reset-password admin@example.com

Either way the account keeps its role and permissions, its open sessions are closed and the reset ends up in the activity log as user.password.reset. There’s no need to stop the service: the state is re-read from the database on every request, so a running instance picks it up immediately.

-reset-admin is the drastic option: it deletes every administrator account and brings back the first-run wizard, to create a new one from scratch. Use it when you want to replace the administrators rather than recover one.

Terminal window
sudo -u sirio /usr/local/bin/sirio-sysadmin -data-dir /var/lib/sirio -reset-admin

It lists the administrator accounts it will delete and how many non-admin users stay, then asks you to type reset to confirm. Non-admin users keep their accounts, passwords and permissions; repositories, pipelines, sites, secrets and the activity log stay where they are, and the reset ends up in the log as admin.reset, one entry per deleted account. Recreate any other administrator afterwards from Users.

Until the wizard is completed, whoever opens the panel first creates the administrator. Run the reset when you can complete the wizard right away, ideally while the panel isn’t exposed beyond a network you trust — or prefer -reset-password, which never opens that window.

Once an update server is set up, Sirio updates itself from Settings → Updates, by hand or automatically: see updates.md. Otherwise, run the install script again, the same way you installed:

Terminal window
curl -fsSLO https://github.com/marsaldev/siriosysadmin/releases/latest/download/install.sh
sudo bash install.sh

It replaces the binary, units and helpers, keeps the data in /var/lib/sirio and the settings in the drop-in, and restarts the service. The running version is shown in Settings → Release and by curl -s localhost:22722/api/status.

Database migrations are applied at startup. Runs still in progress during the restart are marked as failed: no run is left hanging.

All state lives in /var/lib/sirio:

sirio.db database (users, repositories, pipelines, history, audit)
secret.key AES key that encrypts tokens and SSH keys ← without it the database is useless
runs/ execution logs
workspaces/ repository checkouts (regenerable)
Terminal window
sudo systemctl stop sirio-sysadmin
sudo tar czf sirio-backup-$(date +%F).tar.gz -C /var/lib sirio
sudo systemctl start sirio-sysadmin

Keep secret.key separate from the database: together they’re the keys to the house.

Terminal window
sudo systemctl disable --now sirio-sysadmin sirio-pkg.path sirio-docker-install.path sirio-logs.path \
sirio-fail2ban.path sirio-fail2ban-ctl.path sirio-update.path sirio-power.path
sudo rm -rf /etc/systemd/system/sirio-sysadmin.service* /etc/systemd/system/sirio-pkg.* \
/etc/systemd/system/sirio-docker-install.* /etc/systemd/system/sirio-logs.* \
/etc/systemd/system/sirio-fail2ban.* /etc/systemd/system/sirio-fail2ban-ctl.* \
/etc/systemd/system/sirio-update.* /etc/systemd/system/sirio-power.* \
/usr/local/lib/sirio /usr/local/bin/sirio-sysadmin
sudo systemctl daemon-reload
sudo rm -rf /var/lib/sirio # also deletes the data
sudo userdel sirio