Install on Ubuntu
The fastest native deployment path is the deploy/provision.sh script from the osctrl repository. It installs the host dependencies, builds the binaries and frontend, writes service configuration, prepares PostgreSQL and Redis, and starts the services through systemd.
This tutorial walks through a single-server Ubuntu install. It is a good default for a lab, a small deployment, or the first production host you want to understand before automating it.
What You Will Build
Section titled “What You Will Build”The command below installs:
osctrl-tls, listening internally on port9000and exposed by nginx on443,osctrl-api, listening internally on port9002and exposed by nginx on8444,- the React operator frontend, served by nginx on port
8443, - PostgreSQL as the backend database,
- Redis as the cache,
- an initial osctrl environment,
- an initial admin user if you pass
--admin.
The script stores binaries and configuration under /opt/osctrl by default.
Before You Start
Section titled “Before You Start”Use a fresh Ubuntu 22.04 or 24.04 server with a sudo-capable user. The script installs packages and writes system files, so do not run it on a machine where nginx, PostgreSQL, or Redis are already carefully hand-managed unless you have reviewed the script first.
Open these ports to the host:
| Port | Purpose |
|---|---|
443 |
osquery TLS endpoint |
8443 |
operator frontend |
8444 |
osctrl API |
Pick a hostname for the server. In the examples below, replace osctrl.example.com with your DNS name or server IP address.
1. Clone osctrl
Section titled “1. Clone osctrl”Install git if the host does not have it yet, then clone the repository:
sudo apt-get updatesudo apt-get install -y gitgit clone https://github.com/jmpsec/osctrl.gitcd osctrlThe provisioning script auto-detects this source path, but passing --source "$PWD" makes the command easier to read and repeat.
2. Run the Provisioning Script
Section titled “2. Run the Provisioning Script”For a first Ubuntu deployment, let the script install nginx, PostgreSQL, and Redis for you:
./deploy/provision.sh \ --mode dev \ --source "$PWD" \ --dest /opt/osctrl \ --part all \ --nginx \ --postgres \ --redis \ --all-hostname osctrl.example.com \ --adminIn dev mode, the script creates self-signed certificates and a starter environment with short osquery intervals. That makes the first install easy to test. For production, use the production example later in this page.
The script may take a little while when nginx generates dhparam.pem. That pause is normal.
When the install finishes, it prints the operator URL and the generated admin credentials. Save the password somewhere safe; it is generated once.
3. What the Script Does
Section titled “3. What the Script Does”The script performs the boring setup work in the right order:
- Detects Ubuntu and installs required packages such as
git,curl,make,gcc,openssl,bc, andrsync. - Installs
yq, Go, and Node.js throughnvmwhen they are not already present. - Installs and starts PostgreSQL when
--postgresis set. - Creates the
osctrlPostgreSQL database and user. - Installs and starts Redis when
--redisis set, using the default password from the script configuration. - Builds and installs
osctrl-cli,osctrl-tls,osctrl-api, and the frontend. - Generates YAML configuration files in
/opt/osctrl/config. - Verifies the generated service configuration.
- Creates and starts systemd services for
osctrl-tlsandosctrl-api. - Configures nginx as the public TLS entry point.
That is why the one command is long: each flag makes one piece explicit.
4. Verify the Install
Section titled “4. Verify the Install”Check the two osctrl services:
systemctl status osctrl-tlssystemctl status osctrl-apiCheck nginx:
sudo nginx -tsystemctl status nginxThen open the operator frontend:
https://osctrl.example.com:8443Because dev mode uses a self-signed certificate, your browser will warn about the certificate. For a test host, accept the warning. For production, use your own certificate.
You can also check the TLS endpoint directly:
curl -k -I https://osctrl.example.comA ready deployment returns an HTTP response instead of timing out or refusing the connection.
5. Find Logs and Configuration
Section titled “5. Find Logs and Configuration”The generated configuration lives here:
/opt/osctrl/config/tls.yml/opt/osctrl/config/api.ymlThe installed binaries live here:
/opt/osctrl/bin/Use journalctl for service logs:
sudo journalctl -u osctrl-tls -fsudo journalctl -u osctrl-api -fnginx configuration is written under /etc/nginx, with certificates under /etc/nginx/certs.
6. Enroll the Server Itself
Section titled “6. Enroll the Server Itself”If you want the server to enroll itself with osquery during provisioning, add --enroll:
./deploy/provision.sh \ --mode dev \ --source "$PWD" \ --dest /opt/osctrl \ --part all \ --nginx \ --postgres \ --redis \ --all-hostname osctrl.example.com \ --admin \ --enrollThis asks osctrl-cli to generate a quick-add enrollment command for the initial environment and execute it on the host.
7. Use Your Own Certificate
Section titled “7. Use Your Own Certificate”For a production-style install, put your certificate and key on the host and run with --mode prod --type own:
./deploy/provision.sh \ --mode prod \ --type own \ --certfile /etc/certs/osctrl.crt \ --keyfile /etc/certs/osctrl.key \ --source "$PWD" \ --dest /opt/osctrl \ --part all \ --nginx \ --postgres \ --redis \ --all-hostname osctrl.example.com \ --adminMake sure the certificate covers the hostname you pass with --all-hostname.
8. Upgrade Later
Section titled “8. Upgrade Later”To rebuild from the latest code and restart the installed services, use --upgrade:
./deploy/provision.sh \ --upgrade \ --source "$PWD" \ --dest /opt/osctrl \ --part allThe upgrade path refuses to continue if the source checkout has local changes. Commit, stash, or discard those changes before upgrading.
Useful Options
Section titled “Useful Options”| Option | Use |
|---|---|
--mode dev |
Self-signed certificates and development-friendly defaults |
--mode prod |
Production mode |
--type own |
Use the certificate passed with --certfile and --keyfile |
--part tls |
Deploy only the TLS endpoint |
--part api |
Deploy only the API and frontend path |
--all-hostname |
Use the same hostname for all services |
--public-tls-port |
Change the public nginx port for the TLS endpoint |
--public-admin-port |
Change the public nginx port for the operator frontend; the option keeps the script’s legacy name |
--public-api-port |
Change the public nginx port for osctrl-api |
--dest |
Change the install directory from /opt/osctrl |
--admin |
Create an initial admin user and print its password |
--password |
Set the initial admin password instead of generating one |
For the full option reference, see the provision.sh usage page.