Movin'In on Ubuntu 24.04 LTS on Azure
Overview
Movin'In is an open source, self hosted rental property booking marketplace. It gives you three web surfaces from a single server: a customer facing storefront where renters search and book rental properties by location and dates, an admin dashboard where you manage agencies, properties, locations, bookings and users, and a REST API backed by MongoDB. It is a data owning alternative to paying a third party portal a commission on every booking, built with React, Node and MongoDB.
The cloudimg image runs Movin'In 7.0.0, built from its official source at the pinned upstream tag v7.0, on a hardened, fully patched Ubuntu 24.04 LTS base. The Node/Express backend serves the REST API and file storage, MongoDB is the database (bound to the loopback interface only, never reachable from the network), and nginx serves the two React single page applications: the storefront on port 80 and the admin dashboard on port 3003.
The image is deliberately shipped unprovisioned, with an empty database and no secrets. Movin'In's only administrator creation path is server side, and its own setup routine ships with a well known default password, so on the first boot of every VM a one shot service generates this VM's secrets, initialises MongoDB with a per VM database password, and creates a single administrator with a random password written to a root only file — the upstream default password is never created on any running instance. Until that finishes, nothing is published on ports 80, 3003 or 4004 — so no instance is ever reachable from the network in an unprovisioned state, and no secret is ever shared between customers. Backed by 24/7 cloudimg support.
What is included:
- Movin'In 7.0.0 (React + Node/Express + MongoDB), built from the pinned upstream tag
v7.0 - The customer storefront on
:80and the admin dashboard on:3003, both served by nginx - The backend REST API and CDN asset storage on
:4004(Node/Express, managed by systemd) - MongoDB 8.0 Community bound to
127.0.0.1only, with a per VM database password - A per VM database password, JWT and cookie secrets, and administrator password generated on first boot and recorded in a root only file
- Nothing bound to any public port until first boot has provisioned and secured the instance
mongod.service,movinin.serviceandnginx.serviceas enabled systemd units so the platform returns after a reboot- 24/7 cloudimg support
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 sensible starting point; size up if you expect many concurrent renters or large property catalogues. NSG inbound: allow 22/tcp from your management network, and 80/tcp (storefront), 3003/tcp (admin dashboard) and 4004/tcp (backend API) from the networks that need them. Put HTTPS in front of the instance before exposing it to the public internet (see Next steps).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Movin'In by cloudimg, and select Create. On Basics 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), HTTP (80) and custom TCP 3003 and 4004. Then Review + create and Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name movinin \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Then open the storefront, admin and API ports so your browsers and clients can reach them:
az vm open-port --resource-group <your-rg> --name movinin --port 80 --priority 1001
az vm open-port --resource-group <your-rg> --name movinin --port 3003 --priority 1002
az vm open-port --resource-group <your-rg> --name movinin --port 4004 --priority 1003
Step 3 - Confirm the services are running
SSH in as azureuser. First boot generates this VM's secrets, seeds the database and administrator, then binds the public ports; it completes in well under a minute. Confirm the three services are active:
systemctl is-active mongod movinin nginx | paste -sd' ' -
List the listening TCP ports — the storefront (80), admin (3003) and API (4004) are public, while MongoDB (27017) is bound to the loopback interface only:
ss -tlnH | awk '{print $4}' | sed -E 's/.*:([0-9]+)$/\1/' | sort -un | paste -sd' ' -
Confirm the runtime versions:
node --version; mongod --version | head -1

Step 4 - Inspect the per VM secrets and administrator
Every secret is generated on this VM's first boot and never baked into the image. The administrator credentials are written to a root only file:
sudo stat -c '%a %U:%G' /root/movinin-credentials.txt
The backend's JSON web token and cookie secrets are per VM (shown here by length only — the values are never printed), and the MongoDB connection string carries a per VM database password:
for k in MI_JWT_SECRET MI_COOKIE_SECRET; do v=$(sudo grep -E "^$k=" /opt/movinin/backend/.env | cut -d= -f2-); echo "$k: ${#v} chars"; done
Confirm exactly one administrator exists in MongoDB:
DBURI=$(sudo grep -E '^MI_DB_URI=' /opt/movinin/backend/.env | cut -d= -f2- | tr -d '"'); mongosh "$DBURI" --quiet --eval "print('ADMIN users: ' + db.getSiblingDB('movinin').User.countDocuments({type:'ADMIN'}))"

Step 5 - Verify the administrator sign in
Read this VM's administrator e-mail and password from the root only file:
sudo grep -E '^movinin.admin.(email|pass)=' /root/movinin-credentials.txt
The per VM password authenticates against the backend admin sign in endpoint and returns HTTP 200:
curl -sS -o /dev/null -w 'correct password: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d '{"email":"<MOVININ_ADMIN_EMAIL>","password":"<MOVININ_ADMIN_PASSWORD>"}' http://127.0.0.1:4004/api/sign-in/admin
A wrong password is rejected with HTTP 204 (no session issued):
curl -sS -o /dev/null -w 'wrong password: HTTP %{http_code}\n' -H 'Content-Type: application/json' -d '{"email":"<MOVININ_ADMIN_EMAIL>","password":"WrongPassword123"}' http://127.0.0.1:4004/api/sign-in/admin

Step 6 - Open the storefront and admin dashboard
Browse to the customer storefront at http://<your-vm-public-ip>/. This is what your renters see: a property search over location and dates.

Browse to the admin dashboard at http://<your-vm-public-ip>:3003/ and sign in with the administrator e-mail and password from /root/movinin-credentials.txt.

After signing in you land on the bookings dashboard, where you create and manage bookings across your agencies and properties.

From the menu you manage your property catalogue — add properties, set their type, rental term and availability, and publish them to the storefront.

Step 7 - Reboot persistence
The platform is managed by systemd, so it returns automatically after a reboot. First boot runs exactly once (gated by a sentinel file) and then hands off to the long running services:
systemctl is-enabled mongod movinin movinin-firstboot nginx | paste -sd' ' -

Next steps
- Change the administrator password from the admin dashboard profile after your first sign in.
- Configure e-mail (SMTP). Renter e-mail verification and booking notifications need an SMTP provider. Set the
MI_SMTP_*values in/opt/movinin/backend/.envand restartmovinin.service. - Configure a payment gateway. To take payments, add your Stripe or PayPal keys (
MI_STRIPE_SECRET_KEY/MI_PAYPAL_*in the backend.env, and the matching publishable keys in the storefront) and restart the services. - Put HTTPS in front of the instance before exposing it to the public internet — terminate TLS with your own certificate (for example with Certbot and nginx) so credentials and cookies are never sent in clear text.
- Back up MongoDB with
mongodumpon a schedule so your catalogue, customers and bookings are recoverable.
Your Movin'In rental booking platform is now running on Ubuntu 24.04 LTS, secured with credentials unique to this VM. For help, contact cloudimg support at any time.