Pick the path that matches the workstation you'll drive the install from. The target is always a Debian 13 (or 12) VM or bare host running Meridian; what changes is the toolchain on the side that builds the VM and pushes the source.
Jump to: VM appliance (import & boot, fastest) · Apt (Debian 12/13) · Windows path · Linux / macOS path · Bare Debian (manual)
Prebuilt Meridian VM. Download the disk image for your hypervisor,
import it, power on, wait for the DHCP lease, log in at
https://<dhcp-ip> with admin /
password. No Debian install, no apt repo, no
install.sh. ~5 minutes wall-clock.
What you get:
sudo apt upgrade meridian-nip after
first boot to pick up v1.0.1 (install.sh upgrade-path fixes).Pick the disk format your hypervisor speaks:
| Hypervisor | Format | Compressed size | Asset |
|---|---|---|---|
| Hyper-V (Windows host) | .vhdx | ~1 GB | meridian-nip-v1.0.0.vhdx.zst |
| VMware Workstation / Fusion / ESXi · VirtualBox | .ova | ~1 GB | meridian-nip-v1.0.0.ova.zst |
| KVM / libvirt · Proxmox VE | .qcow2 | ~1 GB | meridian-nip-v1.0.0.qcow2.zst |
All three formats are zstd-compressed. Decompress before importing:
# Linux/macOS:
zstd -d meridian-nip-v1.0.0.<format>.zst
# Windows (7-Zip 21.07+ supports .zst), or PowerShell with zstd installed via winget:
zstd -d meridian-nip-v1.0.0.vhdx.zst
.vhdx into C:\VMs\ and create a new Gen 2 VM around it; Secure Boot OFF, bridged network).ovaqm importdisk <vmid> meridian-nip-v1.0.0.qcow2 local-lvmvirt-install --import --name meridian --disk path=...qcow2 --memory 4096 --vcpus 2VM boots in ~30 seconds, picks up DHCP. Find the IP in your hypervisor's console
or DHCP leases, then browse to https://<ip>. Default portal admin:
admin / password. The portal forces a password change on
first login and offers MFA enrollment.
The shipped appliance is built from v1.0.0. The
v1.0.1
patch release contains five install.sh upgrade-path fixes you'll want before
ever running install.sh --upgrade. Add the apt repo and apply it:
ssh admin@<ip> # password: meridiannip
sudo apt update
sudo apt install -y curl gpg ca-certificates
curl -fsSL https://meridiannip.com/meridiannip.gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/meridiannip-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/meridiannip-archive-keyring.gpg] https://meridiannip.com/apt stable main" \
| sudo tee /etc/apt/sources.list.d/meridian.list
sudo apt update
sudo apt upgrade -y meridian-nip
# v1.0.1 onwards stays current via `sudo apt upgrade`.
Every appliance ships with the same default OS account (admin /
meridiannip) and PG role password. After first browser login, change them:
sudo passwd admin # rotate OS password
sudo passwd root # ditto for root
The master encryption key and row-HMAC key were already regenerated per-image when the appliance was scrubbed, so two appliances on the same network can't impersonate each other.
If your target is already a Debian 12 or 13 host, this is the shortest path.
Add the MeridianNIP apt repo, install the package, edit one config file, run
the installer. ~3 minutes of operator time (plus the apt
package fetch). Future versions arrive via sudo apt upgrade.
# Tooling — a Debian minbase doesn't ship curl or gpg:
sudo apt update
sudo apt install -y curl gpg ca-certificates
# Fetch + dearmor the signing key into the system keyring:
curl -fsSL https://meridiannip.com/meridiannip.gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/meridiannip-archive-keyring.gpg
# Add the repo source:
echo "deb [signed-by=/usr/share/keyrings/meridiannip-archive-keyring.gpg] https://meridiannip.com/apt stable main" \
| sudo tee /etc/apt/sources.list.d/meridian.list
sudo apt update
The signing key fingerprint is
5072 F226 10C9 2331 A8E2 428C EE4D C4BD 960D 8B36; the
dearmored bytes go to /usr/share/keyrings/meridiannip-archive-keyring.gpg
and apt verifies every download against it.
sudo apt install meridian-nip
This drops the source tree under /opt/meridian and runs the
Debian postinst hook. On a fresh host with no
/etc/meridian/answers.local.env file, postinst prints a
short notice telling you what to do next — it does not auto-run
the installer until you've given it an answers file (next step).
sudo cp /opt/meridian/answers.example.env /etc/meridian/answers.local.env
sudo $EDITOR /etc/meridian/answers.local.env
# Set PORTAL_DOMAIN, STATIC_IP (optional), ADMIN_CIDR — comments inline.
sudo /opt/meridian/install.sh --unattended --config /etc/meridian/answers.local.env
# Or run interactively (every prompt has an inline explanation):
sudo /opt/meridian/install.sh
Default portal admin: admin / password —
forced change + MFA enroll on first login. The summary at the end
prints the portal URL and DB password; save them.
sudo apt update && sudo apt upgrade meridian-nip
stages the new source and re-runs install.sh --upgrade
automatically against the same answers file. Master keys and the
Postgres database persist across upgrades.
End-to-end with native Windows tools — no WSL, no Linux subshell needed. Hyper-V is the recommended hypervisor (built into Windows, scripted) but VMware Workstation and VirtualBox work too; see the callout under the Hyper-V step.
Prerequisites (all native to Windows 10/11 / Server):
Get-VM works.git in any shell.ssh and scp on the PATH by default. (Settings → Apps → Optional features → "OpenSSH Client" if it isn't already installed.)In a regular PowerShell window (no elevation needed for this step):
cd $HOME
git clone https://github.com/MeridianNIP/meridian.git
cd meridian
copy answers.example.env answers.local.env
notepad answers.local.env
# Set PORTAL_DOMAIN, STATIC_IP (optional), ADMIN_CIDR — comments inline.
You'll push this whole directory (including answers.local.env) to the VM in step 4.
One PowerShell command, ~940 MB:
New-Item -ItemType Directory -Force "C:\VMs\ISOs" | Out-Null
Invoke-WebRequest `
-Uri "https://github.com/MeridianNIP/meridian/releases/latest/download/debian-13.4.0-amd64-meridian-unattended.iso" `
-OutFile "C:\VMs\ISOs\debian-13.4.0-amd64-meridian-unattended.iso"
Verify with the SHA256SUMS file on the release page:
Get-FileHash "C:\VMs\ISOs\debian-13.4.0-amd64-meridian-unattended.iso" -Algorithm SHA256
Right-click PowerShell → Run as administrator, then from the cloned repo:
cd $HOME\meridian
./scripts/hyperv-bootstrap.ps1 `
-VMName meridian `
-Unattended `
-IsoPath "C:\VMs\ISOs\debian-13.4.0-amd64-meridian-unattended.iso"
Walk away ~10 minutes. When it's up, get the VM's DHCP IP:
Get-VMNetworkAdapter -VMName meridian | Select-Object -ExpandProperty IPAddresses
.iso from C:\VMs\ISOs\),
boot it, and walk away the same ~10 minutes. Steps 4 + 5 then apply unchanged.
Native Windows scp — no rsync needed (Windows doesn't ship rsync; scp from OpenSSH is the equivalent). From the cloned repo:
scp -r . admin@<vm-ip>:~/meridian/
The first connection prompts you to accept the VM's host key — answer yes. Then the auth challenge is "what's the password?" — that's meridiannip for the admin account baked into the preseed.
SSH in and let install.sh do the heavy lifting:
ssh admin@<vm-ip> "sudo rm -rf /opt/meridian; sudo mv ~/meridian /opt/meridian; sudo chown -R root:root /opt/meridian; sudo chmod 0755 /opt/meridian; sudo /opt/meridian/install.sh --unattended --config /opt/meridian/answers.local.env"
Wait ~5 minutes for install.sh to finish (apt + pip + service setup). The summary at the end prints the portal URL, admin temp password, and DB credentials — save them.
Default OS account: admin / meridiannip. Default portal admin: admin / password — forced change + MFA enrollment on first browser login.
End-to-end with native Unix tools. The hypervisor is VMware Workstation / Fusion, VirtualBox, Proxmox, KVM / libvirt, or anything that boots a UEFI Gen 2 VM. (Hyper-V is Windows-only — if your workstation is Linux/macOS, pick a cross-platform hypervisor.)
Prerequisites:
git, rsync, ssh — all standard on every distro and on macOS by defaultcurl or wget for the ISO downloadcd ~
git clone https://github.com/MeridianNIP/meridian.git
cd meridian
cp answers.example.env answers.local.env
$EDITOR answers.local.env
# Set PORTAL_DOMAIN, STATIC_IP (optional), ADMIN_CIDR — comments inline.
curl -LO https://github.com/MeridianNIP/meridian/releases/latest/download/debian-13.4.0-amd64-meridian-unattended.iso
curl -LO https://github.com/MeridianNIP/meridian/releases/latest/download/SHA256SUMS
sha256sum -c SHA256SUMS
# expect: debian-13.4.0-amd64-meridian-unattended.iso: OK
Use your hypervisor's UI or CLI to create the VM. Settings:
| Setting | Value |
|---|---|
| Guest OS | Debian GNU/Linux 13 (64-bit) |
| Firmware | UEFI — Secure Boot OFF |
| Disk | 40 GB dynamic |
| Memory | 4 GB |
| vCPUs | 2 |
| Network | Bridged (so the VM gets a LAN IP) |
| CD/DVD | attach the .iso, boot from CD first |
Power on, walk away ~10 minutes for the unattended Debian install. Find the VM's IP via your hypervisor's UI or by checking your DHCP leases.
Standard rsync. Run from the cloned repo:
rsync -az ./ admin@<vm-ip>:~/meridian/
ssh admin@<vm-ip> 'sudo rm -rf /opt/meridian && \
sudo mv ~/meridian /opt/meridian && \
sudo chown -R root:root /opt/meridian && \
sudo chmod 0755 /opt/meridian && \
sudo /opt/meridian/install.sh --unattended \
--config /opt/meridian/answers.local.env'
First SSH connection asks for the host key (yes) + the admin password (meridiannip).
Default OS account: admin / meridiannip. Default portal admin: admin / password — forced change + MFA enroll on first browser login.
For physical hardware, an existing Debian/Ubuntu host, or any scenario where you don't want our preseed ISO. Install Meridian directly on the box it'll run on. Linux-host only — there's no Windows operator step in this path.
Prerequisites:
git clone https://github.com/MeridianNIP/meridian.git /tmp/meridian-src
sudo mkdir -p /opt/meridian
sudo cp -a /tmp/meridian-src/. /opt/meridian/
sudo chown -R root:root /opt/meridian
sudo cp /opt/meridian/answers.example.env /opt/meridian/answers.local.env
sudo $EDITOR /opt/meridian/answers.local.env
# Set PORTAL_DOMAIN, STATIC_IP (optional), ADMIN_CIDR — comments inline.
cd /opt/meridian
sudo ./install.sh --unattended --config /opt/meridian/answers.local.env
# Or interactively (every prompt has an inline explanation):
sudo ./install.sh
Browse to https://<portal-domain>/ui/login. Default portal admin:
admin / password — forced change + MFA enroll on first login.
/healthz should return JSON with "status":"ok" once every component is up