Skip to content

Install the self-contained binary

CI publishes self-contained executables for linux-x64, linux-arm64, and win-x64. Each tarball is a single statically-linked binary with the .NET runtime baked in — there is nothing to install on the host beyond an unzip tool and the binary itself.

Use this path for VMs, bare metal, edge appliances, or air-gapped systems.

Download

Releases are attached to GitLab tag releases. Each release ships:

File SHA-256
ampora-web-linux-x64.tar.gz …sha256
ampora-web-linux-arm64.tar.gz …sha256
ampora-web-win-x64.tar.gz …sha256

Pull the matching SHA-256 file and verify before extracting.

VER=v1.4.2
curl -O "https://gitlab.com/ampora/ampora/-/releases/${VER}/downloads/ampora-web-linux-x64.tar.gz"
curl -O "https://gitlab.com/ampora/ampora/-/releases/${VER}/downloads/ampora-web-linux-x64.tar.gz.sha256"
sha256sum -c ampora-web-linux-x64.tar.gz.sha256
tar xzf ampora-web-linux-x64.tar.gz -C /opt
sudo mv /opt/linux-x64 /opt/ampora

The binary is /opt/ampora/Ampora.Web.

systemd unit

/etc/systemd/system/ampora.service
[Unit]
Description=Ampora — OpAMP management server
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=ampora
Group=ampora
WorkingDirectory=/opt/ampora
ExecStart=/opt/ampora/Ampora.Web
EnvironmentFile=/etc/ampora/ampora.env
Restart=on-failure
RestartSec=5

# Hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
ReadWritePaths=/var/lib/ampora
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
LockPersonality=true
RestrictNamespaces=true
MemoryDenyWriteExecute=true
SystemCallArchitectures=native

[Install]
WantedBy=multi-user.target

Create the service user, working directory and config:

sudo useradd --system --home /var/lib/ampora --shell /usr/sbin/nologin ampora
sudo install -d -o ampora -g ampora /var/lib/ampora /etc/ampora
sudo chown -R ampora:ampora /opt/ampora

Environment file

/etc/ampora/ampora.env
# ASP.NET Core
ASPNETCORE_URLS=http://127.0.0.1:8080
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_FORWARDEDHEADERS_ENABLED=true

# Database
Database__Provider=Postgres
ConnectionStrings__Ampora=Host=db.acme.io;Port=5432;Database=ampora;Username=ampora;Password=...;SSL Mode=Require;Trust Server Certificate=false
AMPORA_AUTO_MIGRATE=1

# Auth
Authentication__Oidc__Authority=https://login.acme.io/realms/ampora
Authentication__Oidc__ClientId=ampora-web
Authentication__Oidc__ClientSecret=...

# Encryption
KeyProtection__MasterKey=BASE64_32_BYTES_HERE

# Self-observability
OpenTelemetry__ServiceName=ampora-server
OpenTelemetry__OtlpEndpoint=http://otelcol.acme.io:4317

# OpAMP
OpAmp__MaxMessageBytes=10485760
OpAmp__HeartbeatWindowSeconds=90
OpAmp__AllowedCapabilityFlags=15

chmod 0640 /etc/ampora/ampora.env and ensure it is owned by root:ampora.

Reverse proxy

Ampora binds to 127.0.0.1:8080 only. A reverse proxy (Nginx, HAProxy, Caddy) terminates TLS and forwards /, /v1/opamp and /v1/metrics to the loopback. Minimal Nginx:

upstream ampora { server 127.0.0.1:8080; keepalive 16; }

server {
    listen 443 ssl http2;
    server_name ampora.acme.io;
    ssl_certificate     /etc/ssl/ampora.crt;
    ssl_certificate_key /etc/ssl/ampora.key;

    # WebSocket / long-poll friendly timeouts
    proxy_read_timeout 1h;
    proxy_send_timeout 1h;

    location / {
        proxy_pass http://ampora;
        proxy_http_version 1.1;
        proxy_set_header Upgrade           $http_upgrade;
        proxy_set_header Connection        $connection_upgrade;
        proxy_set_header Host              $host;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

The shared map for $connection_upgrade:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

Start

sudo systemctl daemon-reload
sudo systemctl enable --now ampora.service
journalctl -u ampora -f

Open https://ampora.acme.io and log in. If the first request never reaches the OIDC provider, see Troubleshooting → OIDC.

Upgrade

sudo systemctl stop ampora
sudo tar xzf ampora-web-linux-x64.tar.gz -C /opt --strip-components=1 --transform 's,^linux-x64,ampora,'
sudo systemctl start ampora

EF migrations apply on startup if AMPORA_AUTO_MIGRATE=1. For air-gapped upgrades you may prefer to run migrations explicitly first:

sudo -u ampora /opt/ampora/Ampora.Web --migrate-only

Air-gapped operation

Two extra knobs matter:

  • OIDC discovery — point Authentication__Oidc__Authority at an IdP reachable from the air-gapped network (your internal Keycloak, ADFS, …). Ampora does not phone home for OIDC discovery.
  • Self-observability — point OpenTelemetry__OtlpEndpoint at an internal collector or set it empty to disable export.

GitOps polling, federation, and HSM/KMS adapters are opt-in and can stay disabled.