Skip to main content

Linux Binary Installation

SolidPing can be run directly as a binary on Linux systems. This is useful for environments where Docker is not available or when you want maximum control over the deployment.

Download​

Download the latest release from GitHub:

# Download the latest release
curl -L -o solidping-linux-amd64.gz https://github.com/fclairamb/solidping/releases/latest/download/solidping-linux-amd64.gz

# Decompress and make it executable
gunzip -c solidping-linux-amd64.gz > solidping
chmod +x solidping

# Move to a system location (optional)
sudo mv solidping /usr/local/bin/

For ARM64 systems:

curl -L -o solidping-linux-arm64.gz https://github.com/fclairamb/solidping/releases/latest/download/solidping-linux-arm64.gz
gunzip -c solidping-linux-arm64.gz > solidping
chmod +x solidping

For RISC-V 64 systems, use solidping-linux-riscv64.gz the same way.

Every release also publishes solidping-checksums.txt, covering all six published .gz/.zip archives. Verify it against the downloaded .gz file itself — gunzip -c above leaves that file in place, so this works whether you run it before or after decompressing:

curl -L -o solidping-checksums.txt https://github.com/fclairamb/solidping/releases/latest/download/solidping-checksums.txt
sha256sum -c --ignore-missing solidping-checksums.txt

--ignore-missing skips the checksum lines for archives you didn't download, so this works no matter which platform's file you fetched.

macOS​

See the macOS guide (Homebrew, binary download, Gatekeeper, launchd).

Checking the installed version​

solidping --version prints the version of the binary, whichever way you installed it. solidping version adds the commit and build time (-o json for a script). Neither starts the server or reads its configuration:

$ solidping --version
solidping version 0.44.0
$ solidping version
Version: 0.44.0
Commit: 1a2b3c4d
Git Time: 2026-11-01T10:00:00Z

A running server reports the same fields at GET /api/mgmt/version.

Running​

Quick Start with SQLite​

# Run with SQLite (data stored in current directory)
./solidping serve

With PostgreSQL​

# Set environment variables
export SP_DB_TYPE=postgres
export SP_DB_URL="postgresql://user:password@localhost:5432/solidping"

# Run the server
./solidping serve

Run Database Migrations​

./solidping migrate

Systemd Service​

Create a systemd service for automatic startup:

sudo nano /etc/systemd/system/solidping.service

Add the following content:

[Unit]
Description=SolidPing Monitoring Platform
After=network.target postgresql.service

[Service]
Type=simple
User=solidping
Group=solidping
WorkingDirectory=/opt/solidping
ExecStart=/usr/local/bin/solidping serve
Restart=always
RestartSec=5

# Environment variables
Environment=SP_DB_TYPE=postgres
Environment=SP_DB_URL=postgresql://solidping:password@localhost:5432/solidping
Environment=SP_SERVER_LISTEN=:4000

# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/solidping

[Install]
WantedBy=multi-user.target

Create the user and directories:

# Create system user
sudo useradd -r -s /bin/false solidping

# Create working directory
sudo mkdir -p /opt/solidping
sudo chown solidping:solidping /opt/solidping

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable solidping
sudo systemctl start solidping
sudo systemctl status solidping

Environment File​

For easier configuration, use an environment file:

sudo nano /opt/solidping/.env
# Database
SP_DB_TYPE=postgres
SP_DB_URL=postgresql://solidping:password@localhost:5432/solidping

# Server
SP_SERVER_LISTEN=:4000

# Email (optional)
SP_EMAIL_ENABLED=true
SP_EMAIL_HOST=smtp.example.com
SP_EMAIL_PORT=587
SP_EMAIL_USERNAME=noreply@example.com
SP_EMAIL_PASSWORD=smtp-password
SP_EMAIL_FROM=noreply@example.com

# Logging
SP_LOG_LEVEL=info

Update the systemd service to use the environment file:

[Service]
EnvironmentFile=/opt/solidping/.env

Nginx Reverse Proxy​

Configure Nginx as a reverse proxy:

server {
listen 80;
server_name monitoring.example.com;
return 301 https://$server_name$request_uri;
}

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

ssl_certificate /etc/letsencrypt/live/monitoring.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/monitoring.example.com/privkey.pem;

location / {
proxy_pass http://127.0.0.1:4000;
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_cache_bypass $http_upgrade;
}
}

Firewall​

Allow traffic on port 4000 (or your configured port):

# UFW
sudo ufw allow 4000/tcp

# firewalld
sudo firewall-cmd --permanent --add-port=4000/tcp
sudo firewall-cmd --reload

# iptables
sudo iptables -A INPUT -p tcp --dport 4000 -j ACCEPT

Logs​

View logs with journalctl:

# Follow logs
sudo journalctl -u solidping -f

# View last 100 lines
sudo journalctl -u solidping -n 100

# View logs since today
sudo journalctl -u solidping --since today

At the default info level, startup ends with a SolidPing is ready line that gives the URL to open, the version and the database. On a fresh install a second line gives the first login. After that, a check run is only logged when its check changes status, for example Check down name="Local Redis" slug=redis-localhost previous=validating error="connection refused" once the confirmation period has passed. Set LOG_LEVEL=debug to see every check run and job.

Updating​

# Stop the service
sudo systemctl stop solidping

# Download new version
curl -L -o /tmp/solidping.gz https://github.com/fclairamb/solidping/releases/latest/download/solidping-linux-amd64.gz
gunzip -c /tmp/solidping.gz > /tmp/solidping
chmod +x /tmp/solidping

# Replace binary
sudo mv /tmp/solidping /usr/local/bin/solidping

# Start the service
sudo systemctl start solidping

File Storage​

Alongside the database, SolidPing writes a handful of blobs — org logos, status-page assets, incident screenshots — under SP_FILESTORAGE_LOCAL_ROOT (default ./data/files, relative to the working directory). With the systemd setup above, that resolves under the persistent WorkingDirectory (/opt/solidping), which ReadWritePaths already covers, so there is nothing extra to mount here — this only matters for containerized deployments. See File Storage for the S3 backend, useful once you run more than one node.

Small hosts (1 GB and less)​

SolidPing runs on a 1 GB Raspberry Pi or a small VPS. A fresh instance idles with about 40 MB of its own memory. Logins are the only bursts: each password check allocates the argon2id memory and gives it back about a second later. On a host with 2 GiB of memory or less, that is 19 MiB per login by default (64 MiB on a larger host, see below).

Read the right number. ps and top report RSS, which includes 70-85 MB of binary pages. Those pages are shared with the page cache and reclaimable. The number that matters is RssAnon in /proc/<pid>/status:

grep -E 'VmRSS|RssAnon|RssFile|VmHWM' /proc/$(pidof solidping)/status

These knobs help, with what each one was measured to do:

SettingEffect
SP_RUNTIME_MEMORY_LIMIT=128MiB (or the native GOMEMLIMIT=128MiB)Soft cap on the Go heap. At 96 MiB the first-boot peak (VmHWM) dropped from 229-245 MB to 169 MB. It is a soft cap: the runtime collects more often near it, it never refuses memory.
Nothing (default)With no cgroup limit and no cap set, a Linux host with at most 2 GiB of RAM gets half of it as the soft cap (512 MiB on a 1 GB Pi). SP_RUNTIME_AUTO_MEMORY_LIMIT=false turns this off.
SP_SERVER_CHECK_WORKER_NBOnly worth lowering if the host runs many slow checks at once. Idle runners cost almost nothing (all goroutines together use about 3 MB of stack).
Nothing (default)On a host with 2 GiB or less (the cgroup limit when one is set, else the host RAM), a single-process install (SP_NODE_ROLE=all, the default) hashes passwords with the OWASP minimum argon2id profile m=19456 t=2 p=1. Each login's transient drops from 64 MiB to 19 MiB, and four concurrent logins peak at about 76 MiB instead of 256 MiB. The server logs password hashing: argon2id small-host profile once at boot when it applies.
SP_AUTH_PASSWORD_ARGON2_AUTO_PROFILE=falseKeeps the 64 MiB profile on a small host. Setting any of SP_AUTH_PASSWORD_ARGON2_MEMORY, _TIME or _THREADS (or the same keys in config.yml or in Server Settings) also keeps your values.
Security trade-off

The smaller argon2id profile makes each stolen password hash cheaper to brute force. It is still the OWASP minimum and still memory-hard. If memory is not the constraint on your small host, force the 64 MiB profile back with SP_AUTH_PASSWORD_ARGON2_AUTO_PROFILE=false. Existing hashes are upgraded to the active profile on the next login. See Authentication.

A fresh install seeds no browser check. Each browser check run starts a headless Chrome (40-120 MB). The browser samples (browser-example-com and js-browser-login) stay available in the create-check sample picker. Test mode seeds them disabled.

See Runtime memory for every SP_RUNTIME_* knob.

Next Steps​