otf
Overview
otf is an open-source, self-hosted alternative to Terraform Enterprise and HCP Terraform. It runs OpenTofu and Terraform plans and applies with a web interface, remote state management, run history and role-based access control. Your team can collaborate on infrastructure as code on its own infrastructure instead of a SaaS.
The SecureAnyCloud image installs otf 0.6.3 as a complete single-node deployment on Ubuntu 24.04 LTS. It combines the otfd daemon, a local PostgreSQL database, and nginx terminating TLS in front. The daemon includes a built-in server runner, so it executes remote runs on its own with no separate agent. It binds to loopback only and runs as a dedicated unprivileged system user. The application encryption secret, the site admin token and the PostgreSQL password are generated fresh on the first boot of every VM, so there is no default login.
What you get:
- otf 0.6.3 (
otfd) and the OpenTofu 1.12.4 CLI. - PostgreSQL backing otf's state, runs and RBAC, bound to loopback.
- nginx terminating TLS on port 443, with an automatic redirect from port 80.
- A per-VM site admin token, application secret and database password, generated on first boot into a root-only credentials file.
- A pre-warmed OpenTofu engine cache, so the first run does not wait on a download.
otfd.service,postgresql.serviceandnginx.serviceas systemd units, enabled and active.- 24/7 SecureAnyCloud support.
Prerequisites
You need an active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point.
Configure the NSG to allow inbound 22/tcp from your management network and 443/tcp for the web UI and the Terraform/OpenTofu API. otf serves everything over HTTPS. Port 80 only issues a redirect to 443.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, select Create a resource, search the Marketplace for otf by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTPS (443). Then select Review + create, and then Create.
Step 2 - Deploy from the Azure CLI
Replace the resource group, location and admin username to suit your environment. These commands launch the latest SecureAnyCloud otf image and open ports 22 and 443.
az vm image terms accept --urn sac1647283583153:otf-ubuntu-24-04:default:latest
az vm create \
--resource-group my-rg \
--name otf1 \
--image sac1647283583153:otf-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group my-rg --name otf1 --port 22 --priority 1001
az vm open-port --resource-group my-rg --name otf1 --port 443 --priority 1002Step 3 - Connect to your VM
Connect to the public IP shown by the deployment. On first boot, otf generates the per-VM secrets and starts the services automatically.
ssh azureuser@<public-ip>Step 4 - Confirm the services are running
The otf daemon, PostgreSQL and nginx are enabled systemd units. Confirm that each is active, and check the unauthenticated health endpoint, which nginx forwards to the daemon.
otfd --version sudo systemctl is-active otfd postgresql nginx curl -fsS http://127.0.0.1:8080/healthzThe output shows otfd version 0.6.3, three active lines, and {"status":"OK"}.
Step 5 - Retrieve your site admin token
Every VM generates a unique site admin token, application secret and database password on first boot, and writes them to a root-only file. Read the token and the URL:
sudo cat /root/otf-credentials.txtThe site admin token is the credential you paste into the web UI. It is also the bearer token for the API and the OpenTofu/Terraform CLI. Store it securely.
Step 6 - Sign in to the web UI
Browse to https://<public-ip>/. The TLS certificate is self-signed on first boot, so your browser warns you on the first visit. Accept the warning, or install a trusted certificate as shown in Step 10.
On the login page, select the site admin link in the bottom right, paste the OTF_SITE_TOKEN value from the credentials file, and select Login. You land on the organizations view, where you create organizations and open their workspaces, runs, state and variables.
Step 7 - Verify the API
The site admin token authenticates the Terraform Enterprise-compatible API. A request with the token succeeds (HTTP 200). A request without one is rejected (HTTP 401). Run these commands on the VM to confirm the round trip:
TOKEN=$(sudo grep '^OTF_SITE_TOKEN=' /root/otf-credentials.txt | cut -d= -f2-)
echo -n 'no token -> '; curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/api/v2/organizations
echo -n 'with token -> '; curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8080/api/v2/organizationsStep 8 - Run your first plan
otf executes runs with the CLI-driven remote workflow. You write an ordinary OpenTofu (or Terraform) configuration whose cloud block points at your otf server. Then tofu plan and tofu apply run remotely on the daemon's built-in server runner. This workflow does not require a VCS.
On your workstation, which has the tofu or terraform CLI installed, save the site admin token so the CLI can authenticate. Replace <public-ip> and <your-token>:
mkdir -p ~/.terraform.d cat > ~/.terraform.d/credentials.tfrc.json <<'JSON' { "credentials": { "<public-ip>": { "token": "<your-token>" } } } JSONCreate a working directory with a minimal configuration. The hostname in the cloud block must match your VM address. The organization and workspace are created automatically if they do not exist:
terraform { cloud { hostname = "<public-ip>" organization = "sac" workspaces { name = "dev" } } } resource "terraform_data" "hello" { input = "hello from otf" }Then initialize and run. Because the certificate is self-signed, either install a trusted certificate (see Step 10) or point the CLI at the VM's certificate first.
# run from the directory holding your main.tf (cloud hostname = <public-ip>) tofu init tofu plan tofu applyThe plan and apply execute on the server. The streamed output, the run status and the resulting state are all recorded in the workspace. Open the workspace in the web UI to watch the run and inspect the managed resources and state.
Step 9 - Connect a VCS provider (optional)
To trigger runs from a Git repository, connect a VCS provider. otf supports GitHub, GitLab and other OAuth providers. You configure them at runtime, and nothing is baked into the image.
In the provider, create an OAuth app. For example, on GitHub go to Settings, then Developer settings, then OAuth Apps. Set the callback URL to https://<your-domain>/oauth/github/callback. Then start otfd with the matching client ID and secret (--github-client-id, --github-client-secret, and --hostname <your-domain>). Add the client ID and secret to /etc/otf/otfd.env and restart the daemon:
sudo systemctl restart otfdFor the full VCS and team/RBAC configuration, see the otf documentation at docs.otf.ninja.
Step 10 - Install a trusted TLS certificate
The image ships a per-VM self-signed certificate, so TLS works out of the box. For a public deployment, point a DNS name at the VM and install a trusted certificate with certbot. Replace <your-domain>:
sudo apt-get update && sudo apt-get install -y certbot
sudo certbot certonly --standalone -d <your-domain>
sudo sed -i "s#ssl_certificate .*#ssl_certificate /etc/letsencrypt/live/<your-domain>/fullchain.pem;#" /etc/nginx/sites-available/otf
sudo sed -i "s#ssl_certificate_key .*#ssl_certificate_key /etc/letsencrypt/live/<your-domain>/privkey.pem;#" /etc/nginx/sites-available/otf
sudo nginx -t && sudo systemctl reload nginxSet OTF_HOSTNAME in /etc/otf/otfd.env to your domain, then restart otfd so that run links and the API advertise the correct host.
Maintenance
otf stores its state, runs and RBAC data in PostgreSQL. Restart or check the daemon with:
sudo systemctl restart otfd
sudo systemctl status otfd --no-pagerunattended-upgrades applies security updates automatically. Back up the PostgreSQL otf database regularly, for example with pg_dump, so you can restore your workspaces, runs and state.
Support
SecureAnyCloud maintains this image and provides 24/7 support. If you have questions or run into issues, contact us at sales@secureanycloud.com.
Deploy on Azure
Launch otf on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com