Deployment guide

Cockpit CMS

Overview

Cockpit CMS is an open source, API-first (headless) content platform. You model content as collections and singletons in the admin interface, manage media in the built-in asset manager, and read everything back through a documented REST and GraphQL Content API. Because it is headless, the same content can feed a website, a mobile app, a static site generator or several frontends at once.

This SecureAnyCloud image serves Cockpit CMS 2.14.0 behind nginx with PHP 8.3 FPM and OPcache on a hardened Ubuntu 24.04 LTS base, patched at build time. Cockpit keeps its content in a self-contained, file-based datastore under storage/data, so there is no separate database server to run or maintain.

The image ships uninstalled, with no users and no application security key. On the first boot of every VM, a one-shot service generates a unique security key, creates a single administrator account with a strong per-VM password, and writes the credentials to a root-only file. Until that finishes, nginx serves Cockpit on the loopback interface only and nothing is published on port 80. No instance is reachable from the network in an unconfigured state, and no secret is shared between customers.

What you get:

  • Cockpit CMS 2.14.0 served by nginx through the PHP 8.3 front controller, managed by systemd
  • The Cockpit admin interface on :80, requiring an administrator sign-in
  • A per-VM administrator account and application security key generated on first boot and recorded in a root-only file
  • A file-based content datastore, shipped empty so no build data is carried into your instance
  • The REST and GraphQL Content API for consuming your content from any frontend
  • nginx.service and php8.3-fpm.service as enabled systemd units
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting size and is comfortable for a single editorial team. Choose a larger size if you serve very high API traffic.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network and 80/tcp so browsers and your frontends can reach Cockpit and its API. Add 443/tcp once you terminate TLS on the VM.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Cockpit CMS 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 HTTP (80).

Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

Run the following to create the VM from the SecureAnyCloud offer, open ports 22 and 80, and print the public IP address.

az vm image terms accept --urn sac1647283583153:cockpit-cms-ubuntu-24-04:default:latest
az vm create \
  --resource-group my-rg \
  --name cockpit-cms \
  --image sac1647283583153:cockpit-cms-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 cockpit-cms --port 80 --priority 900
az vm show --resource-group my-rg --name cockpit-cms --show-details --query publicIps -o tsv

Step 3 - Confirm the services are running

Connect over SSH as the administrator user you chose at deploy time. Confirm that the web tier is up and that first-boot initialisation has completed.

systemctl is-active nginx php8.3-fpm test -f /var/lib/sac/data/cockpit-cms-firstboot.done && echo "first boot: complete" php -r 'require "/var/www/cockpit/bootstrap.php"; echo "Cockpit ".APP_VERSION."\n";'

The output shows active for both services, the first-boot completion line, and the Cockpit version.

Step 4 - Retrieve this VM's administrator credentials

The first boot created an administrator account on this VM, with a password unique to this machine. Read the root-only credentials file with sudo:

sudo cat /root/cockpit-cms-credentials.txt

The file lists the administrator username, the per-VM password and the sign-in URL. Cockpit signs tokens with an application security key that is generated per VM into config/config.php. It is never the shared default from the source code. Run these commands to confirm both without revealing the secrets:

sudo stat -c '%a %U:%G' /root/cockpit-cms-credentials.txt
sudo php -r '$c=require "/var/www/cockpit/config/config.php"; echo "sec-key length: ".strlen($c["sec-key"] ?? "")."\n"; echo "is default: ".(($c["sec-key"] ?? "")==="c3b40c4c-db44-s5h7-a814-b5931a15e5e1" ? "yes" : "no")."\n";'

The credentials file is 600 root:root, and the security key is a long generated value rather than the default.

Step 5 - Sign in to Cockpit

Open http://<your-vm-public-ip>/ in a browser to reach the Cockpit sign-in page. Enter the username <COCKPIT_ADMIN_USER> and the password <COCKPIT_ADMIN_PASSWORD> from the credentials file.

The unauthenticated web installer at /install is disabled on this image, so the only way in is the administrator account created on first boot.

After you sign in, you land on the Cockpit dashboard. The navigation lists the Content, Assets and Settings areas.

Step 6 - Model your content

Cockpit organises content into models. A collection holds many entries of the same shape, such as blog posts, products or team members. A singleton holds a single structured document, such as a homepage or global settings.

Open Content and create a model. Add typed fields (text, WYSIWYG, boolean, date, asset links and more) and save. Your models appear in the Content area, ready for editors to fill.

Step 7 - Create and manage entries

Select a collection and choose Create entry to add content through the generated form. Entries can be published or kept as drafts, and they are available over the API immediately. Editors work entirely in this interface, without touching code.

Step 8 - Consume content over the Content API

Cockpit exposes every model through a REST API. Create an API key in Settings > API, scoped read-only for public frontends, then fetch entries as JSON. From the VM, confirm the API is serving:

curl -s -o /dev/null -w 'login page: HTTP %{http_code}\n' http://127.0.0.1/auth/login
curl -s -o /dev/null -w 'API root: HTTP %{http_code}\n' http://127.0.0.1/api

A typical frontend request looks like this. Replace the host and key with your own:

curl -H "api-key: <API_KEY>" "http://<your-domain>/api/content/items/<MODEL_NAME>"

The API returns your entries as JSON, ready for any website, app or static site generator to render.

Step 9 - Verify the security posture

Run these checks to confirm that the unauthenticated installer is denied, that the datastore is not readable over the web, and that the administrator account is enforced:

curl -s -o /dev/null -w '/install: HTTP %{http_code} (expect 404)\n' http://127.0.0.1/install/
curl -s -o /dev/null -w 'datastore file: HTTP %{http_code} (expect 404)\n' http://127.0.0.1/storage/data/system.sqlite
curl -s -o /dev/null -w 'root path: HTTP %{http_code}\n' http://127.0.0.1/

The installer and the raw datastore both return 404, so an outsider cannot take over the instance or download your content database.

Step 10 - Confirm first boot and ongoing patching

The one-shot first-boot service leaves a completion marker and enables unattended security upgrades, so the OS keeps patching itself. Confirm both:

systemctl is-enabled cockpit-cms-firstboot.service
systemctl is-active unattended-upgrades.service uname -r

Step 11 - Enable HTTPS with Let's Encrypt

Terminate TLS before you send real traffic to Cockpit. Point a DNS record at the VM and allow 443/tcp in the NSG. Then install a certificate for your domain with certbot:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>

Certbot obtains the certificate and rewrites the nginx virtual host to serve Cockpit over HTTPS with automatic renewal.

Step 12 - Back up and maintain your VM

Cockpit's entire state is a directory tree. Back up the content datastore, uploaded assets and the per-VM configuration together:

sudo tar czf <backup-dir>/cockpit-backup-$(date +%F).tgz \
  -C /var/www/cockpit storage/data storage/uploads config/config.php

To restore, extract the archive into /var/www/cockpit on a fresh instance after its first boot. Keep a copy of /root/cockpit-cms-credentials.txt somewhere safe, and change the administrator password from Account after your first sign-in.

Security notes

  • No shared secrets. The image ships with no users and no application security key. Both are generated per VM on first boot, so nothing secret is shared between customers.
  • Loopback until configured. Cockpit is bound to loopback until first boot completes, so an unconfigured instance is never reachable from the network.
  • Installer and datastore blocked. The /install web installer is denied at the nginx layer, and the raw .sqlite datastore, config and dotfiles are never served over the web.
  • Harden access. Change the administrator password after your first sign-in, enable HTTPS before you expose the instance, and scope API keys to read-only for public frontends.
  • Keep the VM patched. Unattended security upgrades are enabled by default.

Architecture summary

Application: Cockpit CMS 2.14.0 (headless content platform, MIT)

Web server: nginx serving the PHP 8.3 front controller

Runtime: PHP 8.3 FPM with OPcache

Datastore: file-based (SQLite), under /var/www/cockpit/storage/data

Document root: /var/www/cockpit

Admin interface: http://<vm>/ (port 80; add TLS on 443)

Content API: REST and GraphQL under /api

First-boot service: cockpit-cms-firstboot.service (per-VM key and administrator)

Credentials file: /root/cockpit-cms-credentials.txt (mode 600, root)

Base OS: Ubuntu 24.04 LTS, hardened and patched at build time

Support

Every SecureAnyCloud image comes with 24/7 support. Email sales@secureanycloud.com with the VM name and, where relevant, the output of the commands in this guide.

Cockpit CMS is open source software licensed under the MIT License. The full licence text ships in the image at /var/www/cockpit/LICENSE.

Deploy on Azure

Launch Cockpit CMS on Ubuntu 24.04 LTS with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure