Applications Azure

Iceshrimp.NET on Ubuntu 24.04 on Azure User Guide

| Product: Iceshrimp.NET on Ubuntu 24.04 LTS on Azure

Overview

Iceshrimp.NET is a decentralized, federated microblogging server that implements the ActivityPub standard, so your instance can interoperate with Mastodon and thousands of other servers across the fediverse. It is a from-scratch rewrite of Iceshrimp with an all-new backend built on .NET for speed and low resource use, an all-new web client built with Blazor WebAssembly, and a Mastodon-compatible client API so many existing mobile and web clients work against it too. The cloudimg image builds Iceshrimp.NET v2026.1.2-beta from source with the .NET 10 SDK, backs it with PostgreSQL, fronts it with nginx, and generates the administrator account and every per-VM secret uniquely on the first boot of each VM. Backed by 24/7 cloudimg support.

What is included:

  • Iceshrimp.NET v2026.1.2-beta built from source (EUPL-1.2), on the .NET 10 / ASP.NET Core 10 runtime
  • The Iceshrimp.NET application running as the unprivileged iceshrimp user, bound to 127.0.0.1:3000 only
  • PostgreSQL as the sole datastore (no Redis required), bound to loopback; nginx fronting the app with an unauthenticated :80/healthz and the full web UI on :80 and :443
  • All per-VM state generated on first boot: the PostgreSQL password, the ASP.NET Data Protection keys and the administrator account - none are baked into the image
  • Account registration closed by default (secure by default); a single administrator account recorded in a root-only credentials file, plus a per-VM self-signed TLS certificate
  • 24/7 cloudimg support

The Iceshrimp.NET web client showing the signed-in timeline with a published note

Prerequisites

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 comfortable size for a single-instance server. NSG inbound: allow 22/tcp from your management network, and 80/tcp + 443/tcp for the web interface. The appliance serves the web UI on port 80 and on port 443 with a per-VM self-signed certificate so the interface works immediately; for production you install your own certificate and domain (see "Set your own domain").

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Iceshrimp.NET by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size (Standard_B2s); under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22), HTTP (80) and HTTPS (443). Then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name iceshrimp \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

az vm open-port --resource-group <your-rg> --name iceshrimp --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name iceshrimp --port 443 --priority 1011

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

On first boot the image generates the per-VM secrets, sets the web domain to the VM public IP, creates the administrator account and starts the stack. Confirm the three services are active:

systemctl is-active postgresql nginx iceshrimp.service

The application (Kestrel) and PostgreSQL both listen on loopback only; nginx is the sole public listener:

sudo ss -tlnp | grep -E ':3000|:5432|:80 |:443 '

Iceshrimp.NET, PostgreSQL and nginx services all active

The application and database bound to loopback, with nginx as the public edge and a root-only credentials file

Step 5 - Check the health endpoint and the API

The unauthenticated :80/healthz returns 200 for load-balancer probes, and the web UI answers on /:

curl -s -o /dev/null -w 'healthz -> %{http_code}\n' http://127.0.0.1/healthz
curl -s -o /dev/null -w 'web UI -> %{http_code}\n' http://127.0.0.1/

You can prove the per-VM administrator password authenticates against the Mastodon-compatible web API. A wrong password is rejected with 403; the real password returns 200:

P=$(sudo grep '^ICESHRIMP_ADMIN_PASSWORD=' /root/iceshrimp-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'login -> %{http_code}\n' -X POST -H 'Content-Type: application/json' \
  --data "{\"username\":\"admin\",\"password\":\"$P\"}" \
  http://127.0.0.1/api/iceshrimp/auth/login

The health endpoint returning 200 and the admin login round-trip returning 403 then 200

Step 6 - Retrieve the per-VM administrator credentials

The administrator username, password and URL are written to a root-only file on first boot. Read them over SSH:

sudo cat /root/iceshrimp-credentials.txt

The file records ICESHRIMP_ADMIN_USERNAME (admin), ICESHRIMP_ADMIN_PASSWORD (unique to your VM) and ICESHRIMP_URL. Store the password in your password manager; it is not recoverable from the file once you change it.

Step 7 - Sign in to the web interface

Open https://<vm-public-ip>/ (or http://<vm-public-ip>/) in your browser. Because the appliance ships a per-VM self-signed certificate, your browser will warn on the HTTPS URL the first time - accept it to proceed, or install your own certificate (see the next step). Sign in with the username admin and the password from the credentials file.

The Iceshrimp.NET sign-in page served by the VM

Once signed in you land on your timeline. Use the Note button to compose and publish a post, which appears immediately on your local timeline.

Composing a note in the Iceshrimp.NET web client

Account and instance options live under Settings.

Account settings in the Iceshrimp.NET web client

Step 8 - Set your own domain before federating (important)

Iceshrimp.NET bakes the web and account domains at initial setup and cannot cleanly change them once content exists. The appliance boots with both set to the VM public IP as a working single-instance evaluation placeholder, so the local timeline, web UI, account login and API all work self-contained. To federate with the wider fediverse you need a real domain and a valid TLS certificate. Point a DNS record at the VM, then edit the configuration and restart the service:

sudo nano /srv/iceshrimp/app/configuration.ini
# set, under [Instance]:
#   WebDomain = social.example.org
#   AccountDomain = example.org
# install a real TLS certificate for nginx at /etc/ssl/iceshrimp/, then:
sudo systemctl restart iceshrimp.service
sudo systemctl reload nginx

Do this before creating real accounts or publishing content - changing the domain afterwards breaks federation.

Step 9 - Version and licence

Iceshrimp.NET is built from source at the pinned upstream tag under the EUPL-1.2 licence and runs on the .NET 10 shared runtime:

head -1 /srv/iceshrimp/app/LICENSE

The EUPL-1.2 licence and the ASP.NET Core 10 runtime

Maintenance and security notes

  • Registration is closed by default. Open it (invite-only or open) under [Security] Registrations in configuration.ini only when you intend to accept sign-ups, and restart the service.
  • Backups: the entire instance state lives in the PostgreSQL iceshrimp database and the media directory at /srv/iceshrimp/app/media. Back both up regularly (pg_dump plus the media directory).
  • Object storage: for anything beyond a small instance, move media to S3-compatible object storage under [Storage:ObjectStorage] in configuration.ini.
  • Updates: the OS receives unattended security updates. Application updates are delivered as new cloudimg image versions.
  • TLS: replace the per-VM self-signed certificate with a CA-issued certificate (for example via a reverse proxy or certbot) for production use.

This image is not affiliated with or endorsed by the Iceshrimp project. Iceshrimp.NET is distributed under the EUPL-1.2 licence.